本文共 3259 字,大约阅读时间需要 10 分钟。
上一篇写完咱们已经具备服务注册发现/通信/通过接口调用功能了,本篇带来负载均衡策略。
RPC框架中,负载均衡策略提供,其实就是根据配置,选择不同的负载策略,常见的有随机/轮询/权重几种负载策略,本篇就带大家来实现它。
这里还是贴出github代码地址,想直接看代码的可以直接下载运行:https://github.com/whiteBX/wrpc
首先这里主要用到了设计模式中的策略模式,定义一个负载策略处理器:
public interface BalanceProcessor { /** * 处理接口 * @param urlList * @return */ String process(String appCode, ListurlList);}
下面来实现轮询模式的策略处理:
public class RoundRobinBalanceProcessor implements BalanceProcessor { private ConcurrentMapcounterMap = new ConcurrentHashMap (); public String process(String appCode, List urlList) { AtomicInteger counter = counterMap.get(appCode); if (counter == null) { counterMap.putIfAbsent(appCode, new AtomicInteger()); } counter = counterMap.get(appCode); int current = getAndIncrement(counter); return urlList.get(current % urlList.size()); } /** * 通过CAS获取不超过最大数的顺序int * * @param ai * @return */ private Integer getAndIncrement(AtomicInteger ai) { while (true) { int current = ai.get(); int next = current >= Integer.MAX_VALUE ? 0 : current + 1; if (ai.compareAndSet(current, next)) { return current; } } }}
这边代码比较简单,主要用到了java并发包的一些东西,通过一个自增数对数组长度取余即可以实现轮询模式。另外这里默认我们线上的服务器数量不是会经常变化的,所以urlList的内容其实是很少变化的,轮询在大部分时间内是不会被破坏的。
下面来看随机模式,这个很简单:
public class RandomProcessor implements BalanceProcessor { public String process(String appCode, ListurlList) { return urlList.get((int) (Math.random() * urlList.size())); }}
接下来来看策略上下文处理:
public class BalanceContext { private BalanceProcessor roundRobinProcessor = new RoundRobinBalanceProcessor(); private BalanceProcessor randomProcessor = new RandomProcessor(); /** * 获取URL * * @param urlList * @return */ public String getUrl(String appCode, ListurlList, BalanceMode balanceMode) { switch (balanceMode) { case ROUND_ROBIN: return roundRobinProcessor.process(appCode, urlList); case RANDOM: return randomProcessor.process(appCode, urlList); default: return null; } }}
然后是改造原有获取url的部分代码,调用我们的策略处理类:
/** * 负载上下文处理器 */private BalanceContext balanceContext = new BalanceContext();/** 负载模式,后续引入spring则从配置文件中读取 */private static String balanceMode = "RANDOM";/** * 获取URL * * @param appCode * @return */public String getUrl(String appCode) { // 初始化url if (urlList.size() == 0) { initUrlList(appCode); } // 随机返回一条,此处以后优化为负载均衡策略 if (urlList.size() > 0) { return balanceContext.getUrl(appCode, urlList, BalanceMode.valueOf(balanceMode)); } else { System.out.println("目前没有服务提供者"); return null; }}
之后大家可以自行测试一下,采用轮询模式的话,获取到的处理服务器会依次轮询所有注册的服务,而采用随机模式则会随机选中服务器进行处理。这里就不贴测试结果了。
另外由于时间关系这里没有写权重的策略,这里先说一下原理,其实很简单的。
权重模式,根据配置,比如5台机器,配置权重依次为40,10,15,25,10.那么只需要在总数100中去随机一个随机数,命中了1-40则选取机器1,命中了41-50则选取机器2,其他同理。另外这里针对可能临时加机器的情况,配置没有及时更新进去的话,对于新机器可以设置默认权重,比如这时新加了一台机器,默认权重设置为10的话,则当前权重算法变为在总数110中随机,随机到101-110则会选取新增加的机器去处理请求即可。
到这里就实现了RPC框架的负载均衡.
后续将一步一步实现调用链路Trace记录/限流等功能,欢迎持续关注!
转载地址:http://lhsni.baihongyu.com/