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】关于checkpoint机制
一.简介 思考一下这个场景:如果重做日志可以无限地增大,同时缓冲池也足够大,那么是不需要将缓冲池中页的新版本刷新回磁盘.因为当发生宕机时,完全可以通过重做日志来恢复整个数据库系统中的数据到宕机发生的时 ...
- 烂泥:【解决】ubuntu使用远程NFS报错
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 今天在ubuntu系统上使用远程NFS,发现一直报错无法使用. 查看NFS挂载命令没有错误,命令如下: mount -t nfs 192.168.1.1 ...
- ubuntu16.04服务器配置ssh免密登录
原版资料英文,链接在此 https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys--2 在客户端操作 ssh-k ...
- 树形dp--hdu 3534 Tree
Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- Linux系统之压缩、解压缩,vi编辑器,系统初始化服务和系统监控
一.正文处理,压缩与解压缩 1.内容重定向>与>> >:覆盖,将>号左边的结果覆盖到>号右边的文件中,如果文件不存在,则先创建一个新的空文件并覆盖 >> ...
- 虚拟机centos6.5 --设置主机名
vi /etc/sysconfig/network #修改HOSTNAME后面的值,机器名 vi /etc/hosts #设置ip和机器名的对应关系 192.168.12.232 master 192 ...
- luluzero的angularJs学习之路_angularJs示例代码
最近开始自学 angularJs这个前端MVC框架,感觉在前端实现MVC很酷有木有.哈哈哈... 先说说我对前端MVC的一个基本的理解吧(刚开始学习接触得还比较浅显,理解可能会有些不到位,还请各位大神 ...
- Tomcat 内存和线程配置优化
1. tomcat 的线程配置参数详情如下: 修改conf/server.xml中的<Connector .../> 节点如下: <Connector port="8080 ...
- windows下 MySQL数据库双向同步 配置步骤
最近在项目中遇到了要实现服务器上MySql数据双向同步,在网上找了很多资料,但是大部分都是在liux系统下配置的, 而且都是互相转载,没有一个详细的步骤,于是决定写一个windows系统下 ...
- codeforces 616E Sum of Remainders (数论,找规律)
E. Sum of Remainders time limit per test 2 seconds memory limit per test 256 megabytes input standar ...