Pingora는 얼마나 멋진가요! 초인기 웹서버, Nginx 능가

WBOY
풀어 주다: 2024-02-19 11:12:17
앞으로
1424명이 탐색했습니다.

Rust를 기반으로 구축된 새로운 HTTP 프록시인 Pingora를 소개하게 되어 기쁩니다. 하루에 1조 개가 넘는 요청을 처리하여 성능을 개선하고 Cloudflare 고객에게 새로운 기능을 제공하는 동시에 원래 프록시 인프라의 CPU 및 메모리 리소스의 1/3만 필요로 합니다.

Cloudflare가 지속적으로 확장됨에 따라 우리는 NGINX의 처리 능력이 더 이상 우리의 요구 사항을 충족할 수 없다는 것을 알게 되었습니다. 수년에 걸쳐 좋은 성능을 발휘했지만 시간이 지남에 따라 우리 규모의 과제를 해결하는 데 한계가 있다는 것을 깨달았습니다. 따라서 우리는 성능 및 기능 요구 사항을 충족하기 위해 몇 가지 새로운 솔루션을 구축해야 한다고 느꼈습니다.

Cloudflare 고객과 사용자는 Cloudflare 글로벌 네트워크를 HTTP 클라이언트와 서버 간의 프록시로 사용합니다. 우리는 네트워크에 연결하는 브라우저 및 기타 사용자 에이전트의 효율성을 향상시키기 위해 많은 논의를 하고 많은 기술을 개발했으며 QUIC 및 HTTP/2 최적화와 같은 새로운 프로토콜을 구현했습니다.

오늘은 이 방정식의 또 다른 관련 측면, 즉 네트워크와 인터넷 서버 간의 트래픽 관리를 담당하는 프록시 서비스에 중점을 둘 것입니다. 이 프록시 서비스는 CDN, Workers fetch, Tunnel, Stream, R2 및 기타 여러 기능과 제품에 대한 지원과 성능을 제공합니다.

기존 서비스를 업그레이드하기로 결정한 이유를 알아보고 Pingora 시스템의 개발 과정을 살펴보겠습니다. 이 시스템은 Cloudflare의 고객 사용 사례와 규모에 맞게 특별히 설계되었습니다.

다른 에이전트를 구축해야 하는 이유

최근에는 NGINX를 사용할 때 몇 가지 제한 사항에 직면했습니다. 일부 제한 사항의 경우 이를 우회할 수 있는 방법을 최적화하거나 채택했습니다. 그러나 더 어려운 몇 가지 제한 사항이 있습니다.

건축적 제한으로 인해 성능이 저하됨

NGINX 작업자(프로세스) 아키텍처 [4]에는 우리 사용 사례에 대한 운영상의 결함이 있어 성능과 효율성이 저하됩니다.

우선, NGINX에서는 각 요청을 단일 작업자만 처리할 수 있습니다. 이로 인해 모든 CPU 코어 간의 로드 불균형이 발생하고[5] 속도 저하가 발생합니다[6].

이러한 요청 프로세스 잠금 효과로 인해 CPU 집약적이거나 IO 작업을 차단하는 요청은 다른 요청의 속도를 저하시킬 수 있습니다. 이 블로그 게시물에서 알 수 있듯이 우리는 이러한 문제를 해결하는 데 많은 시간을 투자했습니다.

우리 사용 사례에서 가장 중요한 문제는 연결 재사용입니다. 이는 우리 컴퓨터가 원본 서버와 TCP 연결을 설정하여 HTTP 요청을 프록시할 때 발생합니다. 연결 풀의 연결을 재사용하면 새 연결에 필요한 TCP 및 TLS 핸드셰이크를 건너뛸 수 있으므로 요청의 TTFB(첫 번째 바이트까지의 시간) 속도가 빨라집니다.

그러나 NGINX 연결 풀[9]은 단일 작업자에 해당합니다. 요청이 작업자에 도달하면 해당 작업자 내의 연결만 재사용할 수 있습니다. 확장을 위해 더 많은 NGINX 작업자를 추가하면 연결이 모든 프로세스에서 더 격리된 풀에 분산되기 때문에 연결 재사용이 더욱 악화됩니다. 이로 인해 TTFB 속도가 느려지고 유지해야 할 연결이 많아져 당사와 고객의 리소스(및 비용)가 소모됩니다. Pingora有多牛逼!超受欢迎 Web 服务器超越Nginx

이전 블로그 게시물에서 언급했듯이 이러한 문제 중 일부에 대한 해결 방법이 있습니다. 그러나 근본적인 문제인 작업자/프로세스 모델을 해결할 수 있다면 이러한 모든 문제는 자연스럽게 해결될 것입니다.

일부 유형의 기능은 추가하기 어렵습니다

NGINX는 훌륭한 웹 서버, 로드 밸런서 또는 간단한 게이트웨이입니다. 하지만 Cloudflare는 그 이상을 수행합니다. 우리는 NGINX를 중심으로 필요한 모든 기능을 구축했지만 NGINX 업스트림 코드베이스에서 너무 많은 차이를 피하는 것은 쉽지 않았습니다.

예를 들어, 요청/요청 실패[10]를 재시도할 때 때로는 다른 요청 헤더 세트를 사용하여 다른 원본 서버로 요청을 보내고 싶을 때가 있습니다. 하지만 NGINX는 이를 허용하지 않습니다. 이 경우 NGINX의 한계를 해결하기 위해 시간과 노력을 투자해야 합니다.

동시에 우리가 강제로 사용해야 하는 프로그래밍 언어는 이러한 어려움을 완화하는 데 도움이 되지 않습니다. NGINX는 순수하게 C로 작성되었으므로 설계상 메모리 안전이 보장되지 않습니다. 이와 같은 타사 코드 기반을 사용하면 오류가 발생하기 쉽습니다. 숙련된 엔지니어라도 메모리 안전 문제에 빠지기 쉬우므로[11], 우리는 이러한 문제를 최대한 피하고 싶습니다.

C를 보완하기 위해 사용하는 또 다른 언어는 Lua입니다. 덜 위험하지만 성능도 떨어집니다. 게다가 복잡한 Lua 코드와 비즈니스 로직을 다룰 때 정적 타이핑이 누락되는 경우가 종종 있습니다[12].

그리고 NGINX 커뮤니티는 그다지 활발하지 않으며 개발이 "밀폐된 문 뒤에서" 수행되는 경우가 많습니다[13].

직접 구축하려면 선택하세요

지난 몇 년 동안 고객 기반과 기능 세트가 계속해서 성장함에 따라 우리는 세 가지 옵션을 계속 평가해 왔습니다.

  • 1. NGINX에 계속 투자하고 비용을 지불하여 우리의 요구 사항을 100% 충족시킵니다. 우리는 필요한 전문 지식을 갖추고 있지만 위에서 언급한 아키텍처 제한을 고려할 때 우리의 요구 사항을 완전히 지원하는 방식으로 이를 재구축하려면 많은 노력이 필요할 것입니다.
  • 2. 다른 타사 프록시 코드 베이스로 마이그레이션합니다. 확실히 envoy[14]나 기타[15] 같은 좋은 프로젝트가 있습니다. 하지만 그 길은 몇 년 안에 같은 주기가 반복될 수 있다는 것을 의미합니다.
  • 3. 내부 플랫폼과 프레임워크를 처음부터 구축하세요. 이 옵션을 사용하려면 엔지니어링에 대한 최대 규모의 선행 투자가 필요합니다.
  • 지난 몇 년 동안 우리는 분기마다 이러한 옵션을 평가했습니다. 어떤 옵션이 가장 좋은지 결정하는 명확한 공식은 없습니다. 몇 년 동안 우리는 계속해서 저항이 가장 적은 길을 택했고 NGINX를 계속해서 향상시켰습니다. 그러나 어떤 경우에는 자체 대행사를 구축하는 ROI가 더 가치 있어 보일 수도 있습니다. 우리는 처음부터 에이전트를 구축하고 드림 에이전트 애플리케이션을 설계하기 시작했습니다.

    핑고라 프로젝트

    디자인 결정

    초당 수백만 건의 요청을 처리할 수 있는 빠르고 효율적이며 안전한 프록시를 구축하기 위해 먼저 몇 가지 중요한 설계 결정을 내려야 했습니다.

    우리는 Rust[16]를 프로젝트 언어로 선택했습니다. 왜냐하면 C가 성능에 영향을 주지 않고 메모리에 안전한 방식으로 할 수 있는 일을 할 수 있기 때문입니다.

    hyper[17]와 같은 훌륭한 기성 타사 HTTP 라이브러리가 있지만 우리는 HTTP 트래픽 처리의 유연성을 최대화하고 우리의 속도에 맞춰 수행할 수 있기를 원했기 때문에 자체 라이브러리를 구축하기로 결정했습니다. 혁신.

    Cloudflare에서는 전체 인터넷의 트래픽을 처리합니다. 우리는 이상하고 RFC를 준수하지 않는 HTTP 트래픽 사례를 많이 지원해야 합니다. 이는 HTTP 사양을 엄격하게 따르는 것과 잠재적 레거시 클라이언트 또는 서버의 광범위한 생태계의 미묘한 차이에 적응하는 것 사이에서 어려운 선택을 해야 하는 HTTP 커뮤니티와 웹의 일반적인 딜레마입니다.

    HTTP 상태 코드는 RFC 9110에 세 자리 정수[18]로 정의되어 있으며 일반적으로 100~599 범위에 있을 것으로 예상됩니다. Hyper는 그러한 구현 중 하나입니다. 그러나 많은 서버는 599에서 999 사이의 상태 코드 사용을 지원합니다. 우리는 논쟁의 다양한 측면을 탐구하는 이 기능에 대한 질문 [19]을 만들었습니다. 하이퍼 팀은 결국 이 변경 사항을 수락했지만 그러한 요청을 거부할 타당한 이유가 있었으며 이는 우리가 지원해야 하는 많은 비준수 사례 중 하나에 불과했습니다.

    HTTP 생태계에서 Cloudflare의 위치를 ​​이행하려면 인터넷의 다양한 위험 환경에서 살아남고 다양한 비준수 사용 사례를 지원할 수 있는 강력하고 관대하며 사용자 지정 가능한 HTTP 라이브러리가 필요합니다. 이를 보장하는 가장 좋은 방법은 자체 아키텍처를 구현하는 것입니다.

    다음 설계 결정은 워크로드 스케줄링 시스템에 관한 것입니다. 우리는 리소스, 특히 연결 풀링을 쉽게 공유하기 위해 멀티프로세싱[20] 대신 멀티스레딩을 선택합니다. 위에서 언급한 특정 범주의 성능 문제를 피하기 위해 작업 도용[21]도 구현되어야 한다고 생각합니다. Tokio 비동기 런타임은 우리의 요구에 완벽하게 들어맞습니다[22].

    마지막으로 우리는 프로젝트가 직관적이고 개발자 친화적이기를 원합니다. 우리가 구축하고 있는 것은 최종 제품이 아니지만 그 위에 더 많은 기능이 구축됨에 따라 플랫폼으로 확장 가능해야 합니다. 우리는 NGINX/OpenResty[23]와 유사한 "요청 수명 주기" 이벤트를 기반으로 프로그래밍 가능한 인터페이스를 구현하기로 결정했습니다. 예를 들어, 요청 필터 단계를 통해 개발자는 요청 헤더가 수신될 때 요청을 수정하거나 거부하는 코드를 실행할 수 있습니다. 이 디자인을 통해 비즈니스 로직과 공통 프록시 로직을 명확하게 분리할 수 있습니다. 이전에 NGINX를 사용하던 개발자는 쉽게 Pingora로 전환하여 생산성을 빠르게 높일 수 있습니다.

    Pingora의 제작 속도가 더 빠릅니다

    이제 빨리 감아 보겠습니다. Pingora는 원본 서버와의 상호 작용(예: 캐시 누락)이 필요한 거의 모든 HTTP 요청을 처리하며, 그 과정에서 많은 성능 데이터를 수집합니다.

    먼저 Pingora가 어떻게 고객의 트래픽 속도를 높이는지 살펴보겠습니다. Pingora의 전체 트래픽은 TTFB 감소 중앙값이 5ms, 95번째 백분위수가 80ms 감소한 것으로 나타났습니다. 코드를 더 빨리 실행하기 때문이 아닙니다. 기존 서비스도 밀리초 미만 범위의 요청을 처리할 수 있습니다.

    모든 스레드에서 연결을 공유하는 새로운 아키텍처를 통해 시간이 절약됩니다. 이는 연결 재사용이 향상되고 TCP 및 TLS 핸드셰이크에 소요되는 시간이 단축된다는 것을 의미합니다. Pingora有多牛逼!超受欢迎 Web 服务器超越Nginx

    모든 고객을 대상으로 Pingora의 신규 연결은 이전 서비스에 비해 초당 1/3에 불과합니다. 한 주요 고객의 경우 연결 재사용이 87.1%에서 99.92%로 증가하여 새로운 연결이 160배 감소했습니다. 관점에서 보면, Pingora로 전환함으로써 우리는 고객과 사용자가 매일 434년 동안 악수하는 시간을 절약할 수 있었습니다.

    추가 기능

    엔지니어에게 친숙한 개발자 친화적인 인터페이스를 제공하는 동시에 이전 제한 사항을 제거하여 더 많은 기능을 더 빠르게 개발할 수 있습니다. 새로운 프로토콜과 같은 핵심 기능은 고객에게 더 많은 것을 제공하는 방법을 위한 구성 요소 역할을 합니다.

    예를 들어, 우리는 큰 장애물 없이 Pingora에 HTTP/2 업스트림 지원을 추가할 수 있었습니다. 이를 통해 우리는 고객에게 곧 gRPC를 제공할 수 있습니다[24]. NGINX에 동일한 기능을 추가하려면 더 많은 엔지니어링 노력이 필요하며 불가능할 수도 있습니다[25].

    최근 Pingora가 R2 스토리지를 캐싱 계층으로 사용하는 Cache Reserve[26]의 출시를 발표했습니다. Pingora에 더 많은 기능을 추가함에 따라 이전에는 불가능했던 새로운 제품을 제공할 수 있게 되었습니다.

    더 효율적

    프로덕션에서 Pingora는 동일한 트래픽 부하에서 기존 서비스보다 약 70% 적은 CPU와 67% 적은 메모리를 소비합니다. 절감 효과는 여러 가지 요인에서 비롯됩니다.

    우리의 Rust 코드는 이전 Lua 코드[27]보다 더 효율적으로 실행됩니다[28]. 게다가 아키텍처에도 효율성 차이가 있습니다. 예를 들어 NGINX/OpenResty에서 Lua 코드가 HTTP 헤더에 액세스하려면 NGINX C 구조에서 이를 읽고 Lua 문자열을 할당한 다음 이를 Lua 문자열에 복사해야 합니다. 그 후 Lua는 새 문자열도 가비지 수집합니다. Pingora에서는 단순한 문자열 액세스입니다.

    멀티스레딩 모델을 사용하면 여러 요청에 걸쳐 데이터를 더욱 효율적으로 공유할 수 있습니다. NGINX에도 공유 메모리가 있지만 구현 제한으로 인해 각 공유 메모리 액세스는 뮤텍스를 사용해야 하며 문자열과 숫자만 공유 메모리에 넣을 수 있습니다. Pingora에서는 대부분의 공유 항목에 원자 참조 카운터 뒤의 공유 참조를 통해 직접 액세스할 수 있습니다[29].

    위에서 언급했듯이 CPU 절약의 또 다른 중요한 부분은 새로운 연결의 감소입니다. TLS 핸드셰이크는 설정된 연결을 통해 데이터를 보내고 받는 것보다 확실히 비용이 더 많이 듭니다.

    더 안전하게

    저희 규모에서는 신속하고 안전하게 기능을 출시하는 것이 어렵습니다. 초당 수백만 건의 요청을 처리하는 분산 환경에서 발생할 수 있는 모든 극단적인 상황을 예측하는 것은 어렵습니다. 퍼지 테스트와 정적 분석은 그 정도만 완화할 수 있습니다. Rust의 메모리 안전 의미 체계는 정의되지 않은 동작으로부터 우리를 보호하고 서비스가 올바르게 실행될 것이라는 확신을 줍니다.

    이러한 보장을 통해 우리는 서비스 변경 사항이 다른 서비스 또는 고객 소스와 어떻게 상호 작용하는지에 더 집중할 수 있습니다. 우리는 메모리 안전과 진단하기 어려운 충돌에 얽매이지 않고 더 높은 속도로 기능을 개발할 수 있었습니다.

    충돌이 발생하면 엔지니어는 충돌이 어떻게 발생했는지, 원인이 무엇인지 진단하는 데 시간을 투자해야 합니다. Pingora가 설립된 이후로 우리는 수천억 건의 요청을 처리했으며 서비스 코드로 인해 아직 충돌이 발생하지 않았습니다.

    사실 Pingora 충돌은 매우 드물기 때문에 충돌이 발생하면 일반적으로 관련 없는 문제를 발견합니다. 최근 서비스가 중단되기 시작한 직후에 커널 버그[30]를 발견했습니다. 또한 과거에는 중요한 디버깅이 거의 불가능했음에도 불구하고 소프트웨어로 인해 발생하는 드문 메모리 오류를 배제했던 일부 컴퓨터에서 하드웨어 문제를 발견했습니다.

    요약

    요약하자면, 우리는 현재와 미래의 제품을 위한 플랫폼 역할을 하는 더 빠르고 효율적이며 다재다능한 사내 에이전트를 구축했습니다.

    우리가 직면한 문제와 애플리케이션 최적화에 대한 기술적인 세부 사항은 물론, Pingora를 구축하고 인터넷의 중요한 부분을 지원하기 위해 출시하면서 배운 교훈에 대해서는 나중에 다루겠습니다. 우리는 또한 오픈 소스 이니셔티브를 소개할 것입니다.

    이 기사는 Yuchen Wu와 Andrew Hauck이 작성한 CloudFlare 블로그에서 복제되었습니다

    링크: https://blog.cloudflare.com/zh-cn/how-we-build-pingora-the-proxy-that-connects-cloudflare-to-the-internet-zh-cn/

    위 내용은 Pingora는 얼마나 멋진가요! 초인기 웹서버, Nginx 능가의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    관련 라벨:
    원천:mryunwei.com
    본 웹사이트의 성명
    본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
    인기 튜토리얼
    더>
    최신 다운로드
    더>
    웹 효과
    웹사이트 소스 코드
    웹사이트 자료
    프론트엔드 템플릿
    회사 소개 부인 성명 Sitemap
    PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!