webdis简单走读
25 Nov 2021
|
|
这是一个redis的http代理,简单看下怎么做的
接受请求request流程
主流程就是一个libevent
server_can_accept accept worker_add_client 然后通过pipe来传给worker
创建若干个worker接受客户端连接
- worker_new
- 创建pipe传消息用pipe(w->link);
- 创建redis链接池pool_new
worker主要动作
- worker_main也是一个eventloop
- worker_pool_connect
- worker_on_new_client
- read & worker_monitor_input
- worker_can_read
- http_client_read
- http_client_execute
- CALLBACK2(message_complete); 这个有两个实现
- http_client_on_message_complete
- worker_process_client
- cmd_run 各种校验/拼命令了
- worker_process_client
- ws_on_message_complete
- http_client_on_message_complete
- CALLBACK2(message_complete); 这个有两个实现
- websocket有单独的逻辑
- http_client_execute
- http_client_read
- worker_can_read
- read & worker_monitor_input
简单说这个逻辑还是比较简单的,主要命令逻辑就是worker_process_client
这个按照http的消息类型来分类
struct worker *w = c->w;
cmd_response_t ret = CMD_PARAM_ERROR;
switch(c->parser.method) {
case HTTP_GET:
if(c->path_sz == 16 && memcmp(c->path, "/crossdomain.xml", 16) == 0) {
http_crossdomain(c);
return;
}
slog(w->s, WEBDIS_DEBUG, c->path, c->path_sz);
ret = cmd_run(c->w, c, 1+c->path, c->path_sz-1, NULL, 0);
break;
case HTTP_POST:
slog(w->s, WEBDIS_DEBUG, c->path, c->path_sz);
ret = cmd_run(c->w, c, c->body, c->body_sz, NULL, 0);
break;
case HTTP_PUT:
slog(w->s, WEBDIS_DEBUG, c->path, c->path_sz);
ret = cmd_run(c->w, c, 1+c->path, c->path_sz-1,
c->body, c->body_sz);
break;
case HTTP_OPTIONS:
http_send_options(c);
return;
default:
slog(w->s, WEBDIS_DEBUG, "405", 3);
http_send_error(c, 405, "Method Not Allowed");
return;
}
内部还要解析具体的命令来分,其实可以直接写死,直接写死就省掉发送命令解析结果的流程了
返回响应流程
cmd_run执行中会指定Content-Type,cmd_select_format
cmd_select_format也会设置回复的回调函数
比如json_reply,raw_reply,custom_type_reply
用cmd_setup设置http response信息
如何实现ACL
这里的ACL是wedis内部的ACL控制,不是redis那侧的控制
redis只支持见到AUTH
在连接的时候就直接auth
if(p->cfg->redis_auth) { /* authenticate. */
if(p->cfg->redis_auth->use_legacy_auth) {
redisAsyncCommand(ac, pool_on_auth_complete, p, "AUTH %s",
p->cfg->redis_auth->password);
} else {
redisAsyncCommand(ac, pool_on_auth_complete, p, "AUTH %s %s",
p->cfg->redis_auth->username,
p->cfg->redis_auth->password);
}
}
如何实现subscirbe
http_client单独有个标记记录是不是subcribe,一直保持连接