使用策略模式-手写本地负载均衡器轮训算法

分析有轮训 随机 权重等本地负载均衡器算法
多个策略的共同行为从集群里取一个出来 本文采用策略模式去手写
 
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就可以验证效果了

 

 

 
posted @ 2023-02-05 15:25  山河永慕~  阅读(48)  评论(0编辑  收藏  举报