单个进程看是一个请求一个请求排队处理, 多个进程来看就是多个进程并发处理自己排队中的请求。
我测试了一下确实是阻塞的,workerman是非阻塞的,为什么webman不搞成非阻塞的,就像golang的gin框架,来一个请求就分配一个协程去执行,不阻塞其它请求的执行
同问,我的项目现在没问题,假如数据库量大了,一个请求从50ms增加到300ms,那我项目的并发能力岂不是急剧下降,相当于下降6倍
workerman和webman都是multi-reactor模型,基于event-loop的reactor,在单个event-loop中就是排队执行的,不论workerman还是webman; golang下面分配的协程最后交给执行线程来执行,实际上是有一个线程池的;对于线程池来说,内部的执行也是排队的,当线程池占满后,同样会阻塞,不同的是对于协程来说,是有类似时间片算法的,是有最大占用时间的,当达到了这个时间后,线程会将协程挂起,执行下一个协程;但值得注意的是,如system call的操作,对于当前执行线程来说是同步阻塞的,也就是说不论是否超出了时间片,该协程也必须等待该行代码执行完才可以出让当前线程; 对于上述描述,我们其实可以把event-loop也看作是线程池(前提是这些服务是否本身支持非阻塞异步),比如steam相关的内容,实际上就是支持非阻塞异步的,所以看起来和线程没有两样; PHP是没有线程的,这里即便是有fiber可以中断/恢复,但是没有一个旁置的执行单元来处理也始终会阻塞当前;如果go没有线程,那么他也和PHP一样,只能依托生态中的包或者拓展的异步非阻塞能力+event-loop完成这样的操作; 另外提一下,即便是swoole也是有一个独立的线程来处理协程的;
composer组件99%都是基于阻塞式开发的,它们不支持异步或协程。
另外协程并不是万能的, 看下 https://www.techempower.com/benchmarks 今年7月份最新压测数据。webman和gin的对比,不管是单查询、多查询、更新、查询+更新、纯文本,所有指标webman都比gin的QPS高1倍左右。你们还要啥自行车。
如果你们的数据库慢,或者操作数据库等存储比较多,就多开一些进程就好了。
另外说一句,PHP没有线程,但C有,其实如果在这一块想要研究的话,可以自己基于C11及以上的标准写一下thread相关的api,编译成动态库,通过PHP:FFI来进行调用;这样的拓展方式比传统的PHP拓展要更简单一些; 目前这一块还是很多PHPer的盲区,也有很多可以探索和创造的轮子; 当然,关于线程库也有很多已经成熟的,比如libpthread。
并发再高,解决不了这位朋友的问题,还是只能用go https://www.workerman.net/q/9057
目前的php生态及各种组件决定webman没办法完全支持异步或协程。
@ontheway 那位朋友的问题,假设他的这个请求是持续性的,那么使用go也解决不了,GPM的线程池是有上限的,占满只是时间问题;另外线程开多了最后还会影响CPU; 但假设那位朋友的问题不是持续性的,即便是同步阻塞也有解决方案,就是多开进程; 甚至业务可以拆分成异步的; 但如果业务一定要同步,并且换go来解决,我只能说治标不治本;也仅仅只是把”能开10个进程“的机器换成了”开20个线程”而已。
@ontheway,这个很好解决啊,慢请求直接开一组进程去处理就好了,不影响其它请求。
@walkor 那位朋友的需求是调用端需要等待请求结果(似乎是QQ群里说过)...所以我才建议直接FPM
思维问题而已,就那个开几个websocket就完全可以处理好,非要用http这种短协议当然不好处理。 1 前端发起请求,生成一个请求ID, 2 后台ws进程保存好请求ID,异步请求接口 3 获取到数据后,扣余额,响应数据给前端,包括请求ID,前端再根据请求ID来判断响应的数据。
@2548a websocket和消息队列,做过技术的一般都想的到,就看那位兄弟用不用而已
同步非阻塞
Which bicycle do u want?[doge]
思路一:webman是单线程多进程,如果处理io频繁业务而非高运算业务可以多开进程解决,但是这不是万能的,毕竟进程的开销还是很大的,且多开进程是在启动程序就决定数量的,不能根据请求数量动态变更,这条路还是要根据自己的业务说话。
思路二:可以保存当前http请求的连接句柄,持有当前请求的句柄后在有必要的时候做返回数据,这个我有实践,比如浏览器的扫码登录这个功能,也就是实现http的长轮训功能,如果不这样实现的话最多同时等待登录的人数只能是当前进程数量。当然这要在足够了解workerman及webman的前提下对框架动动手脚。
至于golang,这和webman及大部分php程序的运行模式都是不一样的,可以说golang是天生支持高并发的,它的来一个请求对应的一个协成,协成的开销很小,当前协成有阻塞它会去执行其他协成,所以从语言层面就有优势。
golang的对于网络io来说的netpoll可以粗略的理解为线程+协程调度版的workerman,协程在线程+调度器之上做的并发,相当于自行实现了http句柄挂起,无须自行开发; golang的systemcall相关的内容,比如文件io等操作,是阻塞的,并没有利用reactor模型,只是线程池; 至于扫码登陆或者其他长轮询场景,可以使用websocket代替,php的socket、stream相关函数同样是可以将句柄挂起;只是说某些场景下仅仅为一个接口实现一个websocket没有必要,所以出现了http来实现服务端长轮询;但如果有多种服务,个人觉得更为完善的websocket会比http更好; golang较于workerman、swoole甚至java的优势,我认为在于天生统一了event-loop、线程池、协程调度等并发场景所需要的组件和功能,并且它的生态也是围绕这些组件和功能开发的,更为“工业化”和“统一”,反观PHP、Java,历史遗留的生态前者和后者都有大量同步阻塞的组件,workerman、swoole等reactor生态在PHP生态中仅占非常小的一部分,需要重复造轮子;Java甚至现在还有大量的JDK8,还有JDBC遗产始终是同步阻塞的,loom这样的写成特性,vertx、netty等reactor生态也同样不火;node.js中虽然天生是异步,但因为是单线程,所以性能也同样不如golang。
做网站来说协程没有什么用处,而且采用协程或者异步还得维护上下文,连接池等等,会加大复杂程度。重点协程主要在io里面比较好,例如文件读写,网络请求等等
单个进程看是一个请求一个请求排队处理,
多个进程来看就是多个进程并发处理自己排队中的请求。
我测试了一下确实是阻塞的,workerman是非阻塞的,为什么webman不搞成非阻塞的,就像golang的gin框架,来一个请求就分配一个协程去执行,不阻塞其它请求的执行
同问,我的项目现在没问题,假如数据库量大了,一个请求从50ms增加到300ms,那我项目的并发能力岂不是急剧下降,相当于下降6倍
workerman和webman都是multi-reactor模型,基于event-loop的reactor,在单个event-loop中就是排队执行的,不论workerman还是webman;
golang下面分配的协程最后交给执行线程来执行,实际上是有一个线程池的;对于线程池来说,内部的执行也是排队的,当线程池占满后,同样会阻塞,不同的是对于协程来说,是有类似时间片算法的,是有最大占用时间的,当达到了这个时间后,线程会将协程挂起,执行下一个协程;但值得注意的是,如system call的操作,对于当前执行线程来说是同步阻塞的,也就是说不论是否超出了时间片,该协程也必须等待该行代码执行完才可以出让当前线程;
对于上述描述,我们其实可以把event-loop也看作是线程池(前提是这些服务是否本身支持非阻塞异步),比如steam相关的内容,实际上就是支持非阻塞异步的,所以看起来和线程没有两样;
PHP是没有线程的,这里即便是有fiber可以中断/恢复,但是没有一个旁置的执行单元来处理也始终会阻塞当前;如果go没有线程,那么他也和PHP一样,只能依托生态中的包或者拓展的异步非阻塞能力+event-loop完成这样的操作;
另外提一下,即便是swoole也是有一个独立的线程来处理协程的;
composer组件99%都是基于阻塞式开发的,它们不支持异步或协程。
另外协程并不是万能的,
看下 https://www.techempower.com/benchmarks 今年7月份最新压测数据。webman和gin的对比,不管是单查询、多查询、更新、查询+更新、纯文本,所有指标webman都比gin的QPS高1倍左右。你们还要啥自行车。
如果你们的数据库慢,或者操作数据库等存储比较多,就多开一些进程就好了。
另外说一句,PHP没有线程,但C有,其实如果在这一块想要研究的话,可以自己基于C11及以上的标准写一下thread相关的api,编译成动态库,通过PHP:FFI来进行调用;这样的拓展方式比传统的PHP拓展要更简单一些;
目前这一块还是很多PHPer的盲区,也有很多可以探索和创造的轮子;
当然,关于线程库也有很多已经成熟的,比如libpthread。
并发再高,解决不了这位朋友的问题,还是只能用go https://www.workerman.net/q/9057
目前的php生态及各种组件决定webman没办法完全支持异步或协程。
@ontheway 那位朋友的问题,假设他的这个请求是持续性的,那么使用go也解决不了,GPM的线程池是有上限的,占满只是时间问题;另外线程开多了最后还会影响CPU;
但假设那位朋友的问题不是持续性的,即便是同步阻塞也有解决方案,就是多开进程;
甚至业务可以拆分成异步的;
但如果业务一定要同步,并且换go来解决,我只能说治标不治本;也仅仅只是把”能开10个进程“的机器换成了”开20个线程”而已。
@ontheway,这个很好解决啊,慢请求直接开一组进程去处理就好了,不影响其它请求。
@walkor 那位朋友的需求是调用端需要等待请求结果(似乎是QQ群里说过)...所以我才建议直接FPM
思维问题而已,就那个开几个websocket就完全可以处理好,非要用http这种短协议当然不好处理。
1 前端发起请求,生成一个请求ID,
2 后台ws进程保存好请求ID,异步请求接口
3 获取到数据后,扣余额,响应数据给前端,包括请求ID,前端再根据请求ID来判断响应的数据。
@2548a websocket和消息队列,做过技术的一般都想的到,就看那位兄弟用不用而已
同步非阻塞
Which bicycle do u want?[doge]
思路一:webman是单线程多进程,如果处理io频繁业务而非高运算业务可以多开进程解决,但是这不是万能的,毕竟进程的开销还是很大的,且多开进程是在启动程序就决定数量的,不能根据请求数量动态变更,这条路还是要根据自己的业务说话。
思路二:可以保存当前http请求的连接句柄,持有当前请求的句柄后在有必要的时候做返回数据,这个我有实践,比如浏览器的扫码登录这个功能,也就是实现http的长轮训功能,如果不这样实现的话最多同时等待登录的人数只能是当前进程数量。当然这要在足够了解workerman及webman的前提下对框架动动手脚。
至于golang,这和webman及大部分php程序的运行模式都是不一样的,可以说golang是天生支持高并发的,它的来一个请求对应的一个协成,协成的开销很小,当前协成有阻塞它会去执行其他协成,所以从语言层面就有优势。
golang的对于网络io来说的netpoll可以粗略的理解为线程+协程调度版的workerman,协程在线程+调度器之上做的并发,相当于自行实现了http句柄挂起,无须自行开发;
golang的systemcall相关的内容,比如文件io等操作,是阻塞的,并没有利用reactor模型,只是线程池;
至于扫码登陆或者其他长轮询场景,可以使用websocket代替,php的socket、stream相关函数同样是可以将句柄挂起;只是说某些场景下仅仅为一个接口实现一个websocket没有必要,所以出现了http来实现服务端长轮询;但如果有多种服务,个人觉得更为完善的websocket会比http更好;
golang较于workerman、swoole甚至java的优势,我认为在于天生统一了event-loop、线程池、协程调度等并发场景所需要的组件和功能,并且它的生态也是围绕这些组件和功能开发的,更为“工业化”和“统一”,反观PHP、Java,历史遗留的生态前者和后者都有大量同步阻塞的组件,workerman、swoole等reactor生态在PHP生态中仅占非常小的一部分,需要重复造轮子;Java甚至现在还有大量的JDK8,还有JDBC遗产始终是同步阻塞的,loom这样的写成特性,vertx、netty等reactor生态也同样不火;node.js中虽然天生是异步,但因为是单线程,所以性能也同样不如golang。
做网站来说协程没有什么用处,而且采用协程或者异步还得维护上下文,连接池等等,会加大复杂程度。重点协程主要在io里面比较好,例如文件读写,网络请求等等