文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Workerman中reusePort属性的作用是什么

2023-06-20 16:54

关注

这篇文章将为大家详细讲解有关Workerman中reusePort属性的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

Workerman是一个高性能的PHP Socket服务器框架。可以用 Workerman 直接在 TCP 层编程,基本的编程套路是:

$w = new Workerman\Worker('tcp://0.0.0.0:80');$w->count = 4;$w->onMessage = function(Workerman\COnnection\TcpConnection $connection, array $data) {    $connection->send('Hello World');};Worker::runAll();

在使用的过程中,不知道你是否留意过 reusePort 这个参数,他默认被设置为 false。这个参数有什么用?什么情况下我们需要把他设置为 true,从而提高性能呢?

1. reuseport 的作用

关于 reusePort 参数,Workerman官方的文档是这么解释的:

开启监听端口复用后允许多个无亲缘关系的进程监听相同的端口,并且由系统内核做负载均衡,决定将socket连接交给哪个进程处理,避免了惊群效应,可以提升多进程短连接应用的性能。

如果没有深入研究过 Linux 网络编程,很难理解这句话。在此简单解释一下:

服务端程序通常通过监听服务器上的某个端口号,来接收客户端的请求。在Linux中,服务器网卡 + 端口号被抽象成了一个 Socket

为了提升性能,一般的服务端程序在运行时都有多个进程(俗称 Worker)监听同一个 Socket,在没有客户端连接到来的时候,这些Worker是处于挂起状态的,不消耗CPU资源。

如果某一刻有一个客户端连接到来,Linux 内核就会同时唤醒这些 Worker,让他们竞争去处理这个连接,

结果只有一个 Worker 可以获得处理这个连接的机会,其他Worker在竞争失败后继续回到挂起状态。唤醒 Worker 的过程是要消耗CPU资源的,Worker 数量越多,消耗的 CPU 资源就越多,造成了资源的浪费。这就是常说的 惊群效应

你也许会问:为什么不每次只唤醒一个Worker呢?很遗憾,Linux内核并没有这样的功能。

幸好,在 Linux 3.9 及以后的版本,加入 reuseport 特性。这个特性有什么用呢?

在有 reuseport 之前,一个端口号只能被一个 Socket 监听,有了 reuseport 之后,这个限制就被打破了:一个端口号可以被多个 Socket 同时监听。

前面说到,Linux 内核没法做到一次只唤醒一个 Worker,但是,内核可以做到将客户端连接均匀地发送到监听统一端口的一群 Socket 上。

如图所示,每个 Worker 都有自己的 Socket,都监听同一个端口。当有客户端连接到来时,内核转发连接到一个 Socket 上,而这个 Socket 只会唤醒自己隶属的那个 Worker。这样就很巧妙地解决了 惊群效应,提高了整体的性能。

由此,我们可以得出结论:如果你的 Linux 内核版本是 3.9 及以上的话,那么在使用 Workerman 时,可以将 reusePort 设置为 true 提升程序运行效率。

2. Workerman 如何利用 reuseport

虽然你只要在 Workerman 中把 reusePort 设置为 true,就能享受到 Linux 的这个高级特性。但 Workerman 的源码中,并不只是开启一个内核参数那么简单。Workerman 为你隐藏了许多的设计细节,我们来研究下。

Worker 类是 Workerman 里最主要的类,其中有个 listen() 函数:

protected function listen(){    ...    if (!$this->_mainSocket) {        ...        $this->_mainSocket = stream_socket_server(...);        ...    }    ...}

listen() 函数的作用就是在当前进程创建一个 Socket 并开始监听请求。

当 reusePort 为 false 时,主进程在创建 Worker 之前就调用了 listen() 函数:

protected function initWorkers() {    ....    if (!$worker->reusePort) {        $worker->listen();    }    ....}

随后主进程通过 pcntl_fork() 创建 Worker。pcntl_fork() 有个特性:创建出来的子进程(Worker)中的变量都是父进程复制而来的,包括父进程创建的 mainSocket。所以,当reusePort为∗∗false∗∗时,所有的Worker都复制父进程的mainSocket。所以,当reusePort为∗∗false∗∗时,所有的Worker都复制父进程的_mainSocket,也即共用一个 Socket。

而当 reusePort 为 true 时,情况就不同了。主进程在创建 Worker 前不会调用 listen(),而是在创建完 Worker 后由每个 Worker 自行发起 listen() 调用:

protected static function forkOneWorkerForLinux($worker) {    ...    $pid = pcntl_fork();    if ($pid === 0) {        if ($worker->reusePort) {            $worker->listen();        }        ...    }    ...}

这样的结果就是,每个子进程(Worker)都创建了自己的 Socket。

最后还有一点,如果想要内核开启 reuseport 功能,需要手动设置 Socket 的 context:

if ($this->reusePort) {    $context = stream_context_create();    stream_context_set_option($context, 'socket', 'so_reuseport', 1);}

关于Workerman中reusePort属性的作用是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯