首页 > 代码库 > 基于redis AE的异步网络框架

基于redis AE的异步网络框架

最近一直在研究redis的源码,redis的高效率令人佩服。

在我们的linux机器上,cpu型号为, 

Intel(R) Pentium(R) CPU G630 @ 2.70GHz
 Intel(R) Pentium(R) CPU G630 @ 2.70GHz


上 set,get 都能达到每秒钟15W的请求处理量,真是佩服这代码的效率。

前几篇文章,主要是介绍了基本的代码,比如字符串处理,链表处理,hash等。这篇文章介绍网络的核心,基于事件反映的异步网络框架。


异步网络处理,是基于epoll的。epoll的分为两种模式,水平触发和边缘触发。ae使用了水平触发,就是一旦有数据,epoll会一直通知,直到就读取完成。而边缘触发则只通知一次。等到状态改变才会去通知。具体可以到网上查阅。

1.结构体源码解析

1.1读写事件结构体

/* File event structure */
typedef struct aeFileEvent {
    int mask; /* one of AE_(READABLE|WRITABLE) */
    aeFileProc *rfileProc;
    aeFileProc *wfileProc;
    void *clientData;
} aeFileEvent;

该结构体表示一个fd对应的事件处理函数和私有数据。当我们要注册一个fd时间时,就会填充该结构体。

1.2 时间事件狗狗提

/* Time event structure */
typedef struct aeTimeEvent {
    long long id; /* time event identifier. */
    long when_sec; /* seconds */
    long when_ms; /* milliseconds */
    aeTimeProc *timeProc;
    aeEventFinalizerProc *finalizerProc;
    void *clientData;
    struct aeTimeEvent *next;
} aeTimeEvent;

当我们注册定时处理事件,会填充相应结构体,添加到数组里

1.3 触发的fd

/* A fired event */
typedef struct aeFiredEvent {
    int fd;
    int mask;
} aeFiredEvent;

该结构体表示一个fd对应的可读可写事件

1.4 ae事件的总结构体

/* State of an event based program */
typedef struct aeEventLoop {
    int maxfd;   /* highest file descriptor currently registered */
    int setsize; /* max number of file descriptors tracked */
    long long timeEventNextId;
    time_t lastTime;     /* Used to detect system clock skew */
    aeFileEvent *events; /* Registered events */
    aeFiredEvent *fired; /* Fired events */
    aeTimeEvent *timeEventHead;
    int stop;
    void *apidata; /* This is used for polling API specific data */
    aeBeforeSleepProc *beforesleep;
} aeEventLoop;


该结构体存储了ae异步事件的基本数据,比如fd大小,时间事件id,注册的时间指针等。


2.ae_epoll 接口

2.1 epoll 结构体

typedef struct aeApiState {
    int epfd;
    struct epoll_event *events;
} aeApiState;

提供epoll的变量定义,

epfd是通过epoll_create 创建。events表示epoll_wait允许监听的数量。

填充aeApiState结构体。

static int aeApiCreate(aeEventLoop *eventLoop)


调用epoll_wait ,获取我们关心的事件,

static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) 



2、api接口


1,创建eventloop

aeEventLoop *aeCreateEventLoop(int setsize)

2.添加事件

int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
        aeFileProc *proc, void *clientData)

3。删除事件,

void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)

4。创建时间事件

long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
        aeTimeProc *proc, void *clientData,
        aeEventFinalizerProc *finalizerProc)

5.删除时间事件

int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id)




使用示例


  //创建loop
    proxy.eventLoop = aeCreateEventLoop(DEFAULT_LOOP_SIZE);

//创建事件事件

if(aeCreateTimeEvent(proxy.eventLoop, 1, serverCron, NULL, NULL) == AE_ERR) 
{
printf("Can‘t create the serverCron time event\n");
exit(1);
}


     /* 服务器监听redis客户端的连接 */
     aeCreateFileEvent(proxy.eventLoop, proxy.server_fd, AE_READABLE, on_client_connected, NULL);

   aeCreateFileEvent(proxy.eventLoop, proxy.evfd, AE_READABLE, reconnect_redis, NULL);



以上就是一个简单的示例。

我写了一个类redisprox的东西,待我上传给大家看看。