Webdis内部解析

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共有,欢迎转载,但未经作者同意必须保留此段声明

时间: 2024-12-02 10:33:45

Webdis内部解析的相关文章

Oracle中SQL语句解析的步骤

我们都知道在Oracle中每条SQL语句在执行之前都需要经过解析,这里面又分为软解析和硬解析.那么这两种解析有何不同之处呢?它们又分别是如何进行解析呢?Oracle内部解析的步骤又是如何进行的呢?下面我们就这些话题进行共同探讨. 在Oracle中存在两种类型的SQL语句,一类为DDL语句,他们是从来不会共享使用的,也就是每次执行都需要进行硬解析.还有一类就是DML语句,他们会根据情况选择要么进行硬解析,要么进行软解析.在Oracle 8i OCP教材的023中1-12有说明SQL语句的解析步骤,

PhantomJS的使用

1. 简介 phantomjs 简单来说是一个基于 WebKit 的"无头浏览器"环境.对"无头",你可以理解成没有一个前端的 GUI 界面,所有的东西都在后台运行. phantomjs 在"无头"界的名声,是源于从 WebKit 里得到的对 DOM / JS 的完整支持. 一个纯后台的,完整功能的浏览器,这东西就有很多可以想像的空间了 -- 抓取,测试等. 2. 安装 http://phantomjs.org/download.html Win

智能运维:美团SQL Advisor的自动化SQL优化实现

介绍 在数据库运维过程中,优化 SQL 是 DBA 团队的日常任务.例行 SQL 优化,不仅可以提升程序性能,还能够降低线上故障的概率. 目前常用的 SQL 优化方式包括但不限于:业务层优化.SQL逻辑优化.索引优化等.其中索引优化通常通过调整索引或新增索引从而达到 SQL 优化的目的.索引优化往往可以在短时间内产生非常巨大的效果.如果能够将索引优化转化成工具化.标准化的流程,减少人工介入的工作量,无疑会大大提高DBA的工作效率. SQLAdvisor 是由美团点评公司北京DBA团队开发维护的

网站静态化

随着SEO 的普及,静态化便成为网站开发的必要技术之一.网页设计 时,网站静态化通常有三种方法可以实现,一种是伪静态,一种是实实在在的静态页面,最后一种是pathinfo技术. 伪静态 下, 如果是apache服务器,是通过.htaccess文件来操作.如果是IIS服务器,则是通过httpd.ini和rewrite.dll来实现.伪静 态处理的关键技术是配置文件的规则如何得到有效的控制,并在html页面里对应起来,一旦规则改变,则html页面里的链接也需要根据规则动态的改变.后 台设置规则,并且

Linq之Expression进阶

目录 写在前面 系列文章 表达式树解析 表达式树特性 编译表达树 总结 写在前面 让我们首先简单回顾一下上篇文章介绍的内容,上篇文章介绍了表达式树的基本概念(表达式树又称为"表达式目录树",以数据形式表示语言级代码,它是一种抽象语法树或者说是一种数据结构),以及两种创建表达式树目录树的方式:以lambda表达式的方式创建,通过API静态方法创建.由于不能将有语句体的lambda表达式转换为表达式树,而有时我们又有这样的需求,那么这种情况你可以选择API的静态方法方式创建,在 .NET

javascript变量作用域一点总结

前言:javascript里变量作用域是个经常让人头痛抓狂的问题,下面通过10++个题目,对经常遇到又容易出错的情况进行了简单总结,代码样例很短很简单 题目一 var name = 'casper'; alert(name); //毫无疑问地输出:casper 题目二 alert(name); //报错:对象未定义,即使用一个压根就不存在的变量,所以出错 age = 24; //这里木有错,但age不是为定义吗?翻下犀牛书,明白了 //给一个未定义的变量赋值,会创建一个全局变量,相当于:var

python中使用smtplib和email模块发送邮件实例_python

SMTP模块 这么多已定义的类中,我们最常用的的还是smtplib.SMTP类,就具体看看该类的用法:smtp实例封装一个smtp连接,它支持所有的SMTP和ESMTP操作指令,如果host和port参数被定义,则smtp会在初始化期间自动调用connect()方法,如果connect()方法失败,则会触发SMTPConnectError异常,timeout参数设置了超时时间.在一般的调用过程中,应该遵connetc().sendmail().quit()步骤. SMTP模块主要方法 下面我们来

javascript变量作用域使用中常见错误总结_javascript技巧

今天在rainweb的博客上,看到了这篇非常好的文章,觉得非常有必要分享出来,相信大家认真读完这篇文章,对js作用域的理解又会上升到一个新的台阶. 前言:javascript里变量作用域是个经常让人头痛抓狂的问题,下面通过10++个题目,对经常遇到又容易出错的情况进行了简单总结,代码样例很短很简单 题目一 复制代码 代码如下: var name = 'casper'; alert(name); //毫无疑问地输出:casper 题目二 复制代码 代码如下: alert(name); //报错:对

CSS3中遮罩使用实例教程

Css遮罩是由苹果公司添加到webkit浏览器引擎中的.遮罩提供一种基于像素级别的,可以控制元素透明度的能力,类似于png24位或png32位中的alpha透明通道的效果. 图像是由rgb三个通道以及在每个像素上定义的颜色组成的.但是在他们之上还有第四个通道,alpha通道,通过亮度定义每个像素上的透明度.白色意味着不透明,黑色意味着透明,介于黑白之间的灰色表示半透明.你可以看到下面的图片 给一个html元素使用css遮罩,就会这样处理.不用给图片应用一个alpha通道,只需要给一个图片运用一个