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.");
} }
@@ -143,18 +146,19 @@ public class SimpleCanalConnector implements CanalConnector {
supportedCompressions.addAll(handshake.getSupportedCompressionsList()); supportedCompressions.addAll(handshake.getSupportedCompressionsList());
// //
ClientAuth ca = ClientAuth.newBuilder() ClientAuth ca = ClientAuth.newBuilder()
.setUsername(username != null ? username : "") .setUsername(username != null ? username : "")
.setNetReadTimeout(soTimeout) .setPassword(ByteString.copyFromUtf8(password != null ? password : ""))
.setNetWriteTimeout(soTimeout) .setNetReadTimeout(soTimeout)
.build(); .setNetWriteTimeout(soTimeout)
writeWithHeader(channel, .build();
Packet.newBuilder() writeWithHeader(
.setType(PacketType.CLIENTAUTHENTICATION) Packet.newBuilder()
.setBody(ca.toByteString()) .setType(PacketType.CLIENTAUTHENTICATION)
.build() .setBody(ca.toByteString())
.toByteArray()); .build()
.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,16 +177,28 @@ 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) {
try { quietlyClose(channel);
channel.close();
} catch (IOException e) {
logger.warn("exception on closing channel:{} \n {}", channel, e);
}
channel = null; channel = null;
} }
} }
private void quietlyClose(Channel channel) {
try {
channel.close();
} catch (IOException e) {
logger.warn("exception on closing channel:{} \n {}", channel, e);
}
}
public void subscribe() throws CanalClientException { public void subscribe() throws CanalClientException {
subscribe(""); // 传递空字符即可 subscribe(""); // 传递空字符即可
} }
@@ -190,19 +206,19 @@ 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()
.setDestination(clientIdentity.getDestination()) .setDestination(clientIdentity.getDestination())
.setClientId(String.valueOf(clientIdentity.getClientId())) .setClientId(String.valueOf(clientIdentity.getClientId()))
.setFilter(filter != null ? filter : "") .setFilter(filter != null ? filter : "")
.build() .build()
.toByteString()) .toByteString())
.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,18 +233,18 @@ 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()
.setDestination(clientIdentity.getDestination()) .setDestination(clientIdentity.getDestination())
.setClientId(String.valueOf(clientIdentity.getClientId())) .setClientId(String.valueOf(clientIdentity.getClientId()))
.build() .build()
.toByteString()) .toByteString())
.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,29 +277,28 @@ 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()
.setAutoAck(false) .setAutoAck(false)
.setDestination(clientIdentity.getDestination()) .setDestination(clientIdentity.getDestination())
.setClientId(String.valueOf(clientIdentity.getClientId())) .setClientId(String.valueOf(clientIdentity.getClientId()))
.setFetchSize(size) .setFetchSize(size)
.setTimeout(time) .setTimeout(time)
.setUnit(unit.ordinal()) .setUnit(unit.ordinal())
.build() .build()
.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)) {
@@ -310,16 +325,16 @@ public class SimpleCanalConnector implements CanalConnector {
public void ack(long batchId) throws CanalClientException { public void ack(long batchId) throws CanalClientException {
waitClientRunning(); waitClientRunning();
ClientAck ca = ClientAck.newBuilder() ClientAck ca = ClientAck.newBuilder()
.setDestination(clientIdentity.getDestination()) .setDestination(clientIdentity.getDestination())
.setClientId(String.valueOf(clientIdentity.getClientId())) .setClientId(String.valueOf(clientIdentity.getClientId()))
.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()
.toByteArray()); .toByteArray());
} catch (IOException e) { } catch (IOException e) {
throw new CanalClientException(e); throw new CanalClientException(e);
} }
@@ -328,16 +343,16 @@ public class SimpleCanalConnector implements CanalConnector {
public void rollback(long batchId) throws CanalClientException { public void rollback(long batchId) throws CanalClientException {
waitClientRunning(); waitClientRunning();
ClientRollback ca = ClientRollback.newBuilder() ClientRollback ca = ClientRollback.newBuilder()
.setDestination(clientIdentity.getDestination()) .setDestination(clientIdentity.getDestination())
.setClientId(String.valueOf(clientIdentity.getClientId())) .setClientId(String.valueOf(clientIdentity.getClientId()))
.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()
.toByteArray()); .toByteArray());
} catch (IOException e) { } catch (IOException e) {
throw new CanalClientException(e); throw new CanalClientException(e);
} }
@@ -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) {