接上節,假如我們的Hello world服務的訪問量劇增,用一個服務已經無法承載, 我們可以把Hello World服務做成一個集羣。
很簡單,我們只需要複製Hello world服務,同時將原來的端口8762修改爲8763。然後啓動這兩個Spring Boot應用, 就可以得到兩個Hello World服務。這兩個Hello world都註冊到了eureka服務中心。這時候再訪問http://localhost:8761, 可以看到兩個hello world服務已經註冊。(服務與註冊參見Spring Cloud 入門教程(一): 服務註冊)。
1. 客戶端的負載均衡
負載均衡可分爲服務端負載均衡和客戶端負載均衡,服務端負載均衡完全由服務器處理,客戶端不需要做任何事情。而客戶端負載均衡技術,客戶端需要維護一組服務器引用,每次客戶端向服務端發請求的時候,會根據算法主動選中一個服務節點。常用的負載均衡算法有: Round Robbin, Random,Hash,StaticWeighted等。
Spring 提供兩輛種服務調度方式:Ribbon+restful和Feign。Ribbon就是一個基於客戶端的負載均衡器, Ribbon提供了很多在HTTP和TCP客戶端之上的控制.
Feign內部也已經使用了Ribbon, 所以只要使用了@FeignClient註解,那麼這一章的內容也都是適用的。
下面就看看如何Spring Cloud如何用Ribbon來實現兩個Hello World服務的負載均衡。以下是Spring cloud的ribbon客戶端負載均衡架構圖。
hello world服務和ribbon均註冊到服務中心
service-hi工程跑了兩個副本,端口分別爲8762,8763,分別向服務註冊中心註冊, 當sercvice-ribbon通過restTemplate調用service-Hellowworld的接口時,利用用ribbon進行負載均衡,會輪流的調用處於兩個不同端口的Hello world服務
2. 創建一個Ribbon服務
1) 創建一個maven工程,取名叫service-ribbon, pom.xml文件如下:
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.chry</groupId>
<artifactId>springcloud.helloworld.ribbon.service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloud.helloworld.ribbon.service</name>
<description>Demo project for Spring Cloud Ribbon</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
2). 創建主類ServiceRibbonApplication
package springcloud.helloworld.ribbon.service;
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.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
@EnableDiscoveryClient向服務中心註冊,並且註冊了一個叫restTemplate的bean。
@ LoadBalanced註冊表明,這個restRemplate是需要做負載均衡的。
3). 創建獲取一個獲取Hello內容的service類
1 package springcloud.helloworld.ribbon.client;
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.stereotype.Service;
5 import org.springframework.web.client.RestTemplate;
6
7 @Service
8 public class HelloService {
9 @Autowired RestTemplate restTemplate;
10
11 public String getHelloContent() {
12 return restTemplate.getForObject("http://SERVICE-HELLOWORLD/",String.class);
13 }
14 }
這裏關鍵代碼就是, restTemplate.getForObject方法會通過ribbon負載均衡機制, 自動選擇一個Hello word服務,
這裏的URL是“http://SERVICE-HELLOWORLD/",其中的SERVICE-HELLOWORLD是Hello world服務的名字,而註冊到服務中心的有兩個SERVICE-HELLOWORLD。 所以,這個調用本質是ribbon-service作爲客戶端根據負載均衡算法自主選擇了一個作爲服務端的SERVICE-HELLOWORLD服務。然後再訪問選中的SERVICE-HELLOWORLD來執行真正的Hello world調用。
3. 啓動ribbon-service應用,我們就可以訪問http://localhost:8901/, 然後每次刷新可以看到以下兩種結果交替出現,表明實際調用的是在不同端口的不同的SERVICE-HELLOWORLD。