作者:邓永强
导语
TAF 是分布式基于 epoll 的多线程非阻塞的高性能且支持同步、异步、单向调用 RPC 框架。框架将网络线程和业务线程隔离,并通过队列和管道实现网络线程和业务线程间通信。框架维护网络连接,实现客户端和服务端远程调用和本地调用基本一样,用户只需关注业务逻辑。框架支持多种语言开发,集高可用,高性能,高并发,高效率等优秀特性。
1 TAF 简介
TAF(Total Application Framework)框架整体划分为五层结构,运营、平台、通信框架、公共库、协议层。框架将网络线程和业务线程隔离,通过消息管道和队列实现业务线程(应用层)和网络线程(传输层)间通信,业务侧只需关注业务逻辑开发。框架协议层使用适宜传输且与语言无关的JCE、WUP协议;提供了完善的公共库;传输层提供完善网络通信机制,包括RPC(单向/同步/异步),过载保护;平台层提供统一管理,负载均衡,容错等机制;运营层前端集发布,监控,自动配置等。
1.1框架比较
目前主要基于taf和基于appPlatform框架的后台开发,因此对两个框架有浅显的了解和学习。两个框架都是RPC通信,taf框架是基于epoll的多线程非阻塞RPC框架,而appPlatform是基于多进程,主要应用于电商形式的后台框架。
2 服务端
2.1 服务端启动过程
服务需要继承taf基类Application, 调用框架main函数,解析服务端配置文件加载到服务端,然后初始客户端通讯器,初始化服务端并创建_epollServer对象,并绑定到AdminAdapter,然后adapters绑定IP和Port,启动业务线程。调用框架waitForShutdown()创建网络线程并监听端口,然后启动网络线程,完成服务启动。
TAF启动过程概述:
1、业务系统服务g_app.main()调用框架Application::main()完成以下过程:
1)调用parseConfig(),解析TAF服务模板内容配置,包括client和server的locator,超时,log,心跳等。
2)调用initializeClient(),初始化客户端通信器_communicator
3)调用initializeServer(),初始化taf基础配置
a. 初始化ServerConfig结构体
b. _epollServer = new TC_EpollServer()
c. 初始化日志服务代理,配置中心代理,信息中心代理,Node代理,管理对象。
d.创建Socket,AdminAdapter给网络线程绑定Socket,并设置连接数,超时,队列等。
4)调用bindAdapter(),线程绑定adapters和端口
5)回调Servant的initialize()方法,业务初始化
6)遍历vector<TC_EpollServer::BindAdapterPtr>,并创建线程组HandleGroup()
7)调用_epollServer->startHandle(),启动业务处理线程组
8)调用epollServer ->createEpoll(),网络线程创建Epoller对象
2、业务系统服务g_app.waitForShutdown() 调用Application::waitForShutdown()完成以下过程:
1)调用_epollServer->waitForShutdown()完成:
a. 遍历线程组,并依次调用start()启动
b. 创建Epoll对象,并监听socket事件
c. 如果有请求调用accept()接收请求信息,如果有关闭请求调用stopThread(),遍历网络线程HandleGroup(),调用join结束网络线程。
2)服务线程结束,调用destroyApp(),析构业务申请资源。
2.2 服务端分析
2.1.1 基础类图
业务服务系统需继承TAF框架Application类初始化服务端基础配置,并创建TC_EpollServer类对象,在Epoll类中创建网络线程类NetThread和BindAdapter,并把线程和adapter绑定。
2.1.2 调用方式
TAF是多线程基于Epoll的RPC框架,主要实现网络线程和业务线程隔离,框架实现底层网络线程,框架维护网络连接队列,数据接收队列,数据发送队列,通过pipe实现网络线程和业务线程间通信,业务侧只需要考虑业务线程处理业务逻辑,很大程度提升业务开发效率。如下图所示:
TAF基于Epoll实现单向、同步、异步的远程RPC通信方式。客户端和服务端调用方式如图所示。客户端首先通过stringtoProxy(obj)方式上报taf主控并获取到当前活跃的服务端IP和端口,然后客户端可以发送连接请求与服务端通信。服务端每台机器需要安装node,node不断上报心跳等信息到taf主控,并通过patch实现主控控制服务节点。如下图所示:
2.1.3 业务线程
1、taf服务提供业务处理线程类Handle,并由HandleGroup统一管理。HandleGroup相当于业务处理线程池。有请求则把请求回调到Servant的onDispatch()方法并分发给业务线程处理,同步调用直接将处理结果写入到消息对列,网络线程取出消息对列数据返回调用方。
每个Servant存在一个BindAdapter()实例,负责统一管理Servant的信息。当服务端接收到客户端的请求,网络线程把请求放到BindAdapter()的消息队列。并唤醒HandleGroup锁,Handle线程从消息对列取出消息。
2.1.4 网络线程
1 、遍历连接长时间无数据,主动关闭并删除链接。
2 、等待epoll消息,事件到来处理epoll消息。
1)连接请求
客户端连接events,建立连接,框架选择网络线程处理连接列表,再把socket加入epoll事件的处理列表,调用accep接收数据
2)停止请求
break到外层,调用stopThread通知线程
3)控制通知:
a .关闭通知,则调用stopThread关闭并删除此连接;
b .发送通知,将网络线程缓存发送,避免关闭网络线程导致数据丢失。
4)数据请求:
a .如果socket收到数据,调用insertRecvQueue()
b .如果缓存有处理结果待发送,发送处理结果给客户端。
c .更新连接表超时时间。