返回 导航

SpringBoot / Cloud

hangge.com

SpringCloud - 服务注册与发现组件Eureka的使用详解4(服务发现与消费、负载均衡)

作者:hangge | 2020-07-03 08:10
    在之前的文章中我演示了如何搭建服务注册中心和服务提供者,本文接着演示如何构建一个服务消费者,它主要完成两个目标:发现服务以及消费服务。其中发现服务的任务由 Eureka 的客户端完成,而服务消费的任务由 Ribbon 完成。
    Ribbon 是一个基于 HTTP TCP 的客户端负载均衡器,它可以在通过客户端中配置的 ribbonServerList 服务端列表去轮询访问以达到均衡负载的作用。当 Ribbon Eureka 联合使用时,Ribbon 的服务实例清单 RibbonServerList 会被 DiscoveryEnabledNIWSServerList 重写,扩展成从 Eureka 注册中心中获取服务端列表。同时它也会用 NIWSDiscoveryPing 来取代 IPing,它将职责委托给 Eureka 来确定服务端是否已经启动。

四、服务发现与消费

1,准备工作

(1)启动之前实现的服务注册中心 eureka-server,具体实现可以参考之前的文章:

(2)通过 java -jar 命令行的方式启动两个不同端口的 hello-service 服务:
hello-service 服务的实现可以参考之前写的文章:SpringBoot - 服务注册与发现组件Eureka的使用详解2(创建并注册服务提供者)
java -jar hello-service-0.0.1-SNAPSHOT.jar --server.port=8081
java -jar hello-service-0.0.1-SNAPSHOT.jar --server.port=8082

(3)启动后通过 Eureka 信息面板中可以看到名为 HELLO-SERVICE 的服务中出现了两个实例单元,分别是通过命令行启动的 8081 端口和 8082 端口的服务。

2,创建服务消费者

(1)创建一个 Spring Boot 工程(ribbon-consumer)来实现服务消费者,首先在 pom 文件中引入相关依赖:
注意:相较于前面的服务提供者 hello-service,这里新增了 Ribbon 模块的依赖 spring-cloud-starter-netflix-ribbon
<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>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Greenwich.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

(2)接着编辑项目的 application.properites 文件,添加如下配置为服务命名,并指定服务注册中心的地址:
#设置端口,防止冲突
server.port=9000
#为服务命名
spring.application.name=ribbon-consumer
#指定服务注册中心的地址
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

(3)主类上添加 @EnableDiscoveryClient 注解,让该应用注册为 Eureka 客户端应用,以获得服务发现的能力。同时,在该主类中创建 RestTemplate Spring Bean 实例,并通过 @LoadBalanced 注解开启客户端负载均衡。
  • 之后我们就可以使用被 @LoadBalanced 注释修饰过的 RestTemplate 来实现面向服务的接口调用。
  • Spring Cloud Ribbon 中实现客户端负载均衡的原理简单来说:就是通过 LoadBalancerInterceptor 拦截器对 RestTemplate 的请求进行拦截,并利用 Spring Cloud 的负载均衡器 LoadBalancerClient 将一服务名为 host URI 转换成具体的服务实例地址的过程。
@SpringBootApplication
@EnableDiscoveryClient
public class RibbonConsumerApplication {

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

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

(4)创建一个 ConsumerController 并实现 /hello-consumer 接口。在该接口中,通过前面定义的 RestTemplate 来实现对 HELLO-SERVICE 服务提供的 /hello 接口进行调用:
注意:可以看到这里访问的地址是服务名 HELLO-SERVICE,而不是一个具体的地址。
@RestController
public class ConsumerController {
    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/hello-consumer")
    public String helloConsumer() {
        // 通过服务名调用服务提供者的接口
        return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody();
    }
}

3,运行测试

(1)启动 ribbon-consumer 应用后,我们可以在 Eureka 信息面板中看到当前除了 HELLO-SERVICE 外,还多了我们实现的 RIBBON-CONSUMER

(2)而通过向 http://localhost:9000/hello-consumer 发起请求是,可以在 ribbon-consumer 应用的控制台中看到如下信息。
    Ribbon 输出了当前客户端维护的 HELLO-SERVICE 的服务列表情况。其中包含了各个实例的位置,Ribbon 就是按照此信息进行轮训访问,以实现基于客户端的负载均衡。
    除此之外还输出了一些其他非常有用的信息,如对各个实例的请求总数量、第一次连接信息、上一次连接信息、总的请求失败数量等。

(3)如果尝试多发起几次请求,并观察两个服务提供者 HELLO-SERVICE 的控制台,可以看到这两个控制台会交替打印如下日志(这个是之前在 HelloController 中对服务信息的输出),说明当前 ribbon-consumer HELLO-SERVICE 的调用是负载均衡的。

附:其他一些常用配置

1,获取服务

(1)当我们启动服务消费者的时候,它会发送一个 REST 请求给服务注册中心,来获取上面注册的服务请求清单。
(2)获取服务是服务消费者的基础,确保 eureka.client.fetch-registry 参数为 true(默认就是 true
#获取服务
eureka.client.fetch-registry=true

2,服务清单更新时间

    为了性能考虑,Eureka Server 会维护一份只读的服务清单来返回给客户端,同时缓存清单会每隔 30 秒更新一次。我们可以通过如下参数修改缓存清单的更新时间:
#修改缓存清单的更新时间。默认为30秒
eureka.client.registry-fetch-interval-seconds=30
评论

全部评论(0)

回到顶部