提交者
GitHub
Merge pull request #88 from crossoverJie/fix-issue-70
Fix issue 70
正在显示
13 个修改的文件
包含
161 行增加
和
22 行删除
| @@ -4,8 +4,10 @@ import com.crossoverjie.cim.client.config.AppConfiguration; | @@ -4,8 +4,10 @@ import com.crossoverjie.cim.client.config.AppConfiguration; | ||
| 4 | import com.crossoverjie.cim.client.init.CIMClientHandleInitializer; | 4 | import com.crossoverjie.cim.client.init.CIMClientHandleInitializer; |
| 5 | import com.crossoverjie.cim.client.service.EchoService; | 5 | import com.crossoverjie.cim.client.service.EchoService; |
| 6 | import com.crossoverjie.cim.client.service.MsgHandle; | 6 | import com.crossoverjie.cim.client.service.MsgHandle; |
| 7 | +import com.crossoverjie.cim.client.service.ReConnectManager; | ||
| 7 | import com.crossoverjie.cim.client.service.RouteRequest; | 8 | import com.crossoverjie.cim.client.service.RouteRequest; |
| 8 | import com.crossoverjie.cim.client.service.impl.ClientInfo; | 9 | import com.crossoverjie.cim.client.service.impl.ClientInfo; |
| 10 | +import com.crossoverjie.cim.client.thread.ContextHolder; | ||
| 9 | import com.crossoverjie.cim.client.vo.req.GoogleProtocolVO; | 11 | import com.crossoverjie.cim.client.vo.req.GoogleProtocolVO; |
| 10 | import com.crossoverjie.cim.client.vo.req.LoginReqVO; | 12 | import com.crossoverjie.cim.client.vo.req.LoginReqVO; |
| 11 | import com.crossoverjie.cim.client.vo.res.CIMServerResVO; | 13 | import com.crossoverjie.cim.client.vo.res.CIMServerResVO; |
| @@ -66,6 +68,9 @@ public class CIMClient { | @@ -66,6 +68,9 @@ public class CIMClient { | ||
| 66 | @Autowired | 68 | @Autowired |
| 67 | private ClientInfo clientInfo; | 69 | private ClientInfo clientInfo; |
| 68 | 70 | ||
| 71 | + @Autowired | ||
| 72 | + private ReConnectManager reConnectManager ; | ||
| 73 | + | ||
| 69 | /** | 74 | /** |
| 70 | * 重试次数 | 75 | * 重试次数 |
| 71 | */ | 76 | */ |
| @@ -90,7 +95,7 @@ public class CIMClient { | @@ -90,7 +95,7 @@ public class CIMClient { | ||
| 90 | * 启动客户端 | 95 | * 启动客户端 |
| 91 | * | 96 | * |
| 92 | * @param cimServer | 97 | * @param cimServer |
| 93 | - * @throws InterruptedException | 98 | + * @throws Exception |
| 94 | */ | 99 | */ |
| 95 | private void startClient(CIMServerResVO.ServerInfo cimServer) { | 100 | private void startClient(CIMServerResVO.ServerInfo cimServer) { |
| 96 | Bootstrap bootstrap = new Bootstrap(); | 101 | Bootstrap bootstrap = new Bootstrap(); |
| @@ -102,14 +107,14 @@ public class CIMClient { | @@ -102,14 +107,14 @@ public class CIMClient { | ||
| 102 | ChannelFuture future = null; | 107 | ChannelFuture future = null; |
| 103 | try { | 108 | try { |
| 104 | future = bootstrap.connect(cimServer.getIp(), cimServer.getCimServerPort()).sync(); | 109 | future = bootstrap.connect(cimServer.getIp(), cimServer.getCimServerPort()).sync(); |
| 105 | - } catch (InterruptedException e) { | 110 | + } catch (Exception e) { |
| 106 | errorCount++; | 111 | errorCount++; |
| 107 | 112 | ||
| 108 | if (errorCount >= configuration.getErrorCount()) { | 113 | if (errorCount >= configuration.getErrorCount()) { |
| 109 | LOGGER.error("连接失败次数达到上限[{}]次", errorCount); | 114 | LOGGER.error("连接失败次数达到上限[{}]次", errorCount); |
| 110 | msgHandle.shutdown(); | 115 | msgHandle.shutdown(); |
| 111 | } | 116 | } |
| 112 | - LOGGER.error("连接失败", e); | 117 | + LOGGER.error("Connect fail!", e); |
| 113 | } | 118 | } |
| 114 | if (future.isSuccess()) { | 119 | if (future.isSuccess()) { |
| 115 | echoService.echo("Start cim client success!"); | 120 | echoService.echo("Start cim client success!"); |
| @@ -139,7 +144,7 @@ public class CIMClient { | @@ -139,7 +144,7 @@ public class CIMClient { | ||
| 139 | errorCount++; | 144 | errorCount++; |
| 140 | 145 | ||
| 141 | if (errorCount >= configuration.getErrorCount()) { | 146 | if (errorCount >= configuration.getErrorCount()) { |
| 142 | - LOGGER.error("重连次数达到上限[{}]次", errorCount); | 147 | + echoService.echo("The maximum number of reconnections has been reached[{}]times, close cim client!", errorCount); |
| 143 | msgHandle.shutdown(); | 148 | msgHandle.shutdown(); |
| 144 | } | 149 | } |
| 145 | LOGGER.error("login fail", e); | 150 | LOGGER.error("login fail", e); |
| @@ -197,6 +202,13 @@ public class CIMClient { | @@ -197,6 +202,13 @@ public class CIMClient { | ||
| 197 | } | 202 | } |
| 198 | 203 | ||
| 199 | 204 | ||
| 205 | + /** | ||
| 206 | + * 1. clear route information. | ||
| 207 | + * 2. reconnect. | ||
| 208 | + * 3. shutdown reconnect job. | ||
| 209 | + * 4. reset reconnect state. | ||
| 210 | + * @throws Exception | ||
| 211 | + */ | ||
| 200 | public void reconnect() throws Exception { | 212 | public void reconnect() throws Exception { |
| 201 | if (channel != null && channel.isActive()) { | 213 | if (channel != null && channel.isActive()) { |
| 202 | return; | 214 | return; |
| @@ -204,9 +216,11 @@ public class CIMClient { | @@ -204,9 +216,11 @@ public class CIMClient { | ||
| 204 | //首先清除路由信息,下线 | 216 | //首先清除路由信息,下线 |
| 205 | routeRequest.offLine(); | 217 | routeRequest.offLine(); |
| 206 | 218 | ||
| 207 | - LOGGER.info("reconnect...."); | 219 | + echoService.echo("cim server shutdown, reconnecting...."); |
| 208 | start(); | 220 | start(); |
| 209 | - LOGGER.info("reconnect success"); | 221 | + echoService.echo("Great! reConnect success!!!"); |
| 222 | + reConnectManager.reConnectSuccess(); | ||
| 223 | + ContextHolder.clear(); | ||
| 210 | } | 224 | } |
| 211 | 225 | ||
| 212 | /** | 226 | /** |
| @@ -87,7 +87,7 @@ public class BeanConfig { | @@ -87,7 +87,7 @@ public class BeanConfig { | ||
| 87 | @Bean("scheduledTask") | 87 | @Bean("scheduledTask") |
| 88 | public ScheduledExecutorService buildSchedule(){ | 88 | public ScheduledExecutorService buildSchedule(){ |
| 89 | ThreadFactory sche = new ThreadFactoryBuilder() | 89 | ThreadFactory sche = new ThreadFactoryBuilder() |
| 90 | - .setNameFormat("scheduled-%d") | 90 | + .setNameFormat("reConnect-job-%d") |
| 91 | .setDaemon(true) | 91 | .setDaemon(true) |
| 92 | .build(); | 92 | .build(); |
| 93 | ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1,sche) ; | 93 | ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1,sche) ; |
| 1 | package com.crossoverjie.cim.client.handle; | 1 | package com.crossoverjie.cim.client.handle; |
| 2 | 2 | ||
| 3 | import com.crossoverjie.cim.client.service.EchoService; | 3 | import com.crossoverjie.cim.client.service.EchoService; |
| 4 | +import com.crossoverjie.cim.client.service.ReConnectManager; | ||
| 4 | import com.crossoverjie.cim.client.service.ShutDownMsg; | 5 | import com.crossoverjie.cim.client.service.ShutDownMsg; |
| 5 | import com.crossoverjie.cim.client.service.impl.EchoServiceImpl; | 6 | import com.crossoverjie.cim.client.service.impl.EchoServiceImpl; |
| 6 | -import com.crossoverjie.cim.client.thread.ReConnectJob; | ||
| 7 | import com.crossoverjie.cim.client.util.SpringBeanFactory; | 7 | import com.crossoverjie.cim.client.util.SpringBeanFactory; |
| 8 | import com.crossoverjie.cim.common.constant.Constants; | 8 | import com.crossoverjie.cim.common.constant.Constants; |
| 9 | import com.crossoverjie.cim.common.protocol.CIMRequestProto; | 9 | import com.crossoverjie.cim.common.protocol.CIMRequestProto; |
| @@ -21,7 +21,6 @@ import org.slf4j.LoggerFactory; | @@ -21,7 +21,6 @@ import org.slf4j.LoggerFactory; | ||
| 21 | 21 | ||
| 22 | import java.util.concurrent.ScheduledExecutorService; | 22 | import java.util.concurrent.ScheduledExecutorService; |
| 23 | import java.util.concurrent.ThreadPoolExecutor; | 23 | import java.util.concurrent.ThreadPoolExecutor; |
| 24 | -import java.util.concurrent.TimeUnit; | ||
| 25 | 24 | ||
| 26 | /** | 25 | /** |
| 27 | * Function: | 26 | * Function: |
| @@ -41,6 +40,8 @@ public class CIMClientHandle extends SimpleChannelInboundHandler<CIMResponseProt | @@ -41,6 +40,8 @@ public class CIMClientHandle extends SimpleChannelInboundHandler<CIMResponseProt | ||
| 41 | 40 | ||
| 42 | private ScheduledExecutorService scheduledExecutorService ; | 41 | private ScheduledExecutorService scheduledExecutorService ; |
| 43 | 42 | ||
| 43 | + private ReConnectManager reConnectManager ; | ||
| 44 | + | ||
| 44 | private ShutDownMsg shutDownMsg ; | 45 | private ShutDownMsg shutDownMsg ; |
| 45 | 46 | ||
| 46 | private EchoService echoService ; | 47 | private EchoService echoService ; |
| @@ -52,8 +53,6 @@ public class CIMClientHandle extends SimpleChannelInboundHandler<CIMResponseProt | @@ -52,8 +53,6 @@ public class CIMClientHandle extends SimpleChannelInboundHandler<CIMResponseProt | ||
| 52 | if (evt instanceof IdleStateEvent){ | 53 | if (evt instanceof IdleStateEvent){ |
| 53 | IdleStateEvent idleStateEvent = (IdleStateEvent) evt ; | 54 | IdleStateEvent idleStateEvent = (IdleStateEvent) evt ; |
| 54 | 55 | ||
| 55 | - //LOGGER.info("定时检测服务端是否存活"); | ||
| 56 | - | ||
| 57 | if (idleStateEvent.state() == IdleState.WRITER_IDLE){ | 56 | if (idleStateEvent.state() == IdleState.WRITER_IDLE){ |
| 58 | CIMRequestProto.CIMReqProtocol heartBeat = SpringBeanFactory.getBean("heartBeat", | 57 | CIMRequestProto.CIMReqProtocol heartBeat = SpringBeanFactory.getBean("heartBeat", |
| 59 | CIMRequestProto.CIMReqProtocol.class); | 58 | CIMRequestProto.CIMReqProtocol.class); |
| @@ -90,10 +89,11 @@ public class CIMClientHandle extends SimpleChannelInboundHandler<CIMResponseProt | @@ -90,10 +89,11 @@ public class CIMClientHandle extends SimpleChannelInboundHandler<CIMResponseProt | ||
| 90 | 89 | ||
| 91 | if (scheduledExecutorService == null){ | 90 | if (scheduledExecutorService == null){ |
| 92 | scheduledExecutorService = SpringBeanFactory.getBean("scheduledTask",ScheduledExecutorService.class) ; | 91 | scheduledExecutorService = SpringBeanFactory.getBean("scheduledTask",ScheduledExecutorService.class) ; |
| 92 | + reConnectManager = SpringBeanFactory.getBean(ReConnectManager.class) ; | ||
| 93 | } | 93 | } |
| 94 | LOGGER.info("客户端断开了,重新连接!"); | 94 | LOGGER.info("客户端断开了,重新连接!"); |
| 95 | // TODO: 2019-01-22 后期可以改为不用定时任务,连上后就关闭任务 节省性能。 | 95 | // TODO: 2019-01-22 后期可以改为不用定时任务,连上后就关闭任务 节省性能。 |
| 96 | - scheduledExecutorService.scheduleAtFixedRate(new ReConnectJob(ctx),0,10, TimeUnit.SECONDS) ; | 96 | + reConnectManager.reConnect(ctx); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | @Override | 99 | @Override |
| 1 | +package com.crossoverjie.cim.client.service; | ||
| 2 | + | ||
| 3 | +import com.crossoverjie.cim.client.thread.ReConnectJob; | ||
| 4 | +import com.google.common.util.concurrent.ThreadFactoryBuilder; | ||
| 5 | +import io.netty.channel.ChannelHandlerContext; | ||
| 6 | +import org.springframework.stereotype.Component; | ||
| 7 | + | ||
| 8 | +import java.util.concurrent.ScheduledExecutorService; | ||
| 9 | +import java.util.concurrent.ScheduledThreadPoolExecutor; | ||
| 10 | +import java.util.concurrent.ThreadFactory; | ||
| 11 | +import java.util.concurrent.TimeUnit; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * Function: | ||
| 15 | + * | ||
| 16 | + * @author crossoverJie | ||
| 17 | + * Date: 2020-04-15 00:26 | ||
| 18 | + * @since JDK 1.8 | ||
| 19 | + */ | ||
| 20 | +@Component | ||
| 21 | +public final class ReConnectManager { | ||
| 22 | + | ||
| 23 | + private ScheduledExecutorService scheduledExecutorService; | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * Trigger reconnect job | ||
| 27 | + * @param ctx | ||
| 28 | + */ | ||
| 29 | + public void reConnect(ChannelHandlerContext ctx) { | ||
| 30 | + buildExecutor() ; | ||
| 31 | + scheduledExecutorService.scheduleAtFixedRate(new ReConnectJob(ctx),0,10, TimeUnit.SECONDS) ; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * Close reconnect job if reconnect success. | ||
| 36 | + */ | ||
| 37 | + public void reConnectSuccess(){ | ||
| 38 | + scheduledExecutorService.shutdown(); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + /*** | ||
| 43 | + * build an thread executor | ||
| 44 | + * @return | ||
| 45 | + */ | ||
| 46 | + private ScheduledExecutorService buildExecutor() { | ||
| 47 | + if (scheduledExecutorService == null || scheduledExecutorService.isShutdown()) { | ||
| 48 | + ThreadFactory sche = new ThreadFactoryBuilder() | ||
| 49 | + .setNameFormat("reConnect-job-%d") | ||
| 50 | + .setDaemon(true) | ||
| 51 | + .build(); | ||
| 52 | + scheduledExecutorService = new ScheduledThreadPoolExecutor(1, sche); | ||
| 53 | + return scheduledExecutorService; | ||
| 54 | + } else { | ||
| 55 | + return scheduledExecutorService; | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | +} |
| 1 | package com.crossoverjie.cim.client.service.impl; | 1 | package com.crossoverjie.cim.client.service.impl; |
| 2 | 2 | ||
| 3 | import com.crossoverjie.cim.client.client.CIMClient; | 3 | import com.crossoverjie.cim.client.client.CIMClient; |
| 4 | +import com.crossoverjie.cim.client.thread.ContextHolder; | ||
| 4 | import com.crossoverjie.cim.common.kit.HeartBeatHandler; | 5 | import com.crossoverjie.cim.common.kit.HeartBeatHandler; |
| 5 | import io.netty.channel.ChannelHandlerContext; | 6 | import io.netty.channel.ChannelHandlerContext; |
| 6 | import org.slf4j.Logger; | 7 | import org.slf4j.Logger; |
| @@ -28,6 +29,7 @@ public class ClientHeartBeatHandlerImpl implements HeartBeatHandler { | @@ -28,6 +29,7 @@ public class ClientHeartBeatHandlerImpl implements HeartBeatHandler { | ||
| 28 | public void process(ChannelHandlerContext ctx) throws Exception { | 29 | public void process(ChannelHandlerContext ctx) throws Exception { |
| 29 | 30 | ||
| 30 | //重连 | 31 | //重连 |
| 32 | + ContextHolder.setReconnect(true); | ||
| 31 | cimClient.reconnect(); | 33 | cimClient.reconnect(); |
| 32 | 34 | ||
| 33 | } | 35 | } |
| @@ -5,12 +5,14 @@ import com.alibaba.fastjson.JSONObject; | @@ -5,12 +5,14 @@ import com.alibaba.fastjson.JSONObject; | ||
| 5 | import com.crossoverjie.cim.client.config.AppConfiguration; | 5 | import com.crossoverjie.cim.client.config.AppConfiguration; |
| 6 | import com.crossoverjie.cim.client.service.EchoService; | 6 | import com.crossoverjie.cim.client.service.EchoService; |
| 7 | import com.crossoverjie.cim.client.service.RouteRequest; | 7 | import com.crossoverjie.cim.client.service.RouteRequest; |
| 8 | +import com.crossoverjie.cim.client.thread.ContextHolder; | ||
| 8 | import com.crossoverjie.cim.client.vo.req.GroupReqVO; | 9 | import com.crossoverjie.cim.client.vo.req.GroupReqVO; |
| 9 | import com.crossoverjie.cim.client.vo.req.LoginReqVO; | 10 | import com.crossoverjie.cim.client.vo.req.LoginReqVO; |
| 10 | import com.crossoverjie.cim.client.vo.req.P2PReqVO; | 11 | import com.crossoverjie.cim.client.vo.req.P2PReqVO; |
| 11 | import com.crossoverjie.cim.client.vo.res.CIMServerResVO; | 12 | import com.crossoverjie.cim.client.vo.res.CIMServerResVO; |
| 12 | import com.crossoverjie.cim.client.vo.res.OnlineUsersResVO; | 13 | import com.crossoverjie.cim.client.vo.res.OnlineUsersResVO; |
| 13 | import com.crossoverjie.cim.common.enums.StatusEnum; | 14 | import com.crossoverjie.cim.common.enums.StatusEnum; |
| 15 | +import com.crossoverjie.cim.common.exception.CIMException; | ||
| 14 | import com.crossoverjie.cim.common.res.BaseResponse; | 16 | import com.crossoverjie.cim.common.res.BaseResponse; |
| 15 | import okhttp3.*; | 17 | import okhttp3.*; |
| 16 | import org.slf4j.Logger; | 18 | import org.slf4j.Logger; |
| @@ -140,6 +142,13 @@ public class RouteRequestImpl implements RouteRequest { | @@ -140,6 +142,13 @@ public class RouteRequestImpl implements RouteRequest { | ||
| 140 | //重复失败 | 142 | //重复失败 |
| 141 | if (!cimServerResVO.getCode().equals(StatusEnum.SUCCESS.getCode())){ | 143 | if (!cimServerResVO.getCode().equals(StatusEnum.SUCCESS.getCode())){ |
| 142 | echoService.echo(cimServerResVO.getMessage()); | 144 | echoService.echo(cimServerResVO.getMessage()); |
| 145 | + | ||
| 146 | + // when client in reConnect state, could not exit. | ||
| 147 | + if (ContextHolder.getReconnect()){ | ||
| 148 | + echoService.echo("###{}###", StatusEnum.RECONNECT_FAIL.getMessage()); | ||
| 149 | + throw new CIMException(StatusEnum.RECONNECT_FAIL); | ||
| 150 | + } | ||
| 151 | + | ||
| 143 | System.exit(-1); | 152 | System.exit(-1); |
| 144 | } | 153 | } |
| 145 | 154 |
| @@ -37,7 +37,7 @@ public class ShutDownCommand implements InnerCommand { | @@ -37,7 +37,7 @@ public class ShutDownCommand implements InnerCommand { | ||
| 37 | private MsgLogger msgLogger; | 37 | private MsgLogger msgLogger; |
| 38 | 38 | ||
| 39 | @Resource(name = "callBackThreadPool") | 39 | @Resource(name = "callBackThreadPool") |
| 40 | - private ThreadPoolExecutor executor; | 40 | + private ThreadPoolExecutor callBackExecutor; |
| 41 | 41 | ||
| 42 | @Autowired | 42 | @Autowired |
| 43 | private EchoService echoService ; | 43 | private EchoService echoService ; |
| @@ -55,10 +55,10 @@ public class ShutDownCommand implements InnerCommand { | @@ -55,10 +55,10 @@ public class ShutDownCommand implements InnerCommand { | ||
| 55 | shutDownMsg.shutdown(); | 55 | shutDownMsg.shutdown(); |
| 56 | routeRequest.offLine(); | 56 | routeRequest.offLine(); |
| 57 | msgLogger.stop(); | 57 | msgLogger.stop(); |
| 58 | - executor.shutdown(); | 58 | + callBackExecutor.shutdown(); |
| 59 | ringBufferWheel.stop(false); | 59 | ringBufferWheel.stop(false); |
| 60 | try { | 60 | try { |
| 61 | - while (!executor.awaitTermination(1, TimeUnit.SECONDS)) { | 61 | + while (!callBackExecutor.awaitTermination(1, TimeUnit.SECONDS)) { |
| 62 | echoService.echo("thread pool closing"); | 62 | echoService.echo("thread pool closing"); |
| 63 | } | 63 | } |
| 64 | cimClient.close(); | 64 | cimClient.close(); |
| 1 | +package com.crossoverjie.cim.client.thread; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * Function: Something about of client runtime sign. | ||
| 5 | + * | ||
| 6 | + * @author crossoverJie | ||
| 7 | + * Date: 2020-04-13 02:10 | ||
| 8 | + * @since JDK 1.8 | ||
| 9 | + */ | ||
| 10 | +public class ContextHolder { | ||
| 11 | + private static final ThreadLocal<Boolean> IS_RECONNECT = new ThreadLocal<>() ; | ||
| 12 | + | ||
| 13 | + public static void setReconnect(boolean reconnect){ | ||
| 14 | + IS_RECONNECT.set(reconnect); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + public static Boolean getReconnect(){ | ||
| 18 | + return IS_RECONNECT.get() ; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + public static void clear(){ | ||
| 22 | + IS_RECONNECT.remove(); | ||
| 23 | + } | ||
| 24 | +} |
| @@ -27,7 +27,9 @@ public enum StatusEnum { | @@ -27,7 +27,9 @@ public enum StatusEnum { | ||
| 27 | /** 账号不在线 */ | 27 | /** 账号不在线 */ |
| 28 | OFF_LINE("7000", "你选择的账号不在线,请重新选择!"), | 28 | OFF_LINE("7000", "你选择的账号不在线,请重新选择!"), |
| 29 | 29 | ||
| 30 | - SERVER_NOT_AVAILABLE("7100", "CIM server is not available, please try again later!"), | 30 | + SERVER_NOT_AVAILABLE("7100", "cim server is not available, please try again later!"), |
| 31 | + | ||
| 32 | + RECONNECT_FAIL("7200", "reconnect fail, continue to retry!"), | ||
| 31 | 33 | ||
| 32 | /** 登录信息不匹配 */ | 34 | /** 登录信息不匹配 */ |
| 33 | ACCOUNT_NOT_MATCH("9100", "The User information you have used is incorrect!"), | 35 | ACCOUNT_NOT_MATCH("9100", "The User information you have used is incorrect!"), |
| @@ -2,6 +2,8 @@ package com.crossoverjie.cim.route.cache; | @@ -2,6 +2,8 @@ package com.crossoverjie.cim.route.cache; | ||
| 2 | 2 | ||
| 3 | import com.crossoverjie.cim.route.kit.ZKit; | 3 | import com.crossoverjie.cim.route.kit.ZKit; |
| 4 | import com.google.common.cache.LoadingCache; | 4 | import com.google.common.cache.LoadingCache; |
| 5 | +import org.slf4j.Logger; | ||
| 6 | +import org.slf4j.LoggerFactory; | ||
| 5 | import org.springframework.beans.factory.annotation.Autowired; | 7 | import org.springframework.beans.factory.annotation.Autowired; |
| 6 | import org.springframework.stereotype.Component; | 8 | import org.springframework.stereotype.Component; |
| 7 | 9 | ||
| @@ -20,6 +22,7 @@ import java.util.concurrent.atomic.AtomicLong; | @@ -20,6 +22,7 @@ import java.util.concurrent.atomic.AtomicLong; | ||
| 20 | @Component | 22 | @Component |
| 21 | public class ServerCache { | 23 | public class ServerCache { |
| 22 | 24 | ||
| 25 | + private static Logger logger = LoggerFactory.getLogger(ServerCache.class) ; | ||
| 23 | 26 | ||
| 24 | @Autowired | 27 | @Autowired |
| 25 | private LoadingCache<String, String> cache; | 28 | private LoadingCache<String, String> cache; |
| @@ -43,7 +46,13 @@ public class ServerCache { | @@ -43,7 +46,13 @@ public class ServerCache { | ||
| 43 | public void updateCache(List<String> currentChilds) { | 46 | public void updateCache(List<String> currentChilds) { |
| 44 | cache.invalidateAll(); | 47 | cache.invalidateAll(); |
| 45 | for (String currentChild : currentChilds) { | 48 | for (String currentChild : currentChilds) { |
| 46 | - String key = currentChild.split("-")[1]; | 49 | + // currentChild=ip-127.0.0.1:11212:9082 or 127.0.0.1:11212:9082 |
| 50 | + String key ; | ||
| 51 | + if (currentChild.split("-").length == 2){ | ||
| 52 | + key = currentChild.split("-")[1]; | ||
| 53 | + }else { | ||
| 54 | + key = currentChild ; | ||
| 55 | + } | ||
| 47 | addCache(key); | 56 | addCache(key); |
| 48 | } | 57 | } |
| 49 | } | 58 | } |
| @@ -54,7 +63,7 @@ public class ServerCache { | @@ -54,7 +63,7 @@ public class ServerCache { | ||
| 54 | * | 63 | * |
| 55 | * @return | 64 | * @return |
| 56 | */ | 65 | */ |
| 57 | - public List<String> getAll() { | 66 | + public List<String> getServerList() { |
| 58 | 67 | ||
| 59 | List<String> list = new ArrayList<>(); | 68 | List<String> list = new ArrayList<>(); |
| 60 | 69 | ||
| @@ -72,4 +81,11 @@ public class ServerCache { | @@ -72,4 +81,11 @@ public class ServerCache { | ||
| 72 | 81 | ||
| 73 | } | 82 | } |
| 74 | 83 | ||
| 84 | + /** | ||
| 85 | + * rebuild cache list | ||
| 86 | + */ | ||
| 87 | + public void rebuildCacheList(){ | ||
| 88 | + updateCache(getServerList()) ; | ||
| 89 | + } | ||
| 90 | + | ||
| 75 | } | 91 | } |
| @@ -153,7 +153,7 @@ public class RouteController { | @@ -153,7 +153,7 @@ public class RouteController { | ||
| 153 | BaseResponse<CIMServerResVO> res = new BaseResponse(); | 153 | BaseResponse<CIMServerResVO> res = new BaseResponse(); |
| 154 | 154 | ||
| 155 | // check server available | 155 | // check server available |
| 156 | - String server = routeHandle.routeServer(serverCache.getAll(),String.valueOf(loginReqVO.getUserId())); | 156 | + String server = routeHandle.routeServer(serverCache.getServerList(),String.valueOf(loginReqVO.getUserId())); |
| 157 | RouteInfo routeInfo = RouteInfoParseUtil.parse(server); | 157 | RouteInfo routeInfo = RouteInfoParseUtil.parse(server); |
| 158 | commonBizService.checkServerAvailable(routeInfo); | 158 | commonBizService.checkServerAvailable(routeInfo); |
| 159 | 159 |
| @@ -3,7 +3,11 @@ package com.crossoverjie.cim.route.service; | @@ -3,7 +3,11 @@ package com.crossoverjie.cim.route.service; | ||
| 3 | import com.crossoverjie.cim.common.enums.StatusEnum; | 3 | import com.crossoverjie.cim.common.enums.StatusEnum; |
| 4 | import com.crossoverjie.cim.common.exception.CIMException; | 4 | import com.crossoverjie.cim.common.exception.CIMException; |
| 5 | import com.crossoverjie.cim.common.pojo.RouteInfo; | 5 | import com.crossoverjie.cim.common.pojo.RouteInfo; |
| 6 | +import com.crossoverjie.cim.route.cache.ServerCache; | ||
| 6 | import com.crossoverjie.cim.route.kit.NetAddressIsReachable; | 7 | import com.crossoverjie.cim.route.kit.NetAddressIsReachable; |
| 8 | +import org.slf4j.Logger; | ||
| 9 | +import org.slf4j.LoggerFactory; | ||
| 10 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 7 | import org.springframework.stereotype.Component; | 11 | import org.springframework.stereotype.Component; |
| 8 | 12 | ||
| 9 | /** | 13 | /** |
| @@ -15,6 +19,11 @@ import org.springframework.stereotype.Component; | @@ -15,6 +19,11 @@ import org.springframework.stereotype.Component; | ||
| 15 | */ | 19 | */ |
| 16 | @Component | 20 | @Component |
| 17 | public class CommonBizService { | 21 | public class CommonBizService { |
| 22 | + private static Logger logger = LoggerFactory.getLogger(CommonBizService.class) ; | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + @Autowired | ||
| 26 | + private ServerCache serverCache ; | ||
| 18 | 27 | ||
| 19 | /** | 28 | /** |
| 20 | * check ip and port | 29 | * check ip and port |
| @@ -23,6 +32,11 @@ public class CommonBizService { | @@ -23,6 +32,11 @@ public class CommonBizService { | ||
| 23 | public void checkServerAvailable(RouteInfo routeInfo){ | 32 | public void checkServerAvailable(RouteInfo routeInfo){ |
| 24 | boolean reachable = NetAddressIsReachable.checkAddressReachable(routeInfo.getIp(), routeInfo.getCimServerPort(), 1000); | 33 | boolean reachable = NetAddressIsReachable.checkAddressReachable(routeInfo.getIp(), routeInfo.getCimServerPort(), 1000); |
| 25 | if (!reachable) { | 34 | if (!reachable) { |
| 35 | + logger.error("ip={}, port={} are not available", routeInfo.getIp(), routeInfo.getCimServerPort()); | ||
| 36 | + | ||
| 37 | + // rebuild cache | ||
| 38 | + serverCache.rebuildCacheList(); | ||
| 39 | + | ||
| 26 | throw new CIMException(StatusEnum.SERVER_NOT_AVAILABLE) ; | 40 | throw new CIMException(StatusEnum.SERVER_NOT_AVAILABLE) ; |
| 27 | } | 41 | } |
| 28 | 42 |
| @@ -22,19 +22,19 @@ app.zk.connect.timeout=15000 | @@ -22,19 +22,19 @@ app.zk.connect.timeout=15000 | ||
| 22 | app.zk.root=/route | 22 | app.zk.root=/route |
| 23 | 23 | ||
| 24 | #路由策略,轮询 | 24 | #路由策略,轮询 |
| 25 | -#app.route.way=com.crossoverjie.cim.common.route.algorithm.loop.LoopHandle | 25 | +app.route.way=com.crossoverjie.cim.common.route.algorithm.loop.LoopHandle |
| 26 | 26 | ||
| 27 | #路由策略,随机 | 27 | #路由策略,随机 |
| 28 | #app.route.way=com.crossoverjie.cim.common.route.algorithm.random.RandomHandle | 28 | #app.route.way=com.crossoverjie.cim.common.route.algorithm.random.RandomHandle |
| 29 | 29 | ||
| 30 | #路由策略,一致性 hash | 30 | #路由策略,一致性 hash |
| 31 | -app.route.way=com.crossoverjie.cim.common.route.algorithm.consistenthash.ConsistentHashHandle | 31 | +#app.route.way=com.crossoverjie.cim.common.route.algorithm.consistenthash.ConsistentHashHandle |
| 32 | 32 | ||
| 33 | #一致性 hash 算法具体实现--自定义有序 map | 33 | #一致性 hash 算法具体实现--自定义有序 map |
| 34 | #app.route.way.consitenthash=com.crossoverjie.cim.common.route.algorithm.consistenthash.SortArrayMapConsistentHash | 34 | #app.route.way.consitenthash=com.crossoverjie.cim.common.route.algorithm.consistenthash.SortArrayMapConsistentHash |
| 35 | 35 | ||
| 36 | #一致性 hash 算法具体实现--TreeMap | 36 | #一致性 hash 算法具体实现--TreeMap |
| 37 | -app.route.way.consitenthash=com.crossoverjie.cim.common.route.algorithm.consistenthash.TreeMapConsistentHash | 37 | +#app.route.way.consitenthash=com.crossoverjie.cim.common.route.algorithm.consistenthash.TreeMapConsistentHash |
| 38 | 38 | ||
| 39 | # Redis 配置 | 39 | # Redis 配置 |
| 40 | spring.redis.host=xx | 40 | spring.redis.host=xx |
-
请 注册 或 登录 后发表评论