协议概况
- beanstalk protocol 是建立在TCP之上的应用层协议。
- 协议采用ASCII编码
- 针对每一个连接,服务端按照接收指令的次序处理和发送响应。
- 协议中所有整型都已十进制小数表示(除非另作说明),并且非负数
- 协议中的名称都是ASICC字符串,由 a-zA-Z0-9-+/;.$_() 组成,但是不能以减号开头,以空字符或者换行结束,每个名称至少一个字符。
- 协议包含两种数据
- 行文本,被用作:
- 客户端指令
- 服务端响应
- 非结构化数据块,被用作:
- 传递job体(一段字节序列)
- 传递统计信息
- 行文本,被用作:
- 服务端不对job体做任何检查或修改,总会按其原有格式返回
- 客户端负责解析job体
- 当结束连接时客户端发送“quit”指令,或者直接断开tcp连接即可
- beanstalkd 支持大量连接,因此最好的做法是客户端保持连接,并尽量复用。
- 当客户端发送协议错误或者服务端出错时会报出下面中的一个错误:
- OUT_OF_MEMORY 服务端无法为job分配足够的内存。
- INTERNAL_ERROR 服务器内部错误,一般不会发生。
- BAD_FORMAT 客户端发送的指令格式非法。
- UNKNOWN_COMMAND 指令不存在
- 当服务端发生错误无法继续服务于当前客户端时,将主动关闭连接
Job 生命周期
job由客户端通过“put”指令创建。 job生命周期中的四个状态:
- ready
- reserved
- delayed
- buried
状态变化:
put reserve delete
—–> [READY] ———> [RESERVED] ——–> *poof*
- beanstalk系统可以有一个或多个tube
- 每一个tuple由一个ready 队列和一个 delay 队列组成
- 每个job的生命周期都在一个tube内流转
- consumer可以发送“watch”,“ignore”来关注或忽略一个tube。
- 设置“watch”的tube将进入consumer的watch list
- consumer可以获取其watch list 中的任意一个tube的job
- 当客户端建立连接,watch list中会有一个名为default的默认tube
- 客户端提交job前如果未使用“use”指令,job则被放入默认tube(default)
- tube在被引用时按需创建
- 如果tube为空(不存在任何 ready,delay,buried jobs)且 没有客户端引用,则被删除
Producer 指令
put
用来将job插入客户端当前tube的队列 格式如下: put <pri> <delay> <ttr> <bytes>\r\n<data>\r\n
- <pri> 优先级(priority) < 2^32 ,数字越小优先级越高,最高优先级0,最低 4,294,967,295
- <delay> 单位秒,整型;表示延迟多少时间将job放入ready队列,job状态为delayed
- <ttr> 单位秒,整型;允许worker执行job的超时时间。从worker reserve一个job开始计时
- 如果worker执行超时(指定时间内未 release\delete\bury)服务端将release job。
- 最小时间1s,客户端设置0,服务端会自动置为1
- <bytes> 整型数字,表示<body>部分字节大小,不包含\r\n,必须小于 max-job-size(默认2^16)
- <data> job体,啥内容都可以,服务端不关心
服务端响应
- “INSERTED <id>\r\n” 表示执行成功,<id> 新put的job id,整型
- “EXPECTED_CRLF\r\n” 表示job体少了”\r\n” 这个两个字符不计入<bytes>
- “JOB_TOO_BIG\r\n” job体大于max-job-size
- “DRAINING\r\n” 服务端处于饱和状态,无法接收新job
use
格式如下: use <tube>\r\n < tube>最长200字节的名字,不存在则(服务端)创建
服务端响应:
USING <tube>\r\n
Worker 指令
欲从服务端队列中消费job的进程。
消费动作包括:reserve\delete\release\bury
reserve
指令格式(两种)
- reserve\r\n
- reserve-with-timeout <seconds>\r\n
服务端响应:
- 如果没有可用job,则会一直阻塞。
- 当获得可用job,如果时间超过<ttr>设置,服务端会被job放回ready队列。
- 可以使用stats-job 来获取job的实际可用时间以及设置的<ttr>
- reserved状态job的<ttr>的最后一秒被服务端用作安全边界。
- 在这一秒内,reserve 该job的客户端无法请求其他job。
- 如果在这一秒内,客户端发起reserve或者在之前发起,但在这一秒还没有返回,服务端返回:
- DEADLINE_SOON\r\n
- 当使用reserve-with-timeout 并设置了一个非负值,超时后返回TIMED_OUT\r\n
- 其他情况将是正常响应,服务端返回:RESERVED <id> <bytes>\r\n<data>\r\n
- <id> job id
- <bytes> job body length
- <data> job body
delete
指令格式:
delete <job_id>\r\n
服务端响应:
- DELETED\r\n 表示成功
- NOT_FOUND\r\n job不存在
release
指令格式:
release <id> <pri> <delay>\r\n
- <id> job id
- <pri> priority 可以重置优先级
- <delay>
服务端响应:
- RELEASED\r\n 表示成功
- BURIED\r\n 服务端没有足够内存将job放入优先级队列数据结构中
- NOT_FOUND\r\n job不存在
bury
指令格式:
bury <id> <pri>\r\n
服务端响应:
BURIED\r\n 表示成功
NOT_FOUND\r\n job不存在,或者是当前客户端并未获取该job
touch
告诉服务端用来延长当前执行的job
指令格式:
touch <id>\r\n
<id> 被当前连接reserved的job id
服务端响应:
TOUCHED\r\n 表示成功
NOT_FOUND\r\n 不存在,或job未被当前客户端reserve
watch
指令格式:
watch <tube>\r\n
服务端响应:
WATCHING <count>\r\n
<count>表示现在在watch list中的数量
ignore
从watch list中移除tube
指令格式:
ignore <tube>\r\n
服务端响应:
WATCHING <count>\r\n 表示成功
NOT_IGNORED\r\n 试图移除watch list 中最后一个tube
peek
客户端预览服务端的job情况
- peek <id>\r\n
- peek-ready\r\n
- peek-delayed\r\n
- peek-buried\r\n
服务端响应:
1. NOT_FOUND\r\n job不存在,或者没有指定状态的job
2. FOUND <id> <bytes>\r\n<data>\r\n
kick
只作用域当前使用的tube,将job从buried转移到ready
- 如果存在buried jobs 则只转移 buried jobs
- 如果不存在buried jobs,则转移 delayed jobs
指令格式:
kick <bound>\r\n
<bound> 整型,表示要kick的job数量
服务端响应:
KICKED <count>\r\n
<count> 表示实际被kicked的job数量
stats-job
获取某一个job的相关信息
指令格式:
stats-job <id>\r\n
服务端响应:
- NOT_FOUND\r\n
- OK <bytes>\r\n<data>\r\n
<data> 是一个yaml (什么是)文件,包含下面的key
- id – job id
- tube – 包含该job的tube名称
- state – ready, delayed, reserved, buried
- pri – job 的优先级
- age – job 被创建的时间,单位秒
- time-left – 距离被放入ready队列的时间,只针对buried,delayed状态的job
- reserves – 被预订的次数
- timeouts – 超时次数
- release – 被释放的次数
- buries – 被隐藏的次数
- kicks – 被kick的次数
stats-tube
获取某一个tube的信息
指令格式:
status-tube <tube>\r\n
服务端响应:
- NOT_FOUND\r\n
- OK <bytes>\r\n<data>\r\n
<data> 是一个yaml 文件,包含下面的key
- name : tube名称
- current-jobs-urgent: 优先级小于1024的ready状态job数量
- current-jobs-ready:ready状态job数量
- current-jobs-reserved: reserved状态job数量
- current-job-delayed:delayed状态job数量
- current-job-buried:buried状态job数量
- total-jobs: job总数
- current-waiting:阻塞在reserve指令的连接数
- pause: tube被暂停的时间,单位:秒
- cmd-pause-tube:tube被暂停的次数
- pause-time-left: 距离暂停结束的时间,单位:秒
stats
获得全局状态
指令格式:
status\r\n
服务端响应:
OK <bytes>\r\n<data>\r\n
<data> 是一个yaml 文件,包含下面的key
- current-jobs-urgent: 优先级小于1024的ready状态job数量
- current-jobs-ready:ready状态job数量
- current-jobs-reserved: reserved状态job数量
- current-job-delayed:delayed状态job数量
- current-job-buried:buried状态job数量
- cmd-指令名称 : 累指令执行次数
- job-timeouts : 累计job超时次数
- total-jobs: 累计job数
- max-job-size: job<bytes>最大值
- current-tubes: tubes数量
- current-connections: 当前打开的连接数
- current-producers : 连接中至少执行过一次put的数量
- current-workers: 连接中至少执行过一次reserve的数量
- current-waiting: 当前阻塞在reserve指令中的连接数量
- total-connections: 累计的连接数量
- pid : 服务端进程id
- version : 服务端版本
- rusage-utime:
- rusage-stime:
- uptime:
- binlog-oldest-index:
- binlog-current-index:
- binlog-max-size:
list-tubes,list-tube-used, list-tube-watched
指令格式:
list-tubes\r\n
服务端响应:
OK <bytes>\r\n<data>\r\n
<data> 是一个yaml 文件,包含tube名称的一个数组
quit
客户端断开连接
pause-tube
暂停某一个tube,在delay期内tube内的job无法被预订。
指令格式:
pause-tube <tube> <delay>\r\n
服务端响应:
- PAUSED\r\n
- NOT_FOUND\r\n