zookeeper Socket Linger Time 관련 이슈

zookeeper 3.3.3 이하 버전에서는 서버와 연결을 담당하는 소켓의 Linger Time을 무조건 2초로 지정하고 있습니다.
이 값을 2초로 지정한 원인은 잘 모르겠습니다만, 아마 네트워크 응답이 느린 상황을 대비한 게 아닐까 싶습니다.

	public NIOServerCnxn(ZooKeeperServer zk, SocketChannel sock,
			SelectionKey sk, Factory factory) throws IOException {
		this.zk = zk;
		this.sock = sock;
		this.sk = sk;
		this.factory = factory;
		sock.socket().setTcpNoDelay(true);
		sock.socket().setSoLinger(true, 2);
		InetAddress addr = ((InetSocketAddress) sock.socket()
				.getRemoteSocketAddress()).getAddress();
		authInfo.add(new Id("ip", addr.getHostAddress()));
		sk.interestOps(SelectionKey.OP_READ);
	}

위와 같은 linger 지정이 문제가 되는 이유는 zookeeper 서버가 클라이언트와의 연결을 종료할 때 비동기가 아니라 동기화 방식으로 세션을 닫으며, 만약 동시에 여러 개의 세션이 닫히는 상황이라면 ‘세션개수 x linger time’만큼 지연이 발생할 수 있기 때문입니다.

public void close() {
synchronized(factory.cnxns){
...

많은 경우, zookeeper 클라이언트와 서버는 같은 네트워크상에 있기 때문에 linger time이 문제가 되는 상황은 거의 없습니다. 설령 linger time이 지정되어 있다고 해도 비동기 방식으로 연결을 종료한다면 역시 문제가 되지 않습니다.
그러나 현재 zookeeper 구조에서 비동기식 방식으로 연결을 닫도록 소스를 수정하는 것은 아무래도 구조상 큰 작업으로 보입니다. (zookeeper 버전이 올라가면서 수정되기를 기다려야 할 것 같네요.)
참고로 zookeeper 3.3.4에서는 soLinger() 부분이 다음과 같이 linger time을 사용하지 않도록 변경되었습니다.

	public NIOServerCnxn(ZooKeeperServer zk, SocketChannel sock,
			SelectionKey sk, Factory factory) throws IOException {
		this.zk = zk;
		this.sock = sock;
		this.sk = sk;
		this.factory = factory;
		sock.socket().setTcpNoDelay(true);
		sock.socket().setSoLinger(false, -1);
		InetAddress addr = ((InetSocketAddress) sock.socket()
				.getRemoteSocketAddress()).getAddress();
		authInfo.add(new Id("ip", addr.getHostAddress()));
		sk.interestOps(SelectionKey.OP_READ);
	}

댓글 남기기