webdis简单走读

这是一个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 各种校验/拼命令了
                • ws_on_message_complete
            • websocket有单独的逻辑

简单说这个逻辑还是比较简单的,主要命令逻辑就是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,一直保持连接


Read More

^