2016-10-24 2 views
0

트래픽이 적은 영구 연결에 대해 적어도 약 1000 가지 (앞으로는 훨씬 더 많은) 처리 할 소켓 서버를 작성해야합니다. 필자는 테스트 용 PHP 초안을 만들었습니다. (우리는 모니터링 하드웨어를 개발 중입니다. 따라서 대화 프로토콜과 하드웨어 기능을 개발하고 테스트해야했습니다.) 저는 클라이언트 몇 대를 연결했을 때 저에게 잘 맞았습니다. 그러나 연결 수가 10 개가되었을 때 몇 가지 중요한 문제가 나타났습니다. 여기에 서버 아키텍처에 대한 정보가 있습니다 :PHP 소켓 서버 문제 (mysql 연결, 최대 연결 제한)

나는 소켓 연결을 기다리고 연결시 pcntl_fork()를 사용하여 자식 프로세스 (이 연결을 제공함)를 만듭니다. 또한 마스터 프로세스에서 MySQL에 대한 PDO 연결을 설정 중입니다. 모든 하위 프로세스는 동일한 단일 PDO 객체를 공유합니다. 처음에는 동시 쿼리 중에 충돌이 발생하는 것을 두려워했지만 스트레스 테스트 (10 명의 어린이가 멈추지 않고 루프에서 쿼리를 작성하는 경우)를 통해조차도 발생하지 않았습니다. 그러나 각 어린이에게는 약 5 만 명이 달려 있기 때문에 운이 좋을 수도 있습니다.하지만이 테스트는 2 시간 정도 걸렸습니다. 하지만 이러한 부하는 서버와 서버 간의 희귀 한 대화로 인해 연결된 1k 클라이언트에서도 존재하지 않아야합니다.

여기 내 첫 번째 질문입니다. 대용량의 하위 프로세스에 대해 단일 PDO 개체를 사용하는 것이 안전합니까 (이상적으로 1000 개 정도가되는 것이 이상적입니까). 각 자식에 대해 단일 연결을 사용할 수 있지만 MySQL은 거의 많은 연결을 지원하지 않습니다.

두 번째 문제는 기생충 MySQL 연결을 얻는 데 있습니다. 앞서 언급했듯이 PDO 객체는 하나뿐입니다. 하지만 하나 이상의 클라이언트가 연결되어 있고 쿼리를 실행 한 후에 mytop에 하나 이상의 DB 연결이 있고 연결 수와 자식 프로세스의 양 사이에 상관 관계를 찾을 수 없습니다. . 예를 들어 나는 3 개의 자식과 5 개의 DB 연결을 가지고있다. 영구 연결을 설정하려고 시도했지만 아무 것도 변경하지 않았습니다.

두 번째 질문 : 해당 추가 연결을 MySQL에 만드는 PDO입니까? 아니면 MySQL 드라이버입니까? 한 연결을 사용하도록 강제 할 수있는 방법이 있습니까? 나는 그것이 내 잘못 일 수 있다고 생각하지 않는다. 내 코드는 PDO 객체를 생성하는 메소드를 호출 할 때마다 콘솔에 경고를 출력한다. 그리고 그것은 스크립트 시작시, 포킹 전에 한 번만 발생한다. 그 후에는 부모의 PDO 객체를 사용하여 하위 노드에서만 쿼리를 실행합니다. 다시 한번 MySQL 제한으로 인해 많은 연결을 가질 여유가 없습니다.

세 번째 질문 : 소켓 연결 자체가 문제 일 수 있습니까? CPU와 데이터베이스 부하를 제외하면 말입니다. 아니면 내가 (예를 들어, 128 연결), 클라이언트의 다른 하나에 최대 연결 수가 초과되면 연결 알려주는 적은 양의 서버를해야합니까?

시간과 가능한 답변에 미리 감사드립니다.

+0

왜 애플리케이션과 데이터베이스 사이에 레이어를 만들겠습니까? 연결 풀링과 연결 재사용에 대해 들어 본 적이 있습니까? 나는 무례한 소리를 내고 싶지 않지만 당신이 경험 한 것만 큼 큰 프로젝트를위한 서비스를 구축하는 것만으로는 충분하지 않은 것 같습니다. – DanFromGermany

+0

귀하의 의견에 대해 무례한 점은 없으며, 그 분야에서 많은 경험이 없기 때문에 기본적으로 질문했습니다. 그러나 우리 모두는 어디에서 시작해야할까요? 또한 나는 연결 풀링이 무엇인지 모르는 초록색이 아니지만, 우리의 계산에 따르면 하나의 DB 연결만으로도 우리의 요구에 맞을 것입니다 (최악의 경우 초당 2 회 이상의 간단한 쿼리가 있어서는 안됩니다). 내 문제는 포크의 작동 방식에 대한 이해가 부족하다는 사실이었습니다. – navij

답변

0

현재 가장 중요한 관심사는 소켓 서버 아키텍처입니다. 각 클라이언트에 대한 프로세스 포킹은 매우 무겁습니다. AFAIK 평균적인 PC는 약 2000 개의 스레드를 허용 할 수 있으며 빠르게 작동하지 않습니다. 프로세스 간 전환은 CPU가 메모리에 상태를 저장해야한다는 것을 의미하며 엄청난 양의 프로세스가있는 경우 CPU가 메모리 IO를 사용하여 실제 작업을 수행하는 데 약간의 시간이 소요됩니다.

영감을 얻기 위해 아파치를보고 싶을 수도 있습니다. 아파치에서는 고정 된 양의 작업자 프로세스/쓰레드를 사용하는데, 각 프로세스/쓰레드는 select 함수와 소켓을 통해 여러 클라이언트와 함께 작동하며 비 차단 모드로되어 있습니다. 이것은 훨씬 더 견고한 접근법입니다.

데이터베이스 IO에 대해서는 데이터베이스 연결의 유일한 소유자가 될 프로세스/스레드를 생성합니다. 작업자 프로세스는 IPC (프로세스의 경우) 또는 잠금없는 큐 (스레드의 경우)를 사용하여 DB IO 프로세스와 통신합니다. 이 접근법은 PDO 구현 세부 사항으로부터 독립적입니다 (스레드가 안전하거나 연결을 생성하는 경우).

P. S. 나는 당신이 실제로 새로운 PDO 산란 의심은 분기 (분기 단지 안에 메모리와 모든 것을 프로세스의 복사본을 의미) 및 PDO 객체를 생성하고 필요에 따라 연결을 종료 개체. 트래픽이 적은 클라이언트와 DB 연결 사이에 상관 관계가 표시되지 않는 이유를 설명 할 수 있습니다.

+0

일부 문구가 잘못되었습니다. 프로세스 포크는 새로운 (하위) 프로세스를 생성합니다. 스레드는 프로세스/포크가 아닙니다. 16 개의 CPU 코어를 가지고 있다면 동일한 프로그램의 15 개 이상의 스레드를 동시에 시작해서는 안됩니다. – DanFromGermany

+0

@DanFromGermany 당신은 분명히 포크로는 맞지만 당신의 의견과 대답 사이에는 모순이 보이지 않습니다. 또한, _thread_와 _process_라는 용어는 상호 교환 적으로 사용합니다. 왜냐하면 대부분의 게시물이 두 가지 모두에 해당되기 때문입니다. "모든 것을위한 프로세스 사용"이이 작업에 대한 올바른 접근 방식이라고 확신하지는 않습니다. – Vovanrock2002

+0

@DanFromGermany 또는 PHP의'fork'는 C의'fork'와는 다른가요? C에서는 동일한 명령어를 가리키는 명령어 포인터 인 경우에도 상위 프로세스의 사본을 생성합니다. 유일한 차이점은'fork' 리턴 값입니다 - 이것은 parent 나 smth와 같이 0입니다. – Vovanrock2002