【云原生&微服务一】SpringCloud之Ribbon实现负载均衡详细案例(集成Eureka、Ribbon)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 【云原生&微服务一】SpringCloud之Ribbon实现负载均衡详细案例(集成Eureka、Ribbon)

一、负载均衡概述

在分布式 或 微服务架构中,服务的提供者往往有多个实例 会注册到服务注册中心中,服务消费者需要使用服务时,需要决定使用哪个服务提供者,这正是负载均衡的体现。
负载均衡也可以理解为:将用户的请求平摊分配到每个服务器上,尽可能的压榨每台服务器的带宽、性能。

负载均衡的方式有两种:

  • 服务端负载均衡

    像以前的老架构,通过nginx对请求做负载均衡,然后下发到指定的tomcat。
  • 客户端负载均衡

    client获取到所有的service实例,然后做负载均衡规则。例如:Ribbon、Feign

本文我们针对SpringCloud如何集成Ribbon实现负载均衡做一个讨论。

注:(版本信息)--

二、Ribbon实现负载均衡

整体项目目录包括三个Module,分别为:eureka-server、ribbon-feign-sample、ribbon-feign-sample-consumer。
在这里插入图片描述
其中eureka-server作为服务注册中心、ribbon-feign-sample作为服务提供者、ribbon-feign-sample-consumer作为服务消费者。

Ribbon 与 RestTemplate 配合使用,实现了微服务之间的调用。

0、最上层父项目spring-cloud-center的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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>

    <!--子模块-->
    <modules>
        <module>ribbon-feign-sample</module>
        <module>ribbon-feign-sample-consumer</module>
        <module>eureka-server</module>
    </modules>

    <artifactId>spring-cloud-center</artifactId>
    <groupId>com.saint</groupId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-center</name>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.7.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--整合spring cloud-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--整合spring cloud alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.5.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <!-- java编译插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

关于Spring-cloud和SpringBoot的版本对应关系,参考博文:SpringBoot、SpringCloud、SpringCloudAlibaba的版本对应关系

1、搭建服务注册中心eureka-server

eureka-server整体代码结构目录如下:
在这里插入图片描述
其整体很简单、仅仅包含一个pom.xml文件、一个配置文件、一个启动类。

1、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">
    <parent>
        <artifactId>spring-cloud-center</artifactId>
        <groupId>com.saint</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <description>eureka-server</description>

    <dependencies>

        <!--集成Eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
    </dependencies>

</project>

2、修改配置文件application.yml

server:
  port: 10010
spring:
  application:
    name: eureka-server
eureka:
  client:
    # 把自身注册到Eureka-server中
    register-with-eureka: true
    # 服务注册中心不需要去检索其他服务
    fetch-registry: false
    # 指定服务注册中心的位置
    service-url:
      defaultZone: http://localhost:10010/eureka
  instance:
    hostname: localhost

3、修改启动类

package com.saint;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * @author Saint
 */
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

这里和普通的启动有一个区别:需要加上 @EnableEurekaServer 注解开启Eureka-Server。

4、启动eureka-server

启动成功后,控制台输出如下:
在这里插入图片描述
进入到eureka-server 的dashboard,可以看到eureka-server已经上线:
在这里插入图片描述

2、搭建服务提供者ribbon-feign-sample

ribbon-feign-sample整体代码结构目录如下:
在这里插入图片描述
其中包含一个pom.xml文件、一个配置文件、一个启动类、一个Controller。

1、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">
    <parent>
        <artifactId>spring-cloud-center</artifactId>
        <groupId>com.saint</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>ribbon-feign-sample</artifactId>
    <groupId>com.saint</groupId>
    <version>0.0.1-SNAPSHOT</version>
    <description>ribbon test service provider</description>

    <dependencies>

        <!--集成eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</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</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
    </dependencies>

</project>

2、修改配置文件application.yml

server:
  port: 8081
spring:
  application:
    name: greeting-service
eureka:
  client:
    # 将当前服务注册到服务注册中心
    service-url:
      defaultZone: http://localhost:10010/eureka

3、修改启动类

package com.saint;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * Saint
 */
@SpringBootApplication
@EnableEurekaClient
public class RibbonFeignSampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(RibbonFeignSampleApplication.class, args);
    }
}

这里和普通的启动有一个区别:需要加上 @EnableEurekaClient 注解开启eureka-client。

4、编写GreetingController

package com.saint.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Saint
 */
@RestController
@RequestMapping("/greeting")
public class GreetingController {

    @GetMapping("/sayHello/{name}")
    public String sayHello(@PathVariable("name") String name) {
        System.out.println("接收到了请求调用 + " + name);
        return "Hello, " + name;
    }
}

5、启动GREETING-SERVICE服务实例1(8081端口)

服务启动成功后,控制台输出如下:
在这里插入图片描述
再看eureka-server dashboard中多了一个 GREETING-SERVICE 服务,并且其有一个实例 192.168.3.32:greeting-service:8081
在这里插入图片描述

6、启动GREETING-SERVICE服务实例2(8082端口)

1> 修改RibbonFeignSampleApplication的配置:
在这里插入图片描述

2> 复制出一个RibbonFeignSampleApplication配置:
在这里插入图片描述
3> 修改第二启动类配置名为:RibbonFeignSampleApplication-8082,启动端口为8082
在这里插入图片描述
4> 运行RibbonFeignSampleApplication-8082
在这里插入图片描述
5> 启动之后,看eureka-server dashboard中GREETING-SERVICE 服务多了一个实例 192.168.3.32:greeting-service:8082
在这里插入图片描述

3、搭建服务消费者ribbon-feign-sample-consumer

ribbon-feign-sample-consumer整体代码结构目录如下:
在这里插入图片描述
其包含一个pom.xml文件、一个application配置文件、一个启动类、一个Http负载均衡配置类、一个Controller。

1、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">
    <parent>
        <artifactId>spring-cloud-center</artifactId>
        <groupId>com.saint</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>ribbon-feign-sample-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <description>ribbon test service provider</description>

    <dependencies>

        <!--集成ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        
        <!--集成eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</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</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

2、修改配置文件application.yml

server:
  port: 9090
spring:
  application:
    name: consumer-service
eureka:
  client:
    # 将当前服务注册到服务注册中心
    service-url:
      defaultZone: http://localhost:10010/eureka

注:服务端口为9090,后面我们进行接口调用的时候会用到。

3、修改启动类

package com.saint;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * Saint
 */
@SpringBootApplication
@EnableEurekaClient
public class RibbonFeignSampleConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(RibbonFeignSampleConsumerApplication.class, args);
    }
}

4、修改HTTP负载均衡配置类--HttpConfig

package com.saint.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * Http配置类
 *
 * @author Saint
 */
@Configuration
public class HttpConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

HttpConfig类的作用:对RestTemple的调用使用Ribbon做负载均衡,将RestTemplate注入到Spring IOC容器中。

5、编写ConsumerController

package com.saint.controller;

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.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author Saint
 */
@RestController
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/say/{name}")
    public String getHello(@PathVariable("name") String name) {
        String res = restTemplate.getForObject("http://GREETING-SERVICE/greeting/sayHello/" + name, String.class);
        return res;
    }
}

ConsumerController中通过RestTemplate调用http://GREETING-SERVICE/greeting/sayHello/{name}

6、启动ribbon-feign-sample-consumer

启动成功后,看eureka-server dashboard中多了一个 CONSUMER-SERVICE 服务,并且其有一个实例 192.168.3.32:consumer-service:9090
在这里插入图片描述

4、使用浏览器进行调用服务消费者

上述步骤中,我们已经依次启动了eureka-server、ribbon-feign-sample-8081、ribbon-feign-sample-8082、ribbon-feign-sample-consumer;三个服务、四个实例。

此处我们针对服务消费者ribbon-feign-sample-consumer做四次接口调用,分别为:

  1. http://localhost:9090/say/saint
  2. http://localhost:9090/say/saint2
  3. http://localhost:9090/say/saint3
  4. http://localhost:9090/say/saint4

在这里插入图片描述
然后我们去看ribbon-feign-sample-8081、ribbon-feign-sample-8082的控制台输出:

1> ribbon-feign-sample-8081控制台输出:
在这里插入图片描述
2> ribbon-feign-sample-8082控制台输出:
在这里插入图片描述

3> 结果说明:
我们可以发现,四个请求,ribbon-feign-sample-8081和ribbon-feign-sample-8082各分担了两个请求。其中ribbon-feign-sample-8081服务实例承担了请求:http://localhost:9090/say/saint2、http://localhost:9090/say/saint4,而ribbon-feign-sample-8082服务实例承担了请求:http://localhost:9090/say/saint、http://localhost:9090/say/saint3。

从现象上来看,已经Ribbon实现了负载均衡,并且默认是按照轮询的方式。

下文我们接着讨论 Ribbon是如何实现负载均衡(源码分析)?

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
5天前
|
Cloud Native API
微服务引擎 MSE 及云原生 API 网关 2024 年 9 月产品动态
微服务引擎 MSE 及云原生 API 网关 2024 年 9 月产品动态。
|
2天前
|
负载均衡 监控 Cloud Native
云原生架构下的微服务治理策略与实践####
在数字化转型加速的今天,云原生技术以其高效、灵活、可扩展的特性成为企业IT架构转型的首选。本文深入探讨了云原生环境下微服务治理的策略与实践路径,旨在为读者提供一个系统性的微服务治理框架,涵盖从服务设计、部署、监控到运维的全生命周期管理,助力企业在云端构建更加稳定、高效的业务系统。 ####
|
2天前
|
Cloud Native API 持续交付
利用云原生技术优化微服务架构
【10月更文挑战第13天】云原生技术通过容器化、动态编排、服务网格和声明式API,优化了微服务架构的可伸缩性、可靠性和灵活性。本文介绍了云原生技术的核心概念、优势及实施步骤,探讨了其在自动扩展、CI/CD、服务发现和弹性设计等方面的应用,并提供了实战技巧。
|
3天前
|
运维 监控 Cloud Native
云原生架构下,微服务治理的艺术与实践####
【10月更文挑战第14天】 在数字化转型的大潮中,云原生技术以其高效、灵活与可扩展性成为企业IT架构的首选。本文深入探讨了云原生架构的核心理念,聚焦于微服务治理的策略与实践,揭示了如何通过精细化管理提升系统的响应速度、稳定性和可维护性。不同于传统的摘要概述,本文摘要旨在直接触及读者关注的核心——即如何在复杂多变的云环境中,实现微服务的高效协同与治理,为读者提供一个清晰的行动指南。 ####
11 1
|
10天前
|
运维 Cloud Native 应用服务中间件
阿里云微服务引擎 MSE 及 云原生 API 网关 2024 年 09 月产品动态
阿里云微服务引擎 MSE 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka )、云原生网关(原生支持Higress/Nginx/Envoy,遵循Ingress标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。API 网关 (API Gateway),提供 APl 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 生命周期阶段。帮助您快速构建以 API 为核心的系统架构.满足新技术引入、系统集成、业务中台等诸多场景需要
|
12天前
|
Cloud Native 测试技术 持续交付
云原生时代的微服务架构实践
【10月更文挑战第5天】随着云计算的普及,云原生概念逐渐深入人心。微服务架构作为云原生的重要组成部分,它强调服务的小型化、自治性和弹性,以适应快速变化的市场需求。本文将探讨如何在云原生环境中设计并实现高效、可靠的微服务架构,包括选择合适的技术栈和最佳实践,以及如何通过持续集成和持续部署(CI/CD)流程来优化开发和运维工作。
|
13天前
|
Cloud Native jenkins 持续交付
云原生时代的微服务架构实践
【10月更文挑战第4天】随着云计算技术的不断成熟,云原生的概念逐渐深入人心。在这篇文章中,我们将探讨如何利用云原生技术构建高效的微服务架构,并分享一些实践经验和代码示例。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的参考。
|
17天前
|
运维 Kubernetes Cloud Native
云原生之旅:从容器化到微服务架构的演进之路
在数字化转型的浪潮中,云原生技术如同一股清流,为现代软件开发和运维带来革命性的变化。本文将通过深入浅出的方式,探索云原生的核心概念、关键技术以及它们如何共同塑造了今天的云基础设施和服务模式。我们将一起走进云原生的世界,了解它如何影响应用程序的设计、部署和扩展,并揭示这一趋势背后的哲学和实践。
26 1
|
10天前
|
缓存 运维 Cloud Native
云原生时代的微服务架构演进
【10月更文挑战第7天】随着云计算技术的飞速发展,云原生已成为现代软件工程的新常态。本文将探讨云原生环境下微服务架构的演进之路,从传统单体应用到分布式微服务的转变,再到容器化和自动化运维的实践,我们将通过一个实际案例来揭示微服务在云平台上的设计、部署和优化过程,以及如何利用云原生技术栈提升系统的弹性、可维护性和扩展性。
|
15天前
|
Cloud Native 持续交付 Docker
云原生之旅:从容器化到微服务架构
【10月更文挑战第2天】在数字化浪潮中,企业纷纷转向云计算以提升灵活性和效率。本文将引导你了解云原生技术的核心概念,包括容器化与微服务架构,并展示如何通过实际代码示例实现这些概念。我们将一起探索如何利用云原生技术来构建、部署和管理现代化应用程序,从而加速创新并保持竞争力。
27 0