1. 簡介
Ribbon is a client side load balancer which gives you a lot of control over the behaviour of HTTP and TCP clients. Feign already uses Ribbon, so if you are using @FeignClient then this section also applies.
- Ribbon 帶有負載均衡功能
- Fegin實現基於Ribbon
2. 代碼實現
2.1涉及的模塊
- eureka-server-singleton:服務註冊中心,端口8761
- eureka-service: 服務提供者,通過profile指定不同端口模擬一組微服務,端口8762、8763
- eureka-service-ribbon:通過Ribbon調用服務提供者提供的服務
2.2 源代碼
2.2.1 Github地址
https://github.com/andyChenHuaYing/spring-cloud-demo
2.2.2 切換
暫時不再採用切換到commit版本,很多小的修正都是後面才修正的,前期沒有規劃好,導致切換之後牽連到一些環境問題需要配置,統一使用第一次發佈的release版本 1.0.0,可通過tag切換git tag -d v1.0
,若想修改,可根據此tag創建新的分支。
2.3 eureka-server-singleton
與 二:Spring Cloud 之Eureka服務發佈與註冊沒有任何區別。
2.4 eureka-service
基於 三:Spring Cloud 之Eureka服務發佈與註冊 改造,其他不變,修改application.yml,利用SpringBoot 的profile特性啓動註冊兩個相同功能的服務實例。
2.4.1 application-8762.yml
兩個配置文件端口不同,其他都一致。拆開放,結構更清晰
server:
port: 8762
spring:
application:
name: eureka-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
2.4.2 application-8763.yml
兩個配置文件端口不同,其他都一致。
server:
port: 8763
spring:
application:
name: eureka-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
2.5 eureka-service-ribbon
2.5.1整體實現步驟
- pom.xml中引入
eureka-server
和netfix-ribbon
依賴 - application.yml中指定配置項,端口、application name、eureka-server地址
- SpringBoot 啓動類添加註解
@EnableEurekaClient @EnableDiscoveryClient
- 使用
@Bean @LoadBalanced
向Spring容器注入org.springframework.web.client.RestTemplate
實例 - 在使用之處使用
@Autowired public RestTemplate restTemplate;
獲取實例,調用服務提供方提供的方法
2.5.2 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-finchley-demo</artifactId>
<groupId>org.oscar.scd</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-service-ribbon</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
</project>
2.5.2 application.yml
server:
port: 8764
spring:
application:
name: eureka-service-ribbon
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
2.5.3 EurekaServiceRibbonApplication
package org.oscar.scd.eureka.service.ribbon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaServiceRibbonApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaServiceRibbonApplication.class, args);
}
}
2.5.4 HelloRibbonController、HelloRibbonService
package org.oscar.scd.eureka.service.ribbon.controller;
import org.oscar.scd.eureka.service.ribbon.service.HelloRibbonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/ribbon")
public class HelloRibbonController {
@Autowired
public HelloRibbonService service;
@GetMapping("/print")
public String print(@RequestParam String name) {
return this.service.hiService(name);
}
}
package org.oscar.scd.eureka.service.ribbon.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloRibbonService {
@Autowired
public RestTemplate restTemplate;
public String hiService(String name) {
return restTemplate.getForObject("http://eureka-service//print?name=" + name, String.class);
}
}
3. 驗證
3.1 創建SpringBoot啓動類
前面都沒有記錄如何創建SpringBoot啓動類,這裏記錄的時候需要通過不同的端口啓動兩個eureka-service實例,簡單記錄一下。
3.1.1 EurekaServerSingletonApplication
最簡單的方式添加一個SpringBoot啓動類型的啓動類就行。
3.1.2 EurekaServiceApplication-8762
3.1.3 EurekaServiceApplication-8763
與8762相同,只是修改 Active profiles 爲8763
3.1.4 EurekaServiceRibbonApplication
最簡單的方式添加一個SpringBoot啓動類型的啓動類就行。
3.2 啓動
依次啓動EurekaServerSingletonApplication
EurekaServiceApplication-8762
EurekaServiceApplication-8763
EurekaServiceRibbonApplication
,啓動完成後Run Dashboard界面:
3.3 訪問服務信息界面
可直接點擊上圖中Run Dashboard中的8761端口直接訪問,也可訪問http://localhost:8761/查看,可看到三個eureka服務都註冊到註冊中心了。
3.4 調用服務
訪問eureka-service-ribbon
提供的服務:http://localhost:8764/ribbon/print?name=oscar,多請求兩次,返回結果在一下兩種中切換,說明負載均衡起作用了。
- 第一次:
- 第二次
4. 思考
- RestTemplate在調用過程中是什麼角色
- 有哪些便捷用法
- eureka是否支持除了REST格式還支持其他協議
- Ribbon如何實現負載均衡的
- 還支持哪些負載均衡算法,隨機、輪詢、加權隨機、加權輪詢、源地址hash、最小連接數
- 如何切換負載均衡算法
- 還有哪些常用可配置項
5. 補充
5.1 總結
本系列只能做個快速入門,體驗一下各個模塊的基礎表現是怎麼樣的,後續會先深入的掌握各個組件的使用,對核心功能會學習源碼如何實現,思考的問題也會在後面爲自己答疑解惑。要深入,要下沉,豐富自己的知識圖譜,提高知識轉化率。
5.2 資料
優先一手資料,官網 > 權威 > 社區 > 論壇
http://cloud.spring.io/spring-cloud-static/Finchley.SR1/multi/multi_spring-cloud-ribbon.html