java应用中如何连接dbproxy_GitHub - alchemystar/hero: 用c语言写的dbproxy

用C语言撸了个DBProxy

前言

笔者在阅读了一大堆源码后,就会情不自禁产生造轮子的想法。于是花了数个周末的时间用C语言撸了一个DBProxy(MySQL协议)。在笔者的github中给这个DBProxy起名为Hero。

为什么采用C语言

笔者一直有C情节,求学时候一直玩C。工作之后,一直使用Java,就把C渐渐放下了。在笔者最近一年阅读了一堆关于linux Kernel(C)和MySQL(C++)的源码后,就萌生了重拾C的想法。同时用纯C的话,势必要从基础开始造一大堆轮子,这也符合笔者当时造轮子的心境。

造了哪些轮子

习惯了Java的各种好用的类库框架之后,用纯C无疑就是找虐。不过,既然做了这个决定,跪着也得搞完。在写Hero的过程中。很大一部分时间就是在搭建基础工具,例如:

Reactor模型

内存池

packet_buffer

协议分包处理

连接池

......

下面在这篇博客里面一一道来

DBProxy的整体原理

Hero(DBProxy)其实就是自己伪装成MySQL,接收到应用发过来的SQL命令后,再转发到后端。如下图所示:

69f88f056b702b8ad7a478dcd31bac2b.png

由于Hero在解析SQL的时候,可以获取各种信息,例如事务这个信息就可以通过set auto_commit和begin等命令存在连接状态里面,再根据解析出来的SQL判断其是否需要走主库。这样就可以对应用透明的进行主从分离以至于分库分表等操作。

当然了,笔者现在的Hero刚把基础的功能搭建好(协议、连接池等),对连接状态还没有做进一步的处理。

Reactor模式

Hero的网络模型采用了Reactor模式,而且是多线程模型,同时采用epoll的水平触发。

采用多线程模型

为什么采用多线程,纯粹是为了编写代码简单。多进程的话,还得考虑worker进程间负载均衡问题,例如nginx就在某个worker进程达到7/8最大连接数的时候拒绝获取连接从而转给其它worker。多线程的话,在accept线程里面通过取模选择一个worker线程就可以轻松的达到简单的负载均衡结果。

采用epoll水平触发

为什么采用epoll的水平触发,纯粹也是为了编写代码简单。如果采用边缘触发的话,需要循环读取直到read返回字节数为0为止。然而如果某个连接特别活跃,socket的数据一直读不完,会造成其它连接饥饿,所以必须还得自己写个均衡算法,在读到一定程度后,去选择其它连接。

Reactor

整体Reactor模型如下图所示:

3a0792824a6ad3b3e75fd840a2de6508.png

其实代码是很简单的,如下面代码所示的就是reactor中的accept处理:

// 中间省略了大量的错误处理

int init_reactor(int listen_fd,int worker_count){

// 注意,这边需要是unsigned 防止出现负数

unsigned int current_worker = 0;

for(;;){

int numevents = 0;

int retval = epoll_wait(reactor->master_fd,reactor->events,EPOLL_MAX_EVENTS,500);

......

for(j=0; j < numevents; j++){

client_fd = accept(listen_fd, (struct sockaddr *) &client_addr, &client_len))

poll_add_event(reactor->wo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值