访问式的web服务(一)
最后更新于:2022-04-02 04:28:12
## 访问式的web服务(一)
![](http://www.ruanyifeng.com/blogimg/asset/2018/bg2018033001.jpg)
web服务的特点都是快速服务的,一个操作要在短时间完成,并响应用户。
但是这样有一些耗时的操作就没法做了,只能使用其他方式了。
还有一些问题,也是传统web服务:“访问一下就操作,再返回,没人访问就是死的”,这种模式所达不到的效果。
* * * * *
[RabbitMQ - RabbitMQ tutorial - Work Queues](http://www.rabbitmq.com/tutorials/tutorial-two-php.html)
> This concept is especially useful in web applications where it's impossible to handle a complex task during a short HTTP request window.(这个概念是特别有用的,**web应用程序是不可能在一个短的HTTP请求窗口中处理复杂的任务。**)
* * * * *
**要改变当前这种情况,就需要使用新的开发模式和技术了,目前来看主要有三种:**
1. 定时任务(例子:定时器)
';
比如每隔几秒钟执行一次什么任务,特点是高频,定时器模式,强调的是每隔多长时间执行一次。例子:每隔三秒钟做一次日志整理备份;每隔一秒钟做一次缓存检查;每隔一秒钟扫描一次所有下线用户,并作下线处理。2. 计划任务(例子:闹钟)
比如每天的闹钟,每个星期几做什么事,特点是重复,比如每天的闹钟,每天都会响(如果我要设置一个十五天后提醒我的闹钟就不行了,这时就得用代办提醒的程序了)3. 延时任务(例子:代办提醒)
比如三天后提醒我做什么,一个月之后自动执行什么事情,特点是单次,执行后就完成了,如果你需要3天后做什么,还需要9天后在做一次,那么你就添加两个这样的任务就行了4. 队列(例子:餐厅排队)
队列的意义其实是缓冲,如果某个操作费时,并且业务不依赖它马上返回执行结果的操作就可以放到队列去,要求的是越快做完越好,>[danger] 注意这里面很重要的一点要考虑,那就是阻塞。被调用方执行过程中是否会阻塞当前调用方。比如定时器是否会被阻塞,如果被阻塞了,那么就不能按照理想的状态一秒钟执行一次了(目前定时使用无限循环和延时睡眠的方式实现的,不知道还有没有其它方式实现),另外多任务的执行,是不是要开启多进程,不然太耗时了。要弄懂这里面的细节,就必须彻底理解程序/进程底层有哪些调用方式。(TODO 待测试:可以拿swoole的定时器做下试验)
有时候需要这几种方式配合起来应用,比如我网站有一亿会员,我是管理员,我现在需要给每个发送会员通知,这么多人,我不可能直接执行发送的程序。
所以我可以把发送会员消息当成一个任务,任务里面有我要发的内容,以及是否为全部成员(也可以是几个会员的id),我写好内容后点击发送就创建这样一个任务可以了,然后另一个程序在后台执行这个任务就可以了(得到任务数据,给每一个给用户发消息),让它在后台慢慢发就可以了,这样我就不用守着程序执行了,其实这就是队列(这个群发的队列跟普通的还有点 差别呢,那就是它在执行的过程中还会更新任务的数据,比如更新已发送了多少,当然可以用其他方式)。
如果情况变成我需要三天后执行这样的任务,那么此时就可以使用2,3两种配合了。创建一个2的任务,任务要做的事就是三天后在创建3的任务/队列。甚至这个给一亿会员发消息做一个队列不好,还可以拆分为每个用户一个队列,总之任务自己还可以创建任务。任务之间是灵活的。
这样不光解决了大任务(复杂耗时任务)不适合 **“传统的基于访问式的web服务”**来做的问题,更重要的意义其实是系统的解耦,这样将复杂的系统模块化了,降低了系统的耦合程度,系统的稳定性,可用性将大大提高,而这是大型系统所必须的面对和考虑的。
定时取决于你对时间精度的要求,最小时间是xx,你不会有这样的要求吧,就算你要求的时间精度很高,要知道cpu的时钟频率是xx,当然每个进程不可能完全独占cpu的时间片,而是每个进程占用一小部分cpu的时间片,cpu每次执行每个进程的一小段,不断地在各个进程中来回切换的。不过它还是很快。对于你的时间精度要求足够了。
时间要求精确的用延时队列(精确程度还是取决于工人数量),比如,半个小时后通知我,15分钟未支付订单自动关闭/三天后自动确认收货等等。要求不精确的用计划任务,比如每天晚上统计一些信息,给超过三十天未登录的用户发送邮件等等这样的任务可以使用计划任务做。
计划任务和队列;计划任务,按时间计划,做某事。而计划,展开那就多种多样了,有一次的,有每个月的,多次的,等等,总之是围绕时间的计划。
队列类型:1. 即时队列;2. 延时队列。
*(RPC本质其实也是访问时模型的)*
这三类又带来了一个问题,那就是:处理程序在什么时候执行?或者说被触发:
1. 在死循环中执行
2. 用系统的定时任务触发
3. 其他程序的触发
(有些情况可以让用户访问时触发,有些则需要单独用后台进程去触发,比如DZ的定时任务就是访问触发的,文章的按时发布,还有的针对用户的业务功能,也可以让用户访问时触发,当然也可以其他进程触发,如果其他进程不及时/实时的话,那么访问时触发就弥补了这个问题。)
~~~
观空调有感
什么时候触发,这要看你对时间精度的要求了,比如闹钟,都是精确到秒的,那么闹钟服务程序就得每隔一秒检测一次,要是大于一秒那就有点后知后觉了,所以这个需要看你的应用场景对时间的精度要求。还有一种情况,现实生活中,空调一关闭,扇叶就能归位,明明已经断电了,它这个是怎么做的呢,难道也有程序触发的吗,其实也是触发,不过这个触发时机和情况有所不同,它是有一个继电器,带磁性,通电时有磁性,所以自动打开了,不通电时由于没有磁性,那么拨片在弹力的作用下就会自动关闭,也就是说弹力一直存在着,只是继电器的磁力与弹力抗衡着使得打开,一旦失去磁力就会关闭,所以这个情况不是检测机制,不过你也可以理解成它是一直检测着,监控着,这是因为它的结构和材料决定了它的这个特性。所以计算机对待此类问题,也肯定有它自身的结构的,所以看清问题的本质很重要。抛开问题的本质和所处空间的环境(计算机),空谈解决方式是没有任何意义的。
note date:2017-7-21 00:22:50
~~~
* * * * *
**可以利用 [第三方监控服务](http://jk.cloud.360.cn/) 来触发**(不过还是不能保证第三方服务的稳定性和可靠性)
[定时任务 · 【官方版】ThinkPHP小程序拼团 && WeiPin3小程序 安装手册 · 看云](https://www.kancloud.cn/tpcms/wxshop/462852)
* * * * *
[Laravel 5.2 文档 服务 —— 任务调度 – Laravel学院](http://laravelacademy.org/post/3267.html)
> 检测的时间精度/粒度是秒
[在WordPress中使用wp-cron插件来设置定时任务_php实例_脚本之家](http://www.jb51.net/article/76183.htm#cmid=167401)
> 它的原理就是将创建的定时任务存储到数据库里,当有人访问的时候就去判断一下是否到时间需要执行这个定时任务,如果到时间则执行。
>
> **因为这种原理,所以执行的时间可能会有一些偏差,但随着网站的浏览量攀升和网络爬虫的不断访问,会让定时任务执行的时间越来越准确。**
DZ的定时任务,是由用户访问触发的,原因是因为DZ要让使用者安装门槛比较低,使用者大多只有虚拟主机而没有服务器,所以这种方式是最好的,但是这样的话就需要考虑并发了,不会可能会出现任务被重复执行的问题,其实DZ这里是使用了锁的,来看一下DZ是怎么做的 [class_cron.php](https://github.com/bluelovers/Discuz/blob/818e2ec412daeabeace808f9a398f84d728d8ec1/discuzx/upload/source/class/class_cron.php)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/885656724289cb218a9ce1c7d4f54976_874x817.png)
可以看到是使用了锁的,再来看一下它的锁是怎么实现的:
DZ的锁不是基于文件的,而是使用的 `common_process 进程锁管理 表 MEMORY 存储引擎`(用内存表做,还是没用锁,这只是把“缝隙”降得最低而已,并发量大的时候还是会出现重复执行的问题的) 做的。
待分析……
2017-7-2 17:59:11
* * * * *
还有,有的时候要保证处理程序只有一个在执行,不能出现并发的情况,那么程序执行时就要检测当前是否在运行了,如果已经在执行当中了,那就什么都不做退出,没有在执行时才去执行。至于怎么防止并发问题,可以用文件锁之类的。
所有的东西都不是凭空捏造,胡乱想象出来的,而是为了解决实际问题而诞生出来的解决方案。所以要以解决问题为目的,看清本质,知道你自己要什么,才是最重要的。否则你就掉进技术的黑洞旋涡,找不到方向。
其实从来都没有什么编程,从来都只是为了解决实际问题而已啊。
web、网站被创造出来也是为了解决实际问题的,当有些问题它不能很好的解决的时候,就要寻找其他的解决方法,而不是web不行,只是它不是专门为解决这个问题而创造的,它是为了其他的,为了解决它擅长的领域的问题而创造的,你像个泼妇一样的为难它,埋怨它有什么意义呢。
* * * * *
一件事物要想发生,要么是自主意识的,要么是被另一个什么事件的发生而触发的。自主就是通过自己不断的循环,触发就是在特定的时机被别人调用,至于这个特定的时机是什么时候,要看应用的实际情况和应用场景。
* * * * *
### web服务也是一种程序
一直以来,我们对程序的执行,都局限于 **[请求-响应]** 的模型,这是web开发做久了的原因。
受学习php影响,脚本执行有超时和内存限制(命令行模式没有这个限制),这就意味着脚本不能够长时间执行。所以潜意识中所有程序都是这样的,不能接受无限循环的代码,程序应该尽早执行完并退出,甚至受web访问式影响,只能写出被动运行的代码,不了解常驻服务程序的结构。但其实并不是这样的,这是思维受禁锢了。
* * * * *
### 参考:
[Discuz! X3 数据字典](http://faq.comsenz.com/library/database/x3/x3_index.htm)
[Discuz! X2 计划任务原理分析](http://blog.csdn.net/fengda2870/article/details/40584315)
[Discuz!开发之进程锁类discuz_process介绍](http://blog.csdn.net/lih062624/article/details/70135965)
[discuz防刷新、防外部提交研究](https://my.oschina.net/jiangbianwanghai/blog/68173?p=1)
[Discuz! X2 计划任务原理分析](http://www.discuz.net/thread-2284868-1-1.html)
[discuz X2 计划任务执行机制解析](http://down.admin5.com/edu/discuz/77126.html)
> Discuz! X2 即将到来新机制介绍:
在 Discuz! X2 中的计划任务引用了新的外部控制机制,以前的机制都是在程序允许的时候,需要有用户或者蜘蛛访问论坛,才能够执行计划任务。现在,在 Discuz! X2 中引如新的远程机制,可以在服务器上使用服务器的计划任务或者服务器的独立进程来监控执行论坛计划任务,也就可以避免在**访问用户较少的时候计划任务执行时间不准确的问题**了。
[discuzX2.5修改帖子点击量](http://youlanzihun.blog.163.com/blog/static/37311710201452342859577/)
[关于计划任务不执行或者重复执行](http://www.qlzhan.com/a/cmsjiaocheng/discuz/2013/60081.html)
[计划任务(今日发帖)有问题的临时解决方法 :)](http://www.qlzhan.com/a/cmsjiaocheng/discuz/2013/60080.html)
[PHP程序员未来发展的方向有哪些?](PHP程序员未来发展的方向有哪些?)
* * * * *
定时任务截图(六星教育):
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/ec7b01d3ba519e39f426caebff8a235f_765x447.jpg)
* * * * *
[fastadmin - 定时任务](http://demo.fastadmin.net/admin/general/crontab?ref=addtabs)
![](http://cdn.aipin100.cn/17-10-30/49208744.jpg)
* * * * *
[Facebook创始人扎克伯格,讲述编程中循环的原理](https://www.ixigua.com/a6452243849740812814/?utm_medium=feed_steam&utm_source=toutiao#mid=7644599489)
> 大公司有自己的分布式管理服务器,所有机器的定时任务都在一个集群上靠自动化达到目的。
[请求 · php笔记 · 看云](https://www.kancloud.cn/xiak/php-node/365315)
[【系统架构】亿级Web 系统的容错性实践【中】](http://mp.weixin.qq.com/s/VTJ3--4j6iJQb5IUe9JwHw)
> 设置超时:怪不得很多软件都会设置超时时间,比如Nginx和PHP,原来是为了容错和性能。
>
> 容错很重要,比如纠错码使得浏览器得以运作。
* * * * *
[Golang在php的web开发中,可以替代哪些应用场景? - 知乎](https://www.zhihu.com/question/265388870/answer/293319812)
> **【短生命周期+同步】** 的PHP-FPM 和 **【长生命周期(逻辑内存常驻)+同步/异步】** 的Swoole联合开发.
> 有个在后台一直运行着的进程,提供主动的辅助php_cli模式,**而不是像原来的http那样被动。**
[【PHP编程】服务器推送其实就是如此简单(一)](https://www.toutiao.com/a6536804858329039363/?tt_from=weixin&utm_campaign=client_share×tamp=1522267086&app=news_article_lite&utm_source=weixin&iid=25315997380&utm_medium=toutiao_android&wxshare_count=1)
> 在 Web 应用中,浏览器和服务器之间使用的是请求 / 响应的**交互模式**。浏览器发出请求,服务器根据收到的请求来生成相应的响应。浏览器再对收到的响应进行处理,展现给用户。
[想成为一名Web开发者?你应该学习Node.js而不是PHP](http://mp.weixin.qq.com/s/x8dm9e7gwLXSEzxE6sQYow)
> 它遵循经典的客户端 - 服务器模型,其中每个页面都初始化应用、数据库连接和 HTML 渲染。这使得当你导航一个网站时,PHP 比 Node.js 应用要慢。Node.js 应用一直运行,只需要初始化一次。因此,随着 HTML5、AJAX 和 WebSocket 等 Web 技术的出现,Node.js 更适合新的 Web 发展方向。
[专访死马:为什么说Egg.js是企业级Node框架](https://mp.weixin.qq.com/s/5aAgEc6lr5B3OerPv_IgGg)
> 清晰的定义了从配置、路由、扩展、中间件到控制器、**定时任务**等各个 Web 应用研发过程中一些最基础的概念
[Systemd 定时器教程 - 阮一峰的网络日志](http://www.ruanyifeng.com/blog/2018/03/systemd-timer.html)
[定时任务常见实现方式](https://mp.weixin.qq.com/s/MbaMgkRfvMUVt1i3a_nFtg)
[Java如何实现任务超时处理](https://mp.weixin.qq.com/s/2yEMqv6v26nnDR6s0kLZnw)
[【原创】分布式之延时任务方案解析 - 孤独烟 - 博客园](https://www.cnblogs.com/rjzheng/p/8972725.html)
~~~
在开发中,往往会遇到一些关于延时任务的需求。例如
生成订单30分钟未支付,则自动取消
生成订单60秒后,给用户发短信
对上述的任务,我们给一个专业的名字来形容,那就是延时任务。那么这里就会产生一个问题,这个延时任务和定时任务的区别究竟在哪里呢?一共有如下几点区别
定时任务有明确的触发时间,延时任务没有
定时任务有执行周期,而延时任务在某事件触发后一段时间内执行,没有执行周期
定时任务一般执行的是批处理操作是多个任务,而延时任务一般是单个任务
~~~
[为什么 PHP 程序员应该学习使用 Swoole](https://www.toutiao.com/a6568284224787317251/?tt_from=weixin&utm_campaign=client_share×tamp=1529319824&app=news_article_lite&utm_source=weixin&iid=33124962994&utm_medium=toutiao_android&wxshare_count=1)
> 【常驻内存】目前传统 PHP框架,在处理每个请求之前,都要做一遍加载框架文件、配置的操作。这可能已经成为性能问题的一大原因,而使用 Swoole 则没有这个问题,一次加载多次使用。
[一个著名的任务调度系统是怎么设计的?](https://mp.weixin.qq.com/s/uQB8uMg-zRfTCzcOt1FJIw)
~~~
“很简单,就是数据库的‘行’锁嘛, 比如SELECT * FROM LOCKS where LOCK_NAME='TRIGGER' FOR UPDATE ,这就把那一行记录给锁住了, 别的事务只能等待当前事务commit以后才能访问。”
队列里面叫task,计划任务里面叫job
定时任务,应该一次把到期的全部取出来,然后开多进程同时并发执行任务。不过进程数不要大于核心数,否则进程切换的开销会很大,多进程并不会发挥高效率。(不过要考虑任务是否需要单例执行,即某一任务同一时刻只能有一个在执行,如果当前任务正在执行,又到时了,在准备起一个进程执行时发现该任务当前在执行,那么就放弃本次调度,不执行。不过还有一种方式,是放弃还是放到队列呢?)
~~~
[ThinkPhp5与Swoole定时任务实践+PHP笔记 · 看云](https://www.kancloud.cn/dapeng235/thinkphp5_swoole_timer)
* * * * *
### php与nginx协同工作的原理
[初中级 PHP 面试基础汇总](https://mp.weixin.qq.com/s/_lqodpKV2pYCEfS4zMf8qQ)(什么是CGI? 什么是FastCGI? php-fpm , FastCGI,Nginx 之间是什么关系?)
[深入NGINX:nginx高性能的实现原理 - panda521 - 博客园](https://www.cnblogs.com/chenjfblog/p/8715580.html)
[深入理解PHP之:Nginx 与 FPM 的工作机制 - 文章 - 伯乐在线](http://blog.jobbole.com/99314/)
[Nginx+Php-fpm运行原理详解 - CSDN博客](https://blog.csdn.net/u013474436/article/details/52972699)
[nginx+php的配置与原理 - CSDN博客](https://blog.csdn.net/dengjiexian123/article/details/53358452)
[php-fpm安装、配置与优化 - CSDN博客](https://blog.csdn.net/QFire/article/details/78680717?locationNum=1&fps=1)
[PHP: FastCGI 进程管理器(FPM) - Manual](http://www.php.net/manual/zh/install.fpm.php)
[PHP-FPM 调优:使用 ‘pm static’ 来最大化你的服务器负载能力](https://mp.weixin.qq.com/s/cWKzgR35zorWL9JYyS9utA)
[线上部署 - ThinkJS 文档](https://thinkjs.org/zh-cn/doc/3.0/deploy.html)(使用 nginx:node.js与nginx)
[PM2实用入门指南 - CSDN博客](https://blog.csdn.net/maquealone/article/details/79550120)
[PHP Socket 初探 —— 硬着头皮继续 libevent(二)](https://mp.weixin.qq.com/s/J_Be3PI47PoLdKHCECJQhQ)
> 下面我们从开始写一个php定时器来步入到代码的节奏中。定时器是大家常用的一个工具,**一般phper一说定时器,脑海中第一个想起的绝逼是Linux中的crontab。难道phper们离开了crontab真的就没法混了吗?是的,真的好羞耻,现实告诉我们就是这样的,他们离开了crontab真的就没法混了。** 那么,是时候通过纯php来搞一波儿定时器实现了!
[PHP declare(ticks=N); 的作用 - 睡着的糖葫芦 - 博客园](https://www.cnblogs.com/loveyouyou616/p/5799933.html)
>[tip] 不要太低估PHP了,很多东西只是你不知道,没有试过,并不代表它就是你想的那样而已。
[Node 定时器详解](https://mp.weixin.qq.com/s/YLpGdzlKkUDhfi_EhgxG7Q)
[运行模式 · easySwoole 3.x](https://www.easyswoole.com/Manual/3.x/Cn/_book/noobCourse/RunMode/Introduction.html) (php有着5种运行模式,常见的有4种:)
[php-cli和php-fpm的关系是什么? - SegmentFault 思否](https://segmentfault.com/q/1010000004664671)
[PHP的线程安全ZTS与非线程NTS安全版本的区别](http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%B1%87/8287.shtml)
[PHP 不会死 —— 我们如何使用 Golang 来阻止 PHP 走向衰亡](https://mp.weixin.qq.com/s/x1QSy6NxlLE_Yv9wX6et2Q)
> 对于开发者来说,理解 *php-fpm* 如何执行应用程序的代码是最有趣的。当一个请求发送时, *php-fpm* 启动一个 PHP 子进程,并且将请求内容作为进程 *状态的* 一部分( `_GET` , `_POST` 和 `_SERVER` 等)。在执行 PHP 脚本期间,状态无法更改,因此获取一组新输入数据的唯一方法是销毁该进程并重新开始。
>
> **像这样的执行模型有很多好处。你不必担心内存使用情况,所有进程都完全隔离,如果其中任何进程死亡,那么它们将自动创建而不会影响其他进程。** 但与此同时,当你尝试扩展应用程序时,这一特性会成为程序开发的绊脚石。
>
> 但任何事都有两面性。所有的企业级框架都要求你加载至少十二个文件,构造多个类并解析一些配置,以便处理简单的用户请求或查询数据库。最糟糕的部分是每个任务完成后,你不得不抛弃这些代码。你刚刚启动的所有代码现在都变得无用,并且永远不能拿来处理另一个请求。**若是说给任何使用 PHP 之外的开发人员听,他们一定会对此满脸困惑,不能理解。**
>
> 多年来,聪明的 PHP 工程师一直试图通过使用延迟加载技术,微框架,优化良好的库,二级缓存等技术来缓解这些问题。但是在你项目结束时,你仍然不得不扔掉你的整个流程并一遍又一遍地重新开始重复的工作。
[动静分离架构,究竟是啥?](https://mp.weixin.qq.com/s/4lgHMBy8UJDWI69h25hN5w)
[没有Nginx,你还能做什么?](https://t.ti-node.com/thread/6494805245070147584)
> 搞Python的同行们,除了能用Flask码Web,也能用Tornado搞异步非阻塞,能够运用线程池来做一些task;相比之下,作为同行的我们,似乎除了会在fpm或者apache\_mod下搞一搞增删改查,似乎别的什么也做不了了,而且在接收新概念的时候,不太容易能接纳(后半句科班生以及优秀的非科班生忽略)。
[PHP-FPM源码分析](https://mp.weixin.qq.com/s/nT60mx1vlEKpRhvSzUZg7g)
* * * * *
last update:2019-1-23 14:54:50