1. 程式人生 > >三、SpringCloud使用Ribbon+RestTemplate實現負載均衡

三、SpringCloud使用Ribbon+RestTemplate實現負載均衡

一、Ribbon簡介

Ribbon是Netflix公司開源的使用在客戶端的一個負載均衡的專案。是SpringCloud Finchley.M8版本結合使用Consul時使用預設負載均衡客戶端。
負載均衡策略有以下,當然我們一可以更具實際需求,來自定義負載均衡策略。
SpringCloud中預設使用ZoneAvoidanceRule策略

類(策略) 說明 實現簡介
ZoneAvoidanceRule 複合判斷server所在區域的效能和server的可用性選擇server 使用ZoneAvoidancePredicate和AvailabilityPredicate來判斷是否選擇某個server,前一個判斷判定一個zone的執行效能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用於過濾掉連線數過多的Server
RandomRule 隨機選擇一個server 在index上隨機,選擇index對應位置的server
RoundRobinRule roundRobin方式輪詢選擇server 輪詢index,選擇index對應位置的server
RetryRule 對選定的負載均衡策略機上重試機制 在一個配置時間段內當選擇server不成功,則一直嘗試使用subRule的方式選擇一個可用的server
WeightedResponseTimeRule 根據響應時間分配一個weight,響應時間越長,weight越小,被選中的可能性越低 一個後臺執行緒定期的從status裡面讀取評價響應時間,為每個server計算一個weight。Weight的計算也比較簡單responsetime 減去每個server自己平均的responsetime是server的權重。當剛開始執行,沒有形成status時,使用roubine策略選擇server
AvailabilityFilteringRule 過濾掉那些因為一直連線失敗的被標記為circuit tripped的後端server,並過濾掉那些高併發的的後端server(active connections 超過配置的閾值) 使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就就是檢查status裡記錄的各個server的執行狀態
BestAvailableRule 選擇一個最小的併發請求的server 逐個考察Server,如果Server被tripped了,則忽略,在選擇其中ActiveRequestsCount最小的server

二、RestTemplate的原理

原理簡介:使用RestTemplate作為負載均衡模版,必須要使用@LoadBalance註解。

通過該註解,將RestTemplate被標記為使用RibbonLoadBalancerClient的作為負載均衡模版。使用restTmeplate發起http請求,請求被Spring攔截器攔截,然後處理攔截的請求,首先ConsulClient通過serviceId獲取所有ServiceInstance,在使用RibbonLoadBalancerClient選擇一個滿足負載策略的ServiceInstance作為請求的service,最後通過RestTemplate請求service。

三、建立服務consulservice3

1、引入依賴

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--用於監控與管理-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

        <!--config server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul</artifactId>
        </dependency>

        <!--服務發現依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--用於consul配置-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-config</artifactId>
        </dependency>


    </dependencies>

2、簡單的配置

spring.application.name=consulservice3
spring.cloud.consul.discovery.instance-id=${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}

3、建立程式啟動入口

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class ConsulService3App {

    @Value("${spring.application.name}")
    private String serviceName;

    @Value("${server.port}")
    private int servicePort;

    @RequestMapping("/say")
    public String say(){
        return "hello world! I'm '" + serviceName + ":" + servicePort + "'";
    }

    public static void main(String[] args){
        SpringApplication.run(ConsulService3App.class, args);
    }

}

4、分別以埠8001和8002啟動consulservice3
這裡寫圖片描述
可以看到服務已經註冊到ConsulServer了,一個偽叢集

三、建立客戶端consulclient3

1、引入依賴

 <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--用於監控與管理-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

        <!--config server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul</artifactId>
        </dependency>

        <!--服務發現依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--用於consul配置-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-config</artifactId>
        </dependency>


    </dependencies>

2、簡單配置

spring.application.name=consulclient3

3、建立啟動引用程式入口
說明:由於簡單教程,所以介面和配置都放在一起了,實際應用中決不允許這麼做

@SpringBootApplication
@EnableDiscoveryClient
@RestController
@Configuration
public class ConsulClient3App {
    @Bean
    @LoadBalanced//此註解必須存在
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Autowired
    private  RestTemplate restTemplate;

    //serviceId獲取service
    private static final String  SERVICE_ID = "consulservice3";

    @RequestMapping("/say")
    public String sayService() {
    //使用restTemplate作為模版,serviceId會被ribbonClient替換為服務的地址
        return restTemplate.getForObject("http://"+SERVICE_ID+"/say",String.class);
    }

    public static void main(String[] args){
        SpringApplication.run(ConsulClient3App.class, args);
    }
}

4、以埠9999啟動consulclient3,呼叫介面,證明負載均衡成功
這裡寫圖片描述
這裡寫圖片描述