乐趣区

关于java:SpringCloud手写Ribbon实现负载均衡

前言

后面咱们学习了 SpringCloud 整合 Consul,在此基础上咱们手写本地客户端实现相似 Ribbon 负载平衡的成果。
注:order 模块调用者 记得敞开 @LoadBalanced注解。
咱们这里只演示 注册核心 consul,至于 zookeeper 也是截然不同。

生产者

member 模块

member 服务须要集群,所以咱们 copy application-consul.yml 文件命名为 application-consul2.yml


服务别名统一,只须要批改端口号即可。
application-consul2.yml 配置文件:

## 服务端口号
server:
  port: 8503
spring:
  application:
    ## 服务别名 -- 服务注册到 consul 名称
 name: consul-member
  ## 注册核心 consul 地址
 cloud:
    consul:
      host: localhost
      port: 8500
 discovery:
        ## consul ip 地址
 hostname: 192.168.3.91

启动 member 集群服务:
idea 运行 AppMember.java 启动 8501 端口
再关上 jar 包门路

shift + 右键 启动 PowerShell 窗口,运行命令:

java -jar E:\ideaworkspaceback\springcloud-zookeeper\springcloud-zookeeper-member\target\springcloud-zookeeper-member-1.0-SNAPSHOT.jar --spring.profiles.active=consul2

启动 8503 端口

关上 http://localhost:8500/ui/dc1/services 能够发现下面 注册了 member 集群服务:

消费者

order 模块

OrderApiController.java管制页面应用原子类来 AtomicInteger 保障操作的原子性。

package com.baba.wlb.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * @Author wulongbo
 * @Date 2021/1/9 15:32
 * @Version 1.0
 */@RestController
public class OrderApiController {
    @Autowired
 private RestTemplate restTemplate;
 @Autowired
 private DiscoveryClient discoveryClient;
 // 应用原子类 AtomicInteger
 private AtomicInteger atomicInteger = new AtomicInteger(1);
 public int add() {return atomicInteger.getAndIncrement(); // 先获取再自增, 对应 a ++
 // 若应用 ++a 则对应办法是 a.incrementAndGet(); 先自增再获取 , // 多说一句 a-- 就是 a.getAndDecrement(); // 若 a = a + 10;————对应 API  a.getAndAdd(10);
 }
    /**
 * springCloud 中,两种形式调用(rest/feign)*
 * @return
 */
 // 订单服务调用会员服务
 @RequestMapping("/getOrder")
    public String getOrder() {
        // 有两种调用形式,一种是采纳服务别名形式调用,另一种是应用别名去注册核心上获取对应服务调用地址
 // 第一种形式
 String url = "http://dy-202006281547:8000/getMember";
 // 第二种形式
 url = "http://zk-member/getMember";
 String result = restTemplate.getForObject(url, String.class);
 return "订单服务调用会员服务:" + result;
 }
    /**
 * springCloud 中,两种形式调用(rest/feign)*
 * @return
 */
 // 订单服务调用会员服务
 @RequestMapping("/getRibbonOrder")
    public String getRibbonOrder() {
        // 第一种形式
 String url = getUri() + "/getMember";
 String result = restTemplate.getForObject(url, String.class);
 return "纯手写 Ribbon 本地负载平衡:" + result;
 }
    public String getUri() {List<ServiceInstance> serviceInstances = discoveryClient.getInstances("consul-member");
 if (serviceInstances == null || serviceInstances.isEmpty()) {return null;}
        int serverSize = serviceInstances.size();
 int count = add();
 int indexServer = count % serverSize;
 return serviceInstances.get(indexServer).getUri().toString();
 }
}

AppOrder.java 启动类,敞开 @LoadBalanced 注解即可:

因为咱们是在 springcloud 集成 zookeeper 我的项目上革新的,所以order 模块 yml 配置也做相应的调整,注册核心批改为 consul,并且在该模块中引入 consul 的 maven 依赖

<!--springcloud 整合 consul-->
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

启动 AppOrder.java,并刷新 http://localhost:8500/ui/dc1/services 能够发现下面 注册了 order 服务:

这里有一个巨坑,导致 order 模块调用不到 member 模块,咱们须要在 yml 配置文件中正文掉:
参考博客:https://blog.csdn.net/apdkapskdad/article/details/93927860

## consul ip 地址
##hostname: 192.168.3.91

消费者调用生产者:拜访 http://localhost:8508/getRibbonOrder


OK! 咱们便达到了负载平衡!

退出移动版