第二篇:SpringCloud之服務消費(Ribbon)
在微服務架構中,業務都會被拆分成一個獨立的服務,服務與服務的通訊是基於Http RESTful的。SpringCloud有兩種服務呼叫方式,一種是Ribbon+RESTTemplate,另一種是Feign。在這一篇文章首先講解下基於Ribbon+REST。
Ribbon簡介
Spring Cloud Ribbon是一個基於HTTP和TCP的客戶端負載均衡工具,它基於Netflix Ribbon實現。通過Spring Cloud的封裝,可以讓我們輕鬆地將面向服務的REST模版請求自動轉換成客戶端負載均衡的服務呼叫。Spring Cloud Ribbon雖然只是一個工具類框架,它不像服務註冊中心、配置中心、API閘道器那樣需要獨立部署,但是它幾乎存在於每一個Spring Cloud構建的微服務和基礎設施中。因為微服務間的呼叫,API閘道器的請求轉發等內容,實際上都是通過Ribbon來實現的,包括後續我們將要介紹的Feign,它也是基於Ribbon實現的工具。
所以,對Spring Cloud Ribbon的理解和使用,對於我們使用Spring Cloud來構建微服務非常重要。Ribbon是一個負載均衡客戶端,可以很好的控制http和tcp的一些行為。Feign預設集成了Ribbon。
Ribbon 已經預設實現了這些配置bean:
- IClientConfig ribbonClientConfig: DefaultClientConfigImpl
- IRule ribbonRule: ZoneAvoidanceRule
- IPing ribbonPing: NoOpPing
- ServerList ribbonServerList: ConfigurationBasedServerList
- ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter
- ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer
服務提供
這一篇文章基於上一篇文章的工程,啟動sso-server 工程;啟動sso-serviceA工程,它的埠為8089;將serviceA的配置檔案的埠改為8090,並啟動,這時你會發現:sso-serviceA在sso-server註冊了2個例項,這就相當於一個小的叢集。訪問localhost:8088如圖所示:
服務呼叫
建一個服務消費者工程,取名為:service-ribbon
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>springboot-ribbon</artifactId>
<groupId>com.chenjay.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sso-ribbon</artifactId>
</project>
在父工程的pom檔案中加入spring-cloud-starter-ribbon依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
在工程的配置檔案指定服務的註冊中心地址為http://localhost:8088/eureka/,程式名稱為 service-ribbon,程式埠為8091。配置檔案application.yml如下:
server:
port: 8091
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8088/eureka/
spring:
application:
name: service-ribbon
在工程的啟動類中,通過@EnableEurekaClient向服務中心註冊;並且向程式的ioc注入一個bean: RestTemplate;並通過@LoadBalanced註解表明這個restRemplate開啟負載均衡的功能。
@SpringBootApplication
@EnableEurekaClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
寫一個測試類HelloService,通過之前注入ioc容器的restTemplate來消費serviceA服務的“/hello”介面,在這裡我們直接用的程式名替代了具體的url地址,在Ribbon中它會根據服務名來選擇具體的服務例項,根據服務例項在請求的時候會用具體的url替換掉服務名,程式碼如下:
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String helloService(String name) {
return restTemplate.getForObject("http://SERVICEA/hello?name="+name,String.class);
}
}
寫一個controller,在controller中用呼叫HelloService 的方法,程式碼如下:
@RestController
public class HelloController {
@Autowired
HelloService helloService;
@GetMapping(value = "/hello")
public String hello(@RequestParam String name){
return helloService.helloService(name);
}
}
測試
在瀏覽器上多次訪問http://localhost:8091/hello?name=chenjay,瀏覽器交替顯示:
這說明當我們通過呼叫restTemplate.getForObject(“http://SERVICEA/hello?name=”+name,String.class)方法時,已經做了負載均衡,訪問了不同的埠的服務例項。
此時的架構
- 一個服務註冊中心,sso-server,埠為8088
- ss-oserviceA工程跑了兩個例項,埠分別為8089,8090,分別向服務註冊中心註冊
- sso-ribbon埠為8091,向服務註冊中心註冊
- 當sercvice-ribbon通過RestTemplate呼叫serviceA的hello介面時,因為用Ribbon進行了負載均衡,會輪流的呼叫serviceA:8089和8090 兩個埠的hello介面;
原始碼下載:https://github.com/chenjary/SpringCloud/tree/master/springboot-ribbon