本篇文章将介绍SpringCloud Ribbon在客户端负载均衡的调用服务。
Ribbon:客户端的负载均衡。
什么是客户端的负载均衡呢?
就是客户端是知道哪些服务是高可用的,哪些服务还没有挂掉。
一、创建一个工程:
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cloud</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.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-ribbon</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二、配置application.properties
server.port=9000
spring.application.name=ribbon-consumer
eureka.client.service-url.defaultZone=http://localhost:8888/eureka/
三、创建一个Controller:
package com.cloud.demo.consumer;
import com.netflix.hystrix.HystrixRequestCache;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import rx.Observable;
import rx.Observer;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
public class ConsumerController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@RequestMapping("/consumer")
public String helloConsumer() throws ExecutionException, InterruptedException {
ServiceInstance instance = loadBalancerClient.choose("stores");
URI uri = URI.create(String.format("http://%s:%s",instance.getHost(),instance.getPort()));
return uri.toString();
}
}
四、启动项目
访问http://127.0.0.1:9000/consumer:
会轮询访问
默认的负载均衡算法是轮询算法。
如果要改为别的算法:在配置文件中加如下代码:
stores.ribbon.NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
在Application中:添加:
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
再进行访问就会发现是随机的了。
但是现在又出现了一个新问题,上面的配置中,地址都是写死在配置文件中的,万一有一个服务挂掉了,就无法将它剔除了。
解决办法:和Eureka结合起来使用。
1.将自己想注册中心注册:
eureka.client.service-url.defaultZone=http://localhost:8888/eureka/
2.在启动类中加入做如下修改:
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
3.Controller中:
package com.cloud.demo.consumer;
import com.netflix.hystrix.HystrixRequestCache;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import rx.Observable;
import rx.Observer;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
public class ConsumerController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private HelloService helloService;
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/consumer")
public String helloConsumer() throws ExecutionException, InterruptedException {
//根据服务调用
return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();
}
}
现在看一下Eureka仪表盘,发现Ribbon也注册进去了:
进行访问就发现实现负载均衡了。