spring cloud Ribbon是基於Netflix Ribbon實現的一套客戶端,負載均衡工具java
簡單的說,Ribbon是Netflix發佈的開源項目,主要功能是提供客戶端的軟件負載均衡算法mysql
,將Netflix的中間層服務層鏈接在一塊兒.Ribbon客戶端組件提供一系列完善的配置項如鏈接nginx
超時,重試等.簡單的說,就是在配置文件中列出Load Balancer(簡稱LB)後面全部的機器,git
Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機鏈接等)去鏈接這些機器.咱們很容易使用Ribbon實現自定義的負載均衡算法github
ribbon原理圖:算法
集中式LBspring
即在服務的消費方和提供方之間使用獨立的LB設施(能夠是硬件,好比F5,也能夠是軟件,如Nginx)由該設施負責把訪問請求經過某一種策略轉發至服務的提供者;sql
進程式LB數據庫
將LB邏輯集成到消費方,消費方從服務中心獲取知有哪些地址可用,而後本身再從這些地址中選擇出一個合適的服務器.緩存
Ribbon就屬於進程內LB,它只是一個類庫,集成於消費方進程,消費方經過他來獲取到服務提供方的地址.
https://github.com/Netflix/ribbon
修改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在工做分紅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結合只是其中的一個實例
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
修改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
問題:依舊輪詢策略,可是加上新需求,每一個服務要求被調用5次.也即
之前是每臺機器一次,如今是每臺機器5次
解析源碼:https://github.com/Netflix/ribbon/blob/master/ribbon-
loadbalancer/src/main/java/com/netflix/loadbalancer/RandomRule.java
參考源碼修改成咱們的需求需的MyRole_YH.java
更新中
編寫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(); } }
測試
客戶端負載均衡器
在SpringCloud中Ribbon負載均衡客戶端,會從eureka註冊中心服務器端上獲取服務註冊信息列表,緩存到本地。
讓後在本地實現輪訓負載均衡策略。
服務器端負載均衡Nginx
nginx是客戶端全部請求統一交給nginx,由nginx進行實現負載均衡請求轉發,屬於服務器端負載均衡。
既請求有nginx服務器端進行轉發。
客戶端負載均衡Ribbon
Ribbon是從eureka註冊中心服務器端上獲取服務註冊信息列表,緩存到本地,讓後在本地實現輪訓負載均衡策略。
既在客戶端實現負載均衡。
應用場景的區別:
Nginx適合於服務器端實現負載均衡 好比Tomcat ,Ribbon適合與在微服務中RPC遠程調用實現本地服務負載均衡,好比Dubbo、SpringCloud中都是採用本地負載均衡。