검색
이 검색 상자를 닫습니다.

쿠키 부스러기 추적: 스토리지 성능 이상 조사

작성자 :

이 게시물에서는 벤치마크 중 하나에서 관찰한 산발적인 스토리지 성능 이상을 식별하고 수정한 방법을 살펴봅니다.

Qumulo에서는 고성능 파일 데이터 플랫폼을 구축하고 XNUMX주마다 업데이트를 지속적으로 출시. 엔터프라이즈급 소프트웨어를 너무 자주 배송하려면 우리가 고품질 제품을 만들었는지 확인하기 위해 광범위한 테스트 제품군이 필요합니다. 당사의 성능 테스트 제품군은 당사의 모든 제품에서 지속적으로 실행됩니다. 플랫폼 제공 업계 표준 벤치마크에 대해 실행되는 파일 성능 테스트를 포함합니다.

스토리지 성능 이상을 입력하십시오.

몇 달 동안 우리는 다중 스트림 읽기 및 쓰기 벤치마크의 변동성을 관찰했습니다. 이러한 벤치마크는 IOzone을 사용하여 클러스터에 대한 동시 읽기 및 동시 쓰기를 생성하고 연결된 모든 클라이언트에서 집계된 처리량을 측정합니다. 특히, 우리는 대부분의 실행이 일관되게 안정적인 성능 목표에 도달하는 이중 모드 분포를 관찰한 반면, 두 번째, 더 작은 결과 세트는 약 200% 더 느린 약 300-10MB/s를 산발적으로 실행했습니다. 다음은 성능 결과를 보여주는 그래프입니다.

문제 특성화

스토리지 성능 이상을 조사할 때 첫 번째 단계는 가능한 한 많은 변수를 제거하는 것입니다. 산발적인 결과는 수개월에 걸쳐 수백 개의 소프트웨어 버전에서 처음 확인되었습니다. 문제를 단순화하기 위해 동일한 하드웨어와 단일 소프트웨어 버전에서 일련의 벤치마크 실행을 시작했습니다. 이 일련의 실행은 동일한 이중 모드 분포를 보여 주었는데, 이는 하드웨어 차이나 소프트웨어 버전별 회귀로 변동성을 설명할 수 없음을 의미합니다.

단일 버전에서 바이모달 성능을 재현한 다음 빠른 실행과 느린 실행에서 수집된 세부 성능 데이터를 비교했습니다. 가장 먼저 튀어나온 것은 노드 간 RPC 대기 시간이 좋은 실행보다 나쁜 실행에서 훨씬 더 높다는 것입니다. 이는 여러 가지 이유가 있을 수 있지만 네트워킹 관련 근본 원인을 암시합니다.

TCP 소켓 성능 탐색

이를 염두에 두고 테스트 실행에서 TCP 소켓 성능에 대한 더 자세한 데이터를 원했기 때문에 성능 테스트 프로파일러를 활성화했습니다. 지속적으로 ss에서 데이터 수집. ss가 실행될 때마다 시스템의 각 소켓에 대한 자세한 통계가 출력됩니다.

>ss -tio6 상태 Recv-Q Send-Q 로컬 주소:포트 피어 주소:포트 ESTAB 0 0 fe80::f652:14ff:fe3b:8f30%bond0:56252 fe80::f652:14ff:fe3b:8f60:42687 sack cube wscale : 7,7- RTO : 204 RTT : 0.046 / 0.01 ATO : 40 MSS : 8940 CWND 10 SSTHRESH 87 bytes_acked : bytes_received 21136738172861 : segs_out 13315563865457 : 3021503845 segs_in : 2507786423 송신 15547.8Mbps lastsnd : 348 lastrcv : 1140 lastack : 348 pacing_rate 30844.2Mbps 재전송:0/1540003 rcv_rtt:4 rcv_space:8546640 ESTAB 0 0 fe80::f652:14ff:fe3b:8f30%bond0:44517 fe80::f652:14ff2 : 4030 RTT : 45514 / 7,7 ATO : 204 MSS : 2.975 CWND 5.791 SSTHRESH 40 bytes_acked : 8940 bytes_received : 10 segs_out : 10 segs_in : 2249367594375 송신 911006516679Mbps lastsnd : 667921849 lastrcv : 671354128 lastack : 240.4 pacing_rate 348Mbps retrans가 1464 / 348 rcv_rtt:288.4 rcv_space:0 …

시스템의 각 소켓은 출력의 한 항목에 해당합니다.

샘플 출력에서 ​​볼 수 있듯이 ss는 분석에 그다지 친숙하지 않은 방식으로 데이터를 덤프합니다. 주어진 성능 테스트에 대해 클러스터 전체의 TCP 소켓 성능을 시각적으로 보기 위해 데이터를 가져오고 다양한 구성 요소를 플롯했습니다. 이 플롯을 사용하면 빠른 테스트와 느린 테스트를 쉽게 비교하고 이상을 찾을 수 있습니다.

이 플롯 중 가장 흥미로운 것은 테스트 중 혼잡 창 크기(세그먼트 단위)였습니다. 혼잡 창( cwnd</var/www/wordpress>: in the above output) is crucially important to TCP performance, as it controls the amount of data outstanding in-flight over the connection at any given time. The higher the value, the more data TCP can send on a connection in parallel. When we looked at the congestion windows from a node during a low-performance run, we saw two connections with reasonably high congestion windows and one with a very small window.

노드 간 RPC 대기 시간을 다시 살펴보면 높은 대기 시간은 작은 정체 창을 가진 소켓과 직접적으로 관련이 있습니다. 이로 인해 한 소켓이 시스템의 다른 소켓에 비해 매우 작은 혼잡 창을 유지하는 이유는 무엇입니까?

하나의 RPC 연결이 다른 연결보다 훨씬 더 나쁜 TCP 성능을 경험하고 있음을 확인하고 돌아가서 ss의 원시 출력을 살펴보았습니다. 우리는 이 '느린' 연결이 나머지 소켓과 다른 TCP 옵션을 가지고 있다는 것을 알아차렸습니다. 특히 기본 tcp 옵션이 있었습니다. 두 연결은 혼잡 기간이 크게 다르며 더 작은 혼잡 기간을 나타내는 라인이 누락되었습니다. sack</var/www/wordpress> and wscale:7</var/www/wordpress>,7.</var/www/wordpress>

ESTAB 0 0 ::ffff:10.120.246.159:8000 ::ffff:10.120.246.27:52312 자루 큐빅 wscale:7,7 rto:204 rtt:0.183/0.179 ato:40 mss:1460 cwnd:293 ssthresh:291 bytes_acked: 140908972 bytes_received:27065 segs_out:100921 segs_in:6489 보내기 18700.8Mbps lastsnd:37280 lastrcv:37576 lastack:37280 pacing_rate 22410.3Mbps rcv_space:29200 ESTAB 0 0 fe80::e61d:2dff :febb:c960%bond0:33610 fe80::f652: 14ff:fe54:d600:48673 큐빅 rto:204 rtt:0.541/1.002 ato:40 mss:1440 cwnd:10 ssthresh:21 bytes_acked:6918189 bytes_received:7769628 segs_out:10435 segs_in:10909 보내기 212.9 Mbps lastsnd:1228 lastrcv:1232 lastack :1228 pacing_rate 255.5Mbps rcv_rtt:4288 rcv_space:1131488

이것은 흥미로웠지만 단 하나의 소켓 데이터 포인트를 보는 것은 기본 TCP 옵션을 갖는 것이 우리의 작은 혼잡 창 문제와 높은 상관관계가 있다는 확신을 주지 못했습니다. 무슨 일이 일어나고 있는지 더 잘 이해하기 위해 일련의 벤치마크 실행에서 ss 데이터를 수집하고 SACK(선택적 확인) 옵션이 없는 소켓의 100%가 기본이 아닌 TCP 옵션이 있는 모든 소켓. 여기서 SACK 옵션이 누락된 소켓과 이러한 TCP 소켓의 성능 사이에는 분명히 상관관계가 있었습니다. 이는 SACK 및 기타 옵션이 성능을 향상시키기 위한 것이므로 의미가 있습니다.

TCP 옵션 설정 방법

연결의 TCP 옵션은 SYN 플래그가 포함된 메시지와 함께 옵션 값을 전달하여 설정됩니다. 이것은 연결을 만드는 데 필요한 TCP 연결 핸드셰이크(SYN, SYN+ACK, ACK)의 일부입니다. 다음은 MSS(최대 세그먼트 크기), SACK 및 WS(창 크기 조정) 옵션이 설정된 상호 작용의 예입니다.

그렇다면 TCP 옵션은 어디로 갔습니까?

누락된 SACK 및 창 크기 조정 옵션을 더 작은 혼잡 창 및 낮은 처리량 연결과 연결했지만 일부 연결에 대해 이러한 옵션이 꺼져 있는 이유를 여전히 알 수 없었습니다. 결국 모든 연결은 동일한 코드를 사용하여 생성되었습니다!

우리는 SACK 옵션에 초점을 맞추기로 결정했습니다. 이는 디버그하기가 더 쉽기를 바라는 단순한 플래그이기 때문입니다. Linux에서 SACK는 sysctl에 의해 전체적으로 제어되며 연결별로 제어할 수 없습니다. 그리고 머신에서 SACK을 활성화했습니다.

>sysctl net.ipv4.tcp_sack
net.ipv4.tcp_sack = 1</var/www/wordpress>

프로그램이 일부 연결에서 이러한 옵션 설정을 놓칠 수 있는 방법에 대해 우리는 당황했습니다. 연결 설정 중에 TCP 핸드셰이크를 캡처하여 시작했습니다. 우리는 초기 SYN 메시지에 예상되는 옵션이 설정되어 있지만 SYN+ACK가 SACK 및 창 크기 조정을 제거했음을 발견했습니다.

우리는 Linux 커널의 TCP 스택을 열어서 SYN+ACK 옵션이 어떻게 만들어지는지 검색하기 시작했습니다. 우리는 발견 tcp_make_synack, 호출 tcp_synack_options:

static unsigned int tcp_synack_options(const struct sock *sk, struct request_sock *req, unsigned int mss, struct sk_buff *skb, struct tcp_out_options *opts, const struct tcp_md5sig_key *md5, struct tcp_fastopen_cookie *foc) { ... if (likely(ireq) ->sack_ok)) { 옵션->옵션 |= OPTION_SACK_ADVERTISE; if (unlikely(!ireq->tstamp_ok)) 남아있는 경우 -= TCPOLEN_SACKPERM_ALIGNED; } ... MAX_TCP_OPTION_SPACE 반환 - 남음; }

들어오는 요청에 SACK 옵션이 설정되어 있는지 여부에 따라 SACK 옵션이 단순히 설정되는 것을 보았는데 이는 별로 도움이 되지 않았습니다. 우리는 SACK이 SYN과 SYN+ACK 사이의 이 연결에서 제거되고 있다는 것을 알고 있었고 여전히 그것이 발생하는 위치를 찾아야 했습니다.

들어오는 요청 구문 분석을 살펴보았습니다. tcp_parse_options:

void tcp_parse_options(const struct net *net, const struct sk_buff *skb, struct tcp_options_received *opt_rx, int estab, struct tcp_fastopen_cookie *foc) { ... case TCPOPT_SACK_PERM: if (opsize == TCPOLEN_SACK_PERM && th->syn && !estab && net->ipv4.sysctl_tcp_sack) { opt_rx->sack_ok = TCP_SACK_SEEN; tcp_sack_reset(opt_rx); } 부서지다; ... }

들어오는 요청에서 SACK 옵션을 긍정적으로 구문 분석하려면 요청에 SYN 플래그가 있어야 하고(그렇게 했습니다) 연결이 설정되지 않아야 하며(그렇지 않았습니다) net.ipv4.tcp_sack sysctl 사용하도록 설정해야 합니다. 운이 없다.

브라우징의 일부로 연결 요청을 처리할 때 tcp_conn_request, 때때로 옵션을 지웁니다.

int tcp_conn_request(struct request_sock_ops *rsk_ops, const struct tcp_request_sock_ops *af_ops, struct sock *sk, struct sk_buff *skb) { ... tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc); if (want_cookie && !tmp_opt.saw_tstamp) tcp_clear_options(&tmp_opt); ... 0을 반환합니다. }

우리는 want_cookie</var/www/wordpress> variable indicates that Linux wants to use the TCP SYN cookies feature, but we didn’t have any idea what that meant.

TCP SYN 쿠키란 무엇입니까?

TCP SYN 쿠키의 특징은 다음과 같습니다.

SYN 범람

TCP 서버는 일반적으로 아직 설정되지 않은 연결에 대한 SYN 대기열의 공간이 제한되어 있습니다. 이 대기열이 가득 차면 서버는 더 이상 연결을 수락할 수 없으며 들어오는 SYN 요청을 삭제해야 합니다.

이 동작은 SYN 플러딩이라는 서비스 거부 공격으로 이어집니다. 공격자는 서버에 많은 SYN 요청을 보내지만 서버가 SYN+ACK로 응답하면 공격자는 응답을 무시하고 연결 설정을 완료하기 위해 ACK를 보내지 않습니다. 이로 인해 서버는 에스컬레이션 백오프 타이머를 사용하여 SYN+ACK 메시지 재전송을 시도합니다. 공격자가 응답하지 않고 계속해서 SYN 요청을 보내면 서버의 SYN 대기열을 항상 꽉 채워 합법적인 클라이언트가 서버에 연결하지 못하도록 할 수 있습니다.

SYN 홍수 방지

TCP SYN 쿠키는 SYN 대기열이 가득 찬 경우에도 서버가 SYN+ACK로 응답하고 연결을 설정할 수 있도록 하여 이 문제를 해결합니다. SYN 쿠키가 하는 일은 일반적으로 SYN 대기열(대략적인 시간 및 소스/목적지 IP 및 포트의 암호화 해시) 항목에 일반적으로 저장되는 옵션을 SYN+ACK의 초기 시퀀스 번호 값으로 인코딩하는 것입니다. 그런 다음 서버는 SYN 대기열 항목을 버리고 이 연결에서 메모리를 낭비하지 않을 수 있습니다. (적법한) 클라이언트가 결국 ACK 메시지로 응답하면 동일한 초기 시퀀스 번호가 포함됩니다. 그런 다음 서버는 시간의 해시를 해독하고 유효한 경우 옵션을 해독하고 SYN 대기열 공간을 사용하지 않고 연결 설정을 완료할 수 있습니다.

SYN 쿠키의 단점

SYN 쿠키를 사용하여 연결을 설정하면 한 가지 단점이 있습니다. 초기 시퀀스 번호에 모든 옵션을 인코딩할 공간이 충분하지 않다는 것입니다. Linux TCP 스택은 최대 세그먼트 크기(필수 옵션)만 인코딩하고 SACK 및 창 크기 조정 옵션을 비롯한 다른 모든 옵션을 거부하는 SYN+ACK를 보냅니다. 이는 서버에 전체 SYN 대기열이 있는 경우에만 사용되기 때문에 일반적으로 문제가 되지 않습니다. 이는 SYN 플러드 공격을 받지 않는 한 가능성이 없습니다.

다음은 서버의 SYN 대기열이 가득 찼을 때 SYN 쿠키로 연결이 생성되는 방식을 보여주는 예제 상호 작용입니다.

스토리지 성능 이상 현상: Qumulo의 TCP 문제

TCP SYN 쿠키를 연구한 후 주기적으로 TCP 옵션이 누락되는 연결에 대한 책임이 있을 가능성이 있음을 인식했습니다. 확실히 우리는 테스트 머신이 SYN 플러드 공격을 받지 않았으므로 SYN 대기열이 가득 차서는 안 된다고 생각했습니다.

우리는 다시 Linux 커널 읽기로 돌아가서 최대 SYN 대기열 크기가 다음과 같이 설정되어 있음을 발견했습니다. inet_csk_listen_start:

int inet_csk_listen_start(struct sock *sk, int backlog) { ... sk->sk_max_ack_backlog = 백로그; sk->sk_ack_backlog = 0; ... }

거기에서 호출자를 추적하여 백로그 값이 들어 시스템 호출 우리는 Qumulo의 소켓 코드를 가져와서 연결을 수신 대기할 때 항상 크기 5의 백로그를 사용한다는 것을 빠르게 확인했습니다.

if (listen(fd, 5) == -1) return error_new(system_error, errno, "listen");

클러스터를 초기화하는 동안 우리는 모든 시스템 간에 연결된 메시 네트워크를 생성하고 있었으므로 충분한 크기의 클러스터에 대해 한 번에 5개 이상의 연결을 생성했습니다. 우리는 내부에서 우리 자신의 클러스터를 SYN 범람시켰습니다!

우리는 Qumulo가 사용하는 백로그 크기를 늘리기 위해 신속하게 변경했으며 모든 나쁜 성능 결과가 사라졌습니다. 케이스가 종료되었습니다!

편집자 참고: 이 게시물은 2020년 XNUMX월에 게시되었습니다.

자세히 알아보기

쿠물로스 엔지니어링 팀 채용 중이며 몇 가지가 있습니다. 채용 – 확인하고 알아보기 쿠물로에서의 삶.

문의하기

시승하기. 새로운 대화형 Hands-On Labs에서 Qumulo를 데모하거나 데모 또는 무료 평가판을 요청하십시오.

Qumulo 블로그 구독 고객 사례, 기술 통찰력, 업계 동향 및 제품 뉴스를 제공합니다.

관련 게시물

위쪽으로 스크롤