一 Ribbon简介
Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP的客户端的行为。为Ribbon配置服务提供者地址后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多负载均衡算法,例如轮询、随机等。当然,我们也可为Ribbon实现自定义的负载均衡算法。
在Spring Cloud中,当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。展示了Ribbon与Eureka配合使用时的架构
搭建负载均衡Ribbon (ribbon-consumer)
接到上篇 http://www.cnblogs.com/grasp/p/9258811.html
继续在springcloud工程中添加模块ribbon-consumer,也是通过start.spring.io提供的模板创建
新的目录
生成的pom.xml文件为
4.0.0
com.xuan
ribbon-consumer
0.0.1-SNAPSHOT
jar
ribbon-consumer
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
2.0.3.RELEASE
UTF-8
UTF-8
1.8
Finchley.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
修改启动文件RibbonConsumerApplication.java,注意增加RestTemplate 的bean注解。
packagecom.xuan.ribbonconsumer;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cloud.client.discovery.EnableDiscoveryClient;importorg.springframework.cloud.client.loadbalancer.LoadBalanced;importorg.springframework.context.annotation.Bean;importorg.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplicationpublic classRibbonConsumerApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate () {return newRestTemplate();
}public static voidmain(String[] args) {
SpringApplication.run(RibbonConsumerApplication.class, args);
}
}
增加测试的消费接口ConsumerController.java
packagecom.xuan.ribbonconsumer;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestMethod;importorg.springframework.web.bind.annotation.RestController;importorg.springframework.web.client.RestTemplate;
@RestControllerpublic classConsumerController {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value= "/ribbon-consumer", method =RequestMethod.GET)publicString helloConsumer() {return restTemplate.getForEntity("http://eureka-client/hello",
String.class).getBody();
}
}
注意要去实现提供者的“hello”接口,在后面在描述具体实现过程。
修改配置文件”application.properties“,让消费者注册中心注册,并且通过注册中心找到服务提供者。
spring.application.name=ribbon-consumer
server.port=9000
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/
为了观察是否进行了负载均衡,在eureka-client模块,增加一个服务提供者接口HelloController.java实现hello接口。
packagecom.xuan.eurekaclient;importcom.netflix.appinfo.InstanceInfo;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.cloud.client.ServiceInstance;importorg.springframework.cloud.client.discovery.DiscoveryClient;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestMethod;importorg.springframework.web.bind.annotation.RestController;importjava.util.List;
@RestControllerpublic classHelloController {private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
@AutowiredprivateDiscoveryClient client;
@Value("${server.port}")
String port;
@RequestMapping(value= "hello", method =RequestMethod.GET)publicString index() {
StringBuffer uriList = new StringBuffer("Hello World " + port + " 端口为您服务!
");
returnuriList.toString();
}
}
如果需要打印服务端的详细明细可以修改为:
packagecom.xuan.eurekaclient;importcom.netflix.appinfo.InstanceInfo;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.cloud.client.ServiceInstance;importorg.springframework.cloud.client.discovery.DiscoveryClient;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestMethod;importorg.springframework.web.bind.annotation.RestController;importjava.util.List;
@RestControllerpublic classHelloController {private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
@AutowiredprivateDiscoveryClient discoveryClient;
@Value("${server.port}")
String port;
@RequestMapping(value= "hello", method =RequestMethod.GET)publicString index() {StringBuffer uriList= new StringBuffer("Hello World " + port + " 端口为您服务!
");
List list = discoveryClient.getInstances("eureka-client");
uriList.append("
discoveryClient.getServices().size() = " +discoveryClient.getServices().size());for( String s : discoveryClient.getServices()){
List serviceInstances =discoveryClient.getInstances(s);for(ServiceInstance si : serviceInstances){
uriList.append("
services:" + s + ":getHost()=" +si.getHost());
uriList.append("
services:" + s + ":getPort()=" +si.getPort());
uriList.append("
services:" + s + ":getServiceId()=" +si.getServiceId());
uriList.append("
services:" + s + ":getUri()=" +si.getUri());
}
}returnuriList.toString();
}
}
在eureka-client模块再增加两个配置文件,使用不同的端口,从而在一天电脑可以启动多个服务提供者,方便测试
增加”application-peer1.properties“文件
spring.application.name=eureka-client
server.port=8091
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/
增加”application-peer1.properties“文件
spring.application.name=eureka-client
server.port=8092
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/
添加完成后eureka-client模块的目录结构为:
设置IDEA编辑器的Edit Configurations,增加两个启动配置,修改过完后的列表和注意的地方:
配置和环境都设置完成后:就可以分别启动模块了:
1.EurekaServerApplication
2.EurekaClientApplication,EurekaClientApplication1,EurekaClientApplication2
启动后打开http://localhost:8080/显示如图:
最后启动RibbonConsumerApplication模块在打开http://localhost:8080/显示如下
消费者RibbonConsumer也注册成功了。
访问消费者提供的接口http://localhost:9000/ribbon-consumer,查看是否进行了负载均衡,刷新一次,端口就变化了一次,说明访问的是不同的服务提供者