{fbmip:fixed type="top" id="mipfixed" dataSlide="header-fixed-slide" class="fb-header-fixed"}
{fbview:mainmenu menuItemCode='$menuItemCode'/}
{/fbmip:fixed}
{fbmip:img fit='cover' src="$banner2['img_url']" alt="$banner2['title']"/}

网站开发的时候如果用PHP执行异步请求

有人说,约束激励创造力。假如真的这样,PHP便是成熟期的创造性解决方案。我刚刚上周建构了初始化Segment.io的API的PHP库,找到了各种有所不同的方法可提升服务端请求性能。

设计师客户端类往API发送数据时,我们的首要任务之一便是确保我的代码绝不冲击到你的核心程序。这是非常艰巨的,特别是采用单线程,无分享的语言,如PHP。

业务商PHP安装方式很多,让问题越来越简单。不幸的,你的服务商容许你设立进程,写入文件与加装自己的扩展。不幸的话,你便得与一些纠缠的邻居分享同一个加装安装,可以上传文件。

完美状态,我们喜爱用最为大的符合构建各种情况。如果行驶PHP时(也许便一两个脚本),你应当详尽解读这些。

我们试著用三种主要方法构建PHP发出请求,下列便是。

一:迅速开启一个套接字(Socket)

搜索PHP异步要求,首先的结果均是相近的方法︰写一个Socket然之后于等候回到后拆除它。

这个想法是打开一次连收到服务端,相连糟糕便加载内容。Socket加载是不久的,所以你你们回到信息,写入之后间接拆除相连。这便节约了等候一次来往的事件。

不过如果你看StackOverflow之上的评论,Socket到底爆发了什么有一些争论。亦让我疑问:Socket怎么构建的异步?

上面是我们的Socket构建:

<?php

private function request($body) {

    $protocol = "ssl";

    $host = "api.segment.io";

    $port = 443;

    $path = "/v1/" . $body;

    $timeout = $this->options['timeout'];


    try {

      # Open our socket to the API Server.

      $socket = fsockopen($protocol . "://" . $host, $port,

                          $errno, $errstr, $timeout);


      # Create the request body, and make the request.

      $req = $this->create_body($host, $path, $content);

      fwrite($socket, $req);

      # ...

    } catch (Exception $e) {

      # ...

    }

}

?>

最后的后果并不悲观。一次fsockopen花了300毫秒,偶然更长。

现实证明,fsockopen是阻塞的——不是异步的!要理解究竟发作了什麼,需求深化研讨fsockopen是怎样任务。当fsockopen选择协议时,需求思索运用哪种socket。这个进程在衔接完成前是阻塞的。

温习一下,internet的根本协议是TCP。它使电脑之间的信息传递牢靠并有序。简直一切HTTP都运转于TCP上。我们用HTTP来简化自定义的客户端运用。

这是TCP Socket创立衔接:

客户端发送SYN音讯给效劳端

效劳端前往SYN-ACK音讯确认包

客户端发送最终ACK包及传送数据

作爲计时的局部,这是传输数据之前完成的完好来回,在fsockopen之前这就曾经前往。一旦衔接开启,我们可以爲socket写入数据。通常,需求30-100ms衔接到我们的效劳器。

TCP衔接比拟快,罪魁祸首是SSL需求的额定握手。SSL也完成在TCP上。TCP握手后又开端TLS握手。

光SSL衔接就需求三次握手,更不要说加上创立公共密匙的工夫。

阅读器的SSL衔接可以共享密匙,防止允许拜访的客户端和效劳端反复握手。可是PHP执行的Socket无法共享密匙,我们只能每次都是重新衔接。

还可以运用socket_set_nonblock创立“非阻塞”的Socket。不过这是在翻开Socket的时分不阻塞,你还是要等候完成才干写入内容。假如准确思索翻开Socket写入数据的工夫,页面加载会慢约100ms。

总结起来:

Socket可以在有权限限制的PHP上运转

fscokopen是阻塞的,即便不阻塞Socket也需求等候再写入数据

SSL衔接分明减慢衔接,由于额定的握手和加密进程

翻开衔接使页面延迟100ms

二,写日志文件

假如你没有其他零碎权限的时分,Sokets是十分棒的方案。这儿我们引见一种在功能上更好的办法,那就是把一切事情以日志方式写到文件。这个日志文件可以被任务进程或许cron做"带外"处置。

基于文件办法的优点是具有最小的API对外恳求。当php代码收回track 或许identify恳求的时分,经过这种办法任务进程可以同时处置100个事情的恳求,而不是仅一个恳求。

这种办法的另外一个优点是php进程可以绝对更快的记载文件,一个写操作往往只需求几毫秒。当php翻开一个文件句柄的时分,用fwrite停止追加写是很复杂的操作。由于纯php不具有“共享内存队列”机制,在这日志文件实践上和“共享内存队列”具有异曲同工的效果。

爲了读日志文件,我应用analytics-pythonlibrary库写了一个python上传脚本。爲了避免日志文件太大,脚本自动停止更名操作。可以静态的写php文件,还可以写内存中的文件句柄,在老恳求创立的中央,新恳求会创立一个新的日志文件。

这种办法没有太多的逻辑,只需开发者多写点cron义务,并且经过PyPI辨别装置我们的python库。(这两段觉得是在给他们的python库做公告,既然python那麼好,用php干嘛,bs)

办法总结(关键点):

写文件较快,零碎资源开支少。

需求耗费磁盘空间,要求守护进程对文件有写权限。

必需运转任务进程处置带外的记载音讯。

三:调用Curl进程

还有一个可选择的办法,我们可以经过exec 操作curl工具来收回恳求。curl恳求才可以做爲独立进程一局部来完成,允许php代码持续执行,而不会阻塞socket衔接。

这种办法的功能介于后面两种办法之间,比soket办法快,比写文件的办法破费更少的零碎资源。

操作 forkd curl 办法,最复杂的例子如下:


如果运行在生产模式,我们不希望等着fork进程的消息输出。所以代码中加添了"> /dev/null 2>&1 &"让进程正确的执行 ,而把任何可能输出都丢弃掉。

同样功能的shell脚本如下:


脚本破费了大约1秒多一点的工夫,占用大约4k的的常驻内存。而curl进程用了 规范SSL 300毫秒完成恳求,exce调用立即相应php顺序。这使得效劳页面能很快相使用户。

笔者用一台普通程度的机器实验,这种办法curl可以每秒呼应100个左右https恳求,而没有任何的内存开支。假如不必SSL,呼应的恳求会更多。

不必等候输出,Fork一个进程十分快。

curl破费了和socket异样工夫呼应一个恳求,但是这个外带的进程。

调用curl需求仅仅普通的unix根底。

Fork发起一个复杂的恳求,只需求几毫秒的工夫,但是少量的同步伐用(forks)会招致零碎变慢。