netty(十五)负载均衡实践
理论:
https://www.cnblogs.com/silyvin/p/9469754.html
client 与后端之间同样要建立心跳,之所以由proxy发起到后端的tcp连接而不是反过来,是因为保持后端的独立性
参考:https://blog.csdn.net/admin1973/article/details/71424160?utm_source=itdadao&utm_medium=referral
在此基础上,作实践,写一个负载均衡服务
本次作实践,序列号承接 netty(十四)netty client重连模型
主函数:轮询(1分钟)本地配置文件,文件中保存信任的后端服务ip port,两次读取不一致,干掉老的(不再信任的),新增新的
public class ProxyServer { public static void main(String[] args) throws InterruptedException { ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); Runnable runnable = new LoadProperty(); scheduledThreadPoolExecutor.scheduleAtFixedRate(runnable, 0, 60, TimeUnit.SECONDS); } private static class LoadProperty implements Runnable { private static Set<String> lastPropertySet = new HashSet<>(); @Override public void run() { System.out.println("开始读取配置"); Set<String> thisTime = null; try { thisTime = readProperties(); } catch (Exception e) { e.printStackTrace(); } Set<String> delSet = getFormer(lastPropertySet, thisTime); for(String item : delSet) { System.out.println("***************去除信任服务" + item); // Client4Reconnect.interrupt(item); } Set<String> newSet = getFormer(thisTime, lastPropertySet); for(String item : newSet) { System.out.println("***************新增信任服务" + item); // Client4Reconnect.create(item); } lastPropertySet = thisTime; System.out.println("结束读取配置"); } } private static Set<String> readProperties() throws Exception { InputStreamReader read = null; Set<String> set = new HashSet<>(); try { String encoding = "UTF-8"; File file = new File("servers.config"); if (file.isFile() && file.exists()) { read = new InputStreamReader(new FileInputStream(file), encoding); BufferedReader bufferedReader = new BufferedReader(read); String lineTxt = null; while ((lineTxt = bufferedReader.readLine()) != null) { set.add(lineTxt); } } else { throw new Exception("找不到指定的文件"); } return set; } catch (Exception e) { throw new Exception(e); } finally { read.close(); } } /** * 返回前者set独有的 * @param former * @param batter * @return */ private static Set<String> getFormer(Set<String> former, Set<String> batter) { Set<String> set = new HashSet<>(); for(String item : former) { if(!batter.contains(item)) { set.add(item); } } return set; } }
首先注释掉真正执行连接的代码:
// Client4Reconnect.interrupt(item);
// Client4Reconnect.create(item);
查看这个轮询读取程序是否ok:
servers配置文件初始:
127.0.0.1:8867
127.0.0.1:8868
127.0.0.1:8866
第2个1分钟
127.0.0.1:8867
127.0.0.1:8868
127.0.0.1:8869
第3个1分钟
127.0.0.1:8867
127.0.0.1:8868
127.0.0.1:8869
127.0.0.1:6666
开始读取配置
***************新增信任服务127.0.0.1:8867
***************新增信任服务127.0.0.1:8868
***************新增信任服务127.0.0.1:8866
结束读取配置
开始读取配置
***************去除信任服务127.0.0.1:8866
***************新增信任服务127.0.0.1:8869
结束读取配置
开始读取配置
***************新增信任服务127.0.0.1:8866
结束读取配置
完成了轮询扫描信任服务清单后,真正连接到后端,方案如下:
代码参见(十四)netty client 重连模型
设计如下的实验:
输出:
开始读取配置
***************新增信任服务127.0.0.1:8867
***************开启信任线程-127.0.0.1:8867:Thread-1
***************新增信任服务127.0.0.1:8868
***************开启信任线程-127.0.0.1:8868:Thread-2
***************新增信任服务127.0.0.1:8866
***************开启信任线程-127.0.0.1:8866:Thread-3
结束读取配置
连接成功-127.0.0.1:8867
--------------新增可用服务127.0.0.1:8867:ALL - [127.0.0.1:8867]
连接成功-127.0.0.1:8866
--------------新增可用服务127.0.0.1:8866:ALL - [127.0.0.1:8867, 127.0.0.1:8866]
连接失败-127.0.0.1:8868
SERVER'S general msg RESPONSE : code: 2
msg: "SERVER:hello"
SERVER'S general msg RESPONSE : code: 2
msg: "SERVER:hello"
重新连接-127.0.0.1:8868
连接失败-127.0.0.1:8868
重新连接-127.0.0.1:8868
连接失败-127.0.0.1:8868
重新连接-127.0.0.1:8868
连接失败-127.0.0.1:8868
重新连接-127.0.0.1:8868
连接失败-127.0.0.1:8868
重新连接-127.0.0.1:8868
连接失败-127.0.0.1:8868
重新连接-127.0.0.1:8868
连接成功-127.0.0.1:8868
--------------新增可用服务127.0.0.1:8868:ALL - [127.0.0.1:8867, 127.0.0.1:8868, 127.0.0.1:8866]
SERVER'S general msg RESPONSE : code: 2
msg: "SERVER:hello"
连接异常中断,重新连接-127.0.0.1:8867
--------------去除可用服务127.0.0.1:8867:ALL - [127.0.0.1:8868, 127.0.0.1:8866]
channelInactive
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
* CLIENT WRITER_IDLE send msg heart_beat...
* CLIENT receive back heart
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
* CLIENT WRITER_IDLE send msg heart_beat...
* CLIENT receive back heart
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
重新连接-127.0.0.1:8867
连接失败-127.0.0.1:8867
开始读取配置
***************去除信任服务127.0.0.1:8867
***************退出信任线程-127.0.0.1:8867:Thread-1
***************去除信任服务127.0.0.1:8868
终止信任,不再重连-127.0.0.1:8867
***************退出信任线程-127.0.0.1:8868:Thread-2
终止信任,断开连接,服务不再启用-127.0.0.1:8868
--------------去除可用服务127.0.0.1:8868:ALL - [127.0.0.1:8866]
***************新增信任服务127.0.0.1:8869
channelInactive
***************开启信任线程-127.0.0.1:8869:Thread-4
结束读取配置
连接成功-127.0.0.1:8869
--------------新增可用服务127.0.0.1:8869:ALL - [127.0.0.1:8866, 127.0.0.1:8869]
SERVER'S general msg RESPONSE : code: 2
msg: "SERVER:hello"
* CLIENT WRITER_IDLE send msg heart_beat...
* CLIENT receive back heart
* CLIENT WRITER_IDLE send msg heart_beat...
* CLIENT receive back heart
* CLIENT WRITER_IDLE send msg heart_beat...
* CLIENT receive back heart
连接异常中断,重新连接-127.0.0.1:8869
channelInactive
--------------去除可用服务127.0.0.1:8869:ALL - [127.0.0.1:8866]
连接失败-127.0.0.1:8869
连接异常中断,重新连接-127.0.0.1:8866
--------------去除可用服务127.0.0.1:8866:ALL - []
channelInactive
连接失败-127.0.0.1:8866
重新连接-127.0.0.1:8869
连接失败-127.0.0.1:8869
重新连接-127.0.0.1:8866
连接失败-127.0.0.1:8866
重新连接-127.0.0.1:8869
连接失败-127.0.0.1:8869
重新连接-127.0.0.1:8866
连接失败-127.0.0.1:8866
重新连接-127.0.0.1:8869
连接失败-127.0.0.1:8869
文件:
链接: https://pan.baidu.com/s/1om4nTH_3tS9utmaO3AI5-w 提取码: fkkg