redis async client 与自有框架集成
hiredis的异步接口已经支持ae libuv libev 和 libevent集成,具体头文件可以参见redis/deps/hiredis/adapters,样例参见redis/deps/hiredis/examples.
完整样例参见: https://github.com/DavadDi/study_example/tree/master/async_redis_client
参照hireids的异步接口和libevent的集成可以很容易和其他网络框架集成,例如asio或者ace等。 以下样例为自己编写reactor框架的集成方式,
支持自动重练和asyncRedisContext对象的创建和释放,重练使用退步算法,最大连接时间间隔为32秒。
使用方式:
将redis_client.hpp 放到 hiredis的adapter目录即可。
#ifndef redis_client_h
#define redis_client_h #include "reactor/define.hpp"
#include "reactor/event_handler.hpp"
#include "hiredis.h"
#include "async.h" using namespace reactor; static void redisReactorAddRead(void *arg);
static void redisReactorDelRead(void *arg);
static void redisReactorAddWrite(void *arg);
static void redisReactorDelWrite(void *arg);
static void redisReactorCleanup(void *arg); void connectCallBack(const redisAsyncContext *c, int status);
void disconnectCallBack(const redisAsyncContext *c, int status); void get_call_fun(redisAsyncContext *c, void *r, void *arg)
{
redisReply *reply = (redisReply *)r;
std::string *key_str = (std::string *)arg; if (reply == NULL)
{
delete key_str;
return;
} LOG_INFO("[%s] -> %s\n", key_str->c_str(), reply->str); delete key_str; /* Disconnect after receiving the reply to GET */
// redisAsyncDisconnect(c);
} // -------------------------------------------------------------------
// !!NOTE, if obj conneted to server faild and unregister from epoll,
// prog exit, this object my leak memory
// ------------------------------------------------------------------- class CRedisClient : public CEventHandler
{
public:
// enum {MAX_BUF_SIZE = 4096};
typedef CEventHandler super; CRedisClient(const char *srv_ip, uint16_t srv_port, reactor::CReactor *reactor)
: super(reactor)
{
m_srv_ip_str = srv_ip;
m_srv_port = srv_port;
} int connect()
{
LOG_DEBUG("Enter CRedisClient connect()");
m_client_status = CONNECT_STATUS::CLIENT_CONNECTING; clear_redis_context(); m_redis_context = redisAsyncConnect(m_srv_ip_str.c_str(), m_srv_port);
if (m_redis_context == nullptr)
{
return -;
} if (m_redis_context->err)
{
LOG_INFO("Connect to %s:%d Error: %s",
m_srv_ip_str.c_str(), m_srv_port, m_redis_context->errstr); return -;
} if (m_timer_id == )
{
m_timer_id = this->reactor()->regist_timer(this, m_timeout_value); // only one time
LOG_DEBUG("Client regist timer to reactor id %d, timeout %d", m_timer_id, m_timeout_value);
} this->attach(); return ;
} virtual ~CRedisClient()
{
// maybe should not free redis context in deconstuct!!
m_delete_redis_context = true;
clear_redis_context();
} virtual int open(void *data = nullptr)
{
m_client_status = CONNECT_STATUS::CLIENT_CONNECTED; m_delete_redis_context = false; if (m_timer_id == )
{
m_timer_id = this->reactor()->regist_timer(this, m_timeout_value); // only one time
LOG_DEBUG("Client regist timer to reactor id %d, timeout %d",
m_timer_id, m_timeout_value);
} LOG_INFO("Connect to RedisServer %s:%d succeed!!",
m_srv_ip_str.c_str(), m_srv_port); return ;
} virtual int handle_input(socket_t socket)
{
redisAsyncHandleRead(m_redis_context);
return ;
} virtual int handle_output(socket_t socket)
{
redisAsyncHandleWrite(m_redis_context);
return ;
} virtual int handle_timeout(uint32_t tm, void *data = nullptr)
{
// LOG_DEBUG("Enter into timeout function....");
if (m_client_status == CONNECT_STATUS::CLIENT_CONNECTED)
{
/* just for test */
std::string key = std::to_string(tm); LOG_DEBUG("Set key %s", key.c_str());
redisAsyncCommand(m_redis_context, NULL, NULL, "SET %s %s",key.c_str(), "aaa");
redisAsyncCommand(m_redis_context, get_call_fun, (char*)new string(key), "GET %s", key.c_str());
}
else
{
static uint32_t last_tm = ;
if ((tm - last_tm) >= m_timeout_interval)
{
//reconnect
LOG_DEBUG("Start reconnect now ...");
this->connect(); m_timeout_interval = m_timeout_interval * ;
if (m_timeout_interval > )
{
m_timeout_interval = ;
} last_tm = tm;
}
} return ;
} virtual int handle_close(socket_t socket = INVALID_SOCKET, uint32_t mask = )
{
LOG_DEBUG("Enter into handle_close()");
m_client_status = CONNECT_STATUS::CLIENT_UNCONNECTED; // epoll call delete this handler
if (mask & RE_MASK_DEL)
{
LOG_DEBUG("Call RE_MASK_DEL now"); if (this->m_timer_id && (this->reactor() != nullptr))
{
this->reactor()->unregist_timer(this->m_timer_id);
this->m_timer_id = ;
} delete this;
return ;
} this->reactor()->del_event(this,);
return ;
} void clear_redis_context()
{
if (m_delete_redis_context && m_redis_context != nullptr)
{
LOG_DEBUG("Call redisAsynFree() now");
redisAsyncFree(m_redis_context);
m_redis_context = nullptr;
}
} int attach()
{
LOG_DEBUG("Enter attatch function... "); redisContext *context = &(m_redis_context->c);
if (m_redis_context->ev.data != NULL)
{
return -;
} // set callback function
redisAsyncSetConnectCallback(m_redis_context,connectCallBack);
redisAsyncSetDisconnectCallback(m_redis_context,disconnectCallBack); this->set_handle(context->fd); // set handler m_redis_context->ev.addRead = redisReactorAddRead;
m_redis_context->ev.delRead = redisReactorDelRead;
m_redis_context->ev.addWrite = redisReactorAddWrite;
m_redis_context->ev.delWrite = redisReactorDelWrite;
m_redis_context->ev.cleanup = redisReactorCleanup;
m_redis_context->ev.data = this; LOG_DEBUG("ac->ev.data %p", m_redis_context->ev.data); this->add_read();
this->add_write(); return ;
} void add_read()
{
LOG_TRACE_METHOD(__func__); if( (this->m_current_event_mask & reactor::EVENT_READ) > )
{
LOG_DEBUG("EV_READ(0x%0x) already in event_mask 0x%x",
reactor::EVENT_READ, this->m_current_event_mask); return;
} this->reactor()->add_event(this, reactor::EVENT_READ);
} void del_read()
{
LOG_TRACE_METHOD(__func__);
this->reactor()->mod_event(this, this->m_current_event_mask&(~reactor::EVENT_READ));
} void add_write()
{
LOG_TRACE_METHOD(__func__);
this->schedule_write();
} void del_write()
{
LOG_TRACE_METHOD(__func__);
this->cancel_schedule_write();
} void clean_up()
{
LOG_TRACE_METHOD(__func__);
} // note!!!
// connenct not succeed. we can free redis context. ]
// But if connect succeed and borken, we don't connect protected:
std::string m_srv_ip_str;
uint16_t m_srv_port; CONNECT_STATUS m_client_status = CONNECT_STATUS::CLIENT_UNCONNECTED; int m_timer_id = ;
uint32_t m_timeout_value = ;
uint32_t m_timeout_interval = ; bool m_delete_redis_context = true;
redisAsyncContext *m_redis_context = nullptr;
}; static void redisReactorAddRead(void *arg)
{
LOG_DEBUG("Enter redisReactorAddRead() arg %p", arg);
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->add_read();
} static void redisReactorDelRead(void *arg)
{
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->del_read();
} static void redisReactorAddWrite(void *arg)
{
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->add_write();
} static void redisReactorDelWrite(void *arg)
{
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->del_write();
} static void redisReactorCleanup(void *arg)
{
CRedisClient *event_handler = (CRedisClient *)arg;
event_handler->clean_up();
} void connectCallBack(const redisAsyncContext *ac, int status)
{
if (status != REDIS_OK)
{
LOG_ERROR("connectCallBack() Error: %s", ac->errstr);
return;
} CRedisClient *event_handler = (CRedisClient *)ac->ev.data;
event_handler->open(); LOG_INFO("RedisClient Connected...");
} void disconnectCallBack(const redisAsyncContext *ac, int status)
{
CRedisClient *event_handler = (CRedisClient *)ac->ev.data;
event_handler->handle_close(,); if (status != REDIS_OK)
{
LOG_INFO("disconnectCallBack()!! Error: %s", ac->errstr);
return;
} LOG_INFO("RedisClient Disconnected...");
} #endif /* redis_client_h */
使用的程序样例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h> //#include <hiredis.h>
//#include <async.h> #include <adapters/redis_client.hpp>
//#include "redis_client.hpp" #include <signal.h> static void signal_handler(int sig)
{
if (sig == SIGINT)
{
reactor::CReactor::instance()->end_event_loop();
}
} /*
void get_call_fun(redisAsyncContext *c, void *r, void *arg)
{
redisReply *reply = (redisReply *)r;
std::string *key_str = (std::string *)arg; if (reply == NULL)
{
delete key_str;
return;
} LOG_INFO("[%s] -> %s\n", key_str->c_str(), reply->str); delete key_str; // Disconnect after receiving the reply to GET
// redisAsyncDisconnect(c);
}
*/ int main (int argc, char **argv)
{
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, signal_handler); CLoggerMgr logger("reactor.prop"); reactor::CReactor *rt = reactor::CReactor::instance();
CRedisClient *redis_client = new CRedisClient("127.0.0.1", , rt);
redis_client->connect(); rt->run_event_loop(); return ;
}
redis async client 与自有框架集成的更多相关文章
- Redis java client ==> Jedis
https://github.com/xetorthio/jedis Jedis is a blazingly small and sane Redis java client. Jedis was ...
- Spring集成Redis集群(含spring集成redis代码)
代码地址如下:http://www.demodashi.com/demo/11458.html 一.准备工作 安装 Redis 集群 安装参考: http://blog.csdn.net/zk6738 ...
- Spring cloud 基础框架集成
Spring cloud 基础框架集成 1. 注册中心 -eurekar 1. pom依赖 <?xml version="1.0" encoding="UTF-8& ...
- Spring+SpringMvc+Mybatis框架集成搭建教程
一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼 ...
- Spring与其他Web框架集成
Spring与多种流行Web应用框架(Struts.JSF和DWR)集成的方法. Spring强大的IoC容器和企业支持特性使其十分适于实现Java EE应用的服务和持续层. 对于表现层,可以在许多不 ...
- Cordova与现有框架的结合,Cordova插件使用教程,Cordova自定义插件,框架集成Cordova,将Cordova集成到现有框架中
一.框架集成cordova 将cordova集成到现有框架中 一般cordova工程是通过CMD命令来创建一个工程并添加Android.ios等平台,这样的创建方式可以完整的下载开发过程中所需要的的插 ...
- Spring MVC 学习总结(十一)——IDEA+Maven+多模块实现SSM框架集成
一.SSM概要 与SSH(Struts/Spring/Hibernate/)一样,Spring+SpringMVC+MyBatis也有一个简称SSM,Spring实现业务对象管理,Spring MVC ...
- Selenium·自动化框架集成
date:2018513 day08aft 一.自动化框架集成分层 1.config 配置(项目配置——测试环境,公司环境,线上环境:以中国人才热线登陆为例,网址.用户名.密码等) 2.public ...
- Spring MVC 学习总结(十)——Spring+Spring MVC+MyBatis框架集成(IntelliJ IDEA SSM集成)
与SSH(Struts/Spring/Hibernate/)一样,Spring+SpringMVC+MyBatis也有一个简称SSM,Spring实现业务对象管理,Spring MVC负责请求的转发和 ...
随机推荐
- 利用mysql对特殊字符和超长字符会进行截断的特性 进行存储型XSS攻击——WordPress <4.1.2 & <=4.2 存储型xss
转自:Baidu Security LabXteam http://xteam.baidu.com/?p=177 漏洞概述 本次漏洞出现两个使用不同方式截断来实现的存储型xss,一种为特殊字符截断,一 ...
- 斐波那契数列 递归 尾递归 递推 C++实现
==================================声明================================== 本文原创,转载请注明作者和出处,并保证文章的完整性(包括本 ...
- 烂泥:kickstart无人值守安装CentOS6.5
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 在本次实验进行之前,首先我们要把公司的网络环境进行介绍. 注意这个网络拓扑图,也是生产环境的一个实例.同时服务器192.168.1.214已关闭ipta ...
- 计算几何--判断两条线段相交--poj 2653
Pick-up sticks Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 8862 Accepted: 3262 De ...
- Linux dsh
一.简介 目前在企业网络中越来越多的出现Linux服务器,而如何方便高效的管理大量的Linux服务器是系统管理员非常关心的一个问题,而dsh正是一个通过命令行有效地管理大量Linux的工具. 二. ...
- apache性能测试工具ab使用详解
下面我们对这些参数,进行相关说明.如下:-n在测试会话中所执行的请求个数.默认时,仅执行一个请求.-c一次产生的请求个数.默认是一次一个.-t测试所进行的最大秒数.其内部隐含值是-n 50000,它可 ...
- OpenXml入门----给Word文档添加表格
下面将展示如何使用Openxm向Word添加表格. 代码中表头和数据我用的同一个TableRow来添加,其实可以通过TableHeader来,其实都一样.后面教程我会给出如何设置单元格样式.表头那一行 ...
- uva133-S.B.S.
The Dole Queue In a serious attempt to downsize (reduce) the dole queue, The New National Green Lab ...
- [转载]ExtJs4 笔记(7) Ext.tip.ToolTip 提示
作者:李盼(Lipan)出处:[Lipan] (http://www.cnblogs.com/lipan/)版权声明:本文的版权归作者与博客园共有.转载时须注明本文的详细链接,否则作者将保留追究其法律 ...
- 第2章 面向对象的设计原则(SOLID):6_开闭原则
6. 开闭原则(Open Closed Principle,OCP) 6.1 定义 (1)一个类应该对扩展开放,对修改关闭.要求通过扩展来实现变化,而且是在不修改己有的代码情况下进行扩展,也不必改动己 ...