SpringCloud教程二:Ribbon(Finchley版)


在上一篇文章,講了服務的注冊和發現。在微服務架構中,業務都會被拆分成一個獨立的服務,服務與服務的通訊是基於http restful的。Spring cloud有兩種服務調用方式,一種是ribbon+restTemplate,另一種是feign。在這一篇文章首先講解下基於ribbon+rest。

一、ribbon簡介

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是一個負載均衡客戶端,可以很好的控制htt和tcp的一些行為。Feign默認集成了ribbon。

ribbon 已經默認實現了這些配置bean:

  • IClientConfig ribbonClientConfig: DefaultClientConfigImpl

  • IRule ribbonRule: ZoneAvoidanceRule

  • IPing ribbonPing: NoOpPing

  • ServerList ribbonServerList: ConfigurationBasedServerList

  • ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter

  • ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer

二、准備工作

這一篇文章基於上一篇文章的工程,啟動eureka-server 工程;啟動eureka-client工程,它的端口為8882;將service-hi的配置文件的端口改為8883,並啟動,這時你會發現:eureka-client在eureka-server注冊了2個實例,我將端口又換成8886,這樣就往eureka-server中注冊了三個實例,這就相當於一個小的集群。如下圖可以看到圖標顯示為3,說明同時啟動了三個實例。

 

 

 

如何在idea下啟動多個實例,請參照這篇文章: https://blog.csdn.net/forezp/article/details/76408139

訪問localhost:8881如圖所示: 如何一個工程啟動多個實例,請看這篇文章:https://blog.csdn.net/forezp/article/details/76408139

 

 

三、建一個服務消費者

重新建一個Maven工程,其中pom如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.liumy</groupId>
 8     <artifactId>ribbon-f-2</artifactId>
 9     <version>1.0-SNAPSHOT</version>
10     <packaging>pom</packaging>
11 
12     <parent>
13         <groupId>org.springframework.boot</groupId>
14         <artifactId>spring-boot-starter-parent</artifactId>
15         <version>2.0.3.RELEASE</version>
16         <relativePath/>
17     </parent>
18 
19     <modules>
20         <module>service-ribbon</module>
21     </modules>
22 
23     <properties>
24         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
25         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
26         <java.version>1.8</java.version>
27         <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
28     </properties>
29 
30     <dependencies>
31         <dependency>
32             <groupId>org.springframework.boot</groupId>
33             <artifactId>spring-boot-starter-test</artifactId>
34             <scope>test</scope>
35         </dependency>
36     </dependencies>
37 
38     <dependencyManagement>
39         <dependencies>
40             <dependency>
41                 <groupId>org.springframework.cloud</groupId>
42                 <artifactId>spring-cloud-dependencies</artifactId>
43                 <version>${spring-cloud.version}</version>
44                 <type>pom</type>
45                 <scope>import</scope>
46             </dependency>
47         </dependencies>
48     </dependencyManagement>
49 
50     <build>
51         <plugins>
52             <plugin>
53                 <groupId>org.springframework.boot</groupId>
54                 <artifactId>spring-boot-maven-plugin</artifactId>
55             </plugin>
56         </plugins>
57     </build>
58 
59 </project>

再重新建一個spring-boot工程,取名為:service-ribbon; 在它的pom.xml繼承了父pom文件,並引入了以下依賴:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.liumy</groupId>
        <artifactId>ribbon-f-2</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.liumy</groupId>
    <artifactId>service-ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>service-ribbon</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

    </dependencies>


</project>

在工程的配置文件指定服務的注冊中心地址為http://localhost:8881/eureka/,程序名稱為 service-ribbon,程序端口為8884。配置文件application.yml如下:

1 eureka:
2   client:
3     serviceUrl:
4       defaultZone: http://localhost:8881/eureka/
5 server:
6   port: 8884
7 spring:
8   application:
9     name: service-ribbon

在工程的啟動類中,通過@EnableDiscoveryClient向服務中心注冊;並且向程序的ioc注入一個bean: restTemplate;並通過@LoadBalanced注解表明這個restRemplate開啟負載均衡的功能。

 1 package com.liumy.serviceribbon;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 6 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 7 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 8 import org.springframework.context.annotation.Bean;
 9 import org.springframework.web.client.RestTemplate;
10 
11 @EnableEurekaClient
12 @SpringBootApplication
13 @EnableDiscoveryClient//通過@EnableDiscoveryClient向服務中心注冊
14 public class ServiceRibbonApplication {
15 
16     public static void main(String[] args) {
17         SpringApplication.run(ServiceRibbonApplication.class, args);
18     }
19 
20     @Bean//向程序的ioc注入一個bean
21     @LoadBalanced//通過@LoadBalanced注解表明這個restRemplate開啟負載均衡的功能。
22     RestTemplate restTemplate(){
23         return new RestTemplate();
24     }
25 }

寫一個測試類HelloService,通過之前注入ioc容器的restTemplate來消費eureka-client服務的“/hello”接口,在這里我們直接用的程序名替代了具體的url地址,在ribbon中它會根據服務名來選擇具體的服務實例,根據服務實例在請求的時候會用具體的url替換掉服務名,代碼如下:

 1 package com.liumy.serviceribbon;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.stereotype.Service;
 5 import org.springframework.web.client.RestTemplate;
 6 
 7 /**
 8  * @ClassName HelloService
 9  * @Descroption TODO ribbon測試service
10  * @Author Yubaba
11  * @Date 2019/10/20 15:11
12  **/
13 @Service
14 public class HelloService {
15 
16     @Autowired
17     RestTemplate restTemplate;
18 
19     public String HelloService(String name){
20         return restTemplate.getForObject("http://EUREKA-CLIENT/hello?name="+name,String.class);
21     }
22 }

寫一個controller,在controller中用調用HelloService 的方法,代碼如下:

 1 package com.liumy.serviceribbon;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.web.bind.annotation.GetMapping;
 5 import org.springframework.web.bind.annotation.RequestParam;
 6 import org.springframework.web.bind.annotation.RestController;
 7 
 8 /**
 9  * @ClassName HelloController
10  * @Descroption TODO ribbon測試controller
11  * @Author Yubaba
12  * @Date 2019/10/20 15:15
13  **/
14 @RestController
15 public class HelloController {
16 
17     @Autowired
18     HelloService helloService;
19 
20     @GetMapping("helloController")
21     public String helloController(@RequestParam("name")String name){
22         return helloService.HelloService(name);
23     }
24 
25 }

在瀏覽器上多次訪問http://localhost:8884/helloController?name=測試,瀏覽器交替顯示:

 

 

 

 

 

 

 

 

 這說明當我們通過調用restTemplate.getForObject(“http://EUREKA-CLIENT/hello?name=”+name,String.class)方法時,已經做了負載均衡,訪問了不同的端口的服務實例。

四、此時的架構

 

 

 (圖例來源於網絡,為了方便理解)

 

  • 一個服務注冊中心,eureka server,端口為8881
  • service-hi工程跑了三個實例,端口分別為8882,8883,8886,分別向服務注冊中心注冊
  • sercvice-ribbon端口為8884,向服務注冊中心注冊
  • 當sercvice-ribbon通過restTemplate調用service-hi的hi接口時,因為用ribbon進行了負載均衡,會輪流的調用eureka-client:8882、8883和8886 三個端口的hello接口

五、參考資料

本文參考了以下:

http://blog.csdn.net/forezp/article/details/69788938

http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html

 

注:本篇為原創文章,其中的過程與實現是參考某BAT頂級架構師的教學完成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM