Swoole 서버에 대한 간략한 분석

coldplay.xixi
풀어 주다: 2021-03-11 09:52:08
앞으로
1869명이 탐색했습니다.

Swoole 서버에 대한 간략한 분석

1. 기본 지식

1.1 Swoole

Swoole은 PHP 개발자가 Swoole을 사용하여 고성능 서버 서비스를 개발할 수 있는 제품입니다. Swoole의 서버 부분에는 많은 콘텐츠가 포함되어 있으며 많은 지식 포인트가 포함되어 있습니다. 이 문서에서는 해당 서버에 대한 간략한 개요만 제공하며, 후속 문서에서는 구체적인 구현 세부 사항을 자세히 소개합니다.

권장(무료): swoole

1.2 네트워크 프로그래밍

1 네트워크 통신은 하나(또는 여러) 머신에서 하나(또는 그 이상) 프로세스를 시작하고 하나(또는 여러) 포트를 모니터링하는 것을 의미합니다. 특정 프로토콜(표준 프로토콜인 http, dns일 수도 있고 자체 정의된 프로토콜일 수도 있음)에 따라 클라이언트와 정보를 교환합니다.

2. 현재 네트워크 프로그래밍의 대부분은 TCP, UDP 또는 상위 계층 프로토콜을 기반으로 합니다. Swoole의 서버 부분은 tcp 및 udp 프로토콜을 기반으로 합니다.

3. UDP를 사용한 프로그래밍은 비교적 간단합니다. 이 기사에서는 주로 TCP 프로토콜 기반의 네트워크 프로그래밍을 소개합니다. 4. TCP 네트워크 프로그래밍은 주로 4가지 유형의 이벤트를 포함합니다. 연결을 시작(연결)하고 서버가 연결을 수락(수락)

메시지 도착: 서버는 클라이언트가 보낸 데이터를 수신합니다. 이 이벤트는 서버의 네트워크 프로그래밍에서 가장 중요한 이벤트입니다. 이러한 유형의 이벤트를 처리하려면 차단 또는 비차단을 사용할 수 있습니다. 또한 서버는 패킷화 및 애플리케이션 계층 버퍼와 같은 문제도 고려해야 합니다.

메시지가 성공적으로 전송되었습니다.전송에 성공했다는 의미입니다. 계층이 커널의 소켓 전송 버퍼로 보낸 데이터를 성공적으로 전송한다고 해서 클라이언트가 데이터를 성공적으로 수락했다는 의미는 아닙니다. 트래픽이 적은 서비스의 경우 일반적으로 데이터가 한꺼번에 전송될 수 있으므로 이러한 이벤트에 신경 쓸 필요가 없습니다. 한번에 모든 데이터를 커널 버퍼로 보낼 수 없다면 메시지가 성공적으로 전송되었는지 주의해야 한다(블로킹 프로그래밍의 경우 시스템 호출(write, writev, send 등)이 반환된 후 전송이 성공하고, 논 블로킹 프로그래밍의 경우 실제 상황을 고려해야 합니다. 작성된 데이터가 예상과 일치하는지 여부)

연결 끊김: 클라이언트 연결 끊김(읽기 반환 0) 및 서버 연결 끊김(읽기 반환 0)을 고려해야 합니다. close, shutdown)5. tcp가 연결을 설정합니다. 프로세스는 아래와 같습니다

● 그림에서 ACK와 SYN은 플래그 비트를 나타내며, seq와 ack는 TCP 패킷의 시퀀스 번호와 확인 시퀀스 번호입니다

6. TCP 연결 해제 과정은 아래와 같습니다.

● 위 그림은 클라이언트가 적극적으로 연결을 끊는 상황도 마찬가지입니다

● 그림에서 FIN과 ACK는 다음과 같습니다. 플래그 비트, seq 및 ack는 TCP 패킷의 시퀀스 번호 및 확인 시퀀스 번호입니다

1.3 프로세스 간 통신

1 프로세스 간 통신에는 명명되지 않은 파이프(파이프), 명명된 파이프(fifo), 신호가 포함됩니다. (신호), 세마포어(semaphore), 소켓(socket), 공유 메모리(shared memory) 및 기타 방법

2. Swoole은 여러 프로세스(Swoole 내부 프로세스를 의미함) 간의 통신을 위해 Unix 도메인 소켓(소켓의 일종)을 사용합니다.

1.4 Socketpair

1. Socketpair는 파이프와 유사하게 소켓 쌍을 만드는 데 사용됩니다. 차이점은 파이프가 양방향 통신을 두 번 만들어야 한다는 것입니다. 또한 소켓이므로 데이터 교환 방법을 정의할 수도 있습니다

2. 소켓 쌍 시스템 호출

sv[0], sv[1] 각각 파일 설명자

를 sv[0]에 저장합니다. sv[1]에 쓰고, sv[1]에서 읽을 수 있습니다.

sv[1]에 쓰고, sv에서 읽을 수 있습니다. [0]

프로세스가 소켓 쌍을 호출한 후 하위 프로세스를 포크하고 하위 프로세스는 기본적으로 sv를 상속받습니다. [0], sv[1] 이 두 파일 설명자는 상위 프로세스와 하위 프로세스 간의 통신을 실현할 수 있습니다. 예를 들어, 상위 프로세스는 sv[0]에 쓰고, 하위 프로세스는 sv[1]에서 읽고, 하위 프로세스는 sv[1]에 쓰고, 상위 프로세스는 sv[0]
  • 에서 읽습니다. 1.5 데몬
  • 1. 데몬은 터미널과 분리되어 주기적으로 특정 작업을 수행하는 데 사용되는 특수한 백그라운드 프로세스입니다.
2. 프로세스 그룹

각 프로세스는 A 프로세스 그룹에 속합니다 그룹 리더의 프로세스 번호(PID)인 프로세스 그룹 번호

프로세스는 자신 또는 하위 프로세스에 대해서만 프로세스 그룹 번호를 설정할 수 있습니다

3.
  • 세션은 여러 프로세스 그룹을 포함할 수 있습니다. 이러한 프로세스 그룹에는 최대 하나의 포그라운드 프로세스 그룹이 있을 수 있습니다(또는 없음). 나머지는 백그라운드 프로세스 그룹입니다.
  • 세션은 최대 하나의 제어 터미널만 가질 수 있습니다.
  • 사용자는 터미널을 통해 터미널을 사용할 수 있습니다. 로그인하거나 네트워크 로그인을 하면 새 세션이 생성됩니다.
  • 프로세스는 새 세션을 생성하기 위해 시스템 호출 setid를 호출합니다. 프로세스는 특정 프로세스 그룹의 리더가 될 수 없습니다. setid 호출이 완료된 후 프로세스는 세션의 첫 번째 프로세스(리드 프로세스)가 되고 새 프로세스 그룹의 리더가 됩니다. 이전에 프로세스에 제어 터미널이 있었다면 해당 프로세스와 터미널의 연결도 끊어집니다
4. 데몬 프로세스 생성 방법

    자식 프로세스를 포크한 후 상위 프로세스가 종료되고 하위 프로세스가 setid를 실행하며 하위 프로세스가 데몬 프로세스가 될 수 있습니다. 이런 방식으로 하위 프로세스는 세션의 리더 프로세스가 되며 터미널을 다시 열 수 있습니다. 이때 다시 포크하여 생성된 하위 프로세스는 더 이상 터미널을 열 수 없습니다(세션의 리더 프로세스만 가능). 터미널을여십시오). 두 번째 포크는 필요하지 않으며 하위 프로세스가 터미널을 다시 여는 것을 방지하기 위한 것입니다
  • linux는 데몬 프로세스를 생성하기 위한 데몬 기능(이 기능은 시스템 호출이 아니라 라이브러리 기능)을 제공합니다

1.6 Swoole tcp 서버 예시

    위 코드를 cli 모드에서 실행하면 어휘 분석과 구문 분석을 통해 opcode가 생성된 후 zend 가상 머신으로 넘겨져 실행됩니다
  • zend 가상 머신이 $를 실행하면 serv->start(), Swoole 서버 시작
  • 위 코드에 설정된 이벤트 콜백은 작업자 프로세스에서 실행됩니다. Swoole 서버 모델은 나중에 자세히 소개하겠습니다. Description
기본 모드는 다중 프로세스를 채택합니다. nginx와 일치하는 모델입니다. 각 프로세스에는 하나의 스레드만 있습니다. 기본 프로세스는 작업자 프로세스를 관리하고 작업자 프로세스는 포트 수신, 연결 수락, 요청 처리 및 연결 종료를 담당합니다. 프로세스가 동시에 포트를 수신하면 천둥 그룹 문제가 발생합니다. Linux 3.9 이전 커널 버전의 경우 Swoole은 천둥 그룹 문제를 해결하지 않습니다.

Linux 커널 3.9 및 후속 버전에서는 이를 허용하는 새로운 소켓 매개변수 SO_REUSEPORT를 제공합니다. 여러 프로세스를 바인딩합니다. 동일한 포트로 설정하면 커널이 새로운 연결 요청을 받으면 처리를 위해 프로세스 중 하나를 깨우게 됩니다. 커널 수준에서는 위에서 언급한 Swoole 그룹 문제를 해결할 수 있는 로드 밸런싱도 수행합니다. 이 매개변수도 추가했습니다

base mode 아래에서 Reactor_number 매개변수는 실제 효과가 없습니다

작업자 프로세스 수를 1로 설정하면 작업자 프로세스가 분기되지 않고 기본 프로세스가 직접 요청을 처리합니다. 모드는 디버깅에 적합합니다

2. 시작 프로세스

php 코드 실행 $serv->start()에 도달하면 메인 프로세스가 서버 시작을 담당하는 int swServer_start(swServer *serv) 함수에 들어갑니다. swServer_start 함수에서 swReactorProcess_start가 호출됩니다. 프로세스와 작업자 프로세스는 각각 자체 이벤트 루프에 들어가 다양한 이벤트를 처리합니다

  • 1.
  • 이 모드는 기본 프로세스, 관리자 프로세스 및 작업자 프로세스가 있는 다중 프로세스 및 다중 스레드입니다. task_worker 프로세스
  • 기본 프로세스 아래에 여러 스레드가 있으며 연결 승인 및 처리를 담당합니다. 요청을 처리하기 위해 반응 스레드로 전달됩니다. 반응 스레드는 데이터 패킷을 수신하고, 처리를 위해 데이터를 작업자 프로세스로 전달한 다음, 작업자 프로세스
  • manager 프로세스에서 반환된 데이터를 처리하는 역할을 담당합니다. 이 프로세스는 단일 스레드이며 주로 작업자 프로세스 관리를 담당합니다. , nginx의 기본 프로세스와 유사합니다. 작업자 프로세스가 비정상적으로 종료되면 관리자 프로세스가 작업자 프로세스
  • worker 프로세스를 다시 포크하는 역할을 담당합니다. 이 프로세스는 단일 스레드이며 구체적으로 요청 처리를 담당합니다
  • task_worker 시간이 많이 걸리는 작업을 처리하는 데 사용되는 프로세스입니다. 기본적으로 활성화되어 있지 않습니다

worker 프로세스는 도메인 소켓을 사용하여 기본 프로세스의 반응 스레드와 통신하며 작업자 프로세스 간 통신은 없습니다

  • 2. process
  • Swoole 서버 시작 항목: swServer_start function

if set 데몬 모드에서 필요한 매개 변수를 확인한 후 먼저 자신을 데몬 프로세스로 전환한 다음 관리자 프로세스를 포크한 다음 리액터 스레드를 생성합니다.

메인 프로세스는 먼저 관리자 프로세스를 분기하고, 관리자 프로세스는 작업자 프로세스와 task_worker 프로세스를 분기하는 역할을 담당합니다. 작업자 프로세스가 int swWorker_loop
    (swServer *serv, int 작업자_id)에 들어간 후, 즉 자체 이벤트 루프에 들어간 후 task_worker도 마찬가지이며 자체 이벤트 루프에 들어갑니다
  • 주 프로세스 pthread_create 반응 스레드, 메인 스레드 및 반응 각 스레드는 자체 이벤트 루프에 들어갑니다. static int swRea-torThread_loop(swThreadParam *param)을 실행하고 이벤트 처리를 기다립니다
  • 3.
    • Swoole 프로세스 모드 구조는 아래 그림과 같습니다.

    위 그림에서는 task_worker 프로세스를 고려하지 않았습니다. 기본적으로 task_worker 프로세스 수는 0

    3개입니다. 프로세스 모드)


    3.1 리액터 스레드와 작업자 프로세스 간의 통신

    1. Swoole 마스터 프로세스와 작업자 프로세스 간의 통신은 아래 그림과 같습니다

    • Swoole은 SOCK_STREAM 대신 SOCK_DGRAM을 사용합니다. 이는 각 리액터 스레드가 여러 요청을 처리한 후 처리를 담당하는 작업자 프로세스로 정보를 전달하기 때문입니다. SOCK_STREAM을 사용하면 작업자 프로세스가 tcp를 하청 처리할 수 없습니다. request
    • swFactoryProcess_start 함수 리액터 스레드와 작업자 프로세스 간의 통신을 위해 작업자 프로세스 수에 따라 해당 개수의 소켓 쌍이 생성됩니다. (자세한 내용은 swPipeUnsock_create 함수 참조)

    2 2개의 리액터 스레드가 있다고 가정합니다. 3개의 작업자 프로세스가 있고 리액터와 작업자 간의 통신은 아래 그림에 나와 있습니다.

    • 각 리액터 스레드는 여러 작업자 프로세스를 모니터링하는 역할을 담당하며 각 작업자 프로세스에는 하나의 리액터 스레드 모니터링만 있습니다(reactor_num < = 작업자_번호). 기본적으로 Swoole은 작업자 프로세스를 할당하고 이를 해당 리액터 스레드에 넘겨 모니터링을 하기 위해 사용합니다.
    • 리액터 스레드는 작업자 프로세스의 데이터를 받은 후 데이터를 처리한다는 점에 주목할 필요가 있습니다. 요청을 보낼 수 없습니다.

    3.리액터 스레드와 작업자 프로세스 간의 통신을 위한 데이터 패킷

    3.2 요청 처리

    1. 마스터 프로세스의 메인 스레드는 포트 수신을 담당합니다(listen code>) 연결을 수락하고(<code>accept, fd 생성), 연결을 수락한 후 요청은 기본적으로 리액터 스레드에 할당되고 fd가 추가됩니다. epoll_ctl 을 통해 해당 리액터 스레드를 처음 조인할 때 쓰기 이벤트를 수신합니다. 새로 허용된 연결에 의해 생성된 소켓의 쓰기 버퍼는 비어 있으므로 쓰기 가능해야 하며 즉시 트리거됩니다. 그런 다음 리액터 스레드는 일부 초기화 작업을 수행합니다listen), 接受连接(accept, 产生一个fd), 接受连接后将请求分配给reactor线程, 默认通过fd % reactor_number进行分配, 之后通过epoll_ctl将fd加入到对应reactor线程中, 刚加入时监听写事件, 因为新接受连接创建的套接字写缓冲区为空, 故而一定可写, 会被立刻触发, 进而reactor线程进行一些初始化操作

    • 存在多个线程同时操作一个epollfd(通过系统调用epoll_create创建)的情况
    • 多个线程同时调用epoll_ctl是线程安全的(对应一个epollfd), 一个线程正在执行, 其他线程会被阻塞(因为需要同时操作epoll底层的红黑树)
    • 多个线程同时调用epoll_wait也是线程安全的, 但是一个事件可能会被多个线程同时接收到, 实际中不建议多个线程同时epoll_wait一个epollfd。Swoole中也是不存在这种情况的, Swoole中每个reactor线程都有自己的epollfd
    • 一个线程调用epoll_wait, 一个线程调用epoll_ctl, 根据man手册, 如果epoll_ctl新加入的fd已经准备好, 会使得执行epoll_wait的线程变成非阻塞状态(可以通过man epoll_wait
    동시에 작동하는 여러 스레드가 있습니다. epollfd의 경우(시스템 호출 epoll_create를 통해 생성됨)

    를 호출하는 여러 스레드가 있습니다. 동시에 epoll_ctl은 스레드로부터 안전하며(하나의 epollfd에 해당) 하나의 스레드가 실행 중이고 다른 스레드는 차단됩니다(epoll의 기반이 되는 레드-블랙 트리가 동시에 작동해야 하기 때문입니다)

    여러 스레드가 동시에 epoll_wait를 호출하는 것도 스레드로부터 안전하지만 여러 스레드가 동시에 이벤트를 수신할 수 있습니다. 실제로는 여러 스레드가 되는 것을 권장하지 않습니다. >epoll_wait epollfd를 동시에 실행합니다. Swoole에는 이러한 상황이 없습니다. Swoole의 각 리액터 스레드에는 자체 epollfd

    맨 매뉴얼에 따르면 한 스레드는 epoll_wait를 호출하고 다른 스레드는 epoll_ctl를 호출합니다. 새로 추가된 epoll_ctl의 fd가 준비되면 epoll_wait를 실행하는 스레드는 비차단 상태가 됩니다(man epoll_wait를 통해 관련 정보를 볼 수 있습니다). 내용)

    • 2. 리액터 스레드에서 fd의 쓰기 이벤트가 발생하며, 처음 가입하고 쓸 데이터가 없는 것으로 확인되면 리액터 스레드가 처리를 담당합니다. , 읽기 이벤트 모니터링이 활성화되고 클라이언트가 보낸 데이터를 수락할 준비가 됩니다
    • 3. 리액터 스레드는 사용자의 요청 데이터를 읽습니다.
    • 요청된 데이터를 받은 후
    • 기본적으로 데이터를 작업자 프로세스에 전달합니다. , fd % 작업자_번호를 통해 할당됩니다.

    리액터가 작업자 프로세스로 전송하는 데이터 패킷에는 헤더가 포함되며 헤더에 리액터 정보가 기록됩니다.
    • 전송된 데이터가 너무 크면 데이터 조각화는 공간적 제약으로 인해 나중에 자세히 설명하겠습니다
    스레드는 여러 개의 리액터가 동시에 동일한 작업자 프로세스로 데이터를 보낼 수 있으므로 Swoole은 SOCK_DGRAM 모드를 사용하여 작업자와 통신합니다. 각 데이터 패킷의 헤더를 통해 작업자 프로세스는 어떤 리액터 스레드가 데이터를 보냈는지 구별할 수 있으며, Request

    🎜4. 작업자 프로세스는 리액터에서 보낸 데이터 패킷을 받은 후, 처리가 완료된 후 요청 결과가 메인 프로세스로 전송됩니다🎜🎜🎜 작업자 프로세스가 메인 프로세스로 보낸 데이터 패킷에는 헤더도 포함되며, 리액터 스레드가 데이터 패킷을 수신하면 해당 리액터 스레드, 요청된 fd 및 기타 정보를 알 수 있습니다🎜🎜🎜5. 메인 프로세스는 작업자 프로세스에서 보낸 데이터 패킷을 수신하고 이를 처리하기 위해 리액터 스레드를 트리거합니다🎜
    • 이 리액터 스레드는 반드시 이전에 작업자 프로세스에 요청을 보낸 리액터 스레드일 필요는 없습니다.
    • 메인 프로세스의 각 리액터 스레드는 작업자 프로세스에서 보낸 데이터 패킷과 작업자 프로세스에서 보낸 데이터 패킷을 모니터링하는 역할을 담당합니다. 각 작업자는 하나의 리액터 스레드 모니터로만 전송되므로 하나의 리액터 스레드만 트리거됩니다

    6. 리액터 스레드는 작업자 프로세스에서 보낸 요청 처리 결과를 처리합니다. 연결 수신 상태를 변경해야 하는 경우(예: close), 则需要先找到监听这个连接的reactor线程, 进而改变这个连接的监听状态(通过调用epoll_ctl)

    • 리액터 처리 스레드와 리액터 수신 스레드가 동일한 스레드가 아닐 수 있습니다
    • 리액터 수신 스레드는 클라이언트가 보낸 데이터를 모니터링하는 역할을 담당합니다. , 그리고 이를 작업자 프로세스로 전달합니다
    • 리액터 처리 스레드는 작업자 프로세스에서 보낸 데이터를 모니터링하는 역할을 담당합니다. 데이터를 메인 프로세스로 보낸 다음 데이터를 클라이언트로 보냅니다.

    Gdb 디버깅 넷.

    4.1 프로세스 모드 시작

    4.2 기본 모드 시작

    五. 요약 및 생각

    1. 이 글에서는 주로 Swoole 서버의 두 가지 모드를 소개합니다. 그리고 처리 모드 두 모드의 네트워크 프로그래밍 모델을 자세히 설명하고 프로세스 모드의 프로세스 간 통신 방법, 요청 처리 흐름 등에 대해 중점적으로 설명합니다.

    2. 메인 프로세스에서 스레드가 요청을 직접 처리하도록 하고(프로세스 간 통신의 오버헤드를 피할 수 있음) 관리자 프로세스를 생성한 다음 관리자 프로세스에서 작업자 프로세스를 생성하고 요청을 처리하는 프로세스는 다음과 같습니다.

    • 개인적으로는 PHP의 멀티스레딩 지원이 그다지 친숙하지 않다고 생각합니다. PHP는 대부분 단일 스레드 프로그래밍만 수행합니다.
    • ZendVM에서 제공하는 TSRM도 멀티스레딩 환경을 지원하지만 사실 이것은 스레드별로 메모리를 격리하는 솔루션이므로 멀티스레딩은 의미가 없습니다

    3. 프로세스 모드에서는 기본 프로세스의 각 리액터 스레드가 동시에 여러 요청을 처리할 수 있으며 여러 요청이 동시에 처리됩니다. 2차원에서 봅니다

    • 메인 프로세스의 관점에서 보면 메인 프로세스는 여러 요청을 동시에 처리하며 모든 요청 패킷이 수신되면 처리를 위해 작업자 프로세스로 전달됩니다
    • 관점에서 작업자 프로세스의 관점에서 볼 때 이 작업자 프로세스가 수신하는 요청은 기본적으로 작업자 프로세스도 요청을 순차적으로 처리합니다. (Swoole의 작업자 프로세스는 phper가 작성한 이벤트 처리 기능을 콜백합니다. 이 함수는 차단될 수 있음) 후속 요청을 처리할 수 없습니다. 이는 대기열 차단 문제입니다. 이 경우 Swoole의 코루틴을 사용하면 단일 요청이 차단될 때 작업자 프로세스가 계속해서 다른 요청을 처리할 수 있습니다.

    4. Swoole 사용 TCP 서버를 생성할 때 tcp는 바이트 스트림 프로토콜이므로 하청을 받아야 하며, Swoole은 클라이언트와 서버 간의 통신 프로토콜을 모르면 하청을 할 수 없습니다. 리액터를 통해 작업자 프로세스로 전달됩니다. 바이트 스트림만 가능하며 사용자가 처리해야 합니다. 물론 일반적으로 Swoole은 tcp 서버를 사용하여 Http, Https 및 기타 프로토콜을 이미 지원하므로 직접 프로토콜을 구축할 필요가 없습니다.

위 내용은 Swoole 서버에 대한 간략한 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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