首页 » PHP教程 » php长驻过程技巧_深究对常驻进程问题再剖析

php长驻过程技巧_深究对常驻进程问题再剖析

访客 2024-12-14 0

扫一扫用手机浏览

文章目录 [+]

事情中的难点问题正是我们知识技能栈全谱查漏补缺的最佳机遇,有问题不可怕,all in、去世磕就完事了,哈哈哈~

一 问题回顾

启动进程时,shm_attach()方法报错:

php长驻过程技巧_深究对常驻进程问题再剖析

failed for key 0x6104e88b: No space left on device

当时定位的缘故原由是:

php长驻过程技巧_深究对常驻进程问题再剖析
(图片来自网络侵删)

主进程非常退出,导致旗子暗记量和共享内存没有回收,资源耗尽,当再次申请资源时,无可用资源导致。

办理方案:清理旗子暗记量及共享内存。

二 问题再次阐发2.1 shm_attach()方法

根据php官方文档中的描述 shm_attach:创建或打开一个共享内存段(Creates or open a shared memory segment),解释:

shm_attach(int$key,int|null$size=null,int$permissions=0666):SysvSharedMemory|false

方法返回一个id,这个id可以用来通过指定的key来访问System V共享内存,第一次调用时创建共享内存段,须要设置参数size 和 可选参数permissions,默认$permissions值为0666。

第二次调用如果利用相同的key,将返回一个不同的SysvSharedMemory实例,但两个实例都访问相同的底层共享内存。
size 和 permissions 参数都会被忽略。

2.2 System V共享内存

System V IPC 机制下的共享内存实质是一段分外的内存区域,进程间须要共享的数据被放在该共享内存区域中,所有须要访问该共享区域的进程都要把该共享区域映射到本进程的地址空间中去。
共享内存许可一个或多个进程通过同时涌如今他们的虚拟地址空间的内存进行通信,而这块虚拟内存的页面被每个共享进程的页表条款所引用,同时并不须要再所有进程的虚拟内存都有相同的地址。

System V共享内存是一种最为高效的进程间通信办法,进程可以直接读写内存,而不须要任何数据的拷贝。
为了在多个进程间交流信息,内核专门留出了一块内存区,可以由须要访问的进程将其映射到自己的私有地址空间。
进程就可以直接读写这一块内存而不要进行数据的拷贝,从而大大提高效率。
由于多个进程共享一段内存,因此也须要依赖某种同步机制。

System V 的IPC(Inter-Process Communication,进程间通信)工具有共享内存、行列步队、旗子暗记量(灯)。

把稳:在IPC的通信模式下,不管是共享内存、行列步队还是旗子暗记量,每个IPC的工具都有唯一的名字,称为"键(key)"。
通过"键",进程能够识别所用的工具。
"键"与IPC工具的关系就犹如文件名称于文件,通过文件名,进程能够读写文件内的数据,乃至多个进程能够公用一个文件。
而在IPC的通信模式下,通过"键"的利用也能使得一个IPC工具能为多个进程所共用。

2.3 再看问题缘故原由

报错信息是在shm_attach()方法,而缺点缘故原由是

failed for key 0x6104e88b: No space left on device。

比较随意马虎确定非硬盘空间问题,加上已经对shm_attach()方法有了上面的理解,那么便是出在共享内存分配/获取。

进一步定位,由2.2可知,System V的IPC工具有共享内存、行列步队和旗子暗记量,个中可查的是共享内存空间和旗子暗记量,查询命令利用ipcs,常用命令如下:

ipcs可用来显示当前Linux系统中的共享内存段、旗子暗记量集、行列步队等的利用情形。
命令示例:ipcs -a或ipc 显示当前系统中共享内存段、旗子暗记量集、行列步队的利用情形;ipcs -m 显示共享内存段的利用情形;ipcs -s 显示旗子暗记量集的利用情形;ipcs -q 显示行列步队的利用情形;ipcrm可用来删除对应的共享内存段、旗子暗记量、行列步队;命令示例:ipcrm -s semid 删除对应的旗子暗记量集ipcrm -m shmid 删除对应的共享内存段ipcrm -q msqid 删除对应的行列步队批量删除可以利用命令:ipcs -s|grep xxx|cut -d" " -f2|xargs -n1 ipcrm -sipcs -s|awk '/xxx/{print $2}'|xargs -n1 ipcrm -sipcs -s|awk '/xxx/{system("ipcrm -s "$2)}'for i in echo `ipcs|grep xxx|cut -d" " -f2`; do ipcrm -s $i; done

通过ipcs -m 和 ipcs -s,确认是共享内存和旗子暗记量满导致,以是直接的办理方法便是先清理共享内存和旗子暗记量:

2.4 根源

为什么会造成共享内存和旗子暗记量满?

一个可以想到的缘故原由便是二者在利用时并没有被正常开释。
那么就须要其他信息来赞助我们更精确地定位问题。

通过与OP合营,以及当时常涌现的问题(征象)结合考虑:

1)发布韶光过长,脚本机kill pid失落败后等待90s后触发kill -9 pid,而强杀进程可能会导致共享变量和旗子暗记量无法正常开释,这是其一;

2)为什么kill pid会无法生效?

常日来说,除非在代码中做了hook处理或触发其他非常情形(权限问题等)导致失落败,常日不会触发这个问题;再考虑kill pid命令,等同于kill -15 pid命令,那么是否是我们的进程没有精确感知到这个旗子暗记量?

基于这个思路,并在测试环境不断考试测验kill pid动作及进程关闭效果(代码日志),终极定位到是所利用的laravel框架版本及依赖的php版本的问题,导致异步旗子暗记量支持的判断失落效。
后面又通过重写进程、进程管理及旗子暗记量管理,彻底办理了这一问题。

三 守护进程3.1 init.d

历史上,Linux 的启动一贯采取init进程来启动做事。
例如:

service apache2 startsudo /etc/init.d/apache2 start/etc/init.d 是 /etc/rc.d/init.d 的软链接(soft link)。
可以通过 ll 命令查看。

ls -ld /etc/init.dlrwxrwxrwx. 1 root root 11 Aug 30 2015 /etc/init.d -> rc.d/init.d

/etc/init.d是用来放做事脚本的,当Linux启动时,会探求这些目录中的做事脚本,并根据脚本的run level确定不同的启动级别。

例如,某台测试机上的/etc/init.d目录下的内容如下:

3.2 systemdinit毛病

init方法启动做事有两个毛病:

1、启动韶光长。
init进程是串行实行,在一个进程启动完毕后,才能启动下一个进程

2、启动脚本繁芜。
init进程只卖力实行启动脚本,脚本自身须要处理各种非常情形,这使得脚本内容过长且不易掌握。

因此,就有了systemd的出身。

systemd概述

关于systemd可以查看freedesktop的这篇文献:systemd System and Service Manager。

大略描述如下:systemd是Linux系统的一套基本构建块。
它供应了一个别系和做事管理器,它作为PID 1运行并启动系统的别的部分。

system的命令位置和版本查看:

[xxx@wx-crm1 ~]$ systemctl --versionsystemd 219+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN[xxx@wx-crm1~]$whichsystemctl /usr/bin/systemctlSystemd 的优点是功能强大,利用方便,缺陷是体系弘大,非常繁芜。
事实上,现在还有很多人反对利用 Systemd,情由便是它过于繁芜,与操作系统的其他部分强耦合,违反"keep simple, keep stupid"的Unix 哲学。

干系争议内容链接:

Solidot | systemd作者鞭笞开源和Linux社区

Solidot | 抗议者创建Systemd分支Uselessd

systemd架构

systemd干系命令

systemctl是systemd的主命令,供应的紧张功能和利用办法如下:

# 重启系统$ sudo systemctl reboot# 关闭系统,割断电源$ sudo systemctl poweroff# CPU停滞事情$ sudo systemctl halt# 停息系统$ sudo systemctl suspend# 让系统进入冬眠状态$ sudo systemctl hibernate

除此之外,还有systemd-analyze,用于查看启动耗时;

# 查看启动耗时$ systemd-analyze# 查看每个做事的启动耗时$ systemd-analyze blame# 显示瀑布状的启动过程流$ systemd-analyze critical-chain# 显示指定做事的启动流$ systemd-analyze critical-chain atd.servicehostnamectl命令用于查看当前主机的信息localectl命令用于掌握系统区域设置和键盘布局设置timedatectl命令用于查看当前时区设置。
loginctl命令用于查看当前登录的用户,等等。
干系观点

1、单元

系统初始化须要做的事情较多,例如启动sshd,须要做很多配置事情。
这个过程中的每一步将会被抽象为一个配置单元 unit。
常日可以认为一个做事是一个配置单元,一个挂载点是一个配置单元,一个交流分区的配置是一个配置单元等。

通过这样的抽象,可以简化文件开拓,例如一个mysql做事对应一个mysql.server文件,这种配置会非常大略,我们也不再须要编写和掩护繁芜的系统5脚本了。

2、依赖关系

systemd已经将大量的启动事情解除了依赖,使得他们可以并发启动,但还有有些任务之间存在依赖关系。
systemd用配置单元定义文件中的关键字来描述配置单元之间的依赖关系。
比如unit A依赖unit B,可以在unit B的定义中用"require A"来表示,这样systemd会担保优先启动A,然后再启动B。

3、事务

这里的事务,与数据库中事务的观点有所不同,是为了担保多个依赖的配置单元之间没有环形引用。
比如有A,B,C三个单元,存在环形依赖关系:

如果存在这一的依赖,那么将无法启动任意一个做事。
systemd会考试测验通过依赖关系的强(required)和弱(want)的分别,通过去掉wants关键字指定的依赖来考试测验冲破循环,无法修复的话将会报错。

4、target和运行级别

systemd用target取代了运行级别的观点。
systemd下目标和常见runlevelt的对应关系如下:

systemd的并发启动事理

紧张有三种办法:办理 socket 依赖;办理D-Bus依赖,即desktop-bus依赖,是一种进程间通信机制;办理文件系统依赖。
详细阐明请查阅参考文献:浅析 Linux 初始化 init 系统,第 3 部分 systemd(https://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/index.html)

- END -

作者:架构精进之路,专注软件架构研究,技能学习与个人发展,关注并私信我回答“01”,送你一份程序员发展进阶大礼包。

Thanks for reading!

标签:

相关文章

大数据三幡,新时代信息时代的智慧之光

随着信息技术的飞速发展,大数据已成为国家战略资源,被誉为“数字石油”。大数据三幡,即数据采集、数据处理和数据分析,是大数据应用的核...

PHP教程 2024-12-15 阅读0 评论0

收单平台php技巧_基于微信的支付分账筹划

第一,商家的交易收入直接进入到平台的账上,如果平台未具备支付牌照,这种办法会存在“二清”问题,不合法律法规;第二,由于须要采取平台...

PHP教程 2024-12-15 阅读0 评论0