假如我们的 Hello world 服务的访问量剧增,用一个服务已经无法承载, 我们可以把 Hello World 服务做成一个集群。
很简单,我们只需要复制 Hello world 服务,同时将原来的端口 8762 修改为 8763。然后启动这两个 Spring Boot 应用, 就可以得到两个 Hello World 服务。这两个 Hello world 都注册到了 eureka 服务中心。这时候再访问 http://localhost:8761, 可以看到两个 hello world 服务已经注册。
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>
</project>
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 类
package springcloud.helloworld.ribbon.client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloService {
@Autowired RestTemplate restTemplate;
public String getHelloContent() {
return restTemplate.getForObject("http://SERVICE-HELLOWORLD/",String.class);
}
}
这里关键代码就是, 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。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于