• 微服务负载均衡实践


    目录

    概述

    环境说明

    步骤

    改造Eureka为单节点

    spring-cloud-loadbalancer

    服务调用

    负载均衡

    OpenFeign

    OpenFeign的使用

    OpenFeign的配置

    总结


     

    概述

    本文介绍微服务的服务调用和负载均衡,使用spring cloud的loadbalancer及openfeign两种技术来实现。

    本文的操作是在微服务的初步使用的基础上进行。

    环境说明

    jdk1.8

    maven3.6.3

    mysql8

    spring cloud2021.0.8

    spring boot2.7.12

    idea2022

    步骤

    改造Eureka为单节点

    为了方便测试,把高可用Eureka还原为单节点Eureka。

    修改eureka_server的application.yml

    1. spring:
    2. application:
    3. name: eureka-server
    4. server:
    5. port: 9000
    6. eureka:
    7. instance:
    8. hostname: localhost
    9. client:
    10. registerWithEureka: false
    11. fetchRegistry: false
    12. serviceUrl:
    13. defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    14. server:
    15. enable-self-preservation: false
    16. eviction-interval-timer-in-ms: 4000

    修改product-service服务和order-service服务的application.yml的Eureka配置如下

    1. eureka:
    2. client:
    3. service-url:
    4. defaultZone: http://localhost:9000/eureka/

    spring-cloud-loadbalancer

    spring-cloud-loadbalancer和ribbon类似,之前的spring cloud版本eureka内部继承了ribbon ,但spring cloud版本升级后,不再内置ribbon(可查看依赖关系),spring cloud提供了自己的负载均衡的实现,可查看 官方文档

    Spring Cloud provides its own client-side load-balancer abstraction and implementation. For the load-balancing mechanism, ReactiveLoadBalancer interface has been added and a Round-Robin-based and Random implementations have been provided for it. In order to get instances to select from reactive ServiceInstanceListSupplier is used. Currently we support a service-discovery-based implementation of ServiceInstanceListSupplier that retrieves available instances from Service Discovery using a Discovery Client available in the classpath.

    服务调用

    之前服务调用时,使用host:ip拼接成URL的方式进行调用,较为麻烦,使用@LoadBalanced注解后,可以使用微服务的服务名称来进行调用,更加方便。

    在创建RestTemplate的时候,申明@LoadBalanced

    使用restTemplate调用远程微服务:不需要拼接微服务的URL,用服务名称替换IP地址

    修改OrderController.java,使用服务名称代替host:port的形式,避免了之前的使用实例元数据进行拼接。

    修改前

    product  = restTemplate.getForObject("http://"+host+":"+port+"/product/1", Product.class);

    修改后

    product  = restTemplate.getForObject("http://service-product/product/1", Product.class);

    启动测试

    启动eureka、product、order服务

    浏览器访问

    能访问到数据,说明服务调用成功了。

    负载均衡

    使用@LoadBalanced注解后,除了方便使用服务名称进行调用之外,更重要的是也实现了服务调用的负载均衡功能。准备两个商品服务,端口号分别为9001、9011,两个商品服务的作用:1.增加系统吞吐率  2.商品服务高可用。

    服务架构及流程如下图:

    修改product-service的controller

    1. @Value("${spring.cloud.client.ip-address}") //springcloud自动获取应用的ip地址
    2. private String ip;

    启动product服务(9001端口)

    修改product服务的yml,修改服务端口为9011

    复制运行配置得到另一个proudct服务

    启动product2服务(9011端口)

    查看Eureka Web页面

    http://localhost:9000/

    看到SERVICE-PRODUCT,有2个在线状态的实例,端口分别是:9001和9011 

    启动order服务

    分别访问9001和9011

    http://localhost:9001/product/1

    http://localhost:9011/product/1

    两个商品服务均正常

    测试负载均衡

    访问如下链接2次

    http://localhost:9002/order/buy/1

    发现实现 第一次访问9001商品服务,第二次访问了9011商品服务,说明实现了客户端的负载均衡

    多次刷新访问http://localhost:9002/order/buy/1,发现9001和9011是交替出现,说明默认使用的负载均衡是轮询策略。

    OpenFeign

    此前的服务调用代码如下:

    restTemplate.getForObject("http://service-product/product/1", Product.class);

    如果请求参数过多是,拼接URL的方式显得麻烦,可以使用OpenFeign来解决。

    OpenFeign 全称 Spring Cloud OpenFeign,它是 Spring 官方推出的一种声明式服务调用与负载均衡组件,它的出现就是为了替代进入停更维护状态的 Feign。

    OpenFeign 是 Spring Cloud 对 Feign 的二次封装,它具有 Feign 的所有功能,并在 Feign 的基础上增加了对 Spring MVC 注解的支持。

    OpenFeign的使用

    order-service操作

    1.导入依赖

    1. <dependency>
    2. <groupId>org.springframework.cloudgroupId>
    3. <artifactId>spring-cloud-starter-openfeignartifactId>
    4. dependency>

    2.配置调用接口

    业务需求:order服务调用product服务

    1. @FeignClient(name = "service-product")
    2. public interface ProductFeignClient {
    3. /**
    4. * 配置需要调用的微服务接口
    5. * @return
    6. */
    7. @RequestMapping(value = "/product/{id}", method = RequestMethod.GET)
    8. Product findById(@PathVariable("id") Long id);
    9. }

     3.在启动类上激活feign

    1. //激活feign
    2. @EnableFeignClients
    3. public class OrderApplication {

    4.通过自动注入的接口调用远程微服务

    修改之前的Controller代码

    1. @RestController
    2. @RequestMapping("/order")
    3. public class OrderController {
    4. @Autowired
    5. private RestTemplate restTemplate;
    6. @Autowired
    7. private DiscoveryClient discoveryClient;
    8. @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    9. public Product findById(@PathVariable Long id){
    10. Product product = null;
    11. product = restTemplate.getForObject("http://service-product/product/1", Product.class);
    12. return product;
    13. }
    14. }

    修改之后的代码

    1. @RestController
    2. @RequestMapping("/order")
    3. public class OrderController {
    4. @Autowired
    5. private ProductFeignClient productFeignClient;
    6. @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    7. public Product findById(@PathVariable Long id){
    8. Product product = null;
    9. //调用微服务
    10. product = productFeignClient.findById(id);
    11. return product;
    12. }
    13. }

    可以看出,OrderController通过注入ProductFeignClient接口实例,并调用接口方法实现了调用。 可以看出不需要自己构建http请求,就像是调用自身工程的方法调用。如果有多个参数可以传递对象参数,避免了拼接url的麻烦。

    测试

    启动服务

    启动eureka、启动product(启动两个实例:9000和9011)、启动order

    浏览器访问

    分别访问,确保product服务能正常访问

    http://localhost:9001/product/1

    http://localhost:9011/product/1

    访问order两次

    http://localhost:9002/order/buy/1

    多次访问,发现9001和9011交替出现,说明实现了负载均衡。

    OpenFeign的配置

    如果需要配置OpenFeign,在application.yml添加相关配置

    配置案例如下:

    1. feign:
    2. client:
    3. config:
    4. feignName: #FeginClient的名称
    5. connectTimeout: 5000 #建立链接的超时时长
    6. readTimeout: 5000 #读取超时时长
    7. loggerLevel: full #Fegin的日志级别
    8. errorDecoder: com.example.SimpleErrorDecoder #Feign的错误解码器
    9. retryer: com.example.SimpleRetryer #配置重试
    10. requestInterceptors: #添加请求拦截器
    11. - com.example.FooRequestInterceptor
    12. - com.example.BarRequestInterceptor
    13. decode404: false #配置熔断不处理404异常
    14. #日志配置
    15. #NONE : 不输出日志(高)
    16. #BASIC: 适用于生产环境追踪问题
    17. #HEADERS : 在BASIC的基础上,记录请求和响应头信息
    18. #FULL : 记录所有
    19. service-product:
    20. logger-level: FULL #配置商品服务日志
    21. compression:
    22. request:
    23. enabled: true #开启请求压缩
    24. mime-types: text/html,application/xml,application/json #设置压缩的数据类型
    25. min-request-size: 2048 #设置触发压缩的大小下限
    26. response:
    27. enabled: true #开启相应压缩
    28. logging:
    29. level:
    30. org.example.order.feign.ProductFeignClient: debug #配置具体接口的日志级别

    总结

    两种服务调用及负载均衡技术:@LoadBalanced方式和OpenFeign的方式。

    1.@LoadBalanced方式是借助于RestTemplate方式进行,可以直接使用服务名称来调用,但需要拼接URL。

    2.OpenFeign的方式是通过声明接口并注入接口进行调用,避免了拼接URL的麻烦。

    完成!enjoy it!

  • 相关阅读:
    Java常用类
    FLStudio21水果免费版本FL2023电音制作软件
    代码提交没有记录到github activity和contribute
    【数据分析实战】金融评分卡建立
    c盘垃圾太多怎么清理?c盘垃圾太多需要重装系统嘛?
    Linux ping向网络主机发送ICMP ECHO REQUEST
    ubuntu无法使用man
    spring mvc:请求执行流程(一)之获取Handler
    用rabbitMq 怎么处理“延迟消息队列”?
    oracle(PLsql)/mysql 建表
  • 原文地址:https://blog.csdn.net/qq_42881421/article/details/133906436