使用策略模式-手写本地负载均衡器轮训算法
分析有轮训 随机 权重等本地负载均衡器算法
多个策略的共同行为从集群里取一个出来 本文采用策略模式去手写
Maven依赖
Maven依赖信息
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<!-- springboot 整合web组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>
package com.shanheyongmu.service; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class MemberService { @Value("${server.port}") private String serverPort; /** * 会员服务提供的接口被订单服务调用 * @param userId * @return */ @GetMapping("/selectUserInfo") public String getUser(Integer userId) { //业务处理 userId //通过打印端口我们好知道 访问集群的哪一台 return "访问的端口号为:" + serverPort; } }
OrderService.java
package com.shanheyongmu.service; 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.net.URI; import java.util.List; @RestController public class OrderService { @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancer loadBalancer; /** * 订单服务调用到我们的会员服务接口 * * @return */ @RequestMapping("/orderToMember") public Object orderToMember() { // 1.根据服务名称从 注册中心获取集群列表地址 List<ServiceInstance> instances = discoveryClient.getInstances("xx-member"); // 2.列表任意选择一个 实现本地rpc调用 rest 采用我们负载均衡的算法 ServiceInstance srviceInstance = loadBalancer.getAddress(instances); URI rpcMemberUrl = srviceInstance.getUri(); String result = restTemplate.getForObject(rpcMemberUrl + "/getUser", String.class); return "订单调用会员返回结果:" + result; } }
LoadBalancer.java
package com.shanheyongmu.loadbalancer; import org.springframework.cloud.client.ServiceInstance; import java.util.List; public interface LoadBalancer { /** * 从注册中心集群列表中获取单个地址 * @param serviceInstances * @return */ ServiceInstance getAddress(List<ServiceInstance> serviceInstances); }
有一个或多个策略 只需要实现loadbalancer接口就好了
package com.shanheyongmu.service.impl; import org.springframework.cloud.client.ServiceInstance; import org.springframework.stereotype.Component; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @Component public class RoundRobinLoadBalancer implements LoadBalancer { /** * 从0开始计数 */ private AtomicInteger atomicInteger = new AtomicInteger(0); @Override public ServiceInstance getAddress(List<ServiceInstance> serviceInstances) { int index = atomicInteger.incrementAndGet() % serviceInstances.size(); return serviceInstances.get(index); } }
打开浏览器 启动多台Member服务 访问orderToMember就可以验证效果了
早年同窗始相知,三载瞬逝情却萌。年少不知愁滋味,犹读红豆生南国。别离方知相思苦,心田红豆根以生。