基本流程
String loadBalancersName = loadBalancers.get(loadBalancerType);
SendLoadBalancer sendLoadBalancer = registerBeanHandler.getBean(loadBalancersName, SendLoadBalancer.class);
String channelLabel = sendLoadBalancer.chooseChannel(smsTemplateVOs,mobiles);;
根据短信模板,选择负载均衡器
根据负载均衡器,选择channel配置文件
根据配置的channel 进行短信发送
负载均衡器
有若干种类
负载均衡器需要实现两个接口
1. 选择channel
2. 获得所有channel
public interface SendLoadBalancer {/**** @description 根据模板、电话负载均衡发送* @param SmsTemplates 模板列表* @param mobile 电话号码* @return 通道类型*/String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile);/**** @description 查询拥有当前模板,活跃状态的通道* @param SmsTemplates 模板列表* @return 通道类型*/Map<String, String> getChannelList(List<SmsTemplateVO> SmsTemplates);
}
channel有两点参数
1. channel 阿里云、腾讯
2. level 权重
@Override
public Map<String, String> getChannelList(List<SmsTemplateVO> SmsTemplates) {
//处理模板
Set<String> channelLabelList = SmsTemplates.stream()
.map(SmsTemplateVO::getChannelLabel).collect(Collectors.toSet());
//查询模板对应的渠道
List<SmsChannelVO> smsChannels =smsChannelService.findChannelInChannelLabel(channelLabelList);
if (!EmptyUtil.isNullOrEmpty(smsChannels)){
return smsChannels.stream()
.collect(Collectors.toMap(SmsChannelVO::getChannelLabel, SmsChannelVO::getLevel));
}
return null;
}
Hash负载均衡
@Component
public class HashSend extends BaseSendLoadBalancer {@Overridepublic String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {//获得当前模板对应的渠道Map<String, String> channelMap = super.getChannelList(SmsTemplates);//取得channel地址ListSet<String> keySet = channelMap.keySet();ArrayList<String> keyList = new ArrayList<String>();keyList.addAll(keySet);// 使用mobile取余int hashCode = mobile.hashCode();int serverListSize = keyList.size();int serverPos = hashCode % serverListSize;return keyList.get(serverPos);}}
1. 根据手机号生成hashcode
2. 对channel长度取余
3. 获得余数
随机
@Overridepublic String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {//获得当前模板对应的渠道Map<String, String> channelMap = super.getChannelList(SmsTemplates);// 取得channel地址ListSet<String> keySet = channelMap.keySet();ArrayList<String> keyList = new ArrayList<String>();keyList.addAll(keySet);Random random = new Random();int randomPos = random.nextInt(keyList.size());return keyList.get(randomPos);}
生成个随机数,然后取余
轮询
@Overridepublic String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {//获得当前模板对应的渠道Map<String, String> channelMap = super.getChannelList(SmsTemplates);// 取得通道地址ListSet<String> keySet = channelMap.keySet();ArrayList<String> keyList = new ArrayList<String>();keyList.addAll(keySet);String channelName = null;synchronized (pos) {if (pos >= keySet.size())pos = 0;channelName = keyList.get(pos);pos ++;}return channelName;}
对pos上锁,让pos++
如果大于channel大小,让pos重置
根据pos获得channel
加权随机
@Overridepublic String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {//获得当前模板对应的渠道Map<String, String> channelMap = super.getChannelList(SmsTemplates);// 取得channel地址ListSet<String> keySet = channelMap.keySet();Iterator<String> iterator = keySet.iterator();List<String> serverList = new ArrayList<String>();while (iterator.hasNext()) {String channel = iterator.next();int weight = Integer.valueOf(channelMap.get(channel));for (int i = 0; i < weight; i++)serverList.add(channel);}Random random = new Random();int randomPos = random.nextInt(serverList.size());return serverList.get(randomPos);}
channel * 权重,放入serverList
在生成随机数
加权轮询
@Overridepublic String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {//获得当前模板对应的渠道Map<String, String> channelMap = super.getChannelList(SmsTemplates);// 取得channel地址ListSet<String> keySet = channelMap.keySet();Iterator<String> iterator = keySet.iterator();List<String> channelListHandler = new ArrayList<String>();while (iterator.hasNext()) {String server = iterator.next();Integer weight = Integer.valueOf(channelMap.get(server));for (int i = 0; i < weight; i++)channelListHandler.add(server);}String channelName = null;synchronized (pos) {if (pos > keySet.size())pos = 0;channelName = channelListHandler.get(pos);pos++;}return channelName;}
和加权随机一样