基本流程
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 {
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
//取得channel地址List
Set<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. 获得余数
随机
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
// 取得channel地址List
Set<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);
}
生成个随机数,然后取余
轮询
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
// 取得通道地址List
Set<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
加权随机
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
// 取得channel地址List
Set<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
在生成随机数
加权轮询
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
// 取得channel地址List
Set<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;
}
和加权随机一样