本篇对ngx_http_upstream_check_module的源码进行扩展,来实现udp健康检查功能。
-关于配置和使用部分可以查看上篇:nginx upstream server主动健康检测模块ngx_http_upstream_check_module 使用和源码分析(上)
-关于源码分析部分可以查看中篇:nginx upstream server主动健康检测模块ngx_http_upstream_check_module 使用和源码分析(中)添加链接描述
static ngx_check_conf_t ngx_check_types[] = {
......
{
NGX_HTTP_CHECK_UDP,
ngx_string("udp"),
ngx_null_string,
0,
ngx_http_upstream_check_send_handler,
ngx_http_upstream_check_recv_handler,
ngx_http_upstream_check_udp_init,
ngx_http_upstream_check_udp_parse,
ngx_http_upstream_check_udp_reinit,
1,
0 },
......
这里定义了名称为udp的新的健康检测类型,其中ngx_http_upstream_check_send_handler和ngx_http_upstream_check_recv_handler两个回调函数是复用原先的实现的,而ngx_http_upstream_check_udp_init、ngx_http_upstream_check_udp_parse和ngx_http_upstream_check_udp_reinit是需要后面重新来实现的。这几个函数的实现留待后面来阐述。
其中NGX_HTTP_CHECK_UDP定义为:
#define NGX_HTTP_CHECK_UDP 0X0020
static ngx_command_t ngx_http_upstream_check_commands[] = {
......
{
ngx_string("check_udp_send"),
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
ngx_http_upstream_check_udp_send,
0,
0,
NULL },
{
ngx_string("check_udp_expect"),
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12,
ngx_http_upstream_check_udp_expect,
0,
0,
NULL },
......
}
为了保存解析到的配置信息,需要对ngx_http_upstream_check_srv_conf_s结构体进行扩展,增加4个字段,定义如下:
struct ngx_http_upstream_check_srv_conf_s {
ngx_uint_t port;
ngx_uint_t fall_count;
ngx_uint_t rise_count;
ngx_msec_t check_interval;
ngx_msec_t check_timeout;
ngx_uint_t check_keepalive_requests;
ngx_check_conf_t *check_type_conf;
ngx_str_t send;
union {
ngx_uint_t return_code;
ngx_uint_t status_alive;
} code;
ngx_array_t *fastcgi_params;
ngx_uint_t default_down;
ngx_uint_t unique;
ngx_uint_t udp : 1; /* 是否udp socket */
ngx_int_t match_part : 1; /* 是否只要部分匹配就可以了 */
ngx_int_t match_offset; /* udp响应期望的内容从哪个字节开始匹配 */
ngx_str_t expect; /* udp响应的期望内容 */
};
check_udp_send配置指令用来读取准备发送到上游服务器的报文内容,格式如下:
check_udp_send [raw:|text:]packet
如果指定了raw格式,那么packet中的内容就是用16进制编码的报文,如果用text格式,那么packet内容就是一个普通的字符串,如果没有指定raw或者text,那么默认是text格式。
下面来实现check_udp_send配置指令的解析函数ngx_http_upstream_check_udp_send函数:
static char *ngx_http_upstream_check_udp_send(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf)
{
ngx_str_t *value;
ngx_http_upstream_check_srv_conf_t *ucscf;
ngx_str_t tmp;
ngx_str_t content;
ngx_int_t r;
value = cf->args->elts;
ucscf = ngx_http_conf_get_module_srv_conf(cf,
ngx_http_upstream_check_module);
/* 如果是text格式,直接取text:后的字符内容即可 */
if (value[1].len > 5 && ngx_strncmp(value[1].data, "text:", 5) == 0) {
ucscf->send.data = value[1].data + 5;
ucscf->send.len = value[1].len - 5;
} /* 如果是raw格式,则需要进行16进制的解码 */
else if(value[1].len > 4 && ngx_strncmp(value[1].data, "raw:", 4) == 0) {