Pre-development Guide

When developing applications with Workerman, you need to understand the following:

I. Differences Between Workerman Development and Regular PHP Development

Workerman development is not very different from regular PHP development, except that the variable functions related to the HTTP protocol cannot be used directly.

1. Different Application Layer Protocols

  • Regular PHP development is generally based on the HTTP application layer protocol, where the WebServer has already completed the protocol parsing for the developer.
  • Workerman supports various protocols, with built-in support for HTTP, WebSocket, etc. Workerman recommends that developers use simpler custom protocols for communication.

2. Request Cycle Differences

  • In PHP web applications, all variables and resources are released after each request.
  • Applications developed with Workerman reside in memory after the first load and parsing, which means class definitions, global objects, and class static members will not be released, facilitating their reuse in subsequent operations.

3. Avoid Duplicate Definitions of Classes and Constants

  • Workerman caches the compiled PHP files, so avoid requiring/inclusive the same class or constant definition file multiple times. It is recommended to use require_once/include_once to load files.

4. Be Cautious with Resource Release in Singleton Patterns

  • Since Workerman does not release global objects or class static members after each request, in singleton patterns like databases, the database instance (which includes a database socket connection) is often stored in static members, allowing Workerman to reuse this database socket connection throughout the process lifecycle. It is important to note that when the database server detects that a connection has been inactive for a period of time, it may actively close the socket connection. When this database instance is used again, it may result in an error (error message similar to mysql gone away). Workerman provides a database class that has reconnection capabilities, which developers can use directly.

5. Avoid Using exit and die

  • Workerman runs in PHP command line mode, and calling exit or die will cause the current process to exit. Even though the child processes will be immediately recreated to continue service, it may still affect the business.

6. Restart the Service to Apply Code Changes

Since Workerman is resident in memory, definitions of PHP classes and functions are loaded once and remain in memory, and will not be re-read from disk. Therefore, you need to restart the service each time you modify the business code for the changes to take effect.

II. Basic Concepts to Understand

1. TCP Transport Layer Protocol

TCP is a connection-oriented, reliable, IP-based transport layer protocol. One important feature of the TCP transport layer protocol is that it is based on a data stream; requests from the client will continuously be sent to the server, and the data received by the server may not be a complete request, and it may also be multiple requests concatenated together. This requires us to distinguish the boundaries of each request within this continuous stream of data. The application layer protocol mainly defines a set of rules for request boundaries to avoid confusion of request data.

2. Application Layer Protocol

The application layer protocol defines how application processes running on different end systems (client, server) communicate with each other through message passing, such as HTTP and WebSocket, which belong to application layer protocols. For example, a simple application layer protocol can be as follows: {"module":"user","action":"getInfo","uid":456}\n" This protocol marks the end of a request with "\n" (note that here "\n" represents a carriage return), and the message body is a string.

3. Short Connections

Short connections refer to the establishment of a connection when both parties have data exchanges. Once the data has been sent, the connection is closed; that is, each connection only completes the transmission of a single business task. HTTP services for WEB sites generally use short connections.

For developing short connection applications, you can refer to the basic development process chapter.

4. Long Connections

Long connections allow multiple packets of data to be sent continuously over a single connection.

Note: Long connection applications must include heartbeat; otherwise, the connection may be disconnected by routing node firewalls due to prolonged inactivity.

Long connections are often used in scenarios where frequent, point-to-point communication occurs. Each TCP connection requires a three-way handshake, which takes time. If every operation involves connecting and then operating, the processing speed will be significantly reduced. Therefore, long connections do not disconnect after each operation, which allows for immediate transmission of data packets during the next operation without establishing a TCP connection again. For instance, database connections are often long connections; frequent communications using short connections may cause socket errors, and frequent socket creation wastes resources.

When it is necessary to actively push data to clients, such as in chat applications, real-time games, or mobile push notifications, long connections are needed.
For developing long connection applications, you can refer to the Gateway/Worker development process.

5. Smooth Restart

The general restart process involves stopping all processes completely and starting to create entirely new service processes. During this process, there will be a brief period where no processes provide services, leading to temporary unavailability of the service, which may result in request failures under high concurrency.

A smooth restart does not stop all processes at once; instead, it stops one process at a time, immediately creating a new process to replace it after stopping a process, until all old processes have been replaced.

Smoothly restarting Workerman can be done using the command php your_file.php reload, which updates the application without affecting service quality.

Note: Only files loaded in on{...} callbacks will automatically update after a smooth restart; files loaded directly in the startup script or hard-coded code will not automatically update when running reload.

III. Distinguishing Between Master Process and Child Processes

It is important to note whether the code is running in the master process or the child process. Generally, code running before the call to Worker::runAll(); executes in the master process, while the code executed in onXXX callbacks belongs to the child process. Also, code written after Worker::runAll(); will never be executed.

For example, in the following code:

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

// Runs in the master process
$tcp_worker = new Worker("tcp://0.0.0.0:2347");
// The assignment process runs in the master process
$tcp_worker->onMessage = function(TcpConnection $connection, $data)
{
    // This part runs in the child process
    $connection->send('hello ' . $data);
};

Worker::runAll();

Note: Do not initialize database, memcache, redis, and other connection resources in the master process, because connections initialized in the master process may be automatically inherited by child processes (especially when using singletons), leading all processes to hold the same connection. The data returned by the server through this connection will be readable across multiple processes, resulting in data confusion. Similarly, if any one process closes the connection (for example, when the master process exits while running in daemon mode, causing the connection to close), it will lead to all child processes' connections being closed together, resulting in unpredictable errors, such as mysql gone away errors.

It is recommended to initialize connection resources in the onWorkerStart method.