Spring Cloud Learning | 第三篇:客户端负载均衡(Ribbon)

一. 客户端负载均衡

      负载均衡在系统架构中是一个非常重要的内容,因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端的清单来自于服务注册中心,比如Eureka服务端。当客户端发送请求到负载均衡模块的时候,该模块按某种算法(比如线性轮询、按权重负载、按流量负载等)从维护的可用服务端清单中取出一台服务端的地址,然后进行转发。

      Spring Cloud有两种客户端负载均衡的服务调用方式,一种是Ribbon+RestTemplate,另一种是Feign(通常在实际应用中,选择Fegin)。这一篇首先讲解第一种。


二. Spring Cloud Ribbon使用步骤

      通过Spring Cloud Ribbon的封装,我们在微服务架构中使用客户端负载均衡调用非常简单,只需要如下两步:

      ①服务提供者只需要启动多个服务实例并注册到一个注册中心或是多个相关联的服务注册中心。

      ②服务消费者直接通过调用被@LoadBalanced注解修饰过的RestTemplate来实现面向服务的接口调用。

      接下来详细介绍实现步骤。


三. 客户端负载均衡实现

3.1 启动服务注册中心和服务提供者

      基于第一篇文章的工程,启动eureka-server工程,端口号是8761;修改eureka-client工程的配置文件中的端口号,启动eureka-client工程两次,端口号分别为8762和8763(即注册两个服务实例)。

      访问localhost:8761,可以看到信息面板已有两个注册服务实例:


3.2 实现负载均衡

      新建一个spring-boot工程,取名为service-ribbon。在pom.xml中引入需要的依赖:

<?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.dan</groupId>
	<artifactId>service-ribbon</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>service-ribbon</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.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>
		<spring-cloud.version>Edgware.SR1</spring-cloud.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>${spring-cloud.version}</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>


</project>
      在application.properties配置服务注册中心、端口号等信息:

spring.application.name=service-ribbon
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka
server.port=8764

      在工程的启动类中,通过@EnableDiscoveryClient向服务中心注册,并且向程序的ioc注入一个bean: restTemplate,并通过@LoadBalanced注解表明这个restRemplate开启负载均衡的功能:

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServiceRibbonApplication.class, args);
	}
	
	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
}
      新建HelloService类,通过注入restTemplate来消费服务提供方eureka-client 的“/hello”接口,在这里我们直接用的服务名替代了具体的url地址,因为在Ribbon中它会根据服务名来选择具体的服务实例,根据服务实例在请求的时候会用具体的url替换掉服务名:
@Service
public class HelloService {

  @Autowired
  RestTemplate restTemplate;

  public String helloService(String name) {
  return restTemplate.getForObject("http://HELLO-SERVICE/hello?name="+name, String.class);
  }

}
      写一个controller,在controller中用调用HelloService 的方法,代码如下:
@RestController
public class HelloController {

	@Autowired
	HelloService helloService;
	
	@RequestMapping(value="/hello")
	public String sayHello(@RequestParam String name) {
		return helloService.helloService(name);
	}
	
}
      启动项目,多次访问localhost:8764/hello?name=Jack,可以发现浏览器显示的内容会不同:
Hello Jack. I am from port:8763
Hello Jack. I am from port:8762

      证明已实现负载均衡,客户端访问了不同的服务实例。

四. 整体架构


      服务注册中心Eureka Server,端口号是8761;

      三个向服务注册中心注册的服务,分别是两个服务实例Hello-service,端口号是8762和8763以及Service-Ribbon,端口号是8764;

      客户端通过访问Service-Ribbon的/hello接口,Service-Ribbon服务通过restTemplate调用实际的服务Hello-Service的/hello接口,由于Ribbon进行负载均衡,所以Service-Ribbon服务轮流调用Hello-Service两个实例中的一个。


源码下载:https://github.com/lingd3/SpringCloudLearning/tree/master/chapter3








《史上最简单的Spring Cloud教程源码》 一、Spring Cloud Alibaba教程 Spring Cloud Alibaba教程:使用Nacos作为服务注册发现组件 Spring Cloud Alibaba教程:使用Nacos作为配置中心 Spring Cloud Alibaba教程:Sentinel的使用 二、Greenwich版本 Spring Cloud Consul 之Greenwich版本全攻略 spring cloud config将配置存储在数据库中 Spring Cloud Sleuth 之Greenwich版本全攻略 Spring Boot Admin 2.1.0 全攻略 阿里分布式事务框架GTS开源了! 三、Finchley版本 Spring Cloud Finchley; Spring Boot 2.0.3 史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka)(Finchley版本) 史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)(Finchley版本) 史上最简单的SpringCloud教程 | 第三篇: 服务消费者(Feign)(Finchley版本) 史上最简单的SpringCloud教程 | 第四篇:断路器(Hystrix)(Finchley版本) 史上最简单的SpringCloud教程 | 第五篇: 路由网关(zuul)(Finchley版本) 史上最简单的SpringCloud教程 | 第六篇: 分布式配置中心(Spring Cloud Config)(Finchley版本) 史上最简单的SpringCloud教程 | 第七篇: 高可用的分布式配置中心(Spring Cloud Config)(Finchley版本) 史上最简单的SpringCloud教程 | 第八篇: 消息总线(Spring Cloud Bus)(Finchley版本) 史上最简单的SpringCloud教程 | 第九篇: 服务链路追踪(Spring Cloud Sleuth)(Finchley版本) 史上最简单的SpringCloud教程 | 第十篇: 高可用的服务注册中心(Finchley版本) 史上最简单的SpringCloud教程 | 第十二篇: 断路器监控(Hystrix Dashboard)(Finchley版本) 史上最简单的SpringCloud教程 | 第十三篇: 断路器聚合监控(Hystrix Turbine)(Finchley版本) 史上最简单的SpringCloud教程 | 第十四篇: Spring Cloud Gateway初体验 史上最简单的SpringCloud教程 | 第十五篇: Spring Cloud Gateway 之Predict篇 史上最简单的SpringCloud教程 | 第十六篇: Spring Cloud Gateway 之filter篇 史上最简单的SpringCloud教程 | 第十七篇: Spring Cloud Gateway 之限流篇 史上最简单的SpringCloud教程 | 第十八篇: spring cloud gateway之服务注册与发现 四、源码篇: 深入理解Feign之源码解析 深入理解Eureka之源码解析 深入理解Ribbon之源码解析 深入理解Hystrix之文档翻译 深入理解Zuul之源码解析 五、进阶篇 Spring Cloud Sleuth超详细实战 拜托!面试请不要再问我Spring Cloud底层原理 微服务注册中心如何承载大型系统的千万级访问? 每秒上万并发下的Spring Cloud参数优化实战 六、D版本 史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka) 史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon) 史上最简单的SpringCloud教程 | 第三篇: 服务消费者(Feign) 史上最简单的SpringCloud教程 | 第四篇:断路器(Hystrix) 史上最简单的SpringCloud教程 | 第五篇: 路由网关(zuul) 史上最简单的SpringCloud教程 | 第六篇: 分布式配置中心(Spring Cloud Config) 史上最简单的SpringCloud教程 | 第七篇: 高可用的分布式配置中心(Spring Cloud Config) 史上最简单的SpringCloud教程 | 第八篇: 消息总线(Spring Cloud Bus) 史上最简单的SpringCloud教程 | 第九篇: 服务链路追踪(Spring Cloud Sleuth) 史上最简单的SpringCloud教程 | 第十篇: 高可用的服务注册中心 史上最简单的SpringCloud教程 | 第十一篇:docker部署spring cloud项目 史上最简单的SpringCloud教程 | 第十二篇: 断路器监控(Hystrix Dashboard) 史上最简单的SpringCloud教程 | 第十三篇: 断路器聚合监控(Hystrix Turbine) 史上最简单的 SpringCloud 教程 | 第十四篇: 服务注册(consul) 七、番外篇: 如何使用MongoDB+Springboot实现分布式ID? 如何在springcloud分布式系统中实现分布式锁? 如何用Redlock实现分布式锁 如何在IDEA启动多个Spring Boot工程实例 JWT如何在Spring Cloud微服务系统中在服务相互调时传
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值