Ribbon是一个基于HTTP和TCP客户端的负载均衡器。
Ribbon可以在通过客户端中配置的ribbonServerList服务端列表去轮询访问以达到均衡负载的作用。
当我们联合Ribbon与Eureka使用时,ribbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心中获取服务端列表。同时它也会用NIWSDiscoveryPing来取代IPing,将职责委托给Eureka来确定服务端是否已经启动。
下面通过实例来试一下如何使用Ribbon来调用服务,并实现客户端的均衡负载效果。
准备工作
启动eureka-server中的服务注册中心:eureka-server
修改person-serviceperson-service中的server-port为2222
启动一个服务提供方:person-service
修改person-service中的server-port为3333,再启动一个服务提供方:person-service
可以看到PERSON-SERVICE服务有两个服务正在运行:
SHPWSUN3.netscout.com:person-service:3333
SHPWSUN3.netscout.com:person-service:2222
使用Ribbon实现客户端负载均衡的消费者
构建一个基本Spring Boot项目,并在pom.xml中加入如下内容:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Dalston.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<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.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</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>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
在应用主类中,通过@EnableDiscoveryClient注解来添加发现服务能力。创建RestTemplate实例,并通过@LoadBalanced注解开启均衡负载能力。
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaRibbonApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaRibbonApplication.class, args);
}
}
创建ConsumerController来消费PERSON-SERVICE的person服务。通过直接RestTemplate来调用服务。
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/person", method = RequestMethod.GET)
public String person() {
return restTemplate.getForEntity("http://PERSON-SERVICE/person?firstname=William&lastname=Sun", String.class).getBody();
}
}
application.properties中配置eureka服务注册中心
spring.application.name=ribbon-consumer
server.port=4444
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
启动该应用,并访问两次:http://localhost:4444/person
然后,打开person-service的两个服务提供方,分别输出了类似下面的日志内容:
端口为2222服务提供端的日志:
2017-05-19 14:03:00.182 INFO 40356 --- [nio-2222-exec-1] c.s.cloud.web.PersonServiceController : /person, host:SHPWSUN3.netscout.com, service_id:person-service, result:Hello Sun William!
端口为3333服务提供端的日志:
2017-05-19 14:02:54.011 INFO 38624 --- [nio-3333-exec-5] c.s.cloud.web.PersonServiceController : /person, host:SHPWSUN3.netscout.com, service_id:person-service, result:Hello Sun William!
可以看到,启动的两个person-service服务端分别被调用了一次。到这里,我们已经通过Ribbon在客户端已经实现了对服务调用的均衡负载。
完整示例可参考:eureka-ribbon