2009-10-22 3 views
7

나는 20-150K TCP 연결을 동시에 처리해야하는 C로 작성하는 데몬이 있습니다. 그들은 장기간 연결이되어 거의 찢어지지 않습니다. 그들은 어떤 주어진 시간에 전송에서 매우 적은 양의 데이터 (자극/응답 프로토콜 일지라도 MTU를 초과하는 경우는 거의 없음)가 있지만 응답 시간은 중요합니다. 나는 현재 유닉스 커뮤니티가 많은 양의 소켓을 얻고 그 응답 지연을 최소화하기 위해 무엇을 사용하고 있는지 궁금하다. 멀티플렉싱을 중심으로하는 디자인이 작업자 풀, 스레드 (연결 당), 고정 크기 스레드 풀에 연결되는 것을 보았습니다. 어떤 제안?현대 멀티 코어/멀티 소켓 머신에서 TCP 수신기를 확장하는 방법

+2

질문을 다시 포맷하십시오. 하나의 수평 스크롤 라인은별로 도움이되지 않습니다. – ndim

+0

왜 C입니까? 얼랭이라고 할 수 없니? – jldupont

+2

@jldupont, 언어 문제가 있습니까? 그것은 언어의 제약과는 반대로 시스템 질문처럼 보입니다. – mrduclaw

답변

7

가장 쉬운 제안은 libevent을 사용하는 것이므로 요구 사항을 준수하는 간단한 비 차단 단일 스레드 서버를 쉽게 작성할 수 있습니다.

각 응답 처리에 시간이 걸리거나 일부 차단 API (예 : DB의 거의 모든 항목)를 사용하는 경우 스레딩이 필요합니다.

  • 하나의 대답은 작동 대기열에서 수신 대기하는 일련의 스레드를 생성하는 작업자 스레드입니다. 원할 경우 스레드 대신 별도의 프로세스가 될 수 있습니다. 가장 큰 차이점은 근로자들에게해야 할 일을 알려주는 의사 소통 체계가 될 것입니다.

  • 다른 방법은 여러 스레드를 사용하고 각 스레드에 150K 연결의 일부를 제공하는 것입니다. 각각은 자신의 프로세스 루프를 가지며 리스닝 포트를 제외하고 싱글 스레드 서버와 거의 동일하게 작동합니다. 리스닝 포트는 단일 스레드에 의해 처리됩니다. 이렇게하면 코어간에로드가 분산되는 데 도움이되지만 차단 리소스를 사용하면이 특정 스레드에서 처리하는 모든 연결이 차단됩니다.

libevent는 신중하게 두 번째 방법을 사용합니다. 그러나 또 다른 대안이 있습니다 : libev. libevent로 잘 알려져 있지 않지만 멀티 루프 구조를 지원합니다.

+1

작업자 스레드 모델과 작업자 프로세스 모델을 모두 고려해야합니다. 실제로 이것을 확장하려는 경우 스레드와 프로세스 모두에 대한 코드를 작성한 다음 시간을 측정해야합니다. 최신 Linux 커널 프로세스에서 전환 오버 헤드는 스레드 전환과 비슷하지만 잠금 세마포를 수행 할 필요가 없습니다. –

0

select (2) 성능을 개선하기 위해 여러 시스템이 개발되었습니다. kqueue, epoll/dev/poll. 이 모든 시스템에서 작업을 기다리는 작업자 스레드 풀을 가질 수 있습니다. 둘 중 하나를 다 끝 마쳤을 때 모든 파일 핸들을 반복해서 설정하지 않아도됩니다.

0

처음부터 시작해야합니까? gearman과 같은 것을 사용할 수 있습니다.

+0

기어맨이 대기 시간이 많이 걸릴 것 같습니다 (별도의 작업 서버로 인해). – cmeerw

+0

나는 똑같은 생각을하고있었습니다 ... 비 반응 응답 시간과 일괄 처리에 대해서는 괜찮을 것 같습니다. – Obi

1

당신이 그것을을 초과하지 않는 시스템 구성 액세스 이이 같은 n 개의 데몬 인스턴스 (프로세스)를 통해 로드 밸런스 연결 일부의 iptables/PF/등을 설정하면 상자 밖으로 작동합니다 . 데몬의 특성을 차단하는 방법에 따라 n은 시스템의 코어 수 또는 몇 배 이상이어야합니다. 이 방법은 원유처럼 보이지만 손상된 데몬을 처리 할 수 ​​있으며 필요한 경우 다시 시작하기도합니다. 또한 마이그레이션은 서비스 중단 대신 새로운 연결을 다른 프로세스 집합 (예 : 새 릴리스 또는 새 상자로 마이그레이션)으로 전환하기 시작할 수 있으므로 부드럽게이됩니다. 그 중에서도 소스 선호도과 같은 몇 가지 기능을 사용하면 문제가되는 세션의 캐싱 및 경합이 크게 향상 될 수 있습니다. 당신이 시스템에 액세스 할 수없는 (또는 작전이 성가 시게 할 수없는) 경우

, 대신 iptables에/PF/등의 (오픈 소스 사람의 많음이있다) 로드 밸런서 데몬를 사용하고도 사용할 수 없음 서비스 데몬.

또한이 접근 방식은 포트 12 개를 구분하는 데 도움이됩니다. 외부 서비스가 낮은 포트 (< 1024)로 서비스해야하는 경우 특권 또는 관리자/루트 또는 커널을 실행하는로드 밸런서 만 필요합니다.

저는 과거에 여러 IP로드 밸런서를 작성했으며 생산 과정에서 매우 오류가 날 수 있습니다. 당신은 그것을 지원하고 디버그하고 싶지 않습니다. 또한 운영 및 관리는 외부 코드보다 코드를 추측하는 경향이 있습니다.

+1

웹 서버가 아닙니다. :) 많은 클라이언트를위한 서버입니다. 클라이언트는 TCP 연결을 유지하고 입력에 대해 예상되는 응답을받습니다. – Obi

+0

** ** 많은 매드 매거진을 ** 아이 **로 읽으셨습니까? – caf

+0

@Obi iptables/pf는 HTTP가 아닌 IP/TCP/UDP입니다. 라이브러리 (libevent?), 스레딩 또는 직선 OpenMP를 사용할 수 있습니다. 마지막은 소스의 특정 중요 지점에서 많은 코어 간 밸런싱을 수행 할 수 있습니다. 또한 인텔의 최근 nehalem/i7은 다시 하이퍼 스레딩을하지만 ICC 또는 GCC가 OpenMP로 이미 지원하는지 (2000 년 초에 이전의 하이퍼 스레딩 시대에 사용했는지는 알 수 없음) IMHE threading provide 동기화 및 캐시 혼합으로 인한 O (n^2) 성능 저하. 또한 일반적으로 분기 예측 오류가 많이 발생합니다. YMMV. @caf ** 무엇 **? – alecco

2

성능이 중요한 경우에는 멀티 스레드 이벤트 루프 솔루션 즉, 연결을 처리하는 작업자 스레드 풀이 필요합니다. 불행하게도, 대부분의 Unix 플랫폼에서 작동하는 추상화 라이브러리가 없습니다 (libevent는 이러한 이벤트 루프 라이브러리의 대부분이 단일 스레드 임에 유의하십시오). 따라서 더러운 작업을 스스로해야합니다.

작업자 스레드의 풀과 에지 트리거는 epoll를 사용하여 의미 Linux에서

(윈도우 I/또한 다중 스레드 환경에서 잘 작동 O 완료 포트를 할 것이다 - 나는 다른 유닉스에 대한 확실하지 않다).

나는 리눅스와 윈도우 I/O 완료 포트에서 추상화를 시도하는 일부 작업을 http://nginetd.cmeerw.org (수행 중이지만 몇 가지 아이디어를 제공 할 수도 있음)했다.

1

제 생각에는 javier의 답변이 가장 적절하다고 생각합니다. 이론을 테스트하려면 node 자바 스크립트 프로젝트를 확인하십시오.

노드는 자바 스크립트를 기계어로 컴파일하는 Google의 v8 엔진을 기반으로하며 특정 작업에서는 c만큼 빠릅니다. 또한 libev를 기반으로하며 완전히 블로킹되지 않도록 설계되었습니다. 즉, 스레드 간 컨텍스트 전환 (모든 것이 단일 이벤트 루프에서 실행 됨)에 대해 걱정할 필요가 없습니다. 그것은 그 점에서 erlang과 매우 유사합니다.

자바 스크립트로 고성능 서버를 작성하는 것은 이제 노드를 사용하여 정말 쉽습니다. 또한 약간의 노력으로 사용자 정의 코드를 작성하고 노드에 대한 바인딩을 호출하여 실제 처리를 수행 할 수 있습니다 (노드 소스를보고이를 수행하는 방법을 참조하십시오. 문서는 다소 간단합니다). 순간). 추악한 대안으로 사용자 정의 C 코드를 응용 프로그램으로 빌드하고 stdin/stdout을 사용하여 통신 할 수 있습니다.

노드를 직접 테스트 한 결과 아무런 문제없이 150k 연결 이상을 테스트했습니다 (물론이 모든 연결이 동시에 통신하려면 심각한 하드웨어가 필요합니다). 평균 node.js의 TCP 연결은 2-3k의 메모리 만 사용하므로 이론적으로 1GB의 RAM 당 350-500k 연결을 처리 할 수 ​​있습니다.

주 - Node.js는 현재 Windows에서 지원되지 않지만 개발 초기 단계 일 뿐이므로 일부 단계에서 이식 될 것이라고 생각합니다.

주 2 - 노드에서 호출하는 코드가 차단되지 않도록해야합니다.

+0

그냥 참고 ... 노드는 이제 기본 라이브러리 인 libuv (libevent와 비슷 함)를 통해 Windows에서 완전히 지원됩니다. libuv는 실제로 Windows의 non-blocking IOCP API를 성공적으로 감싸면서 실제로 libevent보다 Windows에서 빠를 것입니다. 앞서 언급했듯이, libuv는 Windows에서 libevent보다 확장 성이 뛰어날 것입니다 (libevent가 IOCP를 래핑 할 때까지). 그러나 플랫폼 간 비 차단 애플리케이션을 작성하려면 libuv와 libevent 모두 매우 적합한 옵션입니다. – andrew