springcloud gateway 연결 보존 문제

프로젝트 에 서 는 springcloud gateway 를 게 이 트 웨 이 로 사용 하고 상류 와 부하 균형 서버 를 연결 합 니 다.
최근 모니터링 시스템 을 통 해 관찰 한 결과 게 이 트 웨 이와 상류 부하 균형 서버 가 유지 하 는 TCP 연결 이 300+인 것 을 발 견 했 고 호출 자가 연결 을 풀 지 않 은 것 으로 의심 되 었 다.
다음 과 같은 방법 으로 분석 합 니 다.
1)현재 만들어 진 연결 및 포트 데 이 터 를 주기 적 으로 수집 합 니 다.
먼저 10 분 간격 으로 2 시간 연속 채집 한 결과 두 시간 안에 새로 생 긴 포트 가 12 개 도 안 되 는 것 을 발견 하고 샘플링 주 기 를 점차적으로 단축 시 킨 다음 에 마지막 1 초 에 한 번 채집 한 결과 1 초 에 하나의 연결 을 구축 하 는 동시에 하나의 연결 을 닫 는 것 을 발견 했다.300+연결 이 존재 할 때 이런 연결 에 대응 하 는 포트 를 불 활성 포트 라 고 부 르 고 이 300+불 활성 포트 를 기록 했다.
2)좀 더 분석 하기 위해 whireshark 로 가방 을 잡는다.
대부분의 경우 정상 적 인 연결 과 닫 힌 것 으로 밝 혀 졌 으 나 300+개의 비 활성 포트 에 대응 하 는 연결 에는 데이터 가 없 었 다.이 300+개의 비 활성 연결 을 비 활성 연결 이 라 고 한다.동기 화 서둘러 말 인터페이스 에서 실시 간 모니터링 기능 을 호출 하 였 는데 실제 호출 수량 이 매우 적 음 을 발견 하 였 다(분당 10 개 미 만).
3)상류의 부하 균형 엔지니어 와 함께 점검
부하 균형 서버 에서 보 이 는 활성 연결 도 한 자릿수 이 며,게 이 트 웨 이에 있 는 활성 화 된 포트 를 찾 지 못 했다.부하 균형 서버 에서 게 이 트 웨 이의 비활성 연결 에 대응 하 는 연결 을 이미 철거 했다 는 것 이다.부하 균형 엔지니어 에 게 문의 하면 부하 균형 설 비 는 1 시간 이 넘 는 불 활성 연결 에 대해 자발적으로 철거 된다.
상기 분석 을 통 해 외부 시스템 이 부하 균형 설비 와 게 이 트 웨 이 를 통 해 연결 한 후에 어떠한 조작 도 하지 않 았 지만 게 이 트 웨 이 는 이 연결 을 계속 유지 하여 게 이 트 웨 이 의 연결 수 를 지속 적 으로 상승 시 켰 다.
이 문 제 를 해결 하기 위해 서 는 먼저 전통 적 인 TCP 장 연결 유지 체 제 를 돌 이 켜 볼 필요 가 있다.
긴 연결 유 지 를 위해 전통 적 인 TCP 서 비 스 는 심장 박동 으로 유 지 됩 니 다.예 를 들 어 서버 에서 분당 심장 박동 메 시 지 를 보 내 고 계산 기 를 시작 하 며 1 로 설정 합 니 다.클 라 이언 트 가 받 은 후에 메시지 에 응답 하고 서버 에서 답장 메 시 지 를 받 은 후에 계산 기 를 리 셋 합 니 다.응답 을 받 기 위해 1 분 에 심장 박동 메 시 지 를 보 내 고 카운터 에 1 을 추가 합 니 다.세 개의 심장 박동 메 시 지 를 연속 으로 보 내 고 이미 지 를 받 지 못 하면 서버 는 클 라 이언 트 가 연결 되 지 않 았 다 고 생각 하고 이 연결 을 자발적으로 철거 하여 불필요 한 자원 의 점용 을 피 할 것 이다.
우리 가 현재 사용 하고 있 는 springcloud gateway 는 소스 코드 증가 이상 의 심장 박동 체 제 를 직접 수정 하기 어렵 기 때문에 나 는 운영 체제 프로 토 콜 스 택 의 연결 보존 체 제 를 생각 했다.
TCP 프로 토 콜 스 택 의 보존 체 제 는 응용 층 의 긴 연결 유지 체제 와 유사 하 다(물론 응용 층 의 TCP 긴 연결 유지 체 제 는 프로 토 콜 스 택 의 보호 체제 에서 배 운'&').프로 토 콜 스 택 차원 에서 만 완성 되 기 때문에 응용 층 이 부하 의 긴 연결 유 지 를 실현 하 는 것 을 피 할 수 있다.
보존 체 제 는 다음 과 같다.
1)서버 측 에서 지 정 된 시간 내 에 연결 을 판단
(2 시간 부족)데이터 가 없 으 면 탐지 메 시 지 를 보 내 고 타 이 머 를 시작 합 니 다.
2)클 라 이언 트 가 정상적으로 실행 되 고 네트워크 가 가능 하 다 면
클 라 이언 트 는 응답 메 시 지 를 답장 하고 서버 에서 클 라 이언 트 가 정상 이 라 고 생각 하면 다시 시간 을 잽 니 다.
클 라 이언 트 호스트 가 붕괴 되 거나 네트워크 가 도달 하지 못 하면 서버 에서 응답 을 받 지 못 합 니 다.타이머 가 시간 을 초과 한 후(보통 75 초)서버 에서 탐지 메 시 지 를 다시 보 냅 니 다.이렇게 여러 번(보통 10 회)연속 으로 보 냅 니 다.응답 을 받 지 못 하면 서버 는 주 동 으로 연결 을 닫 습 니 다.
물론 중간 에 서버 에서 응답 을 받 으 면 연결 이 정상 이 라 고 생각 하고 탐지 메 시 지 를 보 내지 않 는 다.
다음 명령 을 사용 하면 상기 생존 시간,탐지 메 시 지 를 보 내 는 간격 과 횟수 를 볼 수 있 습 니 다.

#sysctl -a|grep keepalive
net.ipv4.tcp_keepalive_time = 7200(    )
net.ipv4.tcp_keepalive_probes = 9 
net.ipv4.tcp_keepalive_intvl = 75  (    )
활성 화 된 매개 변수 에서 두 시간의 시간 설정 에 대해 논란 이 존재 합 니 다.보통 사람들 은 이 값 이 매우 작 기 를 바 랍 니 다.예 를 들 어 분 급 이지 만 활성 화 된 간격 은 시스템 등급 의 변수 입 니 다.이 값 을 바 꾸 면 이 기능 을 사용 하 는 모든 사용자 에 게 영향 을 줄 수 있 습 니 다.
따라서 Host Requirements RFC 는 활성 간격 을 설정 할 수 있 지만 두 시간 이상 절약 되 지 않 고 프로그램 설정 이 필요 합 니 다.
협의 스 택 의 보존 기능 을 사용 하면 부족 한 두 시간 이 너무 길 고 이 시간 을 단축 하면 어떤 영향 을 미 칠 지 자신 이 없다.
그래서 다른 방법 을 생각해 보 세 요.인터넷 에서 다음 과 같은 코드 를 통 해 게 이 트 웨 이 가 긴 연결 에 대한 유지 방법 을 수정 할 수 있 습 니 다.다음 코드 는 생존 시간 을 3 분 으로 설정 하고 3 분 안에 연결 에 데이터 가 없 으 면 게 이 트 웨 이 는 자발적으로 연결 을 닫 습 니 다.
프로필:

server:
    netty:
        idie-timeout: 300
@Configuration
public class NettyConfig {
    @Bean
    publiWebServerFactoryCustomizer<NettyReactiveWebServerFactory> idleTimeoutCustomizer(
        @Value("${server.netty.idle-timeout}") Duration idleTimeout) {
        return factory -> factory.addServerCustomizers(
            server -> server.tcpConfiguration(
                tcp->tcp.bootstrap(
                   bootstrap->bootstrap.childHandler(new ChannelInitializer<Channel>() {
                       @Override
                       protected void initChannel(Channel channel) {
                           channel.pipeline().addLast(
                               new IdleStateHandler(0, 0, idleTimeout.toNanos(), NANOSECONDS) {
                                   private final AtomicBoolean closed = new AtomicBoolean();
                                   @Override
                                   protected void channelIdle(
                                       ChannelHandlerContext ctx, IdleStateEvent evt) {
                                           if (closed.compareAndSet(false, true)) {
                                               ctx.close();
                                           }
                                       }
                                   }
                               );
                           }
                       }))));
    }
}
시스템 이 출시 된 후에 감시 시스템 을 통 해 게 이 트 웨 이 연결 수가 지속 적 으로 증가 하지 않 았 다 는 것 을 알 게 되 었 다.방금 한숨 돌 렸 다.온라인 업무 시스템 은 자주 오 류 를 보고 하고 게 이 트 웨 이 에 실 패 를 요청 했다.서둘러 네트워크 캡 처 를 배정 한 후에 바로 업 무 를 회복 했다.
그 다음 에 네트워크 캡 처 를 분석 하고 캡 처 는 다음 과 같다.

스냅 백 결 과 를 보면 클 라 이언 트 와 게 이 트 웨 이 가 세 차례 악 수 를 한 뒤 연결 이 이 뤄 졌 으 나,이후 SSL 을 만 드 는 과정 에서 게 이 트 웨 이 가 400 Bad Request 로 되 돌아 와 비 즈 니스 시스템 요청 실패(비 즈 니스 시스템 https 요청 게 이 트 웨 이 사용)를 초래 했 고,위의 코드 에 있 는 설정 이 설정 파일 에 있 는 SSL 관련 설정 을 덮어 씌 워 SSL 연결 이 이 뤄 지지 않 은 것 으로 의심 된다.
우리 의 우수한 엔지니어 들 은 끈기 있 는 정신 에 따라 gateway 에 대해 소스 코드 분석 을 실시 했다.코드 에 대한 분석 을 통 해 이 설정 이 원래 의 SSL 설정 을 덮어 서 SSL 설정 이 효력 이 발생 하지 않 았 기 때문에 상기 코드 를 고 쳤 다.구체 적 으로 다음 과 같다.

@Configuration
public class NettyConfig {
    @Bean
    publiWebServerFactoryCustomizer<NettyReactiveWebServerFactory> idleTimeoutCustomizer(
        @Value("${server.netty.idle-timeout}") Duration idleTimeout) {
        return factory -> factory.addServerCustomizers(
            server -> server.tcpConfiguration(
                tcp->tcp.bootstrap(bootstrap->{
                  //      ,              
                   BootstrapHandlers.updateConfiguration(bootstrap, "IdleStateHandler",
                      (connectionObserver, channel) ->{
                       channel.pipeline().addLast(new IdleStateHandler(0, 0,
                           idleTimeout.toNanos(), NANOSECONDS) {
                                 private final AtomicBoolean closed = new AtomicBoolean();
                                 @Override
                                 protected void channelIdle(ChannelHandlerContext ctx,
                                     IdleStateEvent evt) {
                                     if (closed.compareAndSet(false, true)) {
                                         ctx.close();
                                     }
                                 }
                             });
                         });
                        return bootstrap;
                    }
                )));
    }
}
테스트 검증 진행,모든 OK!
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기