SpringCloud学到刚好够用之三-负载均衡ribbon.md

Posted by lizhao on 07-09,2019

SpringCloud学到刚好够用之三-负载均衡ribbon

[toc]

总览

spring cloud相关技术栈在现在各个互联网公司的普及率已经很高了,这次去面试,基本面试官都有提到这一块,但是有没有实际接触过,只能遗憾的摇摇头。这里记录下学习过程,将一些踩坑的经验写出来,供大家参考。这个系列只会写到很浅的一部分,如有兴趣深入,可以看"这个系列",将会给大家一个方向哈

使用的

简介

Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。

graph LR
Client-->A
A(负载均衡)-->ServiceB1
A-->ServiceB2
A-->ServiceB3
客户端负载均衡        负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们通常所说的负载均衡都指的是服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点之间按照专门用于负载均衡的设备,比如F5等;而软件负载均衡则是通过在服务器上安装一些用于负载均衡功能或模块等软件来完成请求分发工作,比如Nginx等。不论采用硬件负载均衡还是软件负载均衡,只要是服务端都能以类似下图的架构方式构建起来:

负载均衡架构图
        硬件负载均衡的设备或是软件负载均衡的软件模块都会维护一个下挂可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按某种算法(比如线性轮询、按权重负载、按流量负载等)从维护的可用服务端清单中取出一台服务端端地址,然后进行转发。        而客户端负载均衡和服务端负载均衡最大的不同点在于上面所提到服务清单所存储的位置。在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端端清单来自于服务注册中心,比如上一章我们介绍的Eureka服务端。同服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性,默认会创建针对各个服务治理框架的Ribbon自动化整合配置,比如Eureka中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul中的org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration。在实际使用的时候,我们可以通过查看这两个类的实现,以找到它们的配置详情来帮助我们更好地使用它。        通过Spring Cloud Ribbon的封装,我们在微服务架构中使用客户端负载均衡调用非常简单,只需要如下两步:        ▪️服务提供者只需要启动多个服务实例并注册到一个注册中心或是多个相关联的服务注册中心。        ▪️服务消费者直接通过调用被@LoadBalanced注解修饰过的RestTemplate来实现面向服务的接口调用。        这样,我们就可以将服务提供者的高可用以及服务消费者的负载均衡调用一起实现了。

准备内容

  1. 一个eureka
  2. 2个服务名称相同的服务(这里可以直接拷贝上一篇的pro002-eureka-test项目,都叫做SERVER-HI)
  3. ribbon服务

eureka

不多说,看上一篇,直接拿来用

2个服务名称相同的服务

拷贝pro002-eureka-test项目,改一下端口为8763

这个是application.yml

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8763
spring:
  application:
    name: service-hi

ribbon服务

主要步骤

引入相关包:spring-cloud-starter-netflix-ribbon

修改配置文件,端口8764,application.name:service-ribbon

修改添加启动类的注解:EnableDiscoveryClient

加一个@LoadBalanced RestTemplate,下面有具体代码

写一个请求,调用名称为SERVER-HI的服务的hi方法

上述步骤关键代码及图片

  1. 引入相关包:spring-cloud-starter-netflix-ribbon
<?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>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>com.lizhaoblog.scl</groupId>
  <artifactId>pro003-ribbon</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>pro003-ribbon</name>
  <description>ribbon demo</description>

  <properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-ribbon</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>

  1. 修改配置文件,端口8764,application.name:service-ribbon
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8764
spring:
  application:
    name: service-ribbon



  1. 修改添加启动类的注解:EnableDiscoveryClient
package com.lizhaoblog.scl.pro003ribbon;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient
public class Pro003RibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(Pro003RibbonApplication.class, args);
    }
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

  1. 加一个@LoadBalanced RestTemplate,下面有具体代码

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
  1. 写一个请求,调用名称为SERVER-HI的服务的hi方法
/*
 * Copyright (C), 2015-2019
 * FileName: HelloController
 * Author:   zhao
 * Date:     2019/4/20 14:41
 * Description: 测试ribbon
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.lizhaoblog.scl.pro003ribbon.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 〈一句话功能简述〉<br>
 * 〈测试ribbon〉
 *
 * @author zhao
 * @date 2019/4/20 14:41
 * @since 1.0.0
 */
@RestController
public class HelloController {

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping(value = "/hi")
    public String hi(@RequestParam String name){
        return restTemplate.getForObject("http://SERVICE-HI/hi?name=" + name, String.class);
    }
}

测试

主要步骤

运行eureka,hi服务1,hi服务2,ribbon服务

打开eureka面板查看服务数

访问http://localhost:8764/hi?name=lizhao

上述步骤关键代码及图片

  1. 运行eureka,hi服务1,hi服务2,ribbon服务
  2. 打开eureka面板查看服务数
DS Replicas
Instances currently registered with Eureka
Application	AMIs	Availability Zones	Status
SERVICE-HI	n/a (2)	(2)	UP (2) - localhost:service-hi:8762 , localhost:service-hi:8763
SERVICE-RIBBON	n/a (1)	(1)	UP (1) - localhost:service-ribbon:8764
  1. 访问http://localhost:8764/hi?name=lizhao
hi lizhao,i am from port:8763
hi lizhao,i am from port:8762
hi lizhao,i am from port:8763
hi lizhao,i am from port:8762

总结

大致示意图,三个service都注册到eureka中,当请求进来时,查找名为ServiceHI的服务,然后进行调用

graph LR

A-->|注册|Eureka
ServiceHI1-8762-->|注册|Eureka
ServiceHI2-8763-->|注册|Eureka

Client-->A
A(负载均衡Ribbo)-->ServiceHI1-8762
A-->ServiceHI2-8763


广告时间

我是小王,一个喜欢抛转的码人。

  • 所有代码都在这里:
  • 本片对应的章节:pro003
  • 我的csdn:https://lizhao.blog.csdn.net
  • 我的联系方式:QQ3060507060
  • 我的公众号:lizhaoblog、小王老店
  • 我的银行卡及密码:*****************/