fixbug: soTimeout doesn't work.

This commit is contained in:
baiju
2017-06-10 10:07:23 +08:00
parent f6c2eb8963
commit a46ac3b814

View File

@@ -5,7 +5,7 @@ import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.channels.SocketChannel; import java.nio.channels.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -37,7 +37,6 @@ import com.alibaba.otter.canal.protocol.ClientIdentity;
import com.alibaba.otter.canal.protocol.Message; import com.alibaba.otter.canal.protocol.Message;
import com.alibaba.otter.canal.protocol.exception.CanalClientException; import com.alibaba.otter.canal.protocol.exception.CanalClientException;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
/** /**
* 基于{@linkplain CanalServerWithNetty}定义的网络协议接口,对于canal数据进行get/rollback/ack等操作 * 基于{@linkplain CanalServerWithNetty}定义的网络协议接口,对于canal数据进行get/rollback/ack等操作
@@ -57,6 +56,8 @@ public class SimpleCanalConnector implements CanalConnector {
private final ByteBuffer readHeader = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN); private final ByteBuffer readHeader = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN);
private final ByteBuffer writeHeader = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN); private final ByteBuffer writeHeader = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN);
private SocketChannel channel; private SocketChannel channel;
private ReadableByteChannel readableChannel;
private WritableByteChannel writableChannel;
private List<Compression> supportedCompressions = new ArrayList<Compression>(); private List<Compression> supportedCompressions = new ArrayList<Compression>();
private ClientIdentity clientIdentity; private ClientIdentity clientIdentity;
private ClientRunningMonitor runningMonitor; // 运行控制 private ClientRunningMonitor runningMonitor; // 运行控制
@@ -130,7 +131,9 @@ public class SimpleCanalConnector implements CanalConnector {
address = getNextAddress(); address = getNextAddress();
} }
channel.connect(address); channel.connect(address);
Packet p = Packet.parseFrom(readNextPacket(channel)); readableChannel = Channels.newChannel(channel.socket().getInputStream());
writableChannel = Channels.newChannel(channel.socket().getOutputStream());
Packet p = Packet.parseFrom(readNextPacket());
if (p.getVersion() != 1) { if (p.getVersion() != 1) {
throw new CanalClientException("unsupported version at this client."); throw new CanalClientException("unsupported version at this client.");
} }
@@ -144,17 +147,18 @@ public class SimpleCanalConnector implements CanalConnector {
// //
ClientAuth ca = ClientAuth.newBuilder() ClientAuth ca = ClientAuth.newBuilder()
.setUsername(username != null ? username : "") .setUsername(username != null ? username : "")
.setPassword(ByteString.copyFromUtf8(password != null ? password : ""))
.setNetReadTimeout(soTimeout) .setNetReadTimeout(soTimeout)
.setNetWriteTimeout(soTimeout) .setNetWriteTimeout(soTimeout)
.build(); .build();
writeWithHeader(channel, writeWithHeader(
Packet.newBuilder() Packet.newBuilder()
.setType(PacketType.CLIENTAUTHENTICATION) .setType(PacketType.CLIENTAUTHENTICATION)
.setBody(ca.toByteString()) .setBody(ca.toByteString())
.build() .build()
.toByteArray()); .toByteArray());
// //
Packet ack = Packet.parseFrom(readNextPacket(channel)); Packet ack = Packet.parseFrom(readNextPacket());
if (ack.getType() != PacketType.ACK) { if (ack.getType() != PacketType.ACK) {
throw new CanalClientException("unexpected packet type when ack is expected"); throw new CanalClientException("unexpected packet type when ack is expected");
} }
@@ -173,14 +177,26 @@ public class SimpleCanalConnector implements CanalConnector {
} }
private void doDisconnnect() throws CanalClientException { private void doDisconnnect() throws CanalClientException {
if (readableChannel != null) {
quietlyClose(readableChannel);
readableChannel = null;
}
if (writableChannel != null) {
quietlyClose(writableChannel);
writableChannel = null;
}
if (channel != null) { if (channel != null) {
quietlyClose(channel);
channel = null;
}
}
private void quietlyClose(Channel channel) {
try { try {
channel.close(); channel.close();
} catch (IOException e) { } catch (IOException e) {
logger.warn("exception on closing channel:{} \n {}", channel, e); logger.warn("exception on closing channel:{} \n {}", channel, e);
} }
channel = null;
}
} }
public void subscribe() throws CanalClientException { public void subscribe() throws CanalClientException {
@@ -190,7 +206,7 @@ public class SimpleCanalConnector implements CanalConnector {
public void subscribe(String filter) throws CanalClientException { public void subscribe(String filter) throws CanalClientException {
waitClientRunning(); waitClientRunning();
try { try {
writeWithHeader(channel, writeWithHeader(
Packet.newBuilder() Packet.newBuilder()
.setType(PacketType.SUBSCRIPTION) .setType(PacketType.SUBSCRIPTION)
.setBody(Sub.newBuilder() .setBody(Sub.newBuilder()
@@ -202,7 +218,7 @@ public class SimpleCanalConnector implements CanalConnector {
.build() .build()
.toByteArray()); .toByteArray());
// //
Packet p = Packet.parseFrom(readNextPacket(channel)); Packet p = Packet.parseFrom(readNextPacket());
Ack ack = Ack.parseFrom(p.getBody()); Ack ack = Ack.parseFrom(p.getBody());
if (ack.getErrorCode() > 0) { if (ack.getErrorCode() > 0) {
throw new CanalClientException("failed to subscribe with reason: " + ack.getErrorMessage()); throw new CanalClientException("failed to subscribe with reason: " + ack.getErrorMessage());
@@ -217,7 +233,7 @@ public class SimpleCanalConnector implements CanalConnector {
public void unsubscribe() throws CanalClientException { public void unsubscribe() throws CanalClientException {
waitClientRunning(); waitClientRunning();
try { try {
writeWithHeader(channel, writeWithHeader(
Packet.newBuilder() Packet.newBuilder()
.setType(PacketType.UNSUBSCRIPTION) .setType(PacketType.UNSUBSCRIPTION)
.setBody(Unsub.newBuilder() .setBody(Unsub.newBuilder()
@@ -228,7 +244,7 @@ public class SimpleCanalConnector implements CanalConnector {
.build() .build()
.toByteArray()); .toByteArray());
// //
Packet p = Packet.parseFrom(readNextPacket(channel)); Packet p = Packet.parseFrom(readNextPacket());
Ack ack = Ack.parseFrom(p.getBody()); Ack ack = Ack.parseFrom(p.getBody());
if (ack.getErrorCode() > 0) { if (ack.getErrorCode() > 0) {
throw new CanalClientException("failed to unSubscribe with reason: " + ack.getErrorMessage()); throw new CanalClientException("failed to unSubscribe with reason: " + ack.getErrorMessage());
@@ -261,7 +277,7 @@ public class SimpleCanalConnector implements CanalConnector {
unit = TimeUnit.MILLISECONDS; unit = TimeUnit.MILLISECONDS;
} }
writeWithHeader(channel, writeWithHeader(
Packet.newBuilder() Packet.newBuilder()
.setType(PacketType.GET) .setType(PacketType.GET)
.setBody(Get.newBuilder() .setBody(Get.newBuilder()
@@ -275,15 +291,14 @@ public class SimpleCanalConnector implements CanalConnector {
.toByteString()) .toByteString())
.build() .build()
.toByteArray()); .toByteArray());
return receiveMessages(); return receiveMessages();
} catch (IOException e) { } catch (IOException e) {
throw new CanalClientException(e); throw new CanalClientException(e);
} }
} }
private Message receiveMessages() throws InvalidProtocolBufferException, IOException { private Message receiveMessages() throws IOException {
Packet p = Packet.parseFrom(readNextPacket(channel)); Packet p = Packet.parseFrom(readNextPacket());
switch (p.getType()) { switch (p.getType()) {
case MESSAGES: { case MESSAGES: {
if (!p.getCompression().equals(Compression.NONE)) { if (!p.getCompression().equals(Compression.NONE)) {
@@ -315,7 +330,7 @@ public class SimpleCanalConnector implements CanalConnector {
.setBatchId(batchId) .setBatchId(batchId)
.build(); .build();
try { try {
writeWithHeader(channel, Packet.newBuilder() writeWithHeader(Packet.newBuilder()
.setType(PacketType.CLIENTACK) .setType(PacketType.CLIENTACK)
.setBody(ca.toByteString()) .setBody(ca.toByteString())
.build() .build()
@@ -333,7 +348,7 @@ public class SimpleCanalConnector implements CanalConnector {
.setBatchId(batchId) .setBatchId(batchId)
.build(); .build();
try { try {
writeWithHeader(channel, Packet.newBuilder() writeWithHeader(Packet.newBuilder()
.setType(PacketType.CLIENTROLLBACK) .setType(PacketType.CLIENTROLLBACK)
.setBody(ca.toByteString()) .setBody(ca.toByteString())
.build() .build()
@@ -350,7 +365,15 @@ public class SimpleCanalConnector implements CanalConnector {
// ==================== helper method ==================== // ==================== helper method ====================
private void writeWithHeader(SocketChannel channel, byte[] body) throws IOException { private void writeWithHeader(byte[] body) throws IOException {
writeWithHeader(writableChannel, body);
}
private byte[] readNextPacket() throws IOException {
return readNextPacket(readableChannel);
}
private void writeWithHeader(WritableByteChannel channel, byte[] body) throws IOException {
synchronized (writeDataLock) { synchronized (writeDataLock) {
writeHeader.clear(); writeHeader.clear();
writeHeader.putInt(body.length); writeHeader.putInt(body.length);
@@ -360,7 +383,7 @@ public class SimpleCanalConnector implements CanalConnector {
} }
} }
private byte[] readNextPacket(SocketChannel channel) throws IOException { private byte[] readNextPacket(ReadableByteChannel channel) throws IOException {
synchronized (readDataLock) { synchronized (readDataLock) {
readHeader.clear(); readHeader.clear();
read(channel, readHeader); read(channel, readHeader);
@@ -371,7 +394,7 @@ public class SimpleCanalConnector implements CanalConnector {
} }
} }
private void read(SocketChannel channel, ByteBuffer buffer) throws IOException { private void read(ReadableByteChannel channel, ByteBuffer buffer) throws IOException {
while (buffer.hasRemaining()) { while (buffer.hasRemaining()) {
int r = channel.read(buffer); int r = channel.read(buffer);
if (r == -1) { if (r == -1) {