com.github.houbb.config.socket.client.handler.ConfigClientHandler Maven / Gradle / Ivy
/*
* Copyright (c) 2019. houbinbin Inc.
* rpc All rights reserved.
*/
package com.github.houbb.config.socket.client.handler;
import com.alibaba.fastjson.JSON;
import com.github.houbb.config.socket.client.support.channel.ClientChannelManager;
import com.github.houbb.config.socket.client.support.invoke.InvokeService;
import com.github.houbb.config.socket.client.support.listener.ConfigNotifyListener;
import com.github.houbb.config.socket.common.constant.ServiceNameConst;
import com.github.houbb.config.socket.common.req.ConfigNotifyBatchReq;
import com.github.houbb.config.socket.common.req.ConfigNotifyReq;
import com.github.houbb.config.socket.common.rpc.RpcMessageDto;
import com.github.houbb.config.socket.common.util.ChannelUtil;
import com.github.houbb.heaven.util.lang.StringUtil;
import com.github.houbb.log.integration.core.Log;
import com.github.houbb.log.integration.core.LogFactory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* 客户端处理类
*
* TODO: ChannelInboundHandlerAdapter 学习一下对应的方法,然后处理各种场景。
*
* Created: 2019/10/16 11:30 下午
* Project: rpc
*
* @author houbinbin
* @since 0.0.2
*/
public class ConfigClientHandler extends SimpleChannelInboundHandler {
private static final Log log = LogFactory.getLog(ConfigClientHandler.class);
/**
* 调用管理类
*/
private InvokeService invokeService;
/**
* 通知监听类
*/
private ConfigNotifyListener listener;
/**
* 客户端 channel 管理类
* @since 1.5.0
*/
private ClientChannelManager clientChannelManager;
public ConfigClientHandler invokeService(InvokeService invokeService) {
this.invokeService = invokeService;
return this;
}
public ConfigClientHandler listener(ConfigNotifyListener listener) {
this.listener = listener;
return this;
}
public ConfigClientHandler clientChannelManager(ClientChannelManager clientChannelManager) {
this.clientChannelManager = clientChannelManager;
return this;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("客户端注册-----------------------");
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.info("客户端注销-----------------------");
clientChannelManager.unRegister(ctx.channel());
super.channelInactive(ctx);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf)msg;
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
String text = new String(bytes);
log.info("[Client] channelId {} 接收到消息 {}", ChannelUtil.getChannelId(ctx), text);
RpcMessageDto rpcMessageDto = null;
try {
rpcMessageDto = JSON.parseObject(bytes, RpcMessageDto.class);
} catch (Exception exception) {
log.error("RpcMessageDto json 格式转换异常 {}", JSON.parse(bytes));
return;
}
final String methodType = rpcMessageDto.getMethodType();
final String json = rpcMessageDto.getJson();
if(rpcMessageDto.isRequest()) {
// 请求类接口,根据 serviceName 做路由
if(ServiceNameConst.SERVER_CONFIG_NOTIFY.equals(methodType)) {
ConfigNotifyReq notifyReq = JSON.parseObject(json, ConfigNotifyReq.class);
listener.configNotify(notifyReq);
} else if(ServiceNameConst.SERVER_CONFIG_NOTIFY_BATCH.equals(methodType)) {
ConfigNotifyBatchReq notifyReq = JSON.parseObject(json, ConfigNotifyBatchReq.class);
listener.configNotifyBatch(notifyReq);
} else {
log.warn("不支持的方法类型 {}", methodType);
}
} else {
// 丢弃掉 traceId 为空的信息
if(StringUtil.isBlank(rpcMessageDto.getTraceId())) {
log.info("[Server] response traceId 为空,直接丢弃", JSON.toJSON(rpcMessageDto));
return;
}
invokeService.addResponse(rpcMessageDto.getTraceId(), rpcMessageDto);
log.info("[Client] response is :{}", JSON.toJSON(rpcMessageDto));
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// 每一次如果都关闭,会导致长链接丢失。
// 最简单的方法是保持不关闭。
// 同时把服务端,当做注册中心。当然,也可以单独写一个注册中心。
String id = ChannelUtil.getChannelId(ctx.channel());
log.error("[Rpc client] {} meet ex", id, cause);
ctx.flush();
// ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// 每次用完要关闭,不然拿不到response,我也不知道为啥(目测得了解netty才行)
// 个人理解:如果不关闭,则永远会被阻塞。
ctx.flush();
// ctx.close();
final String id = ChannelUtil.getChannelId(ctx.channel());
log.info("{} channelReadComplete", id);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy