HTTP Server
Introduction
ODY Server is a modern, high-performance, event-driven web server for PHP applications built on top of Swoole. It provides a robust foundation for web applications that need to handle concurrent requests efficiently, with minimal resource usage and fast response times.
Unlike traditional PHP setups with Apache or Nginx, ODY Server keeps your application in memory between requests, dramatically improving performance while providing non-blocking I/O operations through coroutines.
How It Works:
- The server starts as a long-running process, avoiding the overhead of repeatedly loading PHP scripts.
- Event-Driven Handling – Requests are processed asynchronously using an event loop, allowing the server to handle thousands of connections concurrently.
- Non-Blocking I/O – The server can process multiple requests without waiting for I/O operations (e.g., database queries, file reads) to complete.
- Worker Processes – The server can spawn multiple worker processes to distribute requests across CPU cores for better performance.
- Developers can define custom request handlers, set custom headers, and control responses directly within the server logic.
Installation
Add ODY Server to your project using Composer:
composer require ody/server
Command Line Tools
ODY Server comes with convenient command-line tools to manage your server instance.
Starting the Server
php ody server:start
Options:
-d, --daemonize
- Run the server in the background-w, --watch
- Enable hot reloading for development
Stopping the Server
php ody server:stop
Reloading Workers
Reload worker processes without downtime to pick up code changes:
php ody server:reload
Configuration
ODY Server can be configured in your project’s config/server.php
file:
return [
'host' => env('SERVER_HOST', '127.0.0.1'),
'port' => env('SERVER_PORT', 9501),
// Number of worker processes
'additional' => [
'worker_num' => env('SERVER_WORKERS', swoole_cpu_num()),
// Enable coroutines for better performance
'enable_coroutine' => true,
// Maximum number of coroutines
'max_coroutine' => 3000,
],
// Files/directories to watch in development mode
'watch' => [
'app',
'config',
'routes',
'.env',
]
];
Environment Variables
You can configure the server using these environment variables in your .env
file:
SERVER_HOST=127.0.0.1
SERVER_PORT=9501
SERVER_WORKERS=4
Performance Tuning
Worker Count
For optimal performance, set the worker count based on your server’s CPU cores:
'worker_num' => swoole_cpu_num() * 2,
Coroutine Settings
Enable coroutines for non-blocking I/O operations:
'enable_coroutine' => true,
'max_coroutine' => 3000,
Hot Reloading
During development, you can enable hot reloading to automatically restart workers when code changes:
php ody server:start -w
Configure which files/directories to watch in your server.php
config:
'watch' => [
'app',
'config',
'routes',
'composer.lock',
],
Standalone Usage
use Ody\Server\ServerManager;
use Ody\Server\ServerType;
use Ody\Foundation\HttpServer;
// Initialize server
ServerManager::init(ServerType::HTTP_SERVER)
->createServer([
'host' => '127.0.0.1',
'port' => 9501,
'mode' => SWOOLE_PROCESS,
'sock_type' => SWOOLE_SOCK_TCP,
])
->setServerConfig([
'worker_num' => 4,
'enable_coroutine' => true,
])
->getServerInstance()
->start();
The HttpServerState
class manages the state of running server processes, allowing for tracking and management of
processes.
$serverState = HttpServerState::getInstance();
// Check if the server is running
if ($serverState->httpServerIsRunning()) {
// Server is running
}
// Get process IDs
$masterPid = $serverState->getMasterProcessId();
$managerPid = $serverState->getManagerProcessId();
$workerPids = $serverState->getWorkerProcessIds();
// Kill processes
$serverState->killProcesses([
$masterPid,
$managerPid,
// ...worker PIDs
]);
// Reload processes
$serverState->reloadProcesses([
$masterPid,
$managerPid,
// ...worker PIDs
]);
// Clear process IDs
$serverState->clearProcessIds();
Troubleshooting
Address Already in Use
If you get an “Address already in use” error:
# Find the process using the port
lsof -i :9501
kill -9 {process_id}
# Stop the server properly
php ody server:stop
Worker Crashes
If worker processes crash frequently, check your logs and consider:
- Increasing memory limit in PHP settings
- Reducing the worker count
- Checking for code errors in event loops
Deployment
For production deployment:
- Set up a process manager like Supervisor
- Run in daemon mode:
php ody server:start -d
- Configure a reverse proxy (Nginx) for SSL termination
Example Supervisor config:
[program:ody-server]
command=php /path/to/project/ody server:start
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/path/to/project/storage/logs/supervisor.log
API Reference
Server Types
The ServerType
class provides constants for different server types:
HTTP_SERVER
: Swoole HTTP server (\Swoole\Http\Server
)WS_SERVER
: Swoole WebSocket server (\Swoole\WebSocket\Server
)TCP_SERVER
: Swoole TCP server (\Swoole\Server
)
Server Events
The ServerEvent
class provides constants for all supported server events:
ON_START
: Server start eventON_WORKER_START
: Worker process start eventON_WORKER_STOP
: Worker process stop eventON_WORKER_EXIT
: Worker process exit eventON_WORKER_ERROR
: Worker process error eventON_PIPE_MESSAGE
: Pipe message eventON_REQUEST
: HTTP request eventON_RECEIVE
: Data receive eventON_CONNECT
: Client connect eventON_DISCONNECT
: Client disconnect eventON_OPEN
: WebSocket open eventON_MESSAGE
: WebSocket message eventON_CLOSE
: Connection close eventON_TASK
: Task eventON_FINISH
: Task finish eventON_SHUTDOWN
: Server shutdown eventON_PACKET
: UDP packet eventON_MANAGER_START
: Manager start eventON_MANAGER_STOP
: Manager stop eventON_BEFORE_START
: Before server start event (not a Swoole event)
ServerManager Class
Methods:
init(string $serverType): static
- Initialize the server manager with a server typecreateServer(?array $config): static
- Create a new server instance with the given configurationsetServerConfig(array $config): static
- Set additional server configurationgetServerInstance(): HttpServer|WsServer
- Get the server instanceregisterCallbacks(array $callbacks): static
- Register event callbackssetWatcher(int $enableWatcher, array $paths, object $serverState): static
- Enable file watching for hot reloadingdaemonize(bool $daemonize): static
- Set the server to run in the backgroundsetLogger(LoggerInterface $logger): self
- Set the logger instancesetConfig(Config $config): self
- Set the configuration instancestart(): void
- Start the server
ServerState Class
Methods:
getInstance(): self
- Get the singleton instancegetInformation(): array
- Get the state informationsetManagerProcessId(?int $id): void
- Set the manager process IDsetMasterProcessId(?int $id): void
- Set the master process IDsetWatcherProcessId(?int $id): void
- Set the watcher process IDsetWorkerProcessIds(array $ids): void
- Set the worker process IDsgetManagerProcessId(): int|null
- Get the manager process IDgetMasterProcessId(): int|null
- Get the master process IDgetWatcherProcessId(): int|null
- Get the watcher process IDgetWorkerProcessIds(): array
- Get the worker process IDsclearProcessIds(): void
- Clear all process IDsreloadProcesses(array $processIds): void
- Reload the specified processeskillProcesses(array $processIds): void
- Kill the specified processes
HttpServerState Class
Methods:
getInstance(): self
- Get the singleton instancehttpServerIsRunning(): bool
- Check if the HTTP server is running
License
ODY Server is open-sourced software licensed under the MIT License.