Zookeeper 클 라 이언 트 오류: Packet len * 범위 밖 입 니 다!

홈 페이지: www. howardliu. cn 블 로그: Zookeeper 클 라 이언 트 오류: Packet len 8854970 is out of range!
이것 은 생산 환경 에서 zookeeper 를 사용 하 는 이상 한 상황 입 니 다. 오 류 는 java.io.IOException: Packet len8854970 is out of range! 입 니 다.그리고 나 서 namespace 를 바 꾸 었 는데 실수 가 없 었 습 니 다. 우연히 일어 난 줄 알 고 중시 하지 않 았 습 니 다.하지만 몇 년 뒤 문제 가 생 겨 심각 성 을 깨 달 았 다.분석 한 결과 일정 시간 마다 특정한 znode 노드 에서 클 라 이언 트 가 설정 한 크기 를 초과 하면 클 라 이언 트 연결 이 실패 하고 zkCli. sh 가 이 노드 를 조작 하 는 데 실패 하 는 것 을 발견 했다.zookeeper 에 간단하게 의존 하 는 시스템 에 대해 서 는 이러한 오 류 를 용인 할 수 있 습 니 다 (단, 해결 해 야 합 니 다).zookeeper 에 강하 게 의존 하 는 시스템 이 라면 이런 오 류 는 재앙 이 라 고 할 수 있다.
1 문제 발견
문제 의 발견 은 비교적 우여곡절 하 다. 먼저 서버 디스크 가 가득 쓰 여 있 는 것 을 발견 했다.그리고 쓸모없는 로 그 를 삭제 하고 이상 한 응용 프로그램 을 다시 시작 합 니 다.다행히 프로젝트 가 시 작 된 후에 로 그 를 추적 해서 터미널 을 끄 는 것 이 좋 은 습관 이 있 습 니 다.결 과 는 오류 로그 에 의 해 도 배 되 었 습 니 다.
ERROR 2017-02-20 10:45:44,729 [Curator-Framework-0] o.a.c.f.i.CuratorFrameworkImpl.logError() (CuratorFrameworkImpl.java:557) - Background retry gave up
org.apache.curator.CuratorConnectionLossException: KeeperErrorCode = ConnectionLoss
        at org.apache.curator.framework.imps.CuratorFrameworkImpl.performBackgroundOperation(CuratorFrameworkImpl.java:838) [curator-framework-2.10.0.jar:na]
        at org.apache.curator.framework.imps.CuratorFrameworkImpl.backgroundOperationsLoop(CuratorFrameworkImpl.java:809) [curator-framework-2.10.0.jar:na]
        at org.apache.curator.framework.imps.CuratorFrameworkImpl.access$300(CuratorFrameworkImpl.java:64) [curator-framework-2.10.0.jar:na]
        at org.apache.curator.framework.imps.CuratorFrameworkImpl$4.call(CuratorFrameworkImpl.java:267) [curator-framework-2.10.0.jar:na]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_111]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_111]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_111]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]

zookeeper 의 클 라 이언 트 는 Apache Curator 를 사용 하기 때문에 zookeeper 와 의 연결 이 끊 기 고 다시 연결 을 만 들 기 때문에 대량의 연결 에 실패 할 수 있 습 니 다.
2 문제 분석
이 항목 에서 zookeepr 의 사용 에 대해 다음 과 같은 몇 가지 장면 이 있 습 니 다. 1. 서비스 상태 데이터: 서비스 상 태 를 zno de 노드 에 기록 합 니 다. 2. 서비스 등록: 서비스 주 소 를 zno de 노드 에 기록 합 니 다. 3. 서비스 발견: zno de 노드 의 사용 가능 한 서비스 주 소 를 가 져 옵 니 다. 4. 감청 노드: 특정한 zno de 노드 나 이 노드 의 바이트 상 태 를 감청 합 니 다.
이 몇 가지 상황 은 zookeeper 의 zno de 노드 와 연결 을 만 들 고 작업 을 수행 해 야 합 니 다.오류 알림 에 따 르 면 java.io.IOException: Packet len8854970 is out of range! out of range 는 특정한 제한 을 초과 하여 코드 만 볼 수 있 습 니 다.
protected final ByteBuffer lenBuffer = ByteBuffer.allocateDirect(4);
protected ByteBuffer incomingBuffer = lenBuffer;

protected void readLength() throws IOException {
    int len = incomingBuffer.getInt();
    if (len < 0 || len >= ClientCnxn.packetLen) {
        throw new IOException("Packet len" + len + " is out of range!");
    }
    incomingBuffer = ByteBuffer.allocate(len);
}

public static final int packetLen = Integer.getInteger("jute.maxbuffer", 4096 * 1024);

코드 를 통 해 쉽게 알 수 있 듯 이 이 오 류 는 len 0 보다 작 거나 packetLen 크기 때문이다. 코드 논리 에 따 르 면 len 0 보다 작 지 않 으 면 packetLen 보다 크다.packetLen 의 값 은 jute.maxbuffer 시스템 변수 정의 또는 기본 4096 * 1024 (4M) 입 니 다.
코드 가 비교적 길 기 때문에 여 기 는 쓰 지 않 겠 습 니 다.대체 적 인 논 리 는 zookeeper 와 연결 한 후에 특정한 노드 에 대해 읽 기와 쓰기 작업 을 해 야 한 다 는 것 이다. 스루풋 을 높이 기 위해 이 노드 의 데이터 크기 가 설정 한 jute.maxbuffer 을 초과 하 는 지 판단 하고 만약 에 이상 을 던 지 는 것 이다.zookeeper 클 라 이언 트 에서 이 부분의 이상 한 처 리 는 비교적 거칠다. 주석 에 도 'this is ugly, you have a better way speak up' 이 라 고 쓰 여 있 기 때문이다.
3 문제 해결
위의 잘못 을 바로 잡 으 면 답 이 분명 하 다.두 가지 방안 만 있 습 니 다.
  • 작업 대기 노드 의 크기 를 줄 이 고 기본 4M
  • 보다 작 습 니 다.
  • 기본 jute.maxbuffer 크기 증가
  • 첫 번 째 방식 은 자신의 구체 적 인 상황 에 따라 구체 적 으로 조작 해 야 한다.여기 에는 아무런 효과 적 인 건의 가 없다.
    두 번 째 방식 에 대해 서 는 비교적 간단 하 다.Zookeeper 대상 을 만 들 기 전에 설정 System.setProperty("jute.maxbuffer", 4096 * 1024 * 10 + ""); 하면 이곳 의 크기 는 자신의 시스템 설정 에 따라 저 는 테스트 값 일 뿐 입 니 다 (설정 이 너무 크 면 이 노드 가 정말 크 면 삼투 에 영향 을 줄 수 있 습 니 다).
    Apache Curator 를 사용 하기 때문에 Zookeeper 대상 을 직접 만 들 필요 가 없 기 때문에 CuratorFramework 대상 을 만 들 기 전에 이 변 수 를 추가 해 야 합 니 다.
    문 제 를 철저히 해결 해 야 지, 화 를 남 겨 서 는 안 된다.(이곳 에는 음소 와 찬바람 이 동반 되 어야 한다...)
    자바 클 라 이언 트 의 문 제 는 해결 되 었 지만 zkCli. sh 를 통 해 연결 할 때 이 문제 가 발생 합 니 다.오 류 는 다음 과 같다.
    2017-02-20 12:08:03,999 [myid:] - WARN  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1102] - Session 0x1591b713cefd2b3 for server localhost/127.0.0.1:2181, unexpected error, closing socket connection and attempting reconnect
    java.io.IOException: Packet len8854970 is out of range!
        at org.apache.zookeeper.ClientCnxnSocket.readLength(ClientCnxnSocket.java:112)
        at org.apache.zookeeper.ClientCnxnSocketNIO.doIO(ClientCnxnSocketNIO.java:79)
        at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:366)
        at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1081)
    
    WATCHER::
    
    WatchedEvent state:Disconnected type:None path:null
    Exception in thread "main" org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /it-monitor/com/wfj/monitor/sales-overview-info
        at org.apache.zookeeper.KeeperException.create(KeeperException.java:99)
        at org.apache.zookeeper.KeeperException.create(KeeperException.java:51)
        at org.apache.zookeeper.ZooKeeper.getChildren(ZooKeeper.java:1472)
        at org.apache.zookeeper.ZooKeeper.getChildren(ZooKeeper.java:1500)
        at org.apache.zookeeper.ZKUtil.listSubTreeBFS(ZKUtil.java:114)
        at org.apache.zookeeper.ZKUtil.deleteRecursive(ZKUtil.java:49)
        at org.apache.zookeeper.ZooKeeperMain.processZKCmd(ZooKeeperMain.java:703)
        at org.apache.zookeeper.ZooKeeperMain.processCmd(ZooKeeperMain.java:588)
        at org.apache.zookeeper.ZooKeeperMain.executeLine(ZooKeeperMain.java:360)
        at org.apache.zookeeper.ZooKeeperMain.run(ZooKeeperMain.java:323)
        at org.apache.zookeeper.ZooKeeperMain.main(ZooKeeperMain.java:282)

    zkCli. sh 를 찾 습 니 다. 맨 아래 자바 명령 에 jute.maxbuffer 에 대한 정 의 를 추가 합 니 다. (D 인자 사용)
    "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
         "-Djute.maxbuffer=41943040" \
         -cp "$CLASSPATH" $CLIENT_JVMFLAGS $JVMFLAGS \
         org.apache.zookeeper.ZooKeeperMain "$@"

    물론 운영 편 의 를 위해 jute.maxbuffer 의 값 을 변수 로 설정 하고 설정 을 수정 하여 값 을 설정 할 수 있 습 니 다.sh 스 크 립 트 수정 으로 인해 다른 문제 가 발생 하지 않도록 합 니 다.

    좋은 웹페이지 즐겨찾기