蓝天

与慢速设备通讯异步化方案

像MySQL、被对接的银行系统等,都可称作慢速设备。它们的共同特点是只提供了同步调用接口,而且响应通常会比较慢。

 

一般业务系统在业务线程或进程中,直接调用它们提供的API进行访问,如下图所示:

 

 

结果造成了以下两大问题:

1) 性能低:同步阻塞方式;

2) 可靠性差:业务系统和慢速设备强耦合。

 

性能低,是因为慢速设备不能快速响应返回结果;可靠性差,是因为业务系统和慢速设备没有解耦合,比如当慢速设备的API因异常被长时间挂起时,会导致业务系统的线程或进程也一同被挂起。

 

要解决性能低,就需要异步化,也就是业务系统可异步访问慢速设备;要解决可靠性差,就需要两者间解耦合。

 

下图所示的方案,针对这两个问题进行了优化,即实现了异步化,也做到了解耦合:

 

 

以MySQL为例,业务系统在向MySQL发起SQL操作时,不再直接调用MySQLAPI,而是将SQL放入到队列中,然后立即返回。

针对每一个MySQL实例,都会有一个侍服线程,与它建立一对一对绑定关系,也就是这个线程专门为它服务的,如果有多个MySQL实例,则有相应个数的侍服线程,侍服线程不会跨MySQL实例。

侍服线程会实时监听队列,当有数据时,立即取出来,然后调用MySQLAPI执行SQL操作,这个过程是同步的,侍服线程会阻塞,直到MySQL返回结果。

 

对于MySQL返回的结果,有两种业务系统的方式:一是由侍服线程回调业务,对结果的处理权在侍服线程;二是将结果存入结果队列,然后业务可以以epoll的方式取出结果,这种方式可以让对结果的处理权回归到业务线程。

 

1) 侍服线程回调业务实现方式

 

下面以伪代码方式,展现实现方式:

void mysql_thread()

{

while (true)

{

sql = _sql_queue.pop(); // 阻塞等待队列中有SQL,如果有,则取出SQL

result = mysql.query(sql); // 调用MySQL接口,进行SQL操作,结果存在result

 

service->callback(result); // 回调业务接口,让业务对结果进行处理

}

}

 

2) 以epoll的方式取出结果

这种方式让对结果的处理权回归到业务线程。实现方式非常简单,只需要结果队列是可以epoll的即可,通常可以借助eventfdpipe来包装一个队列,让这队列可以epoll监听。侍服线程只需要将结果存入结果队列,然后会自动唤醒处于等待状态的epoll

 

异步化方案不能支持事务,关键原因是事务和MySQL连接有绑定关系,同一个连接不支持多个并发的事务

 

posted on 2014-06-24 13:02  #蓝天  阅读(245)  评论(0编辑  收藏  举报

导航