Swoole从入门到入土(3)——TCP服务器[基本配置项]
在这一节的开篇,让我们先解决上一节的“配置”话题。对于server对象,有很多配置项决定了服务端的行为,可以用set的函数进行配置的设置。
1、函数set:用于设置运行时的各项参数。服务器启动后通过 $serv->setting 来访问 Server->set 方法设置的参数数组。
Swoole\Server->set(array $setting): void
$setting:配置项数组。
注意:函数set必须在 Server->start() 前调用。
示例:
$server->set(array(
'reactor_num' => 2, // reactor thread num
'worker_num' => 4, // worker process num
'backlog' => 128, // listen backlog
'max_request' => 50,
'dispatch_mode' => 1,
));
每个配置项的意义,下面会进行介绍。
2、常用配置项
1) 属性reactor_num:设置启动的 Reactor 线程数。【默认值:CPU 核数】(什么是reactor线程呢?点击这里查看上一节常识科普)
说明:
通过此参数来调节主进程内事件处理线程的数量,以充分利用多核。默认会启用 CPU 核数相同的数量。
Reactor 线程是可以利用多核,如:机器有 128 核,那么底层会启动 128 线程。
每个线程能都会维持一个 EventLoop。线程之间是无锁的,指令可以被 128 核 CPU 并行执行。
考虑到操作系统调度存在一定程度的性能损失,可以设置为 CPU 核数 * 2,以便最大化利用 CPU 的每一个核。
建议设置为 CPU 核数的 1-4 倍,但最大不得超过 swoole_cpu_num() * 4。
2) worker_num:设置启动的 Worker 进程数。【默认值:CPU 核数】(什么是Worker进程呢?点击这里查看上一节常识科普)
说明:
如果业务代码是全异步 IO 的,这里设置为 CPU 核数的 1-4 倍最合理。
如果业务代码为同步 IO,需要根据请求响应时间和系统负载来调整,例如:100-500
默认设置为 swoole_cpu_num(),最大不得超过 swoole_cpu_num() * 1000
假设每个进程占用 40M 内存,100 个进程就需要占用 4G 内存,如何正确查看进程的内存占用请参考 Swoole 官方视频教程
举例:
如 1 个请求耗时 100ms,要提供 1000QPS 的处理能力,那必须配置 100 个进程或更多。
但开的进程越多,占用的内存就会大大增加,而且进程间切换的开销就会越来越大。所以这里适当即可。不要配置过大。
3) max_request:设置 worker 进程的最大任务数。【默认值:0 即不会退出进程】
说明:
一个 worker 进程在处理完超过此数值的任务后将自动退出,进程退出后会释放所有内存和资源。
这个参数的主要作用是解决由于程序编码不规范导致的 PHP 进程内存泄露问题。PHP 应用程序有缓慢的内存泄漏,但无法定位到具体原因、无法解决,可以通过设置 max_request 临时解决,但是项目要持久运行还是必须找到内存泄漏的代码并修复。
达到 max_request 不一定马上关闭进程,参考 max_wait_time。
SWOOLE_BASE 下,达到 max_request 重启进程会导致客户端连接断开。
当 worker 进程内发生致命错误或者人工执行 exit 时,进程会自动退出。master 进程会重新启动一个新的 worker 进程来继续处理请求。
4) max_wait_time:设置 Worker 进程收到停止服务通知后最大等待时间【默认值:3】
说明:
经常会碰到由于 worker 阻塞卡顿导致 worker 无法正常 reload, 无法满足一些生产场景,例如发布代码热更新需要 reload 进程。所以,我们加入了进程重启超时时间的选项。
管理进程收到重启、关闭信号后或者达到 max_request 时,管理进程会重起该 worker 进程。分以下几个步骤:
· 底层会增加一个 (max_wait_time) 秒的定时器,触发定时器后,检查进程是否依然存在,如果是,会强制杀掉,重新拉一个进程。
· 需要在 onWorkerStop 回调里面做收尾工作,需要在 max_wait_time 秒内做完收尾。
· 依次向目标进程发送 SIGTERM 信号,杀掉进程。
5) backlog:设置 Listen 队列长度
举例:
如 backlog => 128,此参数将决定最多同时有多少个等待 accept 的连接。
说明:
关于 TCP 的 backlog
· 我们知道 TCP 有三次握手的过程,客户端 syn=>服务端 syn+ack=>客户端 ack,当服务器收到客户端的 ack 后会将连接放到一个叫做 accept queue 的队列里面(linux2.2 之后握手过程分为 syn queue 和 accept queue 两个队列,syn queue 长度由 tcp_max_syn_backlog 决定)
· 队列的大小由 backlog 参数和配置 somaxconn 的最小值决定,我们可以通过 ss -lt 命令查看最终的 accept queue 队列大小,Swoole 的主进程调用 accept(高版本内核调用的是 accept4,为了节省一次 set no block 系统调用)
· 从 accept queue 里面取走。 当 accept queue 满了之后连接有可能成功(成功是通过 TCP 的重传机制,相关的配置有 tcp_synack_retries 和 tcp_abort_on_overflow)
· 也有可能失败,失败后客户端的表现就是连接被重置( 客户端收到 syn+ack 包就认为连接成功了,实际上服务端还处于半连接状态,有可能发送 rst 包给客户端,客户端的表现就是 Connection reset by peer
· 或者连接超时,而服务端会记录失败的记录,可以通过 netstat -s|grep 'times the listen queue of a socket overflowed 来查看日志。如果出现了上述现象,你就应该调大该值了。 幸运的是 Swoole 的 SWOOLE_PROCESS 模式与 PHP-FPM/Apache 等软件不同,并不依赖 backlog 来解决连接排队的问题。所以基本不会遇到上述现象。
6) dispatch_mode:数据包分发策略。【默认值:2】
说明:

建议:
无状态 Server 可以使用 1 或 3,同步阻塞 Server 使用 3,异步非阻塞 Server 使用 1
有状态使用 2、4、5
在UDP模式下:
dispatch_mode=2/4/5 时为固定分配,底层使用客户端 IP 取模散列到不同的 Worker 进程,算法为 ip2long(ClientIP) % worker_num
dispatch_mode=1/3 时随机分配到不同的 Worker 进程
dispatch_mode 配置在 SWOOLE_BASE 模式是无效的,因为 BASE 不存在投递任务,当收到客户端发来的数据后会立即在当前线程 / 进程回调 onReceive,不需要投递 Worker 进程。
注意:
dispatch_mode=1/3 时,底层会屏蔽 onConnect/onClose 事件,原因是这 2 种模式下无法保证 onConnect/onClose/onReceive 的顺序;
非请求响应式的服务器程序,请不要使用模式 1 或 3。例如:http 服务就是响应式的,可以使用 1 或 3,有 TCP 长连接状态的就不能使用 1 或 3。
Swoole最基本配置项就以上这些啦,这一篇到这里就结束了,其它的配置项,包括重启、心跳机制会在之后的文章中慢慢介绍。大家下期见
--------------------------- 我是可爱的分割线 ----------------------------
最后博主借地宣传一下,漳州编程小组招新了,这是一个面向漳州青少年信息学/软件设计的学习小组,有意向的同学点击链接,联系我吧。
Swoole从入门到入土(3)——TCP服务器[基本配置项]的更多相关文章
- 【Swoole】简单安装与创建TCP服务器
		pecl install swoole PHP的异步.并行.高性能网络通信引擎,使用纯C语言编写,提供了php语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据 ... 
- php的异步非阻塞swoole模块使用(一)实现简易tcp服务器--服务端
		绑定tcp服务器的地址 $swserver = new swoole_server("127.0.0.1",9501); 设置tcp服务器装机容量(太危言耸听了-其实就是设置属性) ... 
- HTTP从入门到入土(3)——TCP三次握手
		TCP三次握手 客户端与服务器之间互相发送HTTP请求响应之前需要先进行TCP连接,因为HTTP是一个无连接.无状态协议,不存在连接的概念,只有请求和响应的概念.而请求和响应实际上只是数据包,他们需要 ... 
- php的异步非阻塞swoole模块使用(一)实现简易tcp服务器--客户端
		//实例化一个swoole客户端 $swclient = new swoole_client(SWOOLE_SOCK_TCP); //建立连接---如果连接无效则退出 )){ echo "连 ... 
- Swoole学习(七)Swoole之异步TCP服务器的创建
		环境:Centos6.4,PHP环境:PHP7 <?php //创建TCP服务器 /** * $host 是swoole需要监听的ip,如果要监听本地,不对外服务,那么就是127.0.0.1;如 ... 
- Swoole学习(二)Swoole之TCP服务器的创建
		环境:Centos6.4,PHP环境:PHP7 <?php //创建TCP服务器 /** * $host 是swoole需要监听的ip,如果要监听本地,不对外服务,那么就是127.0.0.1;如 ... 
- swoole 创建tcp服务器
		server.php <?php /** * 创建tcp服务器 * Date: 2019/1/15 */ $serv = new swoole_server('127.0.0.1', 9501) ... 
- Swoole系列(三):建立TCP服务器并发送数据测试
		<?php // 建立tcp服务器下 $host = '0.0.0.0'; $port = 9501; $serv = new swoole_server($host,$port); $serv ... 
- 18-ESP8266 SDK开发基础入门篇--TCP 服务器 RTOS版,串口透传,TCP客户端控制LED
		https://www.cnblogs.com/yangfengwu/p/11112015.html 先规定一下协议 aa 55 02 01 F1 4C 控制LED点亮 F1 4C为CRC高位和低位 ... 
- 17-ESP8266 SDK开发基础入门篇--TCP服务器 RTOS版,小试牛刀
		https://www.cnblogs.com/yangfengwu/p/11105466.html 现在开始写... lwip即可以用socket 的API 也可以用 netconn 的API实 ... 
随机推荐
- Docker-01基本命令
			1.Docker安装 系统镜像为Centos7.x yum包更新到最新 sudo yum update 安装需要的软件包,yum-util提供yum-config-manager功能.另外两个是dev ... 
- [转帖]能使 Oracle 索引失效的六大限制条件
			Oracle 索引的目标是避免全表扫描,提高查询效率,但有些时候却适得其反. 例如一张表中有上百万条数据,对某个字段加了索引,但是查询时性能并没有什么提高,这可能是 oracle 索引失效造成的.or ... 
- [转帖]@Scope("prototype")的正确用法——解决Bean的多例问题
			https://www.jianshu.com/p/54b0711a8ec8 1. 问题,Spring管理的某个Bean需要使用多例 在使用了Spring的web工程中,除非特殊情况,我们都会选择 ... 
- [转帖]Linux文件系统的几个性能测试软件小结
			https://developer.aliyun.com/article/297631#:~:text=Linux%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E7%9A% ... 
- [转帖]windos的kafka设置账号密码
			1.kafka配置文件 server.properties增加 listeners=SASL_PLAINTEXT://127.0.0.1:9092 advertised.listeners=SASL_ ... 
- [转帖]linux时间戳转换成时间指令_时间戳转换公式
			原文地址:http://wanping.blogbus.com/logs/28663569.html 1.时间戳转换为正常显示的时间格式 Freebsd 系统下: 转换命令为: date -r 111 ... 
- overcommit_memory的简单学习
			overcommit_memory的简单学习 背景 前几天一个测试环境启动失败. 总是有如下的提示: Native memory allocation (mmap) failed to map 122 ... 
- [转帖]鹅厂微服务发现与治理巨作PolarisMesh实践-上
			文章目录 概述 定义 核心功能 组件和生态 特色亮点 解决哪些问题 官方性能数据 架构原理 资源模型 服务治理 基本原理 服务注册 服务发现 安装 部署架构 集群安装 SpringCloud应用接入 ... 
- 像elementui一样封装自定义按钮
			<template> <div> <button @click.prevent="coverHandler" class="btn-btn& ... 
- 超级好用的elementui动态循环菜单
			<template> <div> <el-menu @select="selectMenu" :default-active="curren ... 
