社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
想法很简单。通过设置 runtime.GOMAXPROCS(1) 让 golang 的进程变成单线程执行的。类似python用gevent的效果。然后通过调度多个协程实现异步I/O并发。php作为一个子函数跑在go的进程内,php需要yield到其他协程时,通过回调到golang函数来实现。从php里调用go提供的子函数时,go保证保存php的当前上下文。当协程执行权让渡回来的时候,把原来的php上下文恢复。关键的代码在:
ServerContextGet 这几个函数是我加的,获得的是php的(EG/SG/PG)这三个全局context(参见:http://www.cnblogs.com/chance...)。修改过的github.com/deuill/go-php的源代码在:https://github.com/taowen/go-...
完整的php/go混合协程的demo:
执行结果是
可以看到两个sleep 1s,最终只用了1.00099211s。说明协程是并发的。
一些性能指标。走http调用后端,在i7-6700k上,用ab -n 100 -c 4 可以跑出这样的结果
如果不用http调用后端,直接php=>go返回"hello",则可以达到
这些指标只说明了协程切换的成本。实际的收益取决于后端的http服务的延迟,如果耗时很长,通过协程并发则可以收益明显。
这个实验说明了可以用golang实现一个代替nginx+php-fpm的应用服务器。并且提供了一条从php向golang迁移的平滑迁移路径。在一个应用里混合PHP和Go两种语言。
并且可以通过提供golang函数给php调用的方式实现I/O的异步化。像libcurl这样的扩展自身是支持异步回调的,只是php是同步的所以只给php暴露了同步的execute。有了Golang之后,可以把execute变成对异步execute+callback的包装,从而实现基于协程的调度。
作者:taowen
来源:51CTO
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!