Webdis內部解析

軒脈刃發表於2016-05-17

Webdis是redis的http代理,原始碼在:git://github.com/nicolasff/webdis.git

webdis.json是配置檔案

webdis.c是入口程式

 

其中有三個比較重要的結構:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct server {
 
    int fd;
    struct event ev;
    struct event_base *base;   //libevent的event事件
 
    struct conf *cfg;  //配置檔案,設定有多少個程式(http_threads)啥的放在裡面
 
    /* worker threads */
    struct worker **w;  //有多個worker,父程式有多少worker執行緒
    int next_worker;
 
    /* log lock */
    struct {
        pid_t self;
        int fd;
    } log;  //日誌結構
};

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
struct worker {
 
    /* self */
    pthread_t thread; 
    struct event_base *base//libevent的event事件
 
    /* connection dispatcher */
    struct server *s;  //父server
    int link[2]; //由pipe建立的管道,link[0]是管道讀取端,link[1]是管道寫入端
 
    /* Redis connection pool */
    struct pool *pool;  //連線池,與redis連線的連線池
};
1
2
3
4
5
6
7
8
9
10
11
12
13
struct pool {
 
struct worker *w; //worker執行緒
 
struct conf *cfg; //配置檔案
 
const redisAsyncContext **ac; //redis的同步上下文
 
int count; //pool大小,即s->cfg->pool_size_per_thread
 
int cur;
 
};

 

這三個結構每個結構都有一個指標指向父結構,比如pool的worker*

這樣能保證從任意一個結構中都能取得父結構的需要的屬性

 

 

webdis的server-worker-pool的關係是這樣的:

一個Server包含多個worker,每個woker佔一個程式的資源

一個worker包含一個pool

Server的任務是接受HTTP請求,傳遞HTTP的套接字給worker

Worker才是webdis的實際處理類,一方面接受Server傳遞過來的HTTP請求,一方面由pool保持和redis的連線

Pool是連線池,保持了與redis的連線,防止重複的連線操作造成過多的資源浪費

 

webdis的入口是Webdis.c檔案

主要執行了:

Server_new(conf)

server_start(s)

 

——————————-new 的過程開始—————————————-

Server_new主要函式:

conf_read

worker_new * n

 

worker_new主要函式:

Pipe(w->link) //建立管道

w->pool = pool_new(w, s->cfg->pool_size_per_thread);

 

pool_new主要函式:

p->ac = calloc(count, sizeof(redisAsyncContext*));

p->cfg = w->s->cfg;

 

pool中有一個redisAsyncContext結構,這個結構是hiredis的範圍了:

Hiredis是redis的C客戶端庫

https://github.com/antirez/hiredis

Hiredis is a minimalistic C client library for the Redis database.

 

Hiredis:

使用方法大是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
 
int redisAsyncCommand(
 
redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
 
const char *format, ...);
 
int redisAsyncCommandArgv(
 
redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
 
int argc, const char **argv, const size_t *argvlen);
 
void redisAsyncDisconnect(redisAsyncContext *ac);
1
-------------------------------new 的過程結束----------------------------------------
1
  
1
-------------------------------start 的過程開始---------------------------------------

server_start主要函式:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
s->base = event_base_new(); //註冊一個事件
 
worker_start(s->w[i]); //開啟worker
 
s->fd = socket_setup(s->cfg->http_host, s->cfg->http_port); //建立socket
 
 
 
/* start http server */
 
event_set(&s->ev, s->fd, EV_READ | EV_PERSIST, server_can_accept, s);
 
event_base_set(s->base, &s->ev);
 
event_add(&s->ev, NULL);
 
event_base_dispatch(s->base);

 

worker_start主要函式:

1
pthread_create(&w->thread, NULL, worker_main, w);//開了一個執行緒來執行worker_main函式

worker_main主要函式:

1
2
3
4
5
6
7
8
9
10
11
12
w->base = event_base_new(); //註冊event
 
/* monitor pipe link */
event_set(&ev, w->link[0], EV_READ | EV_PERSIST, worker_on_new_client, w);
event_base_set(w->base, &ev);
event_add(&ev, NULL);
 
/* connect to Redis */
worker_pool_connect(w); //worker和pool的連線,即worker和redis的連線
 
/* loop */
event_base_dispatch(w->base);

worker_pool_connect主要函式:

1
pool_connect(w->pool, 1); //指定w->pool來連線redis

 

pool_connect主要函式: //連線redis

1
2
3
4
5
6
7
8
9
ac = redisAsyncConnect(p->cfg->redis_host, p->cfg->redis_port);
 
redisLibeventAttach(ac, p->w->base);
 
redisAsyncSetConnectCallback(ac, pool_on_connect);
 
redisAsyncSetDisconnectCallback(ac, pool_on_disconnect);
 
redisAsyncCommand(ac, NULL, NULL, "AUTH %s", p->cfg->redis_auth);
1
下面就進入到了hiredis的部分了
1
-------------------------------start 的過程結束---------------------------------------
1
  

———————-

作者:yjf512(軒脈刃)

出處:http://www.cnblogs.com/yjf512/

本文版權歸yjf512和cnBlog共有,歡迎轉載,但未經作者同意必須保留此段宣告


相關文章