Nginx代理Laravel Octane Swoole远慢于原生服务,此现象是否正常?
Nginx代理Swoole性能低于原生Laravel Octane Swoole的情况分析
结论先行
这种性能差异属于正常现象,无需过度担忧——你的测试结果中约20%-30%的QPS下降,完全在常规代理场景的合理损耗范围内。
代理变慢的核心原因
- 跨容器网络开销:请求需要先经过Nginx容器,再转发到Swoole应用容器,两次Docker overlay网络的跨容器通信会增加延迟,这是容器化环境下代理的固有损耗。
- Nginx的处理成本:即便关闭了日志,Nginx仍需完成请求解析、
try_files规则处理、代理头设置、请求转发与响应接收等操作,这些步骤会占用CPU和内存资源,带来额外的处理时间。 - TCP连接的额外层级:相比直接连接Swoole,代理场景下请求要经过两次TCP连接(客户端→Nginx、Nginx→Swoole),多了一次连接建立与维护的开销。
测试数据验证
测试地址说明:
http://localhost/up- Nginx代理Swoolehttp://localhost:8000/up- 原生Laravel Octane Swoole
测试结果
cepairda@DESKTOP-2PBE7CR:/mnt/c/Users/Alex$ wrk -t 16 -c 100 http://localhost/up Running 10s test @ http://localhost/up 16 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 59.10ms 55.31ms 571.38ms 87.37% Req/Sec 123.41 62.70 252.00 53.29% 19682 requests in 10.05s, 38.57MB read Requests/sec: 1958.18 Transfer/sec: 3.84MB cepairda@DESKTOP-2PBE7CR:/mnt/c/Users/Alex$ wrk -t 16 -c 100 http://localhost:8000/up Running 10s test @ http://localhost:8000/up 16 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 46.94ms 49.04ms 458.27ms 91.58% Req/Sec 159.88 55.07 323.00 60.14% 25557 requests in 10.10s, 50.40MB read Requests/sec: 2531.07 Transfer/sec: 4.99MB cepairda@DESKTOP-2PBE7CR:/mnt/c/Users/Alex$ wrk -t 16 -c 100 http://localhost/up Running 10s test @ http://localhost/up 16 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 62.75ms 58.53ms 472.44ms 92.58% Req/Sec 114.63 34.76 240.00 75.73% 18326 requests in 10.06s, 35.92MB read Requests/sec: 1821.94 Transfer/sec: 3.57MB cepairda@DESKTOP-2PBE7CR:/mnt/c/Users/Alex$ wrk -t 16 -c 100 http://localhost:8000/up Running 10s test @ http://localhost:8000/up 16 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 54.35ms 56.76ms 488.40ms 91.73% Req/Sec 138.44 45.71 282.00 68.00% 22133 requests in 10.06s, 43.65MB read Requests/sec: 2200.10 Transfer/sec: 4.34MB
使用的配置文件
Nginx配置(来自Octane官方文档)
map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; listen [::]:80; server_tokens off; root /var/www/public; index index.php; charset utf-8; location /index.php { try_files /not_exists @octane; } location / { try_files $uri $uri/ @octane; } #access_log /var/log/nginx/nginx-access.log; access_log off; #error_log /var/log/nginx/nginx-error.log error; error_log off; error_page 404 /index.php; resolver 127.0.0.11; location @octane { set $suffix ""; if ($uri = /index.php) { set $suffix ?$query_string; } proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_pass http://taxi-app:8000$suffix; } }
Docker Compose配置
services: app: build: context: ./ dockerfile: ./docker/Dockerfile target: production # user: ${UID}:${GID} restart: always container_name: taxi-app ports: - 8000:8000 secrets: - production_env volumes: - app-storage:/var/www/storage #- ./app-public:/var/www/public depends_on: postgres-db: condition: service_healthy redis: condition: service_healthy networks: - taxi-postgres-db-network - taxi-webserver-network - taxi-redis-network healthcheck: test: curl -s http://localhost:8000/up >/dev/null || exit 1 interval: 10s timeout: 5s retries: 5 #extra_hosts: # host.docker.internal: host-gateway webserver: build: context: ./ dockerfile: ./docker/Dockerfile target: webserver #image: nginx:1.27-alpine container_name: taxi-webserver restart: always volumes: - app-storage:/var/www/storage - ./docker/local/nginx/:/etc/nginx/conf.d/ - ./storage/logs/nginx/:/var/log/nginx/ ports: - 80:80 networks: - taxi-webserver-network healthcheck: test: curl -s http://localhost/up >/dev/null || exit 1 interval: 10s timeout: 5s retries: 5 postgres-db: image: postgis/postgis:16-3.5-alpine container_name: taxi-postgres-db restart: always ports: - 5432:5432 environment: POSTGRES_DB: ${DB_DATABASE} POSTGRES_USER: ${DB_USERNAME} POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - postgres-data:/var/lib/postgresql/data networks: - taxi-postgres-db-network healthcheck: test: pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE} interval: 10s timeout: 5s retries: 5 redis: image: redis:7.4.1-alpine restart: always container_name: taxi-redis command: - 'redis-server' - '--requirepass ${REDIS_PASSWORD}' volumes: - redis-data:/data networks: - taxi-redis-network healthcheck: test: redis-cli ping interval: 10s timeout: 5s retries: 5 networks: taxi-webserver-network: driver: overlay name: taxi-webserver-network taxi-postgres-db-network: driver: overlay name: taxi-postgres-db-network taxi-redis-network: driver: overlay name: taxi-redis-network volumes: app-storage: driver: local name: taxi-app-storage postgres-data: driver: local name: taxi-postgres-data redis-data: driver: local name: taxi-redis-data secrets: production_env: file: ./app/.production-env
内容的提问来源于stack exchange,提问作者Alex Black
相关产品推荐
相关产品推荐

