PeerKitPeerKit11-17 08:33

Laravist群友杂谈 --- 内存泄露与Supervisor与爬虫

这一次好像离上次发布时间间隔有点久了,刚好今天是清明节,放假就来整理下前阵子群里的聊天.

主角还是Ab兄与Little兄,还有在群里没怎么说话的AceForce

这个话题我很难整理,因为都是一问一答,刚开始想按照自己的想法整合,但觉得还是保留原对话.(绝对不是我懒,真的,看我真挚的眼神!0-0 )

Abraham 问 Little

想使用 php 来抓取一个外部资源,资源更新频率比较高,预计 50 个 token, 每个抓取的频率大概都是 1 分钟一次。 有值得推荐的调配工具或 php 方面的写法么... @little 如果方便的话能指点下吗

Little 回答 Abraham

@Abraham. 如果你只是要高并发抓取,好办,有swoole这样的multi curl网络库,随便单机都能开十几万个线程抓。但是你要有token什么的,我就没搞过了,也许redis里加个计数器,造个token池子这样的弄弄看

Abraham 回应 AceForce

@AceForce 不会 Python,之前用的是 php 和 cron,觉得维护麻烦,后来不做了,现在想重新把那个网站再开开,寻思弄的更“偷懒”一点。laravel 有日程处理,但是 cli 没办法用 mysql 持久连接,这个必须得用,因为爬虫机配置高的话成本有点高。

Abraham

@little cli 是不能持久连接的吧?

little

可以用

AceForce

@Abraham. cli是可以长连接的,打开一个连接不要关,一直丢数据就行

Abraham

@AceForce 每个请求执行一次,请求之间也能共享连接吗?

Little 回答 Abraham

@Abraham. php与mysql的持久连接,是基于进程的,无论是 php-fpm 还是 php-cli。只要你不把这个进程退出关掉,那就是在这个进程之内的所有循环都能用这条连接。

当然 php-cli 的mysql持久连接意义并不大,你完全可以 $conn = DB::Connection,然后把 $conn 暂时存起来或者放到类属性什么的,类不销毁、变量不销毁,这个连接也就在。

php-fpm 是因为跨了多次 HTTP 请求,变量会完全销毁。而 cli 就没有这个问题嘛。

我只是分割线

Abraham


@little 是这样的, 我是直接 cron 一分钟一次的 php -f awesome.php

这种情况是不是就是把这个进程关掉的意思?

little

那不行,进程退出,什么都没了。

little

php awesome.php,常驻内存,自己在 awesome.php里循环,sleep什么的,

然后进程管理用 supervisor ,用 supervisor 就不用 nohup 或者 & 打后台了。想起多少个进程配置下就行。

AceForce

awesome.php常开,一分钟开一个子进程让去处理,

little

自己管理进程多累,supervisor 帮你考虑了一切

AceForce

workerman 不就是这么搞的?

little

搞了子进程,要pcntl_fork ,子进程挂了怎么办,内存超了怎么办

Abraham

两年前用过,我都完全不记得了:) 这个就是我打算重启的东东。



little



你只需要在 awesome.php里,写while true死循环,循环里计数,超过 10万次 exit 进程,避免内存泄露。剩下的让 supervisor 帮你监控管理。

AceForce

其实你还是不太信任你自己嘛。代码写得够健壮,还怕进程挂内存超?

Abraham

@little 当初好像是用 supervisor 重启脚本的,用 cron 总退.

little

我怕 vendor,我怕哪个扩展内存泄露,这说不准的。

vendor在前一篇 谈笑风生 提及过

Abraham

是呀,我虽然记不清了,但是恍惚感觉,好像 php 真的出错过。

cli 直接输出 max memory

little

php-fpm里的这个配置也是这个意思,总还是要定个值,避免问题的。


Abraham

虽然作者说 7 改善了 gc 但还是没底。

little

php扩展里搞出个内存泄露,我们是阻止不了的

AceForce

cli大变量大数组使用完记得unset下,不然不销毁,就会超内存

AceForce

fpm下可以不unset,生命周期不一样嘛

little

自己写的代码我都不太担心,cli 写在循环里,每次循环都赋值的话,理论上也是会被 gc 清理,只是更慢些。

我最担心的就是扩展里的代码,比如装个 php redis 扩展,底层好像依赖 lib c redis 库吧,只要这中间哪个环节有一丁点内存泄露,循环几十万次下来,也就很大了。

以前服务器遇到过问题,老是内存占满了服务器,最后仔细debug,发现就是 memcached 扩展内部弄出来的泄露。连这种最广泛的扩展的某个稳定版本都有内存泄露,不要指望每个扩展的质量都很高了。


爬虫的话题

Abraham

supervisor 远程控制用的是自带的 http 服务器,怎样让他支持 https 知道吗?

Abraham

我突然灵感一现,晕了,不支持可以装个 NGINX 做代理嘛

supervisor是管理进程的工具,提供了一个 xml rpc 接口可以远程监控线程状态,控制线程启动关闭之类的。

littlehz

@Abraham.你理解错了,supervisor的http是supervisorctl进程管理supervisord进程用的,跟业务没关系

Abraham

@littlehz有人实现的这个。



Abraham. 上午 12:20:16

我也想做个类似的,这样在国内的网站后台就能看蜘蛛状态了,可以吗?

littlehz

那也只是内网的,管理下多台服务器的进程,没必要放外网吧

Abraham

只是不想登陆爬虫机,文档上可以配置 9001 接口的 http ,提供了 xml-rpc 难道不就是为了远程访问嘛


然后我用 guzzle 跟他交互,不一定非得是内网

littlehz

我觉得爬虫机应该这么做。一堆的服务器、一堆的进程在爬,你有一堆的出口IP或者代理IP,爬的进程根据IP池几分钟的使用次数决定用哪个出口IP。然后通过supervisor管理这么多服务器,管理接口最好放同一个内网更安全,做个web管理界面限制下访问ip用户名密码

Abraham

这个机器抓 twitter 必须得放外面,因为只抓几千个用户,估计 500M 内存足够了,twitter 提供一个 streaming api,长连接的,资源占用非常少

但是网站(管理端和内容展现的地方)铁定是国内的,我寻思在网站后台能看到一些进程运行情况和基本的日志会比较有帮助

littlehz

没有这么多出口IP,就不用想了。有些网站比较傻,你伪造个X-REAL-IP也许就能过去

Abraham

不是爬知乎的那种互相斗法的爬,是完全在 rate limit 限制之下的合法的爬呀:)

你说的根据 ip 使用调整抓取的方式的,类似策略性的东西我也考虑过,比如说根据特定时间窗口 api 次数的盈余情况去多爬一些头像更新,粉丝数量更新。或者根据对方现在的时间动态调整下频率,但是初期考虑不了那么多,太复杂了. 现在想的的确就是怎样更安全的问题,不过如果把所有端口都关了,禁止外部任何的连接是不是应该没问题?

因为数据库和国内的是互为主从的,如果爬虫机被黑了,给我删库,国内的数据还得恢复,就麻烦死了。之前爬过一次 twitter 大概是两三年前吧,当时它们没提供 streaming api,我是用大量的号,每个号关注好多个号,然后爬这些号的时间线。现在提供的 streaming api 据说是 limit 大幅的提升,推荐抓大量用户的人用这个接口,打算试试。。。

说回 supervisor,@littlehz你觉得只有一台机器的话,用这种远程控制的方法不可靠吗,其实控制的可能性小,我尽量让蜘蛛智能点,主要就是看一下重启频率那些指标性的东西,我还不知道支不支持远程读日志,不支持的话, supervisor 可以把日志写到 mysql 里吗?

littlehz

问题是supervisor的http接口并没有任何安全限制,端口放出去了,别人也能连上这个端口发送个停止进程的指令哦。只能依靠防火墙限制下ip

Abraham

是呀,有个密码还是基于 basic 的,用 nginx 搭个代理可行吗?然后把 supervisor 的 http 设置成本机访问的,让你说的好怕怕的感觉

littlehz

那也可以,但要我做还是把supervisor http接口放内网。自己做个网页管理工具放外网。把supervisor http放外网或者代理下放外网都是一个意思,感觉就像是把mysql 3306放到外网都可以访问一样。

Abraham

那样就要两台机器了

littlehz

怎么就要两台机器呢?

Abraham

屏蔽 twitter 上的艺术,体育,学术帐号让很多不fq的人不得不去消化二手消息。 看着它们天天迷什么鹿什么掏粪我的心都碎了

Abraham

我打算抓回来,在国内开个 web 页面更新它们呀,那样不 fq 的人也可以得到公众人物的消息

@littlehz现在最最初期的设计,得5台,感觉这就心理能承受的极限。。。

俩 mysql, 一个 web,一个爬虫,一个搜索引擎做时间线

看数据量和访问量吧,最开始基础版的不到 1000 吧

littlehz

有优质线路,网页用https,一台就够了吧,放香港就是. HK的ping值一般不会超过70ms,大多数情况是40ms

Abraham

用的 ecs, 多开几个实例,出错了好排查

hk 的没考虑,看看再说吧, 不排除,以前用 hk 的代理总出错,出阴影了

littlehz

没多少访问量的时候怕什么,访问量上去了,在国内加个反向代理缓存下

Abraham

我心理一直感觉美国线路比亚洲的稳定,是错觉,今晚也一直在考虑,要不要把整个 web 都放外面...

littlehz

全部放国外吧,架构更简单,没有国际优质线路就在国内加个nginx cache咯,相当于自建cdn,这个架构比数据库跨国主从好做多了

异地主从、多中心这样的架构就不用考虑,太复杂,一般业务根本驾驭不了。用单中心+异地实时及定点备份+多地cache/cdn这样的方案。

某天早晨........

Abraham

星期日 上午 7:29:17

@littlehz 上次你说 web 和 crawler 都放到 hk 我思考了一阵子,感觉是比较可行的做法,降低了数据库复杂, 现在初步打算这么做, 还没开机器, 可能还得测一下 ping 的速度。 有一个问题, 大陆现在 cdn 基本都要备案, 你感觉机器放外面, 域名仍旧备案,是比较合适的选择吗,

littlehz

上午 8:12:51

@Abraham. 如果你所有机器都放HK,那测下ping,看看稳定性,国内都不用再放反代。速度不会有问题。

当然也可以真机放国外任意机房,你熟悉的就好。在HK或者国内找个反代。这样你万一遇到投诉,最多把你反代机器端走,不至于一锅全端。反代机器有1核1g装个nginx都能支持很大的量


增长见识,开拓视野,纵使路漫漫且曲折,亦胜过盲人摸象般自己闭门造车


官场书屋二维码

小额赞赏

000
评论