一、Ribbon定義
spring cloud Ribbon是基於Netflix Ribbon實現的一套客戶端,負載均衡工具
簡單的說,Ribbon是Netflix發布的開源項目,主要功能是提供客戶端的軟件負載均衡算法
,將Netflix的中間層服務層連接在一起.Ribbon客戶端組件提供一系列完善的配置項如連接
超時,重試等.簡單的說,就是在配置文件中列出Load Balancer(簡稱LB)后面所有的機器,
Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機連接等)去連接這些機器.我們很容易使用Ribbon實現自定義的負載均衡算法
ribbon原理圖:
二、LB負載均衡
集中式LB
即在服務的消費方和提供方之間使用獨立的LB設施(可以是硬件,比如F5,也可以是軟件,如Nginx)由該設施負責把訪問請求通過某一種策略轉發至服務的提供者;
進程式LB
將LB邏輯集成到消費方,消費方從服務中心獲取知有哪些地址可用,然后自己再從這些地址中選擇出一個合適的服務器.
Ribbon就屬於進程內LB,它只是一個類庫,集成於消費方進程,消費方通過他來獲取到服務提供方的地址.
三、官方地址
https://github.com/Netflix/ribbon
四、Ribbon的初始化配置
1、修改microservicecloud-consumer-dept-80工程
修改pom文件
<!-- 將微服務provider側注冊進eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
修改yml文件 添加
eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #向服務中心注冊自己 register-with-eureka: false
對configBean進行新注解@LoadBalanced獲得Rest時加入Ribbon的配置
@Configuration public class ConfigBean { @Bean @LoadBalanced //注解表明這個restRemplate開啟負載均衡的功能。
public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
主啟動類ConSumeAppStart_80添加@EnableEurekaClient
@SpringBootApplication @EnableEurekaClient public class ConSumeAppStart { public static void main(String[] args) { SpringApplication.run(ConSumeAppStart.class); } }
修改DeptController客戶端訪問類
@RestController public class DeptController { //private static final String REST_URL_PREFIX = "http://localhost:8001"; private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT"; //完成真正的通過微服務名字從eureka上找到並訪問 /** * 使用 使用restTemplate訪問restful接口非常的簡單粗暴無腦。 (url, requestMap, * ResponseBean.class)這三個參數分別代表 REST請求地址、請求參數、HTTP響應轉換被轉換成的對象類型。 */ @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX + "/dept/addDept", dept, Boolean.class); } @RequestMapping("/findAll") public List<Dept> findAll() { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/findAll",List.class); } }
先啟動3個eureka集群后,在啟動microservicecloud-config-dept-client-8001並注冊進eureka
啟動ConSumeAppStart_80
測試 訪問地址:http://localhost:80/findAll
效果
五、Ribbon負載均衡
1、架構說明圖
Ribbon在工作分成2步
第一步:先選擇EurekaServer,它優先選擇在同一個區域負載較少的server
第二步:再根據用戶指定策略,在從server取到的服務注冊列表中選擇一個地址.
其中Ribbon提供了多種策略:比如輪詢,隨機和根據時間響應加權
六、創建提供者多服務
參考microservicecloud-provider-dept-8001新建2份,分別命名為8002,8003
新建8002/8003 數據庫,各自微服務分別連各自的數據庫clouddb02/clouddb03
修改8002/8003各自的yml
8002 yml
server: port: 8002 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路徑 type-aliases-package: com.yehui.entity # 所有Entity別名類所在包 mapper-locations: classpath:mybatis/mapper/**/*.xml # mapper映射文件 #應用名稱 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource # 當前數據源操作類型 driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包 url: jdbc:mysql://localhost:3306/clouddb02 # 數據庫名稱 username: root password: root dbcp2: min-idle: 5 # 數據庫連接池的最小維持連接數 initial-size: 5 # 初始化連接數 max-total: 5 # 最大連接數 max-wait-millis: 200 # 等待連接獲取的最大超時時間 eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/ ###是否向注冊中心注冊自己 register-with-eureka: true ###是否需要從eureka上獲取注冊信息 fetch-registry: true instance: instance-id: providerdept_8001 #自定義服務名稱 prefer-ip-address: true #訪問路徑可以顯示IP地址 #信息的描述 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
8003yml
server: port: 8003 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路徑 type-aliases-package: com.yehui.entity # 所有Entity別名類所在包 mapper-locations: classpath:mybatis/mapper/**/*.xml # mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource # 當前數據源操作類型 driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包 url: jdbc:mysql://localhost:3306/clouddb03 # 數據庫名稱 username: root password: root dbcp2: min-idle: 5 # 數據庫連接池的最小維持連接數 initial-size: 5 # 初始化連接數 max-total: 5 # 最大連接數 max-wait-millis: 200 # 等待連接獲取的最大超時時間 eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/,http://localhost:7001/eureka/ instance: instance-id: providerdept_8003 #自定義服務名稱 prefer-ip-address: true #訪問路徑可以顯示IP地址 #信息的描述 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$
備注
端口
數據庫鏈接 jdbc:mysql://localhost:3306/clouddb01
對外暴露的統一的服務實例名
啟動3個eureka集群配置區
啟動3個Dept微服務並各自測試通過
http://localhost:8003/dept/findAll
http://localhost:8001/dept/findAll
http://localhost:8002/dept/findAll
啟動ConSumeAppStart_80
客戶端通過Ribbon完成負載均衡並訪問上一步的Dept微服務
上圖有三個消費者
注意觀察看到返回的數據的數據庫的不同
從上面可以得到:Ribbon其實就是一個軟負載均衡的客戶端組件,他可以和其他所需求請求的客戶端結合使用,和eureka結合只是其中的一個實例
七、Ribbon核心組件IRule
1、IRule算法
IRule:根據特點算法中從服務列表中選取一個要訪問的服務
RoundRobinRule:輪詢算法
RandomRule隨機算法
AvailabilityFilteringRule:會先過濾由於多次訪問故障而處於斷路器跳閘狀態的服務,還有並發的連接數量超過閾值的服務,然后對剩余的服務列表按照輪詢策略進行訪問
WeightedResponseTimeRule:根據平均響應的時間計算所有服務的權重,響應時間越快服務權重越大被選中的概率越高,剛啟動時如果統計信息不足,則使用RoundRobinRule策略,等統計信息足夠會切換到WeightedResponseTimeRule
RetryRule:先按照RoundRobinRule的策略獲取服務,如果獲取失敗則在制定時間內進行重試,獲取可用的服務。
BestAviableRule:會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然后選擇一個並發量最小的服務
ZoneAvoidanceRule:默認規則,符合判斷server所在區域的性能和server的可用性選擇服務器
RetryRule:先根據RoundRonbinRule的策略獲取服務,如果獲取服務失敗則在指定時間內會進行重試,獲取可用的服務
訪問地址:https://github.com/Netflix/ribbon
config類
@Bean public IRule getRule(){ return new RandomRule(); //使用隨機的算法替換默認的輪詢算法 }
測試訪問:http://localhost:80/findAll
2、Ribbon自定義
修改microservicecloud-consumer-dept-80
主啟動類添加@RibbonClient
在啟動該微服務的時候就能去加載我們自定義Ribbon配置類,從而使配置生效,形如:
@RibbonClient(name = "MICROSERVICECLOUD-DEPT",configuration = MyRule.class)
注意細節
步驟:
新建一個MyRule類
@Configuration public class MyRule { @Bean public IRule getRule(){ return new RoundRobinRule(); //使用使用輪詢算法
} }
修改主啟動類新增@RibbonClient注解
@SpringBootApplication @EnableEurekaClient //表明自己是一個eurekaclient.
@RibbonClient(name = "MICROSERVICECLOUD-DEPT",configuration = MyRule.class) public class ConSumeAppStart_80 { public static void main(String[] args) { SpringApplication.run(ConSumeAppStart_80.class); } }
測試http://localhost:80/findAll
3、自定義規則深度解析
問題:依舊輪詢策略,但是加上新需求,每個服務要求被調用5次.也即
以前是每台機器一次,現在是每台機器5次
解析源碼:https://github.com/Netflix/ribbon/blob/master/ribbon-
loadbalancer/src/main/java/com/netflix/loadbalancer/RandomRule.java
參考源碼修改為我們的需求需的MyRole_YH.java
更新中
4、使用DiscoveryClient實現本地負載均衡
編寫controller
@RestController public class DeptController { //獲取服務注冊信息
@Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; @RequestMapping("/find") public List<Dept> find(){ List<ServiceInstance> instances = discoveryClient.getInstances("microservicecloud-dept"); int instacesSize = instances.size(); int index = num%instacesSize; num++; String url = instances.get(index).getUri().toString(); return restTemplate.getForObject(url + "/dept/findAll",List.class); } }
congig類
@Configuration public class ConfigBean { @Bean //@LoadBalanced 這個注解不需要了
public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
測試
5、Ribbon與Nginx區別
客戶端負載均衡器
在SpringCloud中Ribbon負載均衡客戶端,會從eureka注冊中心服務器端上獲取服務注冊信息列表,緩存到本地。
讓后在本地實現輪訓負載均衡策略。
服務器端負載均衡Nginx
nginx是客戶端所有請求統一交給nginx,由nginx進行實現負載均衡請求轉發,屬於服務器端負載均衡。
既請求有nginx服務器端進行轉發。
客戶端負載均衡Ribbon
Ribbon是從eureka注冊中心服務器端上獲取服務注冊信息列表,緩存到本地,讓后在本地實現輪訓負載均衡策略。
既在客戶端實現負載均衡。
應用場景的區別:
Nginx適合於服務器端實現負載均衡 比如Tomcat ,Ribbon適合與在微服務中RPC遠程調用實現本地服務負載均衡,比如Dubbo、SpringCloud中都是采用本地負載均衡。