refactor(canal): 升级JVM参数 (#5544)

- 重点升级JVM参数

- 重构SessionHandler代码, 处理错误请求会响应两次包;
This commit is contained in:
sunxien
2026-01-28 11:20:19 +08:00
committed by GitHub
parent c0619c4217
commit dcea8afc93
4 changed files with 147 additions and 154 deletions

View File

@@ -59,24 +59,34 @@ in
exit;; exit;;
esac esac
JavaVersion=`$JAVA -version 2>&1 |awk 'NR==1{ gsub(/"/,""); print $3 }' | awk -F '.' '{print $1}'` JAVA_VERSION=`$JAVA -version 2>&1 |awk 'NR==1{ gsub(/"/,""); print $3 }' | awk -F '.' '{print $1}'`
str=`file -L $JAVA | grep 64-bit`
JAVA_OPTS="$JAVA_OPTS -Xss1m -XX:+AggressiveOpts -XX:-UseBiasedLocking -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$base/logs" JAVA_OPTS="$JAVA_OPTS -Xss1m -XX:+AggressiveOpts -XX:-UseBiasedLocking -XX:-OmitStackTraceInFastThrow"
if [ $JavaVersion -ge 11 ] ; then JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$base/logs"
if [ $JAVA_VERSION -ge 11 ] ; then
#JAVA_OPTS="$JAVA_OPTS -Xlog:gc*:$base_log/gc.log:time " #JAVA_OPTS="$JAVA_OPTS -Xlog:gc*:$base_log/gc.log:time "
JAVA_OPTS="$JAVA_OPTS" JAVA_OPTS="$JAVA_OPTS -Xlog:gc*:file=$base/logs/adapter/gc.log::filecount=5,filesize=32M"
else else
#JAVA_OPTS="$JAVA_OPTS -Xloggc:$base/logs/canal/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime" JAVA_OPTS="$JAVA_OPTS -Xloggc:$base/logs/canal/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=32M"
JAVA_OPTS="$JAVA_OPTS -XX:+UseFastAccessorMethods -XX:+PrintAdaptiveSizePolicy -XX:+PrintTenuringDistribution" JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:-PrintHeapAtGC -XX:+PrintGCApplicationStoppedTime"
JAVA_OPTS="$JAVA_OPTS -XX:+UseFastAccessorMethods -XX:-PrintReferenceGC -XX:+PrintAdaptiveSizePolicy -XX:+PrintTenuringDistribution"
JAVA_OPTS="$JAVA_OPTS -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1 -XX:+SafepointTimeout -XX:SafepointTimeoutDelay=2000"
JAVA_OPTS="$JAVA_OPTS -XX:+UseCountedLoopSafepoints -XX:+DisableExplicitGC -XX:+ExplicitGCInvokesConcurrent -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses"
fi fi
if [ -n "$str" ]; then OS_ARCH=`file -L $JAVA | grep 64-bit`
if [ $JavaVersion -ge 11 ] ; then if [ -n "$OS_ARCH" ]; then
if [ $JAVA_VERSION -ge 11 ] ; then
# For G1 # For G1
JAVA_OPTS="-server -Xms2g -Xmx3g -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:+UseGCOverheadLimit -XX:+ExplicitGCInvokesConcurrent $JAVA_OPTS" JAVA_OPTS="-server -Xms2g -Xmx3g -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:+UseGCOverheadLimit -XX:+ExplicitGCInvokesConcurrent $JAVA_OPTS"
else else
JAVA_OPTS="-server -Xms2g -Xmx3g -Xmn1g -XX:SurvivorRatio=2 -XX:PermSize=96m -XX:MaxPermSize=256m -XX:MaxTenuringThreshold=15 -XX:+DisableExplicitGC $JAVA_OPTS" # JAVA_OPTS="-server -Xms2g -Xmx3g -Xmn1g -XX:SurvivorRatio=2 -XX:PermSize=96m -XX:MaxPermSize=256m -XX:MaxTenuringThreshold=15 -XX:+DisableExplicitGC $JAVA_OPTS"
## JDK 1.8 2c4g [-XX:ConcGCThreads=1 -XX:ParallelGCThreads=2], 4c8g [-XX:ConcGCThreads=2 -XX:ParallelGCThreads=4]
JAVA_OPTS="$JAVA_OPTS -XX:InitialRAMPercentage=45.0 -XX:MinRAMPercentage=45.0 -XX:MaxRAMPercentage=45.0"
JAVA_OPTS="$JAVA_OPTS -XX:-UseParallelGC -XX:+UseConcMarkSweepGC -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4"
JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70"
JAVA_OPTS="-server -XX:NewRatio=1 -XX:SurvivorRatio=2 -XX:MetaspaceSize=96m -XX:MaxMetaspaceSize=128m "
fi fi
else else
JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=128m $JAVA_OPTS" JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=128m $JAVA_OPTS"

View File

@@ -83,24 +83,35 @@ in
exit;; exit;;
esac esac
JavaVersion=`$JAVA -version 2>&1 |awk 'NR==1{ gsub(/"/,""); print $3 }' | awk -F '.' '{print $1}'` JAVA_VERSION=`$JAVA -version 2>&1 |awk 'NR==1{ gsub(/"/,""); print $3 }' | awk -F '.' '{print $1}'`
str=`file -L $JAVA | grep 64-bit`
JAVA_OPTS="$JAVA_OPTS -Xss1m -XX:-UseBiasedLocking -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$base/logs"
if [ $JavaVersion -ge 11 ] ; then JAVA_OPTS="$JAVA_OPTS -Xss1m -XX:+AggressiveOpts -XX:-UseBiasedLocking -XX:-OmitStackTraceInFastThrow"
JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$base/logs"
if [ $JAVA_VERSION -ge 11 ] ; then
#JAVA_OPTS="$JAVA_OPTS -Xlog:gc*:$base_log/gc.log:time " #JAVA_OPTS="$JAVA_OPTS -Xlog:gc*:$base_log/gc.log:time "
JAVA_OPTS="$JAVA_OPTS" JAVA_OPTS="$JAVA_OPTS -Xlog:gc*:file=$base/logs/adapter/gc.log::filecount=5,filesize=32M"
else else
#JAVA_OPTS="$JAVA_OPTS -Xloggc:$base/logs/canal/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime" JAVA_OPTS="$JAVA_OPTS -Xloggc:$base/logs/canal/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=32M"
JAVA_OPTS="$JAVA_OPTS -XX:+AggressiveOpts -XX:+UseFastAccessorMethods -XX:+PrintAdaptiveSizePolicy -XX:+PrintTenuringDistribution" JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:-PrintHeapAtGC -XX:+PrintGCApplicationStoppedTime"
JAVA_OPTS="$JAVA_OPTS -XX:+UseFastAccessorMethods -XX:-PrintReferenceGC -XX:+PrintAdaptiveSizePolicy -XX:+PrintTenuringDistribution"
JAVA_OPTS="$JAVA_OPTS -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1 -XX:+SafepointTimeout -XX:SafepointTimeoutDelay=2000"
JAVA_OPTS="$JAVA_OPTS -XX:+UseCountedLoopSafepoints -XX:+DisableExplicitGC -XX:+ExplicitGCInvokesConcurrent -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses"
fi fi
if [ -n "$str" ]; then OS_ARCH=`file -L $JAVA | grep 64-bit`
if [ $JavaVersion -ge 11 ] ; then
if [ -n "$OS_ARCH" ]; then
if [ $JAVA_VERSION -ge 11 ] ; then
# For G1 # For G1
JAVA_OPTS="-server -Xms2g -Xmx3g -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:+UseGCOverheadLimit -XX:+ExplicitGCInvokesConcurrent $JAVA_OPTS" JAVA_OPTS="-server -Xms2g -Xmx3g -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:+UseGCOverheadLimit -XX:+ExplicitGCInvokesConcurrent $JAVA_OPTS"
else else
JAVA_OPTS="-server -Xms2g -Xmx3g -Xmn1g -XX:SurvivorRatio=2 -XX:PermSize=96m -XX:MaxPermSize=256m -XX:MaxTenuringThreshold=15 -XX:+DisableExplicitGC $JAVA_OPTS" # JAVA_OPTS="-server -Xms2g -Xmx3g -Xmn1g -XX:SurvivorRatio=2 -XX:PermSize=96m -XX:MaxPermSize=256m -XX:MaxTenuringThreshold=15 -XX:+DisableExplicitGC $JAVA_OPTS"
## JDK 1.8 2c4g [-XX:ConcGCThreads=1 -XX:ParallelGCThreads=2], 4c8g [-XX:ConcGCThreads=2 -XX:ParallelGCThreads=4]
JAVA_OPTS="$JAVA_OPTS -XX:InitialRAMPercentage=45.0 -XX:MinRAMPercentage=45.0 -XX:MaxRAMPercentage=45.0"
JAVA_OPTS="$JAVA_OPTS -XX:-UseParallelGC -XX:+UseConcMarkSweepGC -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4"
JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70"
JAVA_OPTS="-server -XX:NewRatio=1 -XX:SurvivorRatio=2 -XX:MetaspaceSize=96m -XX:MaxMetaspaceSize=128m "
fi fi
else else
JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=128m $JAVA_OPTS" JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=128m $JAVA_OPTS"

View File

@@ -31,127 +31,114 @@ public class SessionHandler extends SimpleChannelHandler {
} }
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
logger.info("message receives in session handler...");
ChannelBuffer buffer = (ChannelBuffer) e.getMessage(); ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
Packet packet = Packet.parseFrom(buffer.readBytes(buffer.readableBytes()).array()); Packet packet = Packet.parseFrom(buffer.readBytes(buffer.readableBytes()).array());
try { try {
String action = null;
String message = null;
String destination = null;
switch (packet.getType()) { switch (packet.getType()) {
case SERVER: case SERVER:
ServerAdmin serverAdmin = ServerAdmin.parseFrom(packet.getBody()); ServerAdmin sa = ServerAdmin.parseFrom(packet.getBody());
action = serverAdmin.getAction(); logger.info("received {} SERVER request in session handler...", sa.getAction());
switch (action) { byte[] svrResp = null;
switch (sa.getAction()) {
case "check": case "check":
message = canalAdmin.check() ? "1" : "0"; svrResp = AdminNettyUtils.ackPacket(canalAdmin.check() ? "1" : "0");
break; break;
case "start": case "start":
message = canalAdmin.start() ? "1" : "0"; svrResp = AdminNettyUtils.ackPacket(canalAdmin.start() ? "1" : "0");
break; break;
case "stop": case "stop":
message = canalAdmin.stop() ? "1" : "0"; svrResp = AdminNettyUtils.ackPacket(canalAdmin.stop() ? "1" : "0");
break; break;
case "restart": case "restart":
message = canalAdmin.restart() ? "1" : "0"; svrResp = AdminNettyUtils.ackPacket(canalAdmin.restart() ? "1" : "0");
break; break;
case "list": case "list":
message = canalAdmin.getRunningInstances(); svrResp = AdminNettyUtils.ackPacket(canalAdmin.getRunningInstances());
break; break;
default: default:
byte[] errorBytes = AdminNettyUtils.errorPacket(301, svrResp = AdminNettyUtils.errorPacket(301, "ServerAdmin action: " + sa.getAction() + " is unknown");
MessageFormatter.format("ServerAdmin action={} is unknown", action).getMessage());
AdminNettyUtils.write(ctx.getChannel(), errorBytes);
break; break;
} }
AdminNettyUtils.write(ctx.getChannel(), AdminNettyUtils.ackPacket(message)); AdminNettyUtils.write(ctx.getChannel(), svrResp);
break; break;
case INSTANCE: case INSTANCE:
InstanceAdmin instanceAdmin = InstanceAdmin.parseFrom(packet.getBody()); InstanceAdmin ia = InstanceAdmin.parseFrom(packet.getBody());
destination = instanceAdmin.getDestination(); logger.info("received {} INSTANCE request in session handler...", ia.getAction());
action = instanceAdmin.getAction(); byte[] instResp = null;
switch (action) { switch (ia.getAction()) {
case "check": case "check":
message = canalAdmin.checkInstance(destination) ? "1" : "0"; instResp = AdminNettyUtils.ackPacket(canalAdmin.checkInstance(ia.getDestination()) ? "1" : "0");
break; break;
case "start": case "start":
message = canalAdmin.startInstance(destination) ? "1" : "0"; instResp = AdminNettyUtils.ackPacket(canalAdmin.startInstance(ia.getDestination()) ? "1" : "0");
break; break;
case "stop": case "stop":
message = canalAdmin.stopInstance(destination) ? "1" : "0"; instResp = AdminNettyUtils.ackPacket(canalAdmin.stopInstance(ia.getDestination()) ? "1" : "0");
break; break;
case "release": case "release":
message = canalAdmin.releaseInstance(destination) ? "1" : "0"; instResp = AdminNettyUtils.ackPacket(canalAdmin.releaseInstance(ia.getDestination()) ? "1" : "0");
break; break;
case "restart": case "restart":
message = canalAdmin.restartInstance(destination) ? "1" : "0"; instResp = AdminNettyUtils.ackPacket(canalAdmin.restartInstance(ia.getDestination()) ? "1" : "0");
break; break;
default: default:
byte[] errorBytes = AdminNettyUtils.errorPacket(301, instResp = AdminNettyUtils.errorPacket(301, "InstanceAdmin action: " + ia.getAction() + " is unknown");
MessageFormatter.format("InstanceAdmin action={} is unknown", action).getMessage());
AdminNettyUtils.write(ctx.getChannel(), errorBytes);
break; break;
} }
AdminNettyUtils.write(ctx.getChannel(), AdminNettyUtils.ackPacket(message)); AdminNettyUtils.write(ctx.getChannel(), instResp);
break; break;
case LOG: case LOG:
LogAdmin logAdmin = LogAdmin.parseFrom(packet.getBody()); LogAdmin la = LogAdmin.parseFrom(packet.getBody());
action = logAdmin.getAction(); logger.info("received {} LOG request in session handler...", la.getType());
destination = logAdmin.getDestination(); byte[] logResp = null;
String type = logAdmin.getType(); switch (la.getType()) {
String file = logAdmin.getFile();
int count = logAdmin.getCount();
switch (type) {
case "server": case "server":
if ("list".equalsIgnoreCase(action)) { if ("list".equalsIgnoreCase(la.getAction())) {
message = canalAdmin.listCanalLog(); logResp = AdminNettyUtils.ackPacket(canalAdmin.listCanalLog());
} else { } else {
message = canalAdmin.canalLog(count); logResp = AdminNettyUtils.ackPacket(canalAdmin.canalLog(la.getCount()));
} }
break; break;
case "instance": case "instance":
if ("list".equalsIgnoreCase(action)) { if ("list".equalsIgnoreCase(la.getAction())) {
message = canalAdmin.listInstanceLog(destination); logResp = AdminNettyUtils.ackPacket(canalAdmin.listInstanceLog(la.getDestination()));
} else { } else {
message = canalAdmin.instanceLog(destination, file, count); logResp = AdminNettyUtils.ackPacket(canalAdmin.instanceLog(la.getDestination(), la.getFile(), la.getCount()));
} }
break; break;
default: default:
byte[] errorBytes = AdminNettyUtils.errorPacket(301, logResp = AdminNettyUtils.errorPacket(301, "LogAdmin type: " + la.getType() + " is unknown");
MessageFormatter.format("LogAdmin type={} is unknown", type).getMessage());
AdminNettyUtils.write(ctx.getChannel(), errorBytes);
break; break;
} }
AdminNettyUtils.write(ctx.getChannel(), AdminNettyUtils.ackPacket(message)); AdminNettyUtils.write(ctx.getChannel(), logResp);
break; break;
default: default:
byte[] errorBytes = AdminNettyUtils.errorPacket(300, logResp = AdminNettyUtils.errorPacket(300, "packet type: " + packet.getType() + " is NOT supported!");
MessageFormatter.format("packet type={} is NOT supported!", packet.getType()).getMessage()); AdminNettyUtils.write(ctx.getChannel(), logResp);
AdminNettyUtils.write(ctx.getChannel(), errorBytes);
break; break;
} }
} catch (Throwable exception) { } catch (Throwable exception) {
byte[] errorBytes = AdminNettyUtils.errorPacket(400, String error = "something goes wrong with channel: " + ctx.getChannel() + ", exception: "+ ExceptionUtils.getStackTrace(exception);
MessageFormatter.format("something goes wrong with channel:{}, exception={}", AdminNettyUtils.write(ctx.getChannel(), AdminNettyUtils.errorPacket(400, error));
ctx.getChannel(),
ExceptionUtils.getStackTrace(exception)).getMessage());
AdminNettyUtils.write(ctx.getChannel(), errorBytes);
} }
} }
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { // public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
logger.error("something goes wrong with channel:{}, exception={}", // logger.error("something goes wrong with channel:{}, exception={}",
ctx.getChannel(), // ctx.getChannel(),
ExceptionUtils.getStackTrace(e.getCause())); // ExceptionUtils.getStackTrace(e.getCause()));
// ctx.getChannel().close();
ctx.getChannel().close(); // }
} //
// public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { // }
} //
// public void setCanalAdmin(CanalAdmin canalAdmin) {
public void setCanalAdmin(CanalAdmin canalAdmin) { // this.canalAdmin = canalAdmin;
this.canalAdmin = canalAdmin; // }
}
} }

View File

@@ -52,19 +52,15 @@ public class SessionHandler extends SimpleChannelHandler {
@SuppressWarnings({ "deprecation" }) @SuppressWarnings({ "deprecation" })
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
logger.info("message receives in session handler...");
long start = System.nanoTime(); long start = System.nanoTime();
ChannelBuffer buffer = (ChannelBuffer) e.getMessage(); ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
Packet packet = Packet.parseFrom(buffer.readBytes(buffer.readableBytes()).array()); Packet packet = Packet.parseFrom(buffer.readBytes(buffer.readableBytes()).array());
ClientIdentity clientIdentity = null;
try { try {
switch (packet.getType()) { switch (packet.getType()) {
case SUBSCRIPTION: case SUBSCRIPTION:
Sub sub = Sub.parseFrom(packet.getBody()); Sub sub = Sub.parseFrom(packet.getBody());
if (StringUtils.isNotEmpty(sub.getDestination()) && StringUtils.isNotEmpty(sub.getClientId())) { if (StringUtils.isNotEmpty(sub.getDestination()) && StringUtils.isNotEmpty(sub.getClientId())) {
clientIdentity = new ClientIdentity(sub.getDestination(), ClientIdentity clientIdentity = new ClientIdentity(sub.getDestination(), Short.parseShort(sub.getClientId()), sub.getFilter());
Short.valueOf(sub.getClientId()),
sub.getFilter());
MDC.put("destination", clientIdentity.getDestination()); MDC.put("destination", clientIdentity.getDestination());
// 尝试启动,如果已经启动,忽略 // 尝试启动,如果已经启动,忽略
@@ -84,8 +80,7 @@ public class SessionHandler extends SimpleChannelHandler {
ackBytes.length, ackBytes.length,
System.nanoTime() - start)); System.nanoTime() - start));
} else { } else {
byte[] errorBytes = NettyUtils.errorPacket(401, byte[] errorBytes = NettyUtils.errorPacket(401, "destination or clientId is null. Sub: " + sub);
MessageFormatter.format("destination or clientId is null", sub.toString()).getMessage());
NettyUtils.write(ctx.getChannel(), NettyUtils.write(ctx.getChannel(),
errorBytes, errorBytes,
new ChannelFutureAggregator(sub.getDestination(), new ChannelFutureAggregator(sub.getDestination(),
@@ -99,12 +94,12 @@ public class SessionHandler extends SimpleChannelHandler {
case UNSUBSCRIPTION: case UNSUBSCRIPTION:
Unsub unsub = Unsub.parseFrom(packet.getBody()); Unsub unsub = Unsub.parseFrom(packet.getBody());
if (StringUtils.isNotEmpty(unsub.getDestination()) && StringUtils.isNotEmpty(unsub.getClientId())) { if (StringUtils.isNotEmpty(unsub.getDestination()) && StringUtils.isNotEmpty(unsub.getClientId())) {
clientIdentity = new ClientIdentity(unsub.getDestination(), ClientIdentity clientIdentity = new ClientIdentity(unsub.getDestination(), Short.parseShort(unsub.getClientId()), unsub.getFilter());
Short.valueOf(unsub.getClientId()),
unsub.getFilter());
MDC.put("destination", clientIdentity.getDestination()); MDC.put("destination", clientIdentity.getDestination());
embeddedServer.unsubscribe(clientIdentity); embeddedServer.unsubscribe(clientIdentity);
stopCanalInstanceIfNecessary(clientIdentity);// 尝试关闭 stopCanalInstanceIfNecessary(clientIdentity);// 尝试关闭
byte[] ackBytes = NettyUtils.ackPacket(); byte[] ackBytes = NettyUtils.ackPacket();
NettyUtils.write(ctx.getChannel(), NettyUtils.write(ctx.getChannel(),
ackBytes, ackBytes,
@@ -114,8 +109,8 @@ public class SessionHandler extends SimpleChannelHandler {
ackBytes.length, ackBytes.length,
System.nanoTime() - start)); System.nanoTime() - start));
} else { } else {
byte[] errorBytes = NettyUtils.errorPacket(401, String error = "destination or clientId is null. Unsub: " + unsub;
MessageFormatter.format("destination or clientId is null", unsub.toString()).getMessage()); byte[] errorBytes = NettyUtils.errorPacket(401, error);
NettyUtils.write(ctx.getChannel(), NettyUtils.write(ctx.getChannel(),
errorBytes, errorBytes,
new ChannelFutureAggregator(unsub.getDestination(), new ChannelFutureAggregator(unsub.getDestination(),
@@ -129,8 +124,9 @@ public class SessionHandler extends SimpleChannelHandler {
case GET: case GET:
Get get = CanalPacket.Get.parseFrom(packet.getBody()); Get get = CanalPacket.Get.parseFrom(packet.getBody());
if (StringUtils.isNotEmpty(get.getDestination()) && StringUtils.isNotEmpty(get.getClientId())) { if (StringUtils.isNotEmpty(get.getDestination()) && StringUtils.isNotEmpty(get.getClientId())) {
clientIdentity = new ClientIdentity(get.getDestination(), Short.valueOf(get.getClientId())); ClientIdentity clientIdentity = new ClientIdentity(get.getDestination(), Short.parseShort(get.getClientId()));
MDC.put("destination", clientIdentity.getDestination()); MDC.put("destination", clientIdentity.getDestination());
Message message = null; Message message = null;
// if (get.getAutoAck()) { // if (get.getAutoAck()) {
@@ -147,10 +143,7 @@ public class SessionHandler extends SimpleChannelHandler {
message = embeddedServer.getWithoutAck(clientIdentity, get.getFetchSize()); message = embeddedServer.getWithoutAck(clientIdentity, get.getFetchSize());
} else { } else {
TimeUnit unit = convertTimeUnit(get.getUnit()); TimeUnit unit = convertTimeUnit(get.getUnit());
message = embeddedServer.getWithoutAck(clientIdentity, message = embeddedServer.getWithoutAck(clientIdentity, get.getFetchSize(), get.getTimeout(), unit);
get.getFetchSize(),
get.getTimeout(),
unit);
} }
// } // }
@@ -165,7 +158,9 @@ public class SessionHandler extends SimpleChannelHandler {
dataSize += CodedOutputStream.computeBytesSizeNoTag(rowEntry); dataSize += CodedOutputStream.computeBytesSizeNoTag(rowEntry);
} }
messageSize += dataSize; messageSize += dataSize;
messageSize += 1 * rowEntries.size(); // messageSize += 1 * rowEntries.size();
messageSize += rowEntries.size();
// packet size // packet size
int size = 0; int size = 0;
size += com.google.protobuf.CodedOutputStream.computeEnumSize(3, size += com.google.protobuf.CodedOutputStream.computeEnumSize(3,
@@ -173,6 +168,7 @@ public class SessionHandler extends SimpleChannelHandler {
size += com.google.protobuf.CodedOutputStream.computeTagSize(5) size += com.google.protobuf.CodedOutputStream.computeTagSize(5)
+ com.google.protobuf.CodedOutputStream.computeRawVarint32Size(messageSize) + com.google.protobuf.CodedOutputStream.computeRawVarint32Size(messageSize)
+ messageSize; + messageSize;
// recyle bytes // recyle bytes
// ByteBuffer byteBuffer = (ByteBuffer) // ByteBuffer byteBuffer = (ByteBuffer)
// ctx.getAttachment(); // ctx.getAttachment();
@@ -210,9 +206,6 @@ public class SessionHandler extends SimpleChannelHandler {
// NettyUtils.write(ctx.getChannel(), byteBuffer, // NettyUtils.write(ctx.getChannel(), byteBuffer,
// null); // null);
} else { } else {
Packet.Builder packetBuilder = CanalPacket.Packet.newBuilder();
packetBuilder.setType(PacketType.MESSAGES).setVersion(NettyUtils.VERSION);
Messages.Builder messageBuilder = CanalPacket.Messages.newBuilder(); Messages.Builder messageBuilder = CanalPacket.Messages.newBuilder();
messageBuilder.setBatchId(message.getId()); messageBuilder.setBatchId(message.getId());
if (message.getId() != -1) { if (message.getId() != -1) {
@@ -224,9 +217,10 @@ public class SessionHandler extends SimpleChannelHandler {
} }
} }
} }
byte[] body = packetBuilder.setBody(messageBuilder.build().toByteString())
.build() Packet.Builder packetBuilder = CanalPacket.Packet.newBuilder();
.toByteArray(); packetBuilder.setType(PacketType.MESSAGES).setVersion(NettyUtils.VERSION);
byte[] body = packetBuilder.setBody(messageBuilder.build().toByteString()).build().toByteArray();
NettyUtils.write(ctx.getChannel(), body, new ChannelFutureAggregator(get.getDestination(), NettyUtils.write(ctx.getChannel(), body, new ChannelFutureAggregator(get.getDestination(),
get, get,
packet.getType(), packet.getType(),
@@ -235,8 +229,7 @@ public class SessionHandler extends SimpleChannelHandler {
message.getId() == -1));// 输出数据 message.getId() == -1));// 输出数据
} }
} else { } else {
byte[] errorBytes = NettyUtils.errorPacket(401, byte[] errorBytes = NettyUtils.errorPacket(401, "destination or clientId is null. Get: " + get);
MessageFormatter.format("destination or clientId is null", get.toString()).getMessage());
NettyUtils.write(ctx.getChannel(), NettyUtils.write(ctx.getChannel(),
errorBytes, errorBytes,
new ChannelFutureAggregator(get.getDestination(), new ChannelFutureAggregator(get.getDestination(),
@@ -249,11 +242,10 @@ public class SessionHandler extends SimpleChannelHandler {
break; break;
case CLIENTACK: case CLIENTACK:
ClientAck ack = CanalPacket.ClientAck.parseFrom(packet.getBody()); ClientAck ack = CanalPacket.ClientAck.parseFrom(packet.getBody());
MDC.put("destination", ack.getDestination());
if (StringUtils.isNotEmpty(ack.getDestination()) && StringUtils.isNotEmpty(ack.getClientId())) { if (StringUtils.isNotEmpty(ack.getDestination()) && StringUtils.isNotEmpty(ack.getClientId())) {
MDC.put("destination", ack.getDestination());
if (ack.getBatchId() == 0L) { if (ack.getBatchId() == 0L) {
byte[] errorBytes = NettyUtils.errorPacket(402, byte[] errorBytes = NettyUtils.errorPacket(402, "batchId should assign value. Ack: "+ack);
MessageFormatter.format("batchId should assign value", ack.toString()).getMessage());
NettyUtils.write(ctx.getChannel(), NettyUtils.write(ctx.getChannel(),
errorBytes, errorBytes,
new ChannelFutureAggregator(ack.getDestination(), new ChannelFutureAggregator(ack.getDestination(),
@@ -265,7 +257,7 @@ public class SessionHandler extends SimpleChannelHandler {
} else if (ack.getBatchId() == -1L) { // -1代表上一次get没有数据,直接忽略之 } else if (ack.getBatchId() == -1L) { // -1代表上一次get没有数据,直接忽略之
// donothing // donothing
} else { } else {
clientIdentity = new ClientIdentity(ack.getDestination(), Short.valueOf(ack.getClientId())); ClientIdentity clientIdentity = new ClientIdentity(ack.getDestination(), Short.parseShort(ack.getClientId()));
embeddedServer.ack(clientIdentity, ack.getBatchId()); embeddedServer.ack(clientIdentity, ack.getBatchId());
new ChannelFutureAggregator(ack.getDestination(), new ChannelFutureAggregator(ack.getDestination(),
ack, ack,
@@ -274,8 +266,7 @@ public class SessionHandler extends SimpleChannelHandler {
System.nanoTime() - start).operationComplete(null); System.nanoTime() - start).operationComplete(null);
} }
} else { } else {
byte[] errorBytes = NettyUtils.errorPacket(401, byte[] errorBytes = NettyUtils.errorPacket(401, "destination or clientId is null. Ack: " + ack);
MessageFormatter.format("destination or clientId is null", ack.toString()).getMessage());
NettyUtils.write(ctx.getChannel(), NettyUtils.write(ctx.getChannel(),
errorBytes, errorBytes,
new ChannelFutureAggregator(ack.getDestination(), new ChannelFutureAggregator(ack.getDestination(),
@@ -288,25 +279,23 @@ public class SessionHandler extends SimpleChannelHandler {
break; break;
case CLIENTROLLBACK: case CLIENTROLLBACK:
ClientRollback rollback = CanalPacket.ClientRollback.parseFrom(packet.getBody()); ClientRollback rollback = CanalPacket.ClientRollback.parseFrom(packet.getBody());
MDC.put("destination", rollback.getDestination()); if (StringUtils.isNotEmpty(rollback.getDestination()) && StringUtils.isNotEmpty(rollback.getClientId())) {
if (StringUtils.isNotEmpty(rollback.getDestination()) ClientIdentity clientIdentity = new ClientIdentity(rollback.getDestination(), Short.parseShort(rollback.getClientId()));
&& StringUtils.isNotEmpty(rollback.getClientId())) { MDC.put("destination", rollback.getDestination());
clientIdentity = new ClientIdentity(rollback.getDestination(),
Short.valueOf(rollback.getClientId()));
if (rollback.getBatchId() == 0L) { if (rollback.getBatchId() == 0L) {
embeddedServer.rollback(clientIdentity);// 回滚所有批次 embeddedServer.rollback(clientIdentity);// 回滚所有批次
} else { } else {
embeddedServer.rollback(clientIdentity, rollback.getBatchId()); // 只回滚单个批次 embeddedServer.rollback(clientIdentity, rollback.getBatchId()); // 只回滚单个批次
} }
new ChannelFutureAggregator(rollback.getDestination(), new ChannelFutureAggregator(rollback.getDestination(),
rollback, rollback,
packet.getType(), packet.getType(),
0, 0,
System.nanoTime() - start).operationComplete(null); System.nanoTime() - start).operationComplete(null);
} else { } else {
byte[] errorBytes = NettyUtils.errorPacket(401, byte[] errorBytes = NettyUtils.errorPacket(401, "destination or clientId is null. Rollback: " + rollback);
MessageFormatter.format("destination or clientId is null", rollback.toString())
.getMessage());
NettyUtils.write(ctx.getChannel(), NettyUtils.write(ctx.getChannel(),
errorBytes, errorBytes,
new ChannelFutureAggregator(rollback.getDestination(), new ChannelFutureAggregator(rollback.getDestination(),
@@ -318,42 +307,38 @@ public class SessionHandler extends SimpleChannelHandler {
} }
break; break;
default: default:
byte[] errorBytes = NettyUtils.errorPacket(400, byte[] errorBytes = NettyUtils.errorPacket(400, "packet type: " + packet.getType() + " is NOT supported!");
MessageFormatter.format("packet type={} is NOT supported!", packet.getType()).getMessage());
NettyUtils.write(ctx.getChannel(), errorBytes, new ChannelFutureAggregator(ctx.getChannel() NettyUtils.write(ctx.getChannel(), errorBytes, new ChannelFutureAggregator(ctx.getChannel()
.getRemoteAddress() .getRemoteAddress()
.toString(), null, packet.getType(), errorBytes.length, System.nanoTime() - start, (short) 400)); .toString(), null, packet.getType(), errorBytes.length, System.nanoTime() - start, (short) 400));
break; break;
} }
} catch (Throwable exception) { } catch (Throwable exception) {
byte[] errorBytes = NettyUtils.errorPacket(400, String error = "something goes wrong with channel: " + ctx.getChannel() + ", exception: " + ExceptionUtils.getStackTrace(exception);
MessageFormatter.format("something goes wrong with channel:{}, exception={}", byte[] errorBytes = NettyUtils.errorPacket(400, error);
ctx.getChannel(),
ExceptionUtils.getStackTrace(exception)).getMessage());
NettyUtils.write(ctx.getChannel(), errorBytes, new ChannelFutureAggregator(ctx.getChannel() NettyUtils.write(ctx.getChannel(), errorBytes, new ChannelFutureAggregator(ctx.getChannel()
.getRemoteAddress() .getRemoteAddress().toString(), null, packet.getType(), errorBytes.length, System.nanoTime() - start, (short) 400));
.toString(), null, packet.getType(), errorBytes.length, System.nanoTime() - start, (short) 400));
} finally { } finally {
MDC.remove("destination"); MDC.remove("destination");
} }
} }
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { // public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
logger.error("something goes wrong with channel:{}, exception={}", // logger.error("something goes wrong with channel:{}, exception={}",
ctx.getChannel(), // ctx.getChannel(),
ExceptionUtils.getStackTrace(e.getCause())); // ExceptionUtils.getStackTrace(e.getCause()));
//
// ctx.getChannel().close();
// }
ctx.getChannel().close(); // public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
} // // logger.info("remove binding subscription value object if any...");
// // ClientIdentity clientIdentity = (ClientIdentity) ctx.getAttachment();
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { // // // 如果唯一的订阅者都取消了订阅,直接关闭服务,针对内部版本模式下可以减少资源浪费
// logger.info("remove binding subscription value object if any..."); // // if (clientIdentity != null) {
// ClientIdentity clientIdentity = (ClientIdentity) ctx.getAttachment(); // // stopCanalInstanceIfNecessary(clientIdentity);
// // 如果唯一的订阅者都取消了订阅,直接关闭服务,针对内部版本模式下可以减少资源浪费 // // }
// if (clientIdentity != null) { // }
// stopCanalInstanceIfNecessary(clientIdentity);
// }
}
private void stopCanalInstanceIfNecessary(ClientIdentity clientIdentity) { private void stopCanalInstanceIfNecessary(ClientIdentity clientIdentity) {
List<ClientIdentity> clientIdentitys = embeddedServer.listAllSubscribe(clientIdentity.getDestination()); List<ClientIdentity> clientIdentitys = embeddedServer.listAllSubscribe(clientIdentity.getDestination());
@@ -386,8 +371,8 @@ public class SessionHandler extends SimpleChannelHandler {
} }
} }
public void setEmbeddedServer(CanalServerWithEmbedded embeddedServer) { // public void setEmbeddedServer(CanalServerWithEmbedded embeddedServer) {
this.embeddedServer = embeddedServer; // this.embeddedServer = embeddedServer;
} // }
} }