php 获取数组中前N个值

 PHP  php 获取数组中前N个值已关闭评论
6月 072017
 

如下,获取数组中的前2个元素:

难道还有更方便的方法?

 Posted by at 下午 2:41

PHP 协程示例

 PHP  PHP 协程示例已关闭评论
4月 102017
 

在PHP没有协程的时候,我们也玩过并发多线程,但是,对于结果的实时处理就没那么方便了(尽管也可以实现),有了协程之后,代码看起来就会舒服许多,参考下面的multi_cmd.php

 

multi_cmd.php :

我们见到的更多的可能是并发执行多个任务,每个任务都完成后(如: curl异步多请求)在一并处理结果,如果处理结果本身也是需要时间的话,就会比较浪费时间,如果能完成一个处理一个的结果,效果会好一些

 

上面脚本存在瑕疵:

1、为了避免某个流阻塞整个进程,上面使用了非阻塞;但是,后面的死循环却导致了大量cpu的占用,所以,考虑使用stream_select会更好一些

2、为了能控制并发数就更好了,并发太大也可能不是好事

 

改进的脚本如下:

 

注意:

在使用stream_select 的时候, 是否阻塞也就不重要了

 Posted by at 下午 12:54

PHP 中执行命令的几种方式比较

 PHP  PHP 中执行命令的几种方式比较已关闭评论
4月 042017
 

system/exec 函数:

这两个函数会利用/bin/sh 指定的shell来执行指定的命令,所以,指定的命令实际上不仅可以包含可以执行的命令和参数,还可以是对应shell的内置命令以及shell支持的控制结构。

缺点: 无法区分标准输出与标准错误

注意: 这两个函数执行的外部命令默认继承了php进程的标准输入、标准输出和标准错误,你可以通过返回值得到进程的标准输出,但是标准错误却悄悄地流进了php进程定义的标准错误输出里面去了;更加隐晦的是,对于php-fpm进程来讲,该外部进程也默认listen(继承来的)了php-fpm监听的端口,但是肯定不会去处理php-fpm请求,一般情况下不会有问题,特殊情况下回让你莫名其妙

pcntl_exec 函数

该函数会取代当前执行的进程空间,而且是不会再回到当前进程空间,可能你很少会用到该函数,但是,当你确实需要该函数的时候,却又是没有其他函数可以替代的,如:

echo 2 是不可能被执行到的

注意: pcntl_exec不同于其他函数,并不会使用shell来执行指定的命令,而且指定的命令需要是要执行的可执行文件的全路径

proc_open 函数

这个是我最喜欢的函数:

  1. 可以通过proc_close得到外部进程的返回值
  2. 可以定义外部进程的标准输入、标准输出、标准错误,并且可以区分外部进程的标准输出和标准错误
  3. 一定程度上还可以实现并行执行多个外部命令

 

proc_open 示例:

 

 Posted by at 下午 2:59

关于php-fpm reload的优雅实现

 PHP  关于php-fpm reload的优雅实现已关闭评论
12月 082016
 

我们知道,nginx的reload是不会影响服务的,php-fpm也有reload 功能,而且确实不是restart,但是却是影响服务的,下面给出一种改进方式,是的php-fpm的reload不影响服务

修改源代码:

 

重写init脚本:

 

注意:

  1. 该功能要求linux内核版本较高,需要支持socket的SO_REUSEPORT 特性,我的3.10的内核已经支持了
  2. php-fpm 的pid文件是php-fpm进程来维护的,同时启动多个php-fpm不太方便,所以需要玩一些手段;虽然不指定pid文件参数也可以,但是我不知道如何才能方便地拿到php-fpm的pid信息,所以还是指定了pid参数
 Posted by at 下午 4:25

关于PHP中的长连接

 PHP  关于PHP中的长连接已关闭评论
11月 292016
 

长连接(也叫持久连接)是啥?

对于PHP来讲,如果是运行在web模式,每次请求完成,php会回收所有需要的申请的资源,但是也可以申请一些特殊的资源,php可以不回收,比如:长连接。

优点: 长连接省却了每次连接的麻烦,也有效减少了timewait的数量

长连接真的好吗?

  1. PHP中没有提供关闭(销毁)长连接的方法,当长连接出现意外时,将无所适从,更常见的是请求超时,都很不方便处理
  2. 同一个服务只能存在一个连接,如果想非阻塞地并发请求同一个服务(相同的目标ip、port),做不到!第二次的pfsockopen得到的是第一次pfsockopen的那个连接,php不会标识一个长连接是否在使用中

鉴于上面两点,感觉长连接真的好鸡肋

 Posted by at 上午 9:39

PHP5 升级到PHP7时curl注意事项

 PHP  PHP5 升级到PHP7时curl注意事项已关闭评论
11月 092016
 

(从大量的CLOSE_WAIT发现的问题)

脚本:

 

对于curl来说:

  1. 如果请求头中含有 Connection: close 则,执行完请求之后,curl会主动关闭连接,即使不主动curl_close() 也没有关系
  2. 如果请求头中没有Connection: close,则:
    1. 如果curl句柄被销毁了,则连接自动关闭
    2. 如果句柄没有被销毁(如: 被保存到了全局(或其他静态)变量中),则:
      1. PHP5中,curl_close() 可以关闭连接
      2. PHP7中,curl_close() 不会关闭连接(或许他猜测你可能还会用到),如果你不小心把句柄保存起来了,那么会有什么问题呢? 问题:
        服务器端等待足够长时间后要关闭连接,而客户端却不做任何处理,导致连接处于CLOSE_WAIT状态,如果足够多,会导致local port被用完。
        不过,这个问题看似不好解决,也比PHP5中好处理,PHP5中如果调用了curl_close,而且还把curl句柄保存了起来,则可能会出现保存了大量的句柄而自己却不知道(就是所谓的内存泄漏)

 

 Posted by at 下午 7:35

关于php的max_execution_time

 PHP  关于php的max_execution_time已关闭评论
9月 032016
 

缘起:

一个php-fpm的请求执行时间会比较长,总是执行不完就中止了;查看php错误日志,显示执行时长超过了60s。

为什么呢?

参考php官方文档:http://php.net/manual/en/info.configuration.php#ini.max-execution-time

max_execution_time integer

This sets the maximum time in seconds a script is allowed to run before it is terminated by the parser. This helps prevent poorly written scripts from tying up the server. The default setting is 30. When running PHP from the command line the default setting is 0.

The maximum execution time is not affected by system calls, stream operations etc. Please see the set_time_limit() function for more details.

You can not change this setting with ini_set() when running in safe mode. The only workaround is to turn off safe mode or by changing the time limit in the php.ini.

Your web server can have other timeout configurations that may also interrupt PHP execution. Apache has a Timeout directive and IIS has a CGI timeout function. Both default to 300 seconds. See your web server documentation for specific details.

说明:

  1. 命令行执行php没有执行时长限制,尽管显式在php.ini中配置、或者ini_set(“max_execution_time”, n)、或者set_time_limit(n) 都是没用的;
  2. 尽管使用ini_set(…) 、set_time_limit(..) 后,也能通过ini_get(..)发现设置的值确实发生变化了,对于命令行也是没有作用的
  3. 命令行php -i 查看到的 max_execution_time 总是0
  4. 所以: 命令行程序对于PHP执行时长限制的担心都是多余的,cli 模式下max_execution_time被硬编码为0了
  5. max_execution_time 的默认值是30s

 

关于set_time_limit:  http://php.net/manual/en/function.set-time-limit.php

  1. set_time_limit(n) 会重置时间计数器,就是说是从该函数调用的时候计数n的
  2. php-fpm的脚本中执行set_time_limit(n)、或者ini_set(“max_execution_time”, n) 是无效的
    虽然这样更加安全,但是不符合定义: http://php.net/manual/en/info.configuration.php ;这里
    有说明max_execution_time的可修改限制为PHP_INI_ALL,就是说任何条件下都可以随时修改: http://php.net/manual/en/configuration.changes.modes.php

 

结论:

  1. 命令行程序对于PHP执行时长限制的担心都是多余的
  2. php-fpm环境下,试图在脚本中修改max_execution_time是没有用的
  3. 所以,max_execution_time 一般在php.ini 中定义

 

 Posted by at 下午 4:41

PHP编译问题

 PHP  PHP编译问题已关闭评论
8月 032016
 

php 的configure选项中启用模块时,有些是–with-extname ,有些是 –enable-extname ;有何区别?

  1. –enable-extname  用于模块不需要任何依赖,可以直接开启
  2. –with-extname 用于模块有第三方依赖,需要先安装依赖
  3. 其它就没有差别了
  4. 参考: http://stackoverflow.com/questions/1255055/compiling-php-with-modules-vs-using-shared-modules

如何将尽可能多的模块编译为动态扩展?

 

如何编译所有模块:

./configure –enable-all=shared

如何编译除去指定模块外的所有模块:(下面去掉了两个不太熟悉的模块)

./configure –enable-all=shared –with-enchant=no –with-gmp=no

如何在with模块的时候指定依赖的安装路径:

 

编译选项示例:

 

如何将php.ini php-fpm.conf  php.d php-fpm.d 都放到/etc/php 目录下?如下:

编译选项:

–sysconfdir=/etc/php   : 指示 php-fpm.conf   php-fpm.d 安装到 /etc/php 下

–with-config-file-path=/etc/php :指示 php.ini 安装到 /etc/php 下

–with-config-file-scan-dir=/etc/php/php.d : 指示 php.d 安装到 /etc/php 下

 

php.ini 的安装位置和 –sysconfdir没有关系,默认 ${prefix}/lib

php-fpm.conf 的位置和–with-config-file-path 没有关系,默认 ${prefix}/etc 下

 

 

 

 Posted by at 下午 12:55

systemtap 跟踪PHP

 Linux & Unix, PHP  systemtap 跟踪PHP已关闭评论
6月 282016
 

参考资料:

http://php.net/manual/zh/features.dtrace.php

通过mark的方式,了解php都提供了哪些探针:

php探针完全版: all_probes.stp

 

 Posted by at 下午 5:31

php 之 xhprof

 PHP  php 之 xhprof已关闭评论
6月 062016
 

参考资料:http://blog.aboutc.net/profiling/17/php-profiler-xhprof

这里不说别的,只记录一个小有意思的事情:

由于所谓的PHP内存泄漏,在程序跑上几分钟后就耗尽内存而退出,据说xhprof很是厉害,可以分析是哪个函数占用了太多内存;由于xhprof没有现成的环境,配置起来花费了一些功夫,最后发现,是pdo_mysql的execute占用了90%+的内存,天哪,用了N多年的东西突然有问题了?冥思苦想,夜不能寐。

突然间,想到一个其他的办法,就是在每段代码前后添加memory_get_usage()来检查是否内存使用有发生变化,如果没有变化,则这部分代码没有问题;如果有变化,则这部分代码有问题;(注意:如果这部分代码有函数调用,则函数调用不应该有大的返回值,如果有自己看着处理);就这样,通过二分法一步一步排查,终于发现,小朋友为了提高性能,使用类的静态变量数组cache了sql查询的结果,这个cache没有大小限制。

然后回到xhprof分析的结果,可以想象,之所以xhprof认为pdo_mysql的execute有问题,是因为这些内存都是该函数申请的,你说pdo_mysql 冤不冤?

 Posted by at 下午 3:40