spring cloud 客戶端負載均衡 - Ribbon

Spring Cloud Ribbon是一個基於HTTP和TCP的客戶端負載均衡工具,基於Netflix Ribbon實現的,Ribbon不像註冊中心、網關那樣須要單獨部署,它是做爲一個工具直接集成到Service裏。後面要講到的Feign裏面也集成了Ribbon。git

一、手動搭建一個客戶端負載均衡

準備工做:github

  • 準備一個由 peer一、peer2 構成的配置中心
  • 準備一個由 service-1(8091)、service-1(8092) 構成的服務端集羣
  • 準備一個Ribbon客戶端

添加pom依賴web

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
View Code

Ribbon客戶端,使用@EnableDiscoveryClient向Eureka註冊:spring

@SpringBootApplication
@EnableDiscoveryClient
public class RibbonServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run( RibbonServiceApplication.class, args );
    }

    /**
     * 實例化RestTemplate,經過@LoadBalanced註解開啓均衡負載
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
View Code

調用Service-1提供的服務:後端

@Service
public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    public UserDto getUser(Long userId) {
        ResponseEntity<UserDto> responseEntity = restTemplate.getForEntity("http://service-1/getUser/{1}", UserDto.class, userId);
        return responseEntity.getBody();
    }
}
View Code

依次啓動註冊中心、Service-1兩個實例和Ribbon,所有啓動成功後,能夠看到service-1啓動了兩個實例,以下圖所示: 架構

訪問 Ribbon 客戶端接口:http://localhost:9000/user/getByUserId負載均衡

刷新頁面,後端Service-1的兩個實例分別輸出日誌:dom

service-1:8091ide

8091 provides servicespring-boot

service-1:8092

8092 provides service
8092 provides service

系統架構如圖所示:

 二、Ribbon配置

自動化配置

上面搭建負載均衡過程當中沒有任何Ribbon相關的配置,是由於Spring Cloud整合Eureka和Ribbon時作了不少默認配置。

在沒有引入Spring Cloud Eureka時,Spring Cloud Ribbon 已經默認實現了這些配置bean:

  • IClientConfig :Ribbon客戶端配置,默認採用 com.netflix.client.config.DefaultClientConfigImpl 

  • IRule :Ribbon的負載均衡策略,默認採用 com.netflix.loadbalancer.ZoneAvoidanceRule

  • IPing:Ribbon實例心跳檢查策略,默認採用 com.netflix.loadbalancer.NoOpPing,經過看實現能夠看出:不會檢查實例是否可用,始終返回true

  • ServerList:服務實例清單維護列表,默認採用 com.netflix.loadbalancer.ConfigurationBasedServerList

  • ServerListFilter :服務實例清單過濾機制,默認採用 org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter

  • ILoadBalancer :負載均衡器,默認採用 com.netflix.loadbalancer.ZoneAwareLoadBalancer

自定義配置:代碼+RibbonClient方式

@RibbonClient(value = "service-1", configuration = MyRibbonConfig.class)
public class RibbonServiceApplication {

自定義負載爲隨機時:

@Configuration
public class MyRibbonConfig {
    @Bean
    public IRule ribbonRule() {   new RandomRule();   }
}

當自定義負載換爲輪詢時:

@Configuration
public class MyRibbonConfig {
    @Bean
    public IRule ribbonRule() {   new RoundRobinRule();   }
}

分別在上面兩種狀況下刷新頁面 http://localhost:9000/user/getByUserId (以刷新8次爲例,觀察service-1兩個實例控制檯打印的log):

  • 當爲 RandomRule 時發現service-1在8091和8092兩個實例隨機提供服務。
  • 當爲 RoundRobinRule 時發現service-1在8091和8092兩個實例輪流提供服務。

自定義配置:代碼+配置文件方式(Components of load balancer

在properties裏配置,經過反射方式建立,配置方式以下:

以 `<clientName>.ribbon.` 爲前綴,加上下面的屬性名(屬性名來自 org.springframework.cloud.netflix.ribbon.PropertiesFactory 類):

NFLoadBalancerClassName
NFLoadBalancerRuleClassName
NFLoadBalancerPingClassName
NIWSServerListClassName
NIWSServerListFilterClassName

配置ribbon負載方式(針對service-1服務設置):

service-1:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

將自定義類賦給對應的屬性能夠作到服務級別的自定義配置。

三、附錄

  本文Demo地址:Ribbon Service

相關文章
相關標籤/搜索