【Spring註解驅動開發】使用@Lazy註解實現懶加載

寫在前面

Spring在啟動時,默認會將單實例bean進行實例化,並加載到Spring容器中。也就是說,單實例bean默認在Spring容器啟動的時候創建對象,並將對象加載到Spring容器中。如果我們需要對某個bean進行延遲加載,我們該如何處理呢?此時,就需要使用到@Lazy註解了。

項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

懶加載

懶加載就是Spring容器啟動的時候,先不創建對象,在第一次使用(獲取)bean的時候,創建並使用對象,大家是不是想到了在【設計模式】專題中的單例模式呢?對單例模式不太了解的同學可以猛戳《淺談JAVA設計模式之——單例模式(Singleton)》,也可以查看《設計模式匯總——你需要掌握的23種設計模式都在這兒了!》來系統學習每種設計模式。

非懶加載模式

此時,我們將PersonConfig2類的配置修改成單實例bean,如下所示。

package io.mykit.spring.plugins.register.config;

import io.mykit.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試@Scope註解設置的作用域
 */
@Configuration
public class PersonConfig2 {
    @Bean("person")
    public Person person(){
        System.out.println("給容器中添加Person....");
        return new Person("binghe002", 18);
    }
}

接下來,在SpringBeanTest類中創建testAnnotationConfig5()方法,如下所示。

@Test
public void testAnnotationConfig5(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    System.out.println("IOC容器創建完成");
}

運行SpringBeanTest類中的testAnnotationConfig5()方法,輸出的結果信息如下所示。

給容器中添加Person....
IOC容器創建完成

可以看到,單實例bean在Spring容器啟動的時候就會被創建,並加載到Spring容器中。

懶加載模式

我們在PersonConfig2的person()方法上加上@Lazy註解將Person對象設置為懶加載,如下所示。

package io.mykit.spring.plugins.register.config;

import io.mykit.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試@Scope註解設置的作用域
 */
@Configuration
public class PersonConfig2 {

    @Lazy
    @Bean("person")
    public Person person(){
        System.out.println("給容器中添加Person....");
        return new Person("binghe002", 18);
    }
}

此時,我們再次運行SpringBeanTest類中的testAnnotationConfig5()方法,輸出的結果信息如下所示。

IOC容器創建完成

可以看到,此時,只是打印出了“IOC容器創建完成”,說明此時,只創建了IOC容器,並沒有創建bean對象。

那麼,加上@Lazy註解后,bean是何時創建的呢?我們在SpringBeanTest類中的testAnnotationConfig5()方法中獲取下person對象,如下所示。

@Test
public void testAnnotationConfig5(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    System.out.println("IOC容器創建完成");
    Person person = (Person) context.getBean("person");
}

此時,我們再次運行SpringBeanTest類中的testAnnotationConfig5()方法,輸出的結果信息如下所示。

IOC容器創建完成
給容器中添加Person....

說明,我們在獲取bean的時候,創建了bean對象並加載到Spring容器中。

那麼,問題又來了,只是第一次獲取bean的時候創建bean對象嗎?多次獲取會不會創建多個bean對象呢?我們再來完善下測試用例,在在SpringBeanTest類中的testAnnotationConfig5()方法中,再次獲取person對象,並比較兩次獲取的person對象是否相等,如下所示。

IOC容器創建完成
給容器中添加Person....
true

從輸出結果中,可以看出使用@Lazy註解標註后,單實例bean對象只是在第一次從Spring容器中獲取對象時創建,以後每次獲取bean對象時,直接返回創建好的對象。

總結

懶加載,也稱延時加載。僅對單例bean生效。單例bean是在Spring容器啟動的時候加載的,添加@Lazy註解后就會延遲加載,在Spring容器啟動的時候並不會加載,而是在第一次使用此bean的時候才會加載,但當你多次獲取bean的時候不會重複加載,只是在第一次獲取的時候會加載,這不是延遲加載的特性,而是單例Bean的特性。

好了,咱們今天就聊到這兒吧!別忘了給個在看和轉發,讓更多的人看到,一起學習一起進步!!

項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

寫在最後

如果覺得文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公眾號,跟冰河學習Spring註解驅動開發。公眾號回復“spring註解”關鍵字,領取Spring註解驅動開發核心知識圖,讓Spring註解驅動開發不再迷茫。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※回頭車貨運收費標準

Zookeeper實現服務註冊/發現

what that?

Zookeeper在分佈式開發中使用頻繁,但許多框架都對其進行了封裝,初學者可能無法較好的理解其工作原理,該文章演示了使用Zookeeper實現服務註冊,服務發現的簡單demo,希望能達到拋磚引玉的效果;

why need RegisterCenter?

之所以需要訪問註冊和服務發現是因為分佈式系統中,服務之間需要相互調用,但若每個服務自己維護一份依賴的服務信息的話,就顯得很麻煩,且自身維護的數據無法保證其實時性,當依賴的服務信息發生變更時,無法及時獲取更新,解決方案就是引入一個註冊中心,服務提供方將自己的信息寫入到註冊中心,服務使用方從註冊中心來獲取服務信息; 如下圖:

client表示服務使用方,server表示服務提供方

實現的效果: 客戶端可自動發現服務信息,當服務狀態發生變化時(上線,下線,更換地址),客戶端可以及時響應變化,效果如下圖:

效果演示

實現

  1. 首先保證Zookeeper以安裝啟動,且可以正常訪問

  2. 創建Maven項目並添加Zookeeper的Java客戶端依賴(注意版本號需>3.6)

    				<dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.6.1</version>
            </dependency>
    
  3. 編寫服務提供方

    package com.jerry;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.ZooDefs;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.data.ACL;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.*;
    import java.nio.charset.StandardCharsets;
    import java.util.ArrayList;
    import java.util.Enumeration;
    
    import static java.net.InetAddress.getLocalHost;
    
    public class UserService {
    
        public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
            new UserService().serving();
        }
    
        public void serving() throws IOException, KeeperException, InterruptedException {
            //獲取本機ip地址
            String ip = null;
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface ni = (NetworkInterface) networkInterfaces.nextElement();
                Enumeration<InetAddress> nias = ni.getInetAddresses();
                while (nias.hasMoreElements()) {
                    InetAddress ia = (InetAddress) nias.nextElement();
                    if (!ia.isLinkLocalAddress() && !ia.isLoopbackAddress() && ia instanceof Inet4Address) {
                        ip = ia.getHostAddress();
                    }
                }
            }
            int port = 8988;
    
            //啟動服務
            ServerSocket socket = new ServerSocket(port);
            System.out.println("服務器已啟動...");
            //註冊服務
            serverRegister(ip, port);
            //處理請求
            clientHandler(socket);
        }
    
        private void clientHandler(ServerSocket socket) throws IOException {
            while (true) {
                Socket accept = socket.accept();
                InputStream inputStream = accept.getInputStream();
                byte[] barr = new byte[1024];
                while (true) {
                    int size = inputStream.read(barr);
                    if (size == -1) {
                        //System.out.println("客戶端已關閉..");
                        accept.close();
                        break;
                    }
                    String s = new String(barr, 0, size);
                    //輸出客戶端消息
                    System.out.println(accept.getInetAddress().getHostAddress() + ": " + s);
                }
            }
    
        }
    
        private void serverRegister(String ip, int port) throws IOException, KeeperException, InterruptedException {
            //註冊服務
            ZooKeeper zooKeeper = new ZooKeeper("10.211.55.4: 2181",3000, null);
            try {
                ArrayList<ACL> acl = new ArrayList<>();
                acl.add(new ACL(31, ZooDefs.Ids.ANYONE_ID_UNSAFE));
                zooKeeper.create("/userServer", (ip + ":" + port).getBytes(StandardCharsets.UTF_8), acl, CreateMode.EPHEMERAL);
                System.out.println("服務發布成功!");
            } catch (KeeperException | InterruptedException e) {
                e.printStackTrace();
                throw e;
            }
        }
    }
    
  4. 編寫服務服務使用方

    package com.yyh;
    
    import org.apache.zookeeper.*;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class UserClient implements Watcher {
        String node = "/userServer"; //服務信息所在的節點 服務提供方和服務消費方一致
        private ZooKeeper zooKeeper;
        String server_ip;
        int server_port;
    
        public static void main(String[] args) throws Exception {
            //開始服務監聽
            UserClient userClient = new UserClient();
            userClient.run();
            //當訪問可用時與服務交互
            Scanner scanner = new Scanner(System.in);
            while (true){
                System.out.println("輸入要發送的信息(e:退出)");
                String text = scanner.next();
                if (text.equals("e"))System.exit(-1);
                if (userClient.server_ip == null){
                    System.err.println("沒有可用的服務...");
                }else {
                    userClient.sendToServer(text);
                }
            }
        }
        
        private void run() throws Exception {
            //連接zookeeper
            zooKeeper = new ZooKeeper("10.211.55.4:2181", 3000, null);
            //嘗試獲取服務信息
            getServerInfo();
            //添加對服務信息的永久監聽
            zooKeeper.addWatch(node,this,AddWatchMode.PERSISTENT);
        }
    
        //獲取服務信息
        private void getServerInfo()  {
            try {
                byte[] data = zooKeeper.getData(node, false, null);
                String[] infos = new String(data).split(":");
                server_ip = infos[0];
                server_port = Integer.parseInt(infos[1]);
                System.out.println("獲取服務信息成功!");
                System.out.println(server_ip+":"+ server_port);
            } catch (KeeperException e) {
                System.err.println("服務信息不存在! 等待服務上線........");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        //當節點狀態發送變化時將執行該方法(通知處理)
        @Override
        public void process(WatchedEvent event) {
            if (event.getPath().equals(node)) {
                //根據具體邏輯處理不同的事件類型,此處只關心節點的創建刪除和更新
                if (event.getType() == Event.EventType.NodeCreated) {
                    System.err.println("服務上線了");
                    getServerInfo();
                } else if (event.getType() == Event.EventType.NodeDataChanged) {
                    System.err.println("服務更新了");
                    getServerInfo();
                }else if (event.getType()== Event.EventType.NodeDeleted){
                    server_ip = null;
                    server_port = 0;
                    System.err.println("服務下線了");
                }
            }
        }
    
        public void sendToServer(String text) {
            InetSocketAddress server_address = new InetSocketAddress(server_ip, server_port);
            Socket socket = new Socket();
            try {
                socket.connect(server_address);
                //System.out.println("連接服務器成功!");
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write(text.getBytes());
                System.out.println("消息發送成功!");
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
  5. 打包服務端代碼,該步驟可忽略,僅為了測試客戶端正確性, 為了在打包時附帶其全部依賴,此處藉助Spring的打包插件,在pom中添加以下內容:

    		<build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>1.5.6.RELEASE</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    

    注意:Spring-boot打包插件會自動獲取項目中的主函數,必須保證主函數只有一個,所以需要暫時註釋客戶端的主函數,最後執行maven的package,得到jar包

  6. 將jar上傳至虛擬機並運行

    java -jar ZookeeperTest-1.0-SNAPSHOT.jar
    

    若沒有其他問題則客戶端依然可以正常連接服務器發送消息;

以上便是使用Zookeeper實現服務註冊和服務發現的具體步驟,在實際開發中,我們可能還會將提供的服務部署為集群,這時可將集群中的各個服務信息作為子節點註冊到指定節點下,客戶端監聽該節點變化,獲取子節點列表從而獲取到服務列表,還可以在此基礎上加上負載均衡算法實現對服務列表的合理訪問; 如圖:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

Dubbo+Zookeeper集群案例

一.開源分佈式服務框架

1.Dubbo是阿里巴巴公司開源的一個高性能優秀的服務框架,使得應用可通過高性能的 RPC 實現服務的輸出和輸入功能,可以Spring框架無縫集成。
   Dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:①面向接口的遠程方法調用;②智能容錯和負載均衡;③服務自動註冊和發現

2.結構圖

節點角色說明:

Provider: 暴露服務的服務提供方。
Consumer: 調用遠程服務的服務消費方。
Registry: 服務註冊與發現的註冊中心。
Monitor: 統計服務的調用次數和調用時間的監控中心。
Container: 服務運行容器。
 

調用關係說明

0服務容器負責啟動,加載,運行服務提供者provider。
1服務提供者provider在啟動時,(通過連接服務器的client)向註冊中心註冊自己可以提供的服務。(其實就是註冊一些provider自己的ip:port以及對自己提供的服務的描述,比如能幹什麼!)
2服務消費者consumer在啟動時,向註冊中心訂閱自己所需的服務。並註冊自己的ip:port等信息。
3註冊中心返回服務提供者provider地址列表給消費者consumer,如果有變更,註冊中心將基於長連接推送變更數據給消費者consumer。
4服務消費者consumer,從註冊中心返回的提供者provider地址列表中,基於軟負載均衡算法,選一台提供者provider進行調用,如果調用失敗,再選另一台調用。
5服務消費者consumer和提供者provider,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心monitor。
Dubbo 架構具有以下幾個特點,分別是連通性、健壯性、伸縮性、以及向未來架構的升級性。

二.Dubbo作用

  dubbo其實就是一个中間層管理工具,他是一個框架,裏面可以裝你想裝的服務,一般註冊中心大多用zookeeper,當然除了zookeeper,還要Redis等也可以做註冊中心。  
 

三.Dubbo+Zookeeper(註冊中心使用Zookeeper),Zookeeper其實是樹狀結構。

1.可以把register理解成房產中介,provider是賣房的人,張三想賣掉自己在秦淮區的學區房,李四想賣掉自己在棲霞區的學區房,consumer王五是想在棲霞區買學區房給自己孩子上學,王五去中介諮詢后,中介返回給王五的需求 滿足者是李四,王五從中介那得到李四的電話,自己打電話找李四買房。

比如Provider註冊的是  192.168.1.(描述121是吃飯,122睡覺,123打遊戲,124健身四種不同的服務)
2-0、 、dubbo–這是dubbo在ZooKeeper上創建的根節點  /dubbo
2-1 、 Dubbo在Zookeeper上註冊的節點目錄:假設接口名稱是:com.bob.dubbo.service.CityDubboService。
這是服務節點,代表了Dubbo的一個服務  /dubbo/com.bob.dubbo.service.CityDubboService
2-2 、 Dubbo啟動時,Consumer和Provider都會把自身的URL格式化為字符串,然後註冊到zookeeper相應節點下,作為一個臨時節點,當連斷開時,節點被刪除。
這是服務提供者的根節點,其子節點代表了每一個服務真正的提供者/dubbo/com.bob.dubbo.service.CityDubboService/providers
這是服務消費者的根節點,其子節點代表每一個服務真正的消費者;/dubbo/com.bob.dubbo.service.CityDubboService/consumers
2-3、 Consumer在啟動時,不僅僅會註冊自身到 …/consumers/目錄下,同時還會訂閱…/providers目錄下所有子節點,具體的看你訂閱具體是哪一個節點(比如訂閱健身這些服務),實時獲取其上Provider的URL字符串信息。register返回給Consumer這個ip–192.168.1.124,Consumer拿着這個iP直接去找Provider調用這項服務–健身。
2-4 、監控中心啟動時訂閱com.bob.dubbo.service.CityDubboService目錄下的所有提供者和消費者URL。

 

四.Dubbo——Zookeeper補充:

支持以下功能:

 
當提供者出現斷電等異常停機時,註冊中心能自動刪除提供者信息
當註冊中心重啟時,能自動恢復註冊數據,以及訂閱請求
當會話過期時,能自動恢復註冊數據,以及訂閱請求
當設置<dubbo:registry check=”false” />時,記錄失敗註冊和訂閱請求,後台定時重試
可通過設置<dubbo:registry username=”admin” password=”124″ />設置zookeeper 登錄信息
可通過<dubbo:registry group=”dubbo” />設置 zookeeper 的根節點,不設置將使用無 根樹
支持 * 號通配符 <dubbo:redistry group=”*” version=”*” />,可訂閱服務的所有分組 和所有版本的提供者
 
補充:
  消費者從ZK獲取provider地址列表后,會在本地緩存一份。當ZK註冊中心所有節點全部宕掉之後,消費者可以使用本地緩存的服務列表和provider進行通信。
ZK的意義在於為consumer和provider提供服務地址的發布/訂閱服務,讓消費者及時感知最新的服務列表,consumer真正調用provider是通過某種通信協議直接調用,並不依賴ZK。
 
所以當zookeeper宕機之後,不會影響消費者調用服務提供者,影響的是zookeeper宕機之後如果提供者有變動,增加或者減少,zk無法把變更通知推送給consumer,consumer會因為感知不到變更時間,不去拉取最新的服務列表,導致本地緩存的服務列表有可能過時的。

完結,個人理解,如有偏差,請大家指正,謝謝!

2020-06-09 10:58:28

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※推薦台中搬家公司優質服務,可到府估價

Kubernetes內部域名解析的那些事兒

前言

    在kubernets環境中,服務發現大都是基於內部域名的方式。那麼就涉及到內部域名的解析。從1.11版本開始,kubeadm已經使用第三方的CoreDNS替換官方的kubedns作為集群內部域名的解析組件。

kubernets中的4種DNS策略

None

表示空的DNS設置,這種方式一般用於想要自定義 DNS 配置的場景,往往需要和 dnsConfig 配合一起使用達到自定義 DNS 的目的。

Default

此種方式是讓kubelet來決定使用何種DNS策略。而kubelet默認的方式,就是使用宿主機的/etc/resolv.conf文件。

同時,kubelet也可以配置指定的DNS策略文件,使用kubelet參數即可,如:–resolv-conf=/etc/resolv.conf

ClusterFirst

此種方式是使用kubernets集群內部中的kubedns或coredns服務進行域名解析。若解析不成功,才會使用宿主機的DNS配置來進行解析。

ClusterFistWithHostNet

在某些場景下,我們的 POD 是用 HOST 模式啟動的(HOST模式,是共享宿主機網絡的),一旦用 HOST 模式,表示這個 POD 中的所有容器,都要使用宿主機的 /etc/resolv.conf 配置進行DNS查詢,但如果你想使用了 HOST 模式,還繼續使用 Kubernetes 的DNS服務,那就將 dnsPolicy 設置為 ClusterFirstWithHostNet。

策略配置示例

DNS策略,需要在Pod,或者Deployment、RC等資源中,設置 dnsPolicy 即可,以 Pod 為例:

apiVersion: v1
kind: Pod
metadata:
   labels:
    name: cadvisor-nodexxxx
    hostip: 192.168.x.x
  name: cadvisor-nodexxxx
  namespace: monitoring
spec:
  containers:
  - args:
    - --profiling
    - --housekeeping_interval=10s
    - --storage_duration=1m0s
    image: google/cadvisor:latest
    name: cadvisor-nodexxxx
    ports:
    - containerPort: 8080
      name: http
      protocol: TCP
    resources: {}
    securityContext:
      privileged: true
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
  dnsPolicy: ClusterFirst
  nodeName: nodexxxx

kubernets中域名解析流程

# Pod中的resolv.conf的解析配置

[root@l-k8s01 ~]# kubectl exec -it nginx-deploy-5754944d6c-dtzpj cat /etc/resolv.conf

nameserver 10.96.0.2
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

[root@l-k8s01 ~]# kubectl get svc -n kube-system |grep dns

kube-dns   ClusterIP  10.96.0.2   <none>   53/UDP,53/TCP,9153/TCP   158d

a)文件中配置的 nameserver 一般是k8s集群內部的dns服務的ClusterIP,無法ping,但是可以訪問。

b)意味着集群Pod內部的所有域名的解析,都要經過kubedns的虛擬ip 10.96.0.2 進行解析。

c)resolv.conf中search域分別是default.svc.cluster.local svc.cluster.local cluster.local,在kubernets中,域名的全稱必須是 service-name.namespace.svc.cluster.local 。

d)假如集群中有一個svc(Service)名為a,在某個Pod中執行命令 curl a 時,在此Pod中會根據/etc/resolv.conf進行解析流程。選擇nameserver 10.96.0.2進行解析,將字符串’a’帶入到/etc/resolv.conf文件中不同的search域,依次進行查找,如下:

a.default.svc.cluster.local -> a.svc.cluster.local -> a.cluster.local

先查找 a.default.svc.cluster.local ,若找不到,則再查找 a.svc.cluster.local ,依次往下進行,直到找到為止。

curl效率分析

在集群中若存在一個名為a的svc,在Pod中curl a和curl a.default都能實現請求,那麼兩種方式哪個的效率高呢?

那肯定是curl a啦,因為發起此請求時,通過/etc/resolv.conf中第一列的search域就能直接找到 a.default.svc.cluster.local ,直接避免了下一級的查找。

容器中訪問外部域名講述

下文將通過示例說明Pod訪問外部域名時發起的相應的請求信息。

以請求baidu.com為例,因為DNS容器一般不具備bash,所以無法通過docker exec的方式進入容器抓包,所以此處採用 進入到DNS容器的網絡中(不是發起DNS請求的容器)的姿勢去抓包,抓包姿勢準備好后,同時在某容器中訪問baidu.com,即可看到在進行的DNS查找的過程中都產生了什麼樣的數據包。

 

### 實操

# 進入dns容器網絡,準備好抓包姿勢

# 查看Pod所在具體的node節點

[root@master1 ~]# kubectl get pods -n kube-system -o wide|grep dns

coredns-5c48579f88-8wprg  1/1   Running  16    30d   10.244.4.120   node1
coredns-5c48579f88-rsnpr   1/1   Running   0     30d   10.244.5.142   node2

# 這裏以node1上的容器為操作對象,所以到node1節點上進行操作

# 找到容器並打印對應的NS ID

[root@node1 ~]# docker ps |grep dns

a964bbb43534 c0f6e815079e "/coredns -conf /etc…" 2 days ago Up 2 days k8s_coredns_coredns-5c48579f88-8wprg_kube-system_b1e7f3c3-98eb-4843-b156-1d203f98bd74_16
fbd12d2f9c7c k8s.gcr.io/pause:3.1 "/pause" 5 days ago Up 5 days k8s_POD_coredns-5c48579f88-8wprg_kube-system_b1e7f3c3-98eb-4843-b156-1d203f98bd74_3

[root@node1 ~]# docker inspect –format “{{.State.Pid}}”  a964bbb43534

21617

# 進入此容器的網絡Namespace

[root@node1 ~]# nsenter -n -t 21617

# 抓包姿勢就緒

[root@node1 ~]# tcpdump -i eth0 udp dst port 53|grep ‘baidu.com’

 

# 在另外的某容器中,進行域名查找操作

說明:一般pod中沒有nslookup命令,故需要手動安裝,根據不同環境自選以下操作。

### Centos

]# cat /etc/redhat-release

CentOS Linux release 7.5.1804 (Core)

]# yum -y install bind-utils

### Debian

# cat /etc/issue

Debian GNU/Linux 9

# apt-get install dnsutils -y

root@jenkins-7d66bf7977-cm4x4:~# nslookup baidu.com 10.244.4.120

 

注意:10.244.4.120是node1上的dns pod在kubernets集群中的內部通信ip地址。因為環境中有兩個dns pod,將其指定要單個具體的容器,能夠使抓包數據完整。

 

# 隨後,在前面就緒的抓包姿勢窗口就能看到數據包的出現

[root@node1 ~]# tcpdump -i eth0 udp dst port 53|grep ‘baidu.com’

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:57:50.791154 IP 10.244.4.127.51794 > node1.domain: 55406+ A? baidu.com.infra.svc.cluster.local. (51)
16:57:50.792540 IP 10.244.4.127.56306 > node1.domain: 27958+ A? baidu.com.svc.cluster.local. (45)
16:57:50.793439 IP 10.244.4.127.59799 > node1.domain: 27048+ A? baidu.com.cluster.local. (41)
16:57:50.799463 IP 10.244.4.127.39116 > node1.domain: 2303+ A? baidu.com. (27)

說明:

a)數據包中显示的 infra 是執行nslookup的pod的NameSpace;

b)根據數據显示,在真正解析到 baidu.com 之前,經歷了baidu.com.infra.svc.cluster.local. > baidu.com.svc.cluster.local. > baidu.com.cluster.local. 三次DNS請求。

請求浪費的原因

上文在正確請求到baidu.com之前,有過三次無效請求,即意味着請求浪費,那為什麼會出現那種情況呢,請繼續往下看。

 

# Pod中的resolv.conf的解析配置

root@jenkins-7d66bf7977-cm4x4:/# cat /etc/resolv.conf
nameserver 10.96.0.2
search infra.svc.cluster.local svc.cluster.local cluster.local host.com
options ndots:5

 

# options ndots:5 解釋

如果查詢的域名包含的點”.”,不到5個,那麼進行DNS查找,將使用非完全限定名稱(或者叫絕對域名),如果你查詢的域名包含點數大於等於5,那麼DNS查詢,默認會使用絕對域名進行查詢。

如果我們請求的域名是,a.b.c.d.e,這個域名中有4個點,那麼容器中進行DNS請求時,會使用非絕對域名進行查找,使用非絕對域名,會按照 /etc/resolv.conf 中的 search 域,走一遍追加匹配:

a.b.c.d.e.cicd.svc.cluster.local. ->

a.b.c.d.e.svc.cluster.local. ->

a.b.c.d.e.cluster.local.

直到找到為止。如果走完了search域還找不到,則使用 a.b.c.d.e. ,作為絕對域名進行DNS查找。

 

說明:

a)請求域名中點數少於5個時,先走search域,最後將其視為絕對域名進行查詢;

b)請求域名中點數大於等於5個時,直接視為絕對域名進行查找,只有當查詢不到的時候,才繼續走 search 域。

優化請求浪費

使用全限定域名

當訪問某域名時,以 ‘.’ 為後綴,即使用 完全限定域名(絕對域名),這樣發起的域名請求時將不會走search域進行匹配,而是直接使用整個原始域名字符串為個體進行解析。

 

如:

nslookup baidu.com.

配置特定ndots

在kubernets中,ndots值默認是5。是因為,Kubernetes 認為,內部域名,最長為5,要保證內部域名的請求,優先走集群內部的DNS,而不是將內部域名的DNS解析請求,有打到外網的機會,Kubernetes 設置 ndots 為5是一個比較合理的行為。

如果有特定業務需求,也可配置ndots,如下:

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsConfig:
    options:
      - name: ndots
        value: "1"

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

網頁設計最專業,超強功能平台可客製化

RocketMQ系列(三)消息的生產與消費

前面的章節,我們已經把RocketMQ的環境搭建起來了,是一個兩主兩從的異步集群。接下來,我們就看看怎麼去使用RocketMQ,在使用之前,先要在NameServer中創建Topic,我們知道RocketMQ是基於Topic的消息隊列,在生產者發送消息的時候,要指定消息的Topic,這個Topic的路由規則是怎樣的,這些都要在NameServer中去創建。

Topic的創建

我們先看看Topic的命令是如何使用的,如下:

./bin/mqadmin updateTopic -h

usage: mqadmin updateTopic -b <arg> | -c <arg>  [-h] [-n <arg>] [-o <arg>] [-p <arg>] [-r <arg>] [-s <arg>] -t
       <arg> [-u <arg>] [-w <arg>]
 -b,--brokerAddr <arg>       create topic to which broker
 -c,--clusterName <arg>      create topic to which cluster
 -h,--help                   Print help
 -n,--namesrvAddr <arg>      Name server address list, eg: 192.168.0.1:9876;192.168.0.2:9876
 -o,--order <arg>            set topic's order(true|false)
 -p,--perm <arg>             set topic's permission(2|4|6), intro[2:W 4:R; 6:RW]
 -r,--readQueueNums <arg>    set read queue nums
 -s,--hasUnitSub <arg>       has unit sub (true|false)
 -t,--topic <arg>            topic name
 -u,--unit <arg>             is unit topic (true|false)
 -w,--writeQueueNums <arg>   set write queue nums

其中有一段,-b <arg> | -c <arg>,說明這個Topic可以指定集群,也可以指定隊列,我們先創建一個Topic指定集群,因為集群中有兩個隊列broker-abroker-b,看看我們的消息是否在兩個隊列中負載;然後再創建一個Topic指向broker-a,再看看這個Topic的消息是不是只在broker-a中。

創建兩個Topic,

./bin/mqadmin updateTopic -c 'RocketMQ-Cluster' -t cluster-topic -n '192.168.73.130:9876;192.168.73.131:9876;192.168.73.132:9876'

./bin/mqadmin updateTopic -b 192.168.73.130:10911 -t broker-a-topic

第一個命令創建了一個集群的Topic,叫做cluster-topic;第二個命令創建了一個只在broker-a中才有的Topic,我們指定了-b 192.168.73.130:10911,這個是broker-a的地址和端口。

生產者發送消息

我們新建SpringBoot項目,然後引入RocketMQ的jar包,

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.3.0</version>
</dependency>

然後配置一下生產者的客戶端,在這裏使用@Configuration這個註解,具體如下:

@Configuration
public class RocketMQConfig {

    @Bean(initMethod = "start",destroyMethod = "shutdown")
    public DefaultMQProducer producer() {
        DefaultMQProducer producer = new
                DefaultMQProducer("DefaultMQProducer");
											producer.setNamesrvAddr("192.168.73.130:9876;192.168.73.131:9876;192.168.73.132:9876;");
        return producer;
    }
}
  • 首先創建一個生產者組,名字叫做DefaultMQProducer;
  • 然後指定NameServer,192.168.73.130:9876;192.168.73.131:9876;192.168.73.132:9876;
  • 最後在@Bean註解中指定初始化的方法,和銷毀的方法;

這樣,生產者的客戶端就配置好了,然後再寫個Test類,在Test類中向MQ中發送消息,如下,

@SpringBootTest
class RocketmqDemoApplicationTests {

    @Autowired
    public DefaultMQProducer defaultMQProducer;

    @Test
    public void producerTest() throws Exception {

        for (int i = 0;i<5;i++) {
            Message message = new Message();
            message.setTopic("cluster-topic");
            message.setKeys("key-"+i);
            message.setBody(("this is simpleMQ,my NO is "+i).getBytes());

            SendResult sendResult = defaultMQProducer.send(message);
            System.out.println("SendStatus:" + sendResult.getSendStatus());
            System.out.println("BrokerName:" + sendResult.getMessageQueue().getBrokerName());
        }
    }
}
  • 我們先自動注入前面配置DefaultMQProducer;
  • 然後在Test方法中,循環5次,發送5個消息,消息的Topic指定為cluster-topic,是集群的消息,然後再設置消息的key和內容,最後調用send方法發送消息,這個send方法是同步方法,程序運行到這裡會阻塞,等待返回的結果;
  • 最後,我們打印出返回的結果和broker的名字;

運行一下,看看結果:

SendStatus:SEND_OK
BrokerName:broker-b
SendStatus:SEND_OK
BrokerName:broker-b
SendStatus:SEND_OK
BrokerName:broker-b
SendStatus:SEND_OK
BrokerName:broker-b
SendStatus:SEND_OK
BrokerName:broker-a

5個消息發送都是成功的,而發送的隊列有4個是broker-b,1個broker-a,說明兩個broker之間還是有負載的,負載的規則我們猜測是隨機。

我們再寫個測試方法,看看broker-a-topic這個Topic的發送結果是什麼樣子的,如下:

@Test
public void brokerTopicTest() throws Exception {

    for (int i = 0;i<5;i++) {
        Message message = new Message();
        message.setTopic("broker-a-topic");
        message.setKeys("key-"+i);
        message.setBody(("this is broker-a-topic's MQ,my NO is "+i).getBytes());

        defaultMQProducer.send(message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("SendStatus:" + sendResult.getSendStatus());
                System.out.println("BrokerName:" + sendResult.getMessageQueue().getBrokerName());
            }

            @Override
            public void onException(Throwable e) {
                e.printStackTrace();
            }
        });

        System.out.println("異步發送 i="+i);

    }
}
  • 消息的Topic指定的是broker-a-topic,這個Topic我們只指定了broker-a這個隊列;
  • 發送的時候我們使用的是異步發送,程序到這裏不會阻塞,而是繼續向下執行,發送的結果正常或者異常,會調用對應的onSuccess和onException方法;
  • 我們在onSuccess方法中,打印出發送的結果和隊列的名稱;

運行一下,看看結果:

異步發送 i=0
異步發送 i=1
異步發送 i=2
異步發送 i=3
異步發送 i=4
SendStatus:SEND_OK
SendStatus:SEND_OK
SendStatus:SEND_OK
SendStatus:SEND_OK
BrokerName:broker-a
SendStatus:SEND_OK
BrokerName:broker-a
BrokerName:broker-a
BrokerName:broker-a
BrokerName:broker-a

由於我們是異步發送,所以最後的日誌先打印了出來,然後打印出返回的結果,都是發送成功的,並且隊列都是broker-a,完全符合我們的預期。

消費者

生產的消息已經發送到了隊列當中,再來看看消費者端如何消費這個消息,我們在這個配置類中配置消費者,如下:

@Bean(initMethod = "start",destroyMethod = "shutdown")
public DefaultMQPushConsumer pushConsumer() throws MQClientException {
    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("DefaultMQPushConsumer");
    consumer.setNamesrvAddr("192.168.73.130:9876;192.168.73.131:9876;192.168.73.132:9876;");
    consumer.subscribe("cluster-topic","*");
    consumer.registerMessageListener(new MessageListenerConcurrently() {
        @Override
        public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
            if (msgs!=null&&msgs.size()>0) {
                for (MessageExt msg : msgs) {
                    System.out.println(new String(msg.getBody()));
                    System.out.println(context.getMessageQueue().getBrokerName());
                }
            }

            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        }
    } );
    return consumer;
}
  • 我們創建了一個消費者組,名字叫做DefaultMQPushConsumer;
  • 然後指定NameServer集群,192.168.73.130:9876;192.168.73.131:9876;192.168.73.132:9876;
  • 消費者訂閱的Topic,這裏我們訂閱的是cluster-topic,後面的*號是對應的tag,代表我們訂閱所有的tag;
  • 最後註冊一個併發執行的消息監聽器,實現裡邊的consumeMessage方法,在方法中,我們打印出消息體的內容,和消息所在的隊列;
  • 如果消息消費成功,返回CONSUME_SUCCESS,如果出現異常等情況,我們要返回RECONSUME_LATER,說明這個消息還要再次消費;

好了,這個訂閱了cluster-topic的消費者,配置完了,我們啟動一下項目,看看消費的結果如何,

this is simpleMQ,my NO is 2
broker-b
this is simpleMQ,my NO is 3
broker-b
this is simpleMQ,my NO is 1
broker-b
this is simpleMQ,my NO is 0
broker-a
this is simpleMQ,my NO is 4
broker-b

結果符合預期,cluster-topic中的5個消息全部消費成功,而且隊列是4個broker-b,1個broker-a,和發送時的結果是一致的。

大家有問題歡迎評論區討論~

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※回頭車貨運收費標準

※推薦評價好的iphone維修中心

※超省錢租車方案

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

※推薦台中搬家公司優質服務,可到府估價

俄羅斯西伯利亞飆高溫 北極圈小鎮破天荒測攝氏38°C

摘錄自2020年6月22日聯合報報導

根據氣象數據網站的資料顯示,過去曾出現攝氏零下68°C極端低溫的俄羅斯西伯利亞小鎮維爾霍揚斯克(Verkhoyansk),竟在昨天測得攝氏38°C高溫。

美聯社報導,彙整俄羅斯氣象數據網站Pogoda iKlimat的資料指出,維爾霍揚斯克鎮20日高溫達到攝氏38°C(華氏100.4°F)。

西伯利亞大部分地區今年出現異常高溫,導致大規模野火重創當地森林。俄羅斯薩哈共和國(Sakha Republic)的維爾霍揚斯克鎮在北極圈內,位於首都莫斯科(Moscow)東北方大約4660公里處。

全球變遷
氣候變遷
國際新聞
俄羅斯
西伯利亞
歷史高溫
全球暖化

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

※回頭車貨運收費標準

6萬不到的大空間7座車 是否能超越神車宏光?

動力方面,北汽幻速H3採用的是1。5L動力發動機,最大功率113馬力,最大扭矩為150牛米。匹配一款5速手動變速箱。主要競爭對手分析:銷量神車 五菱宏光指導價:4。18-6。98萬銷量大得驚人的宏光是幻速H3的主要競爭對手,而我們可以拿幻速H3新上市的車型簡單對比一下同價位的宏光。

近日,北汽幻速官方宣布,北汽幻速H3手動舒適天窗版車型已經正式上市!它的售價僅為5.98萬元,這款車型是在H3舒適型的基礎上加入了許多配置,但是售價沒有增加!

先來看看這款新車型帶有的亮點配置

電動天窗

8英寸液晶屏

GpS導航、藍牙

ABS+EBD

倒車雷達

行車自動落鎖/解鎖

前排駕駛席安全氣囊

對於一輛售價不足6萬的MpV來說,這樣的配置還是相當給力的。

我們再來看看幻速H3的車身尺寸,首先它的車身長寬高為4660*1770*1780mm,帶行李架車型高度為1800mm。軸距達到了2800mm,並且提供7或8座的座椅布局,實用性表現不錯。

而且其後備廂的儲物空間可以擴展至3573L。

外觀設計在這個價位中有着較好的表現,中網設計簡約,但是頭燈造型犀利。車身的輪廓線條比較分明、幹練。

動力方面,北汽幻速H3採用的是1.5L動力發動機,最大功率113馬力,最大扭矩為150牛米。匹配一款5速手動變速箱。

主要競爭對手分析:

銷量神車 五菱宏光

指導價:4.18-6.98萬

銷量大得驚人的宏光是幻速H3的主要競爭對手,而我們可以拿幻速H3新上市的車型簡單對比一下同價位的宏光。

可以說,幻速H3手動舒適天窗版車型還是要多出許多舒適性配置的,性價比表現不錯。而宏光的起售價則更多,有更多的車型可選擇。

編者語:

低價的MpV市場發展到現在,在配置、性價比方面的競爭也日益激烈了!如果你覺得幻速H3手動舒適天窗版的配置足夠給力的話,就去多了解這款車吧!本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※回頭車貨運收費標準

中國駕校都教會了我們什麼?一出門就狗帶了

5萬元左右。為毛人家德國高速路上如果出現什麼事故,救護車都能第一時間暢通無阻的到達現場,車子都會讓出一條路來,看看人家要上的課程吧。德國的考駕照流程,也是分為理論和路考的,3測試、理論課、駕駛課、除此之外還要參加急救培訓課程。

從駕校畢業出來的孩子

你們是否覺得教練最厲害的地方

其實不是他們的技術有多叼

而是他們是比費玉清還要厲害的黃段子

從他們身上你能學到最多的就是說段子

話說國內的駕校都是要經過交通部門管理的,負責監考的也是交管部門,照理來說,強強聯手,門下出來個個都是優秀畢業生。

可是偏偏上路后就出現一些令人驚訝的各種奇葩事情。

收費那麼貴,教出來的是小學生?首先個人角度看,中國駕校的收費算是比較合理的,畢竟一分錢一分貨。

什麼鬼,考完科目一了還他么分不清路牌標識,死記硬背拿了90分,最後還是都還給教練了。

尼瑪,為什麼這個車位我會倒不進去,明明這倒車方法在駕校學得挺6的啊!

長途開車上路訓練為毛都是一些比較偏僻的地方,教練說是比較少車,沒那麼危險,然後吃飯的時候轉臉就去飯店老闆那裡嘿嘿嘿了,回扣杠杠的,我就問一句以後上路我專挑車少的地方走嘛?

什麼,還掛科,叫你沒準備好禮物吧,你看人家誰誰誰買了煙就一次性通過了。

套路,都是套路啊,實際學到的東西並不多,靠得還是後天的積累。

都說德國駕照是世界上難考的幾本駕照之一,和中國到底有什麼差距呢,一起來探討一下吧!

首先看一下人家的教練車和我們的教練車有什麼不一樣,不必羡慕,畢竟人家的費用總共下來要1.5萬元左右。

為毛人家德國高速路上如果出現什麼事故,救護車都能第一時間暢通無阻的到達現場,車子都會讓出一條路來,看看人家要上的課程吧。

德國的考駕照流程,也是分為理論和路考的,3測試、理論課、駕駛課、除此之外還要參加急救培訓課程。

安全意識

在參加理論考試之前,參考人員必須去參加一場約10小時的急救課程,學會各種各樣的急救措施,而且在德國在遇到交通事故的時候,你是有義務要下車對傷者進行急救措施的。

汽車構本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

德系車居然被日系車幹掉?美國安全機構公布最安全轎車

5L自然吸氣,配搭的是CVT,但是油耗方面則意外地不如雅閣以及凱美瑞。日產西瑪官方指導價:23。48-26。78萬作為天籟的孿生兄弟,西瑪有着一個更為年輕的外觀,而在操控上也是往着運動這個方面走去。雖然舒適性有所降低,但整體還是相對優秀。

前言

安全始終買車的頭等大事,在購車的時候我們經常會考慮汽車的安全配置如何,而且會考慮汽車的實際碰撞成績,而除了我國的C-NAp以外,美國IIHS(美國高速公路安全保險協會)也是一個公正的測試機構,而最近曝光測試眾多車型燈光不及格的也是這個組織。而今年已經過了,那麼有那些車型是獲得了最高安全評定,獲得top safety pick+評定呢?

這次有着38款車型獲得了這個殊榮,而在我國有售的轎車車型就有以下車型:

雪佛蘭沃藍達

雪佛蘭沃藍達是在國際中頗具盛名的混動車型,不過採用的是增程式混動,也就是充電以及的用汽油發動機發電的方式提供電能,綜合油耗較低。不過較高的售價是制約它在國內發展的因素。

現代伊蘭特

官方指導價:9.98-15.18萬

這裏所說的伊蘭特並不是說那個老掉牙的伊蘭特,而是我國的領動。這一款緊湊型轎車不僅顏值高,而且1.4T以及雙離合變速箱帶來的油耗表現相當不錯,但就是雙離合常見的頓挫還是有所表現。

馬自達3昂克賽拉

官方指導價:11.49-15.99萬

馬自達3昂克賽拉有着超高的顏值,以及在操控或者說是駕駛樂趣上有着不低的造詣,深受年輕人的喜愛。不過後排空間相對較小,這對於一些家庭用戶來說只能是夠用的地步,和着它2700mm軸距所不符。

豐田卡羅拉

官方指導價:10.78-17.58萬

卡羅拉對於豐田來說一直都是走量的車型,全球銷售量高。原因就是很好地保持了豐田家用車價格低廉,質量可靠的特點,而且後排空間極其優秀,對於家庭用戶來說非常適合。但就是外觀內飾上稍顯中庸,年輕人應該會喜歡更年輕的豐田雷凌。

馬自達6阿特茲

官方指導價:17.58-23.98萬

阿特茲和昂克賽拉一樣都是使用了“魂動”設計以及“創馳藍天”技術,所以顏值高、低油耗以及優秀的操控成為了標配。在之前的改款中還終於對之前備受詬病的內飾進行了改良,終於和外觀相適應。

日產天籟

官方指導價:17.58-23.88萬

天籟一直都有着“移動沙發”之稱,不僅僅是沙發的舒適程度,還有底盤的舒適程度都可以說是在同價位中出類拔萃的。動力方面則是有着2.0以及2.5L自然吸氣,配搭的是CVT,但是油耗方面則意外地不如雅閣以及凱美瑞。

日產西瑪

官方指導價:23.48-26.78萬

作為天籟的孿生兄弟,西瑪有着一個更為年輕的外觀,而在操控上也是往着運動這個方面走去。雖然舒適性有所降低,但整體還是相對優秀。不過在我國較高的售價是一個邁不過去的門檻。

斯巴魯力獅

官方指導價:21.98-29.98萬

斯巴魯在我國始終是一個比較小眾的品牌,這和它並沒有在我國實現國產有着很大的關係。但是它價格以及競爭力是不容小覷的,2.5L車型起售價也是22萬不到,作為一款進口車性價比頗高。不過筆者更希望能看到它的在我國實現量產。

豐田凱美瑞

官方指導價:18.48-32.98萬

對於凱美瑞相信大家都非常熟悉了,它的特點就是油耗低故障率低,在空間表現上還相當不錯。唯獨是中庸外觀確實不能讓年輕消費者感冒。

奧迪A4

官方指導價:29.98-43.00萬

新一代奧迪A4不僅性能更強,而且外觀上更寬更低矮,看起來更動感。可以說是今年最受歡迎的豪華中型車。

雷克薩斯ES

‍官方指導價:29.80-65.40萬

雷克薩斯ES作為日系豪車的代表,駕駛非常輕便,整體屬於不錯的水準,對於追求精緻感和豪華感的消費者來說ES是個不錯的選擇。

沃爾沃S60/V60

‍官方指導價:26.69-63.69萬

沃爾沃關於安全方面的知識儲備以及技術儲備還是豐厚的。也是這樣做出了這兩款車型,可以說是旅行版以及三廂版車型。

全文總結:IIHS評出的這些最安全車型中主要還是大家能夠買得起的車型,這些車型中日系車居多也能夠說明一定的問題,不過考慮到中外的車型還是會有一些差異,因此這份榜單也僅供參考,汽車的安全性只是其次,安全首先還是在於自身養成良好的駕駛習慣和安全意識。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※推薦台中搬家公司優質服務,可到府估價

就是不買思域 高顏值合資家用車有什麼好的選擇?

59-22。89萬凌渡的設計還是秉承了大眾一貫的沉穩風格,但是主要是整車的線條勾勒上凸顯出了一種運動轎跑的感覺,修長的車身讓人很容易誤以為它其實是一款中型轎車,而沉穩中透露出一種運動風的設計也讓大眾凌渡的接受人群非常廣泛。

前言

作為一款家用轎車,動力表現和極限性能往往不是這類消費者所注重的東西,更多人或許僅僅是要一台車有着漂亮的外觀和不錯的空間表現,重要的是,價格一定要合適。十五萬左右的售價或許是最多人考慮的。

2016年,可以說合資緊湊型轎車市場被本田思域搶盡了風頭,各種的加價提車讓多少預算有限的消費者頭疼不已。除了本田思域之外,還有什麼高顏值運動范兒的家用轎車可以受到消費者的青睞?今天的幾款車或許可以滿足這些消費者的胃口。

東風標緻308

指導價格:9.97-15.97萬

東風標緻308使用了全新的家族化點陣式前臉,看上去更加俊朗,肌肉線條豐富,更凸顯出這款緊湊型轎車的運動氛圍。車身側麵線條柔和修長,營造出一種小溜背的感覺,車尾設計簡約為主,以亮面黑色烤漆提升辨識度的同時,配合以獅爪造型的尾燈,更彰顯了一種個性。

推薦車型:標緻308 2016款230THp豪華版;指導價格:13.57萬。

上汽大眾凌渡

指導價格:14.59-22.89萬

凌渡的設計還是秉承了大眾一貫的沉穩風格,但是主要是整車的線條勾勒上凸顯出了一種運動轎跑的感覺,修長的車身讓人很容易誤以為它其實是一款中型轎車,而沉穩中透露出一種運動風的設計也讓大眾凌渡的接受人群非常廣泛。

推薦車型:凌渡 230TSI DSG風尚版;指導價格:15.99萬。

起亞-K3

指導價格:9.68-15.08萬

起亞近年來一直秉承着一種剛硬運動的風格造車,也正因為如此,起亞的車型吸引了相當大一部分年輕人爭相購買,起亞K3同樣使用了家族式的虎嘯式前臉設計,整車以長車頭,短車尾的轎跑式造型為主要設計語言,這也使得起亞K3的年輕定位更加明顯。

推薦車型:2016款起亞K3 1.4T 自動GLS;指導價格:13.28萬。

全文總結:以上三款車型都是在目前終端上有着不小的優惠幅度的車型,而且在品控和動力總成上也是比較可靠的類型,相比較到目前還有不少地方需要加價提車,候車時長較久的車型來說,只要你對品牌沒有頑固的執着,就可以考慮一下啦。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

網頁設計最專業,超強功能平台可客製化