SpringCloud Ribbon是基於Netflix Ribbon實現的一套基於客戶端Client的負載均衡工具。mysql
Ribbon主要的功能是提供客戶端的軟件負載均衡算法,將Netflix的中間層服務鏈接在一塊兒,提供一系列完善的配置項如鏈接超時、重試等。nginx
簡單地說,就是在配置文件中列出Load Balancer(LB)後面全部的機器,Ribbon會自動地幫助你基於某種規則(如簡單輪詢、隨機鏈接等)去鏈接這些機器。git
集中式LB:github
在服務的消費方和提供方之間使用獨立的LB設施(能夠是硬件(F5),也能夠是軟件(nginx)),由這些設施負責把訪問請求經過某種策略轉發至服務的提供方。(至關於公務員考公,國家選舉)算法
進程內LB:spring
將LB的邏輯集成到消費方,消費方從服務註冊中心獲知有哪些地址可用,而後本身在從這些地址中選擇出一個合適的服務器。(至關於客戶點餐選擇人少的取餐點取餐)sql
Ribbon就屬於進程內LB,它只是一個類庫,集成於消費方進程,消費方經過它來獲取服務提供方的地址。數據庫
<!--引入Ribbon相關:ribbon->eureka->config--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!--微服務provider方引入eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <!--沒有帶sever表示就是client客戶端--> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.4.6.RELEASE</version> </dependency>
server:
#80端口被佔用,選擇了81測試
port: 81
#spring的配置
spring:
application:
name: springcloud-consumer-dept #默認註冊進eureka中的實例名稱(顯示大寫)
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/springcloud_db01?useUnicode=true&characterEncoding=utf-8
username: root
password: admin
#eureka的配置,肯定客戶端服務註冊到eureka服務列表內
eureka:
client:
register-with-eureka: false #不向eureka註冊本身
service-url: #使用eureka集羣測試
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
在consumer客戶端的配置類上加上@LoadBanlanced,表示當前的請求在客戶端作負載均衡;服務器
@Configuration public class SpringBeanConfig { @Bean @LoadBalanced //Ribbon基於客戶端作負載均衡 public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
@RestController public class DeptConsumerController { @Autowired private RestTemplate restTemplate; //服務端的請求地址,這裏是本機localhost,也能夠是其餘任意的服務機ip地址 //private static final String REST_URL_PREFIX = "http://localhost:8001"; //負載均衡後經過服務名來獲取,由於由客戶端選舉定位到隨機的一個Eureka註冊中心去訪問 private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT"; }
啓動測試訪問接口:http://localhost:8002/consumer/dept/get/2,訪問成功。restful
總結:Ribbon和Eureka整合後consumer能夠直接調用服務而不用關心地址和端口號。
Ribbon的負載均衡實現策略主要有:輪詢、隨機、重試三種。下面演示Ribbon的負載均衡,採用建立三個服務提供方的方式,並啓用三個Eureka服務註冊地址。具體思路圖以下:
這裏每一個請求者都是一個單體服務,擁有本身獨立的數據庫,訪問接口。可是提供暴露到註冊中心的實例名是惟一的,用於客戶端來作訪問地址的惟一請求,而Ribbon則會經過@LoadBalanced註解對應識別客戶端請求查詢可用的服務列表,調用對應的負載均衡策略。
(1)單個的provider中主要的application.yml配置:
server: port: 8001 #mybatis的配置 mybatis: type-aliases-package: com.fengye.springcloud.pojo mapper-locations: classpath:mybatis/mapper/*Mapper.xml configuration: map-underscore-to-camel-case: true #spring的配置 spring: application: name: springcloud-provider-dept #默認註冊進eureka中的實例名稱(多個服務提供方應該惟一) datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/springcloud_db01?useUnicode=true&characterEncoding=utf-8 #db01/02/03 username: root password: admin #eureka的配置,肯定客戶端服務註冊到eureka服務列表內 eureka: client: service-url: #集羣配置 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
(2)在服務提供方provider的Controller設置請求的調用接口,同時設置負載均衡端口信息:
@RestController @RequestMapping("/dept") public class DeptController { @Autowired private DeptService service; //集羣狀況下,用於訂單服務查看到底調用的是哪一個商品微服務節點 @Value("${server.port}") private String port; @GetMapping("/queryById/{id}") public Dept queryById(@PathVariable("id") Long id){ Dept dept = service.queryById(id); Dept result = new Dept(); BeanUtils.copyProperties(dept, result); result.setDname(result.getDname() + " data from port=" + port); //查看員工屬於哪一個端口 System.out.println(result.getDname()); return result; }; }
(1)請求調用controller接口編寫:
@RestController public class DeptConsumerController { /** * 消費者:不該該有service實現層 * RestTemplate:提供多種便捷的訪問遠程http服務的方法,提供簡單的restful服務模板(使用簡單無腦粗暴) * 參數類型:(url, requestMap, ResponseBean.class)分別表明REST請求地址、請求參數、HTTP響應轉換被轉換成的對象類型 */ @Autowired private RestTemplate restTemplate; //負載均衡後經過服務名來獲取 private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT"; @RequestMapping("/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id){ Dept result = restTemplate.getForObject(REST_URL_PREFIX + "/dept/queryById/" + id, Dept.class); System.out.println("客戶端請求:data from port= " + result.getDname()); return result; } }
(2)服務調用方獲取並請求調用請求端口,獲取並打印訪問的端口信息,連續多請求幾回:
控制檯打印:
能夠看到每次訪問請求的端口都在不停變化,客戶端consumer基於Ribbon實現了負載均衡。
Ribbon文檔相關:
https://github.com/Netflix/ribbon
示例代碼已上傳至Github地址:
https://github.com/devyf/SpringCloud_Study/tree/main/springcloud_hello