2017-03-22 7 views
1

Linux에서 실행되며 TCP를 사용하는 푸시 기반 메시징 서비스를 구현하는 C++로 작성된 서버 프로그램이 있습니다. 푸시 방식으로 인해 더 긴 시간 동안 열어 두어야하는 많은 동시 연결 (약 1 백만 개를 계획 중)이있을 수 있습니다. 대부분의 경우 이러한 연결은 가끔씩 중단되어 유휴 상태가되며 전송은 대다수의 경우 동시에 발생합니다.많은 수의 파일 설명자와 함께 select()를 사용하는 외부 코드

대량의 소켓을 멀티플렉싱하기 위해 epoll을 사용하고 RLIMIT_NOFILE을 수정하여 실제로 많은 양의 소켓에서 잘 작동합니다.

내 문제는 동일한 프로그램에서 다른 유형의 연결, 특히 FastCGI (FastCGI SDK의 libfcgi 사용)가 내부 파일 설명자에 select()을 사용하는 HTTP 요청을 받아들이는 것입니다. 이는 파일 설명자가 1024 (FD_SETSIZE)보다 커지면 프로그램의 epoll 부분이 1024 이하의 대부분의 fd 숫자를 사용하면 발생합니다.

가장 좋은 방법은 무엇인지 궁금합니다. 이 문제를 처리 할 수 ​​있습니다.

select()을 사용하는 외부 코드를 모두 수정하고 poll()을 대신 사용해야합니까?

epoll 기반 코드 (특히 accept() 호출)가 1024보다 큰 파일 설명자 만 사용하도록 유도 할 수 있습니까? 아래 내용은 select() 기반 코드입니다.

나는 FD_SETSIZE의 가치를 어떻게 든 올릴 수 있다고 생각하지만, select()이 작동하는 방식 때문에 성능이 많이 나빠질 것이라고 생각합니다. 실제 해결책이 아니라 해킹으로 생각합니다.

답변

1

나는 자신의 파일 디스크립터를 얻을 수 있도록 이러한 것들을 자신의 프로세스로 옮기는 것이 좋습니다. 내가 제안하는 것은 단일 TCP 연결을 통해 많은 수의 TCP 연결을 멀티플렉싱하는 프로토콜을 가지고 있다는 것입니다. 서버가 개별 클라이언트가 아닌 멀티플렉서와 ​​통신합니다. 멀티플렉서는 동일한 시스템 또는 다른 시스템에서 실행될 수 있으며 수만 개의 클라이언트 연결을 처리 할 수 ​​있으며 서버에 대한 단일 연결 만 수행합니다.

큰 장점 중 하나는 서버 컴퓨터가 많은 TCP 연결 상태를 처리 할 필요가 없다는 것입니다. 패킷 삭제, 재전송, 중복 패킷, 잘못된 SYN, 느린 링크 등과 같은 인터넷 정크를 처리 할 필요가 없습니다. 각 클라이언트마다 버퍼를 보낼 필요는 없지만 클라이언트의 버퍼링을 수행 할 수있는 빠르고 깨끗한 멀티플렉서 만 사용해야합니다.

이 작업이 너무 많거나 불가능할 경우 dup2을 사용하여 파일 설명 자의 번호를 높은 번호의 설명자로 다시 지정할 수 있습니다. 멀티플렉서를 사용할 것을 강력하게 제안합니다. 처리하려는 연결 수는 단일 프로세스에서 너무 많습니다.

+0

서버는 이미 여러 인스턴스로 실행되도록되어 있으며 클라이언트는 무작위로 또는로드에 따라 사용 가능한 서버 중 하나를 선택합니다. 다른 멀티플렉싱 레이어를 추가하는 것도 가능하지만 코드를 더 많이 변경해야하기 때문에 지금은이 방법을 사용하고 싶지 않습니다. dup2는 유망한 것으로 들립니다. 이제는'dup2'에 전달 된'newfd'가 다른 곳에서 이미 사용되지 않았는지 확인해야합니다. 왜냐하면'dup2'가 임의의 fds를 닫는 것을 원하지 않기 때문입니다. –

+0

"처리하려는 연결 수가 너무 많아 단일 프로세스에서 처리 할 수 ​​없습니다."정말 그렇게하니? 그들은 대부분의 시간 동안 유휴 상태이며 어떤 것이 옮겨지면 실제로 모든 사람들 (또는 그들 그룹)에게 동일한 데이터입니다. 나는 TCP 재전송이 많은 클라이언트들에게 문제가 될 것이라고 생각한다. (다른 VM을 사용하는 클라이언트와 동일한 물리적 인 머신상의 서버와 클라이언트로 대부분 테스트했다.) 그러나 서버가 모든 요청에 ​​대해 내 유스 케이스에 충분히 빠르다. –

+0

@AlemariusNexus 시작할 때, 설정 한도만큼 많은 파일 기술자를여십시오 (아마도'/ dev/null'을 열어서). 1,024 이하를 닫으십시오. 이제'dup2'에 파일 디스크립터 풀이 있습니다. 파일 디스크립터가 끝나면 파일 디스크립터를 닫지 않고 여분의 파일 디스크립터 중 하나를'dup2 '한다. –