服务注册发现Eureka之三:Spring Cloud Ribbon实现客户端负载均衡(客户端负载均衡Ribbon之三:使用Ribbon实现客户端的均衡负载)
在使用RestTemplate来消费spring boot的Restful服务示例中,我们提到,调用spring boot服务的时候,需要将服务的URL写死或者是写在配置文件中,但这两种方式,无论哪一种,一旦ip地址发生了变化,都需要改动程序,并重新部署服务,使用Ribbon的时候,可以有效的避免这个问题。
前言:
软负载均衡的实现方式有两种,分别是服务端的负载均衡和客户端的负载均衡
服务端负载均衡:当浏览器向后台发出请求的时候,会首先向反向代理服务器发送请求,反向代理服务器会根据客户端部署的ip:port映射表以及负载均衡策略,来决定向哪台服务器发送请求,一般会使用到nginx反向代理技术。
客户端负载均衡:当浏览器向后台发出请求的时候,客户端会向服务注册器(例如:Eureka Server),拉取注册到服务器的可用服务信息,然后根据负载均衡策略,直接命中哪台服务器发送请求。这整个过程都是在客户端完成的,并不需要反向代理服务器的参与。
一、启动Eureka Server 和 启动微服务,并注册到Eureka Server上
请参考该例: 《服务注册发现Eureka之一:Spring Cloud Eureka的服务注册与发现》
二、服务提供端
2.1、为了更好的追踪负载均衡的分发,我将《服务注册发现Eureka之一:Spring Cloud Eureka的服务注册与发现》的示例修改一下,增加计数器的展示:
package com.dxz.compute;
import java.time.LocalDateTime; import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; @RestController
public class ComputeController {
private final Logger logger = Logger.getLogger(getClass());
@Autowired
private DiscoveryClient client; @RequestMapping(value = "/add", method = RequestMethod.GET)
public Integer add(@RequestParam Integer a, @RequestParam Integer b, @RequestParam Integer sn) {
ServiceInstance instance = client.getLocalServiceInstance();
Integer r = a + b;
logger.info("/add, host:" + instance.getHost() + ", service_id:" + instance.getServiceId() + ", result:" + r+ ",sn="+sn +",time="+ LocalDateTime.now());
return r;
}
}
2.2、为了演示负载均衡的效果,再启动一个为服务,注意需要将端口号改成不一致
如在eclipse中再拷贝一个

spring.application.name=compute-service
server.port=2224
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
三、服务消费端
1、构建consumer-movie-ribbon项目,在pom.xml中引入ribbon依赖
在引入Eureka依赖的时候,默认里面含有ribbon依赖
<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.dxz</groupId>
<artifactId>consume-movie-ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version> <!--配合spring cloud版本 -->
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<!--设置字符编码及java版本 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--增加eureka-server的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!--用于测试的,本例可省略 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <!--依赖管理,用于管理spring-cloud的依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Brixton.SR3</version> <!--官网为Angel.SR4版本,但是我使用的时候总是报错 -->
<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>
</project>
2、添加@LoadBalanced注解,实现负载均衡
ribbon负载均衡策略默认为轮循方式
package com.dxz.compute.demo1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.client.RestTemplate; import com.dxz.compute.loadbalance.ExcludeFromComponentScan;
import com.dxz.compute.loadbalance.TestConfiguration; @SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "compute-service", configuration = TestConfiguration.class)
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type=FilterType.ANNOTATION,value=ExcludeFromComponentScan.class)})
public class SpringbootRestTemplateApplication { @Bean
@LoadBalanced // 添加负载均衡支持,很简单,只需要在RestTemplate上添加@LoadBalanced注解,那么RestTemplate即具有负载均衡的功能
public RestTemplate restTemplate() {
return new RestTemplate();
} public static void main(String[] args) {
SpringApplication.run(SpringbootRestTemplateApplication.class, args);
}
}
在consumer-movie-ribbon中通过RestTemplate 调用上面的2个服务提供方的服务。注意下面的url,是实例名称(不需要ip:port),restTemplate将有Ribbon提供的负载均衡功能。
package com.dxz.compute.demo1;
import java.util.concurrent.atomic.AtomicInteger; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; @RestController
public class RestTemplateController {
@Autowired
private RestTemplate restTemplate; private AtomicInteger sn = new AtomicInteger(0);
@RequestMapping(value = "/test", method = RequestMethod.GET)
public void test(@RequestParam Integer a, @RequestParam Integer b) {// 将原来的ip:port的形式,改成注册到Eureka Server上的应用名即可
System.out.println("==============================");
String result = restTemplate.getForObject("http://compute-service/add?a="+a +"&b="+b + "&sn="+sn.incrementAndGet(), String.class);
System.out.println("返回结果:"+result);
}
}
3、自定义负载均衡策略
package com.dxz.compute.loadbalance; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RetryRule;
import com.netflix.loadbalancer.RoundRobinRule; /**
* @Configuration注解不能放在@SpringBootApplication所在的包下 如果放在此包下,默认全部负载均衡使用此策略
*/
@Configuration
@ExcludeFromComponentScan
public class TestConfiguration { @Bean
public IRule ribbonRule() {
//return new RandomRule(); //设置负载均衡的规则为随机
return new RoundRobinRule(); //默认的轮询策略
}
}
4、指定对某个客户端使用自定义负载均衡
@RibbonClient(name = "compute-service", configuration = TestConfiguration.class)指定调用“compute-service”服务的客户端,使用TestConfiguration.class里配置的负载均衡策略。其他客户端不受影响。
package com.dxz.compute.demo1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.client.RestTemplate; import com.dxz.compute.loadbalance.ExcludeFromComponentScan;
import com.dxz.compute.loadbalance.TestConfiguration; @SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "compute-service", configuration = TestConfiguration.class)
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type=FilterType.ANNOTATION,value=ExcludeFromComponentScan.class)})
public class SpringbootRestTemplateApplication {
...
}
5、如果将上面的TestConfiguration@Configuration注解放在@SpringBootApplication所在的包下,所以的客户端都按照这个策略进行。
a、在@Configuration包下创建ExcludeFromComponentScan注解,注解见下面:
package com.dxz.compute.loadbalance;
public @interface ExcludeFromComponentScan {
}
b、在入口类中排除此注解不扫描
package com.dxz.compute.demo1; @SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "compute-service", configuration = TestConfiguration.class)
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type=FilterType.ANNOTATION,value=ExcludeFromComponentScan.class)})
public class SpringbootRestTemplateApplication { @Bean
@LoadBalanced // 添加负载均衡支持,很简单,只需要在RestTemplate上添加@LoadBalanced注解,那么RestTemplate即具有负载均衡的功能
public RestTemplate restTemplate() {
return new RestTemplate();
} ...
}
c、在TestConfiguration中使用此注解
@Configuration
@ExcludeFromComponentScan
public class TestConfiguration { @Bean
public IRule ribbonRule() {
//return new RandomRule(); //设置负载均衡的规则为随机
return new RoundRobinRule(); //默认的轮询策略
}
}
6、开启多个compute-service微服务,测试结果

通过消费端服务调用服务提供方,负载均衡的结果如下:
第一种用轮询策略:
@Bean
public IRule ribbonRule() {
//return new RandomRule(); //设置负载均衡的规则为随机
return new RoundRobinRule(); //默认的轮询策略
}
下面2台服务提供方日志:


第二种:随机策略
@Configuration
@ExcludeFromComponentScan
public class TestConfiguration { @Bean
public IRule ribbonRule() {
return new RandomRule(); //设置负载均衡的规则为随机
//return new RoundRobinRule(); //默认的轮询策略
}
}
两台服务提供方日志如下:


服务消费端日志:


服务注册发现Eureka之三:Spring Cloud Ribbon实现客户端负载均衡(客户端负载均衡Ribbon之三:使用Ribbon实现客户端的均衡负载)的更多相关文章
- 服务注册发现Eureka之二:高可用服务注册中心
前言 在Spring Cloud系列文章的开始,我们就介绍了服务注册与发现,其中,主要演示了如何构建和启动服务注册中心Eureka Server,以及如何将服务注册到Eureka Server中,但是 ...
- 服务注册发现Eureka
一 Eureka相关概念 1 Peer 2 Zone 3 Region 地理区域 3 CAP理论 4 在线扩容 5 二 注册发现 Eureka 1 搭建Server服务端 ...
- 服务注册发现Eureka之一:Spring Cloud Eureka的服务注册与发现
Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁 ...
- spring cloud(二)服务(注册)中心Eureka
Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现.也是springcloud体系中最重要最核心的组 ...
- SpringCloud服务的注册发现--------Eureka
1,什么叫做服务的注册与发现 服务的注册与发现基于注册中心,注册中心本身是一个服务,也相当于一个载体,其他服务的注册需要注册到这个注册中心上. 注册:当服务器启动的时候,会将自己的服务器信息,通过别名 ...
- SpringCloud服务的注册发现--------Eureka自我保护机制
1,Eureka 自我保护机制 Eureka注册中心,一些服务会注册到Eureka 服务器上,例如之前的member服务,order服务. 在网络不通的情况下,如果一个bmember 挂了,但是Eur ...
- SpringCloud服务的注册发现--------Eureka实现高可用
1,Eureka作为注册中心,掌管者服务治理的功能,十分重要,如果注册中心的服务一旦宕机,所有的服务就会挂了,为此,实现注册中心的集群(高可用)就显得十分必要了 2,Eureka 搭建集群 实现原理就 ...
- springcloud(五,多个服务注册中心eureka)
spring cloud (一.服务注册demo_eureka) spring cloud (二.服务注册安全demo_eureka) spring cloud (三.服务提供者demo_provid ...
- 服务注册发现consul之三:服务发现比较:Consul vs Zookeeper vs Etcd vs Eureka
这里就平时经常用到的服务发现的产品进行下特性的对比,首先看下结论: Feature Consul zookeeper etcd euerka 服务健康检查 服务状态,内存,硬盘等 (弱)长连接,kee ...
随机推荐
- Android Touch事件之一:Touch事件在父ViewGroup和子View之间的传递篇
2015-11-26 17:00:22 前言:Android的Touch事件传递和View的实现紧密相连,因此理解Touch事件的传递,有助于我们更好的理解View的工作原理. 1. 几个重要的方法: ...
- java异常(编程思想)
通过异常处理错误 java的基本理念是“结构不佳的代码不能运行” 发现错误的理想时机是在编译阶段,也就是在你试图运行程序之前.然而编译期间并不能找出所有的错误,余下的问题必须在运行间解决.这就需要错误 ...
- SpringContextUtil spring上下文获取工具类
package com.midea.biz; import org.springframework.beans.BeansException; import org.springframework.c ...
- 【linux基础】生成目录下所有图片的路径
command ls *.jpg > list.txt result .png .png .png .png .png command ls /home/xxx/input/*.png > ...
- git的使用基础
/*游戏或者运动才能让我短暂的忘记心痛,现如今感觉学习比游戏和运动还重要——曾少锋*/ 在Git-Bash中配置自己的名字和Email: git config --global user.name & ...
- CentOS使用安装光盘建立本地软件源
本实验的目的是使用CentOS的两张DVD安装光盘作为本地软件源,避免执行yum安装命令时每次都要从网络重新下载. 安装createrepo软件包 createrepo是制作软件源所需要的一个工具,默 ...
- 蓝桥杯 BASIC-3:字母图形
基础练习 字母图形 时间限制:1.0s 内存限制:256.0MB 问题描述 利用字母可以组成一些美丽的图形,下面给出了一个例子: ABCDEFG BABCDEF CBABCD ...
- ASP.NET MVC开发基础
一.ASP.Net MVC的开发模式 (1)处理流程 在ASP.Net MVC中,客户端所请求的URL是被映射到相应的Controller去,然后由Controller来处理业务逻辑,或许要从Mode ...
- com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. 问题解决方法
一.问题 今天用mybatis连接数据库时出现了如下错误: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The serve ...
- 对比dfs与bfs的存储机制以及bfs与队列的关系
dfs由于是利用递归进行遍历,所以每种情况在时空上不会出现冲突,所以可以利用数组将每种情况的各个元素的值进行存储(即存储当前位) 而bfs由于并不是利用递归,不能将每种情况的值进行不冲突地存储,但由于 ...