一起来学Spring Cloud | 第三章:服务消费者 (负载均衡Ribbon)

一、负载均衡的简介:

负载均衡是高可用架构的一个关键组件,主要用来提高性能和可用性,通过负载均衡将流量分发到多个服务器,多服务器能够消除单个服务器的故障,减轻单个服务器的访问压力。

1、服务端负载均衡: 客户端请求到负载均衡服务器,负载均衡服务器根据自身的算法将该请求转给某台真正提供业务的服务器,该服务器将响应数据给负载均衡服务器,负载均衡服务器最后将数据返回给客服端, 服务端负载均衡完全由服务器处理,客户端不需要做任何事情。 常见例子, 例如:nginx

2、客服端负载均衡: 基于客户端的负载均衡,简单的说就是在客户端程序里面,维护一组服务器引用,自己设定一个调度算法,在向服务器发起请求的时候,先执行调度算法计算出向哪台服务器发起请求,然后再发起请求给服务器,常见例子, 例如:Ribbon

二、Ribbon的简介:

上一篇文章,讲了服务的注册和发现。在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的。Spring cloud提供两种服务调度方式,一种方式是ribbon+restTemplate,另一种方式是feign。这章先讲解下基于ribbon+restful的服务请求方式。

ribbon是一个负载均衡客户端,提供了很多在HTTP和TCP客户端之上的控制。Feign内部也已经使用了Ribbon, 所以只要使用了@FeignClient注解,也能实现本章功能。

三、准备集群服务:

通过标题我们也知道ribbon有负载均衡的功能,所以首先需要准备一个服务器集群,这一篇文章基于上一篇文章的工程,继续进行完善的。

  1. 启动eureka-server 工程,eureka注册中心就启动了。

  2. 启动springcloud-eureka-client工程,上篇文章我们知道springcloud-eureka-client工程的端口为9300。

  3. 将springcloud-eureka-client工程的端口改成9400(修改application.properties文件),然后再启动springcloud-eureka-client。

通过上面三个步骤,我们就相当于在eureka服务上启动了两个springcloud-eureka-client服务,但是端口号不同,输入 http://localhost:8761/  查看页面效果

四、新建 Ribbon客户端模块:

重新新建一个spring-boot工程,取名为:springcloud-ribbon-client

<parent>标签就是引入我们第一章节新建的父工程的pom.xml文件,具体可参考:一起来学Spring Cloud | 第一章 :如何搭建一个多模块的springcloud项目

1<?xml version="1.0" encoding="UTF-8"?> 2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 6 <parent> 7 <groupId>com.haly</groupId> 8 <artifactId>springcloud</artifactId> 9 <version>0.0.1-SNAPSHOT</version> 10 </parent> 11 12 <groupId>com.haly</groupId> 13 <artifactId>springcloud-ribbon-client</artifactId> 14 <version>0.0.1-SNAPSHOT</version> 15 <name>springcloud-ribbon-client</name> 16 <description>新建一个springcloud项目</description> 17 18 <dependencies> 19 <dependency> 20 <groupId>org.springframework.cloud</groupId> 21 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 22 </dependency> 23 <dependency> 24 <groupId>org.springframework.boot</groupId> 25 <artifactId>spring-boot-starter-web</artifactId> 26 </dependency> 27 <dependency> 28 <groupId>org.springframework.cloud</groupId> 29 <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> 30 </dependency> 31 </dependencies> 32 33 <build> 34 <plugins> 35 <plugin> 36 <groupId>org.springframework.boot</groupId> 37 <artifactId>spring-boot-maven-plugin</artifactId> 38 </plugin> 39 </plugins> 40 </build> 41 42</project> 43

新增springcloud-ribbon-client的配置文件application.properties

1server.port=9500 2spring.application.name=springcloud-ribbon-client 3eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ 4

新增启动类SpringcloudRibbonClientApplication

@EnableDiscoveryClient向服务中心注册,并且注册了一个叫restTemplate的bean。

@ LoadBalanced注解表明,这个restRemplate是需要做负载均衡的。

1package com.haly; 2 3import org.springframework.boot.SpringApplication; 4import org.springframework.boot.autoconfigure.SpringBootApplication; 5import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6import org.springframework.cloud.client.loadbalancer.LoadBalanced; 7import org.springframework.context.annotation.Bean; 8import org.springframework.web.client.RestTemplate; 9 10@SpringBootApplication 11@EnableDiscoveryClient 12public class SpringcloudRibbonClientApplication { 13 14 public static void main(String[] args) { 15 SpringApplication.run(SpringcloudRibbonClientApplication.class, args); 16 } 17 18 @Bean 19 @LoadBalanced 20 RestTemplate restTemplate() { 21 return new RestTemplate(); 22 } 23} 24

 新建一个service类,用来调用第二章在springcloud-eureka-client模块中的hello方法,springcloud-eureka-client模块的搭建,详情参考:一起来学Spring Cloud | 第二章:服务注册和发现组件 (Eureka)

1package com.haly.service; 2 3import org.springframework.beans.factory.annotation.Autowired; 4import org.springframework.stereotype.Service; 5import org.springframework.web.client.RestTemplate; 6 7@Service 8public class RibbonService { 9 @Autowired 10 RestTemplate restTemplate; 11 12 public String getHello(String name) { 13 return restTemplate.getForObject("http://springcloud-eureka-client/hello?name="+name,String.class); 14 } 15 16} 17

ps: 我们请求时用springcloud-eureka-client服务名代替了ip地址,在ribbon中它会根据服务名来选择具体的服务实例,根据服务实例在请求的时候会用具体的url替换掉服务名。

新建一个controller名为:RibbonController,来接收浏览器访问,RibbonController的getHello方法调用RibbonService的getHello方法

1package com.haly.controller; 2 3import org.springframework.beans.factory.annotation.Autowired; 4import org.springframework.web.bind.annotation.GetMapping; 5import org.springframework.web.bind.annotation.RequestParam; 6import org.springframework.web.bind.annotation.RestController; 7 8import com.haly.service.RibbonService; 9 10 11@RestController 12public class RibbonController { 13 @Autowired 14 RibbonService ribbonService; 15 16 @GetMapping(value = "/getHello") 17 public String getHello(@RequestParam String name) { 18 return ribbonService.getHello(name); 19 } 20 21} 22

打开浏览器输入http://localhost:9500/getHello?name=young码农   多次访问页面会交替出现如下结果

从上图可以验证,当我们通过调用restTemplate.getForObject("http://springcloud-eureka-client/hello?name="+name,String.class)方法时,已经做了负载均衡,访问了不同的端口的服务实例。

五、实验总结:

本章结束后,项目结构:

  1. 一个服务注册中心,eureka server,端口为8761

  2. springcloud-eureka-client工程跑了两个实例,端口分别为9300,9400,分别向服务注册中心注册

**3. springcloud-ribbon-client端口为9500,向服务注册中心注册
**

4. 当springcloud-ribbon-client通过restTemplate调用springcloud-eureka-client的hello接口时,因为用ribbon进行了负载均衡,会轮流的9300和9400 两个服务端口的hello接口

 

代码交流 2021