CuriousY A world with wonder

Get 'broken pipe' error when running Flask server

| Comment

Problem

如题。

Reason

这个问题的原因是Flask自带的event loop的是单线程处理请求的,有多个请求同时发生时,而多个请求之间有相互依赖的关系(可以参见stackoverflow中这个问题的例子),产生了死锁,就产生了这个error。

Solution

使用可以更好地处理并发请求的HTTP server来运行Flask写好的web server程序(当然这个HTTP server要支持Python的WSGI协议)。

可选的HTTP server库有:

  • gunicorn
  • uWSGI(通过Nginx可以搭建分布式的server)
  • gevent(使用协程,提高了处理请求的能力)
  • twisted(强大的异步处理库,使用多进程/线程处理请求)

Conclusion

Flask本身就是设计为开发web server的app的库,而不是web server本身。所以在开发web server时可以用Flask自带的HTTP server来生成server,而在放入生产环境中时必须要考虑使用其他HTTP server来提供更强劲的web service。

Use cron-style schedule correctly

| Comment

遇到的一个坑

我在Aurora上新建了一个cron的job,并希望它每天run一次。然后发现这个job每隔两三分钟就会被Aurora给Kill掉,研究了半天Aurora自动Kill job的机制(参考上一篇blog),然后把这个job的cron_collision_policy改成了CANCEL_NEW。果然job不会被kill了,但是发现这个job并没有像预想的那样每天只run一次,而是job执行结束后立马又开始run了。

Cron的机制

首先cron发起自Unix系统,其中的crontab命令想必都是听说过的,这个命令其实就是修改了/etc/crontab文件。打开这个文件,可以看到这样的内容:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

里面已经对cron的机制有了简单的说明。简单地说,就是使用了5个位置(以空格为界)来分别表示不同的time scope,通过符号的组合可以定义最短每分钟执行一次到最长每年执行一次。

这里需要先解释下cron里面可以使用的一些符号:

  • *:它表示’every one’,比如第一个*表示每分钟,第二个表示每小时,以此类推。所以默认的* * * * * 就表示每一分钟。
  • number:一般的数字,对不同的位置范围要求是不一样的,表示指定的某个时间内。比如* 14 * * *表示每天的14点内的每一分钟。
  • ,:用来连接不同的符号,让这些符号可以共同作用于同一个time scope。比如0,30 12,18 * * *表示每天12点整,12点半,18点整和18点半。
  • -:它用来连接两个数字,表示这两个数字之间都选取上。比如9-17 * * * *表示每个小时的第9到第17分钟。
  • /n: 它表示’every nth‘,也就是步长,其实这个功能用,也可以实现,主要是为了简洁和方便。比如*/2 * * * *表示每两分钟,而*/1*其实是等价的。再比如说* 12 10-16/2 * ** 12 10,12,14,16 * *是等价的。

以上,我们可以用这些符号写出任何我们想要的时间段。

结合crontab,举个复杂一点的例子:

*/10 12-18/2 1-15,17,20-25 * * root backup.sh

这个例子会在每个月的1到15号,17号,20-25号的12点,14点,16点和18点的0分,10分,20分…来以root的身份执行backup.sh脚本。

回到坑里来

问题其实出在cron job里面的cron设置上,我把每天执行一次写成了* * */1 * *,而*/1*其实是等价的,所以这个cron的意义是每分钟执行一次,这也就能解释为什么我的Aurora job会有collision了。解决方法是把它改成0 0 * * *就可以了(会在每天0点整执行)。

Aurora Job被Kill的原因

| Comment

这里说的是非人为因素的被kill,根据目前实践的情况来看,主要有下面两种原因:

是OOM(out of memory)了,可以通过检查job的schema分配的内存和实际消耗的内存来确定。解决方案是在job schema里面增加内存的分配。

是Cron的job发生冲突了,而且此job的schema中的Collision Policies为KILL_EXISTING(default就是这个),那么根据官方文档是会被kill掉的:

The cron_collision_policy field specifies the scheduler’s behavior when a new cron job is triggered while an older run hasn’t finished. The scheduler has two policies available:

  • KILL_EXISTING: The default policy - on a collision the old instances are killed and a instances with the current configuration are started.
  • CANCEL_NEW: On a collision the new run is cancelled.

解决方案一是取消所有的同名job,然后重新schedule此job。(注意使用aurora cron deschedule xxx会把正在run的job从cron类型变成adhoc类型的job,并不会终止它,还需要使用aurora job killall xxx来把active的job终止掉。)二是在job的schema里面把cron_collision_policy设为CANCEL_NEW

Create production job in Aurora

| Comment

Problem

想create一个Aurora job,其中production=True,发现如下error message:

[root@pica-service bin]# aurora job create main/root/devel/source_datapump_datapump_task_systest-auto-master1901forecast_weather14714300361 /tmp/aurora_708374195

 INFO] Creating job source_datapump_datapump_task_systest-auto-master1901forecast_weather14714300361

Job creation failed due to error:

        Insufficient resource quota: CPU quota exceeded by 1.00 core(s); RAM quota exceeded by 1000.00 MB; DISK quota exceeded by 1000.00 MB

但我的资源明明是够的啊。

Reason

然后在官方文档上看到这么一句:

To grant quota to a particular role in production, an operator can use the command aurora_admin set_quota.

虽然说的不是很清楚,推测一下就是我要先设置一个quota供production的job使用。

然后我用aurora的命令查了下root role的quota,果然没设置都是0:

[root@pica-service bin]# aurora quota get main/root

 INFO] Getting quota for: root

Allocated:

  CPU: 0.0

  RAM: 0.000000 GB

  Disk: 0.000000 GB

Production shared pool resources consumed:

  CPU: 0.0

  RAM: 0.000000 GB

  Disk: 0.000000 GB

Production dedicated pool resources consumed:

  CPU: 0.0

  RAM: 0.000000 GB

  Disk: 0.000000 GB

Non-production shared pool resources consumed:

  CPU: 0.9

  RAM: 0.224609 GB

  Disk: 0.224609 GB

Non-production dedicated pool resources consumed:

  CPU: 0.0

  RAM: 0.000000 GB

  Disk: 0.000000 GB

Solution

要先对所在角色赋予一定的资源,然后才能创建production的job:

[root@pica-service bin]# aurora_admin set_quota main root 10 10gb 10gb

 INFO] Setting quota for user:root cpu:10.000000 ram:10240 disk: 10240

 INFO] Response from scheduler: OK (message: )

 

[root@pica-service bin]# aurora job create main/root/devel/source_datapump_datapump_task_systest-auto-master1901forecast_weather14714300361 /tmp/aurora_708374195

 INFO] Creating job source_datapump_datapump_task_systest-auto-master1901forecast_weather14714300361

 INFO] Checking status of main/root/devel/source_datapump_datapump_task_systest-auto-master1901forecast_weather14714300361

Job create succeeded: job url=http://10.66.136.96:8081/scheduler/root/devel/source_datapump_datapump_task_systest-auto-master1901forecast_weather14714300361

A Aurora job cannot be killed

| Comment

Problem

问题是这样的,我写了个脚本来list出所有的Aurora job然后逐一killall来删除所有的job。然而执行完脚本后,过了一段时间发现还有一个job还在Mesos里run。

这不是要逆天了嘛,速速kill掉:

[root@pica-service bin]# aurora job killall main/root/devel/source_nike_test_test_0

No tasks to kill found for job main/root/devel/source_nike_test_test_0

Job killall succeeded

显示kill成功了啊,但是回去mesos上一看,job还在那run的好好的呢。

于是我灵机一动,先创建一个同名的job再删除不就行了(感觉自己好机智)。

然而:


[root@pica-service bin]# aurora job create main/root/devel/source_nike_test_test0 /tmp/aurora708374195

 INFO] Creating job source_nike_test_test_0

Job creation failed due to error:

        Job root/devel/source_nike_test_test_0 already exists

就在我看着Aurora job的页面发呆的时候,突然发现这个job和别的job不太一样啊,它是cron的job!再联想下aurora命令是单独有一个cron的选项的,要删除cron的job需要走这个选项才行:

[root@pica-service bin]# aurora cron deschedule main/root/devel/source_nike_test_test_0

 INFO] Removing cron schedule for job main/root/devel/source_nike_test_test_0

Cron descheduling succeeded.

Conclusion

Aurora的job分两种:普通job和cron job。普通job又可以由它的service属性分为service job和adhoc job。普通job都可以通过aurora job killall来删除,而cron job则需要通过aurora cron deschedule来删除。

顺便说一下Aurora和Mesos之间的关系:Mesos提供了Api来创建它的task,而Aurora会根据自己的job去调用Mesos的Api(比如说一个cron job就是定期去call这个Api)。所以如果看到Mesos上有一个Task一直在run,那可不是Mesos的问题,它只是一个任劳任怨地小工头,后面的大老板说啥它做啥而已。

| Page 21 of 25 |