Implementing high-concurrency server with PHP
When it comes to high concurrency, there is no way to bypass I/O multiplexing and then specify the specific platform Linux, there is no way to bypass epoll. I won’t go into the principle of why epoll is efficient. Interested students can search and study it by themselves.
How to play epoll in php? First, you must install a libevent library, and then install an event extension or libevent extension, and you can play happily.
Some people are confused about the difference between the libevent library and the libevent extension. Simply put, the libevent library It is the encapsulation of epoll in C language and has nothing to do with PHP; the libevent extension is the communication bridge between PHP and the libevent library. In fact, many extensions of PHP do this. There are some excellent C language libraries. If PHP wants to use them directly, it can be connected to PHP through PHP extensions.
Choose between libevent extension and event extension. Personally, I prefer event extension because it is more object-oriented. Go to http://pecl.php.net and search for extensions corresponding to your PHP version, download it, compile and install it and it will be OK. When compiling with multiple versions of PHP installed on your computer, pay attention to the version of phpize that matches the one. , make no mistake, the typical five steps:
phpize ./configure make make install php -m | grep event #看看装上了没
The transport layer of the server we want to implement is the TCP protocol. There are too many application layer protocols and are too complicated. Due to space limitations, we will simply use the HTTP server as an example. For example, the HTTP protocol itself is very complex. There are many details to implement, and we will not fully implement the HTTP protocol.
First, create a socket, three steps, socket_create, socket_bind, socket_listen. Why these three steps? It's very simple. No matter what your transport layer protocol is, you have to choose a version of the network layer protocol below, IPV4 or IPV6. You have to choose a transport layer working method, full duplex, half duplex or simplex, TCP. Or UDP, you have to choose one, socket_create is these three options; after determining the network layer and transport layer, you have to tell me which port to listen to, which corresponds to socket_bind; then you have to enable monitoring and specify a client Queue length, this is what socket_listen does.
After creation, we will not introduce synchronous blocking. A process can hold at most one connection at the same time. If more connections are requested at the same time, you have to wait. If the queue length specified by socket_listen is exceeded, 504 must be returned. . The same goes for multiple processes. Several processes have several concurrent processes. Processes are expensive resources, and the context switching of processes is time-consuming and laborious, resulting in inefficiency of the entire system.
It doesn't matter, we have epoll, it is not a dream to hold thousands of requests, first implement a Reactor. The libevent library is the Reactor mode. Calling the function directly is using the Reactor mode, so there is no need to worry about how to implement the Reactor mode in PHP.
<?php use Event; use EventBase; class Reactor { protected $reactor; protected $events; public static $instance = null; const READ = Event::READ | Event::PERSIST; const WRITE = Event::WRITE | Event::PERSIST; public static function getInstance() { if (is_null(self::$instance)) { self::$instance = new self(); self::$instance->reactor = new EventBase; } return self::$instance; } public function add($fd, $what, $cb, $arg = null) { switch ($what) { case self::READ: $event = new Event($this->reactor, $fd, self::READ, $cb, $arg); break; case self::WRITE: $event = new Event($this->reactor, $fd, self::WRITE, $cb, $arg); break; default: $event = new Event($this->reactor, $fd, $what, $cb, $arg); break; } $event->add(); $this->events[(int) $fd][$what] = $event; } public function del($fd, $what = 'all') { $events = $this->events[(int) $fd]; if ($what == 'all') { foreach ($events as $event) { $event->free(); } } else { if ($what != self::READ && $what != self::WRITE) { throw new \Exception('不存在的事件'); } $events[$what]->free(); } } public function run() { $this->reactor->loop(); } public function stop() { foreach ($this->events as $events) { foreach ($events as $event) { $event->free(); } } $this->reactor->stop(); } }
The above code is very simple. Let me briefly explain the concept. EventBase is a container, which contains Event instances. In this way, the above code is very easy to understand. Then a Server.
<?php use Throwable;use Monolog\Handler\StreamHandler;class Server{ protected $ip; protected $port; protected $socket; protected $reactor; public function __construct($ip, $port) { $this->ip = $ip; $this->port = $port; } public function start() { $socket = $this->createTcpConnection(); stream_set_blocking($socket, false); Reactor::getInstance()->add($socket, Reactor::READ, function($socket) { $conn = stream_socket_accept($socket); stream_set_blocking($conn, false); (new Connection($conn))->handle(); }); Reactor::getInstance()->run(); } public function createTcpConnection() { $schema = sprintf("tcp://%s:%d", $this->ip, $this->port); $socket = stream_socket_server($schema, $errno, $errstr); if ($errno) { throw new \Exception($errstr); } return $socket; } }
Connection
<?phpclass Connection{ protected $conn; protected $read_buffer = ''; protected $write_buffer = ''; public function __construct($conn) { $this->conn = $conn; } public function handle() { Reactor::getInstance()->add($this->conn, Reactor::READ, \Closure::fromCallable([$this, 'read'])); } private function read($conn) { $this->read_buffer = ''; if (is_resource($conn)) { while ($content = fread($conn, 65535)) { $this->read_buffer .= $content; } } if ($this->read_buffer) { Reactor::getInstance()->add($conn, Reactor::WRITE, \Closure::fromCallable([$this, 'write'])); } else { Reactor::getInstance()->del($conn); fclose($conn); } } private function write($conn) { if (is_resource($conn)) { fwrite($conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html;charset=utf8\r\nContent-Length:11\r\nConnection: keep-alive\r\n\r\nHello!world"); } } }
first creates a Socket in three steps and sets it to non-blocking mode. Then add the socket to the Reactor to listen for readable events. Readable means that it can only be read when there is data in the buffer. A readable event occurs, indicating that a new connection is coming. Use stream_socket_accept
to receive the new connection Conn, and put Conn in Reactor to monitor readable events. If a readable event occurs, it indicates that the client has data sent. Read in a loop until there is no data, and then put Conn in the Reactor to listen for writable events. If a writable event occurs, it means that the client data has been sent. Assemble the protocol and write the response.
If the application layer is HTTP protocol, please pay attention to the Connection: keep-alive header, because the connection needs to be reused, so do not close the connection as soon as it is finished.
After finishing the work, use ab
to test the concurrency, and add the -k
parameter to multiplex the connection. There is no problem with i5 8G, 3W concurrency, of course we don’t have it here. Disk I/O, the actual situation is to read files from the disk, and read files through Linux system calls, and there are several file copy operations, which is relatively expensive. The common solution is sendfile, zero copy directly from an FD To another FD, the efficiency is relatively high. The disadvantage is that PHP does not have a ready-to-implement sendfile extension, so you have to do it yourself, and the development cost is a bit high.
ab test PO picture:
This is the idea of implementing a high-concurrency server in PHP. As long as it is solved with EPOLL, the idea is the same. It is a three-step process. Put it under Reactor to monitor FD events. Of course, this is just the simplest model, and there are many areas that can be improved. For example, multi-process, copy nginx, one main process and N worker processes. The purpose of multi-process is to use multi-core parallel work. The same is true for C language implementation, but you may not use the libevent library and encapsulate EPOLL yourself. After all, the libevent library is a bit heavy, and you can’t use many things in libevent; of course, the C language has a bunch of data structures and functions defined on the data structures. The operations need to be written, there is no GC, the memory must be managed by yourself, and there must be good design. When running multiple processes, you need to work on IPC inter-process communication. The development difficulty is much greater than that of PHP, and the development cycle is also very long. If you are interested Students can play with one by themselves.
For more PHP related technical articles, please visit the PHP Tutorial column to learn!
The above is the detailed content of Implementing high-concurrency server with PHP. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











This tutorial demonstrates how to efficiently process XML documents using PHP. XML (eXtensible Markup Language) is a versatile text-based markup language designed for both human readability and machine parsing. It's commonly used for data storage an

JWT is an open standard based on JSON, used to securely transmit information between parties, mainly for identity authentication and information exchange. 1. JWT consists of three parts: Header, Payload and Signature. 2. The working principle of JWT includes three steps: generating JWT, verifying JWT and parsing Payload. 3. When using JWT for authentication in PHP, JWT can be generated and verified, and user role and permission information can be included in advanced usage. 4. Common errors include signature verification failure, token expiration, and payload oversized. Debugging skills include using debugging tools and logging. 5. Performance optimization and best practices include using appropriate signature algorithms, setting validity periods reasonably,

Static binding (static::) implements late static binding (LSB) in PHP, allowing calling classes to be referenced in static contexts rather than defining classes. 1) The parsing process is performed at runtime, 2) Look up the call class in the inheritance relationship, 3) It may bring performance overhead.

A string is a sequence of characters, including letters, numbers, and symbols. This tutorial will learn how to calculate the number of vowels in a given string in PHP using different methods. The vowels in English are a, e, i, o, u, and they can be uppercase or lowercase. What is a vowel? Vowels are alphabetic characters that represent a specific pronunciation. There are five vowels in English, including uppercase and lowercase: a, e, i, o, u Example 1 Input: String = "Tutorialspoint" Output: 6 explain The vowels in the string "Tutorialspoint" are u, o, i, a, o, i. There are 6 yuan in total

What are the magic methods of PHP? PHP's magic methods include: 1.\_\_construct, used to initialize objects; 2.\_\_destruct, used to clean up resources; 3.\_\_call, handle non-existent method calls; 4.\_\_get, implement dynamic attribute access; 5.\_\_set, implement dynamic attribute settings. These methods are automatically called in certain situations, improving code flexibility and efficiency.

PHP and Python each have their own advantages, and choose according to project requirements. 1.PHP is suitable for web development, especially for rapid development and maintenance of websites. 2. Python is suitable for data science, machine learning and artificial intelligence, with concise syntax and suitable for beginners.

PHP is a scripting language widely used on the server side, especially suitable for web development. 1.PHP can embed HTML, process HTTP requests and responses, and supports a variety of databases. 2.PHP is used to generate dynamic web content, process form data, access databases, etc., with strong community support and open source resources. 3. PHP is an interpreted language, and the execution process includes lexical analysis, grammatical analysis, compilation and execution. 4.PHP can be combined with MySQL for advanced applications such as user registration systems. 5. When debugging PHP, you can use functions such as error_reporting() and var_dump(). 6. Optimize PHP code to use caching mechanisms, optimize database queries and use built-in functions. 7

PHP is widely used in e-commerce, content management systems and API development. 1) E-commerce: used for shopping cart function and payment processing. 2) Content management system: used for dynamic content generation and user management. 3) API development: used for RESTful API development and API security. Through performance optimization and best practices, the efficiency and maintainability of PHP applications are improved.
