1. 基础数据结构
1.0 记录文件
tarsImportantClass.cpp
1.1 TC_ThreadRecMutex
1.2 TC_HandleBase
1.3 BaseNotify
1.4 NotifyObserver
1.5 Application
1.6 TC_Config
1.7 Communicator
1.8 TC_EpollServer
TC_EpollServer内部嵌套的类:
class SendContext;
class RecvContext;
class Handle;
class BindAdapter;
class Connection;
class ConnectionList;
class NetThread;
1.9 TC_EpollServer::NotifyInfo
class NotifyInfo
{
public:
NotifyInfo();
~NotifyInfo();
void init(TC_Epoller *ep); // 初始化
void add(uint64_t data); // 添加关联数据
void notify(); // 通知notify醒过来
void release(); // 释放掉
int notifyFd(); // 获取通知fd
protected:
TC_Socket _notify; // 通知fd
TC_Epoller *_ep; //
uint64_t _data; //关联到通知句柄的事件
};
1.10 TC_Epoller
1.11 NetThread(TC_EpollServer的内嵌类)
搜索关键字 “class NetThread”,构造函数搜索“TC_EpollServer::NetThread::NetThread”
class NetThread : public TC_Thread, public TC_HandleBase
{
public:
public:
NetThread(TC_EpollServer *epollServer, int index); // 构造函数
virtual ~NetThread(); // 析构函数
int getIndex() const { return _threadIndex; } // 获取网络线程的index
virtual void run();// 网络线程执行函数
void terminate(); // 停止网络线程
void createEpoll(uint32_t maxAllConn); // 生成epoll
void initUdp(const unordered_map<int, BindAdapterPtr> &listeners); // 初始化udp监听
bool isTerminate() const { return _bTerminate; } // 是否服务结束了
TC_Epoller* getEpoller() { return &_epoller; }// 获取Epoller对象
void notify(); // 唤醒网络线程
void close(const shared_ptr<RecvContext> &data); // 关闭连接
void send(const shared_ptr<SendContext> &data); // 发送数据
vector<TC_EpollServer::ConnStatus> getConnStatus(int lfd); // 获取某一监听端口的连接数
size_t getConnectionCount(){ return _list.size(); } // 获取连接数
void debug(const string &s) const; // 记录日志
void info(const string &s) const; // INFO日志
void tars(const string &s) const; // TARS日志
void error(const string &s) const;// 记录错误日志
void enAntiEmptyConnAttack(bool bEnable); // 是否启用防止空链接攻击的机制
void setEmptyConnTimeout(int timeout);// 设置空连接超时时间
void setUdpRecvBufferSize(size_t nSize=DEFAULT_RECV_BUFFERSIZE);// 设置udp的接收缓存区大小,单位是B,最小值为8192,最大值为DEFAULT_RECV_BUFFERSIZE
protected:
Connection *getConnectionPtr(uint32_t uid){ return _list.get(uid); } // 获取连接
void addTcpConnection(Connection *cPtr);// 添加tcp链接
void addUdpConnection(Connection *cPtr);// 添加udp连接
void delConnection(Connection *cPtr, bool bEraseList = true, EM_CLOSE_T closeType=EM_CLIENT_CLOSE);// 删除链接
void processPipe(); // 处理管道消息
void processNet(const epoll_event &ev); // 处理网络请求
int getEmptyConnTimeout() const; // 空连接超时时间
bool isEmptyConnCheck() const; // 是否空连接检测
friend class BindAdapter;
friend class ConnectionList;
friend class TC_EpollServer;
private:
TC_EpollServer *_epollServer; // 服务
std::thread::id _threadId;// net线程的id
int _threadIndex; // 线程索引
TC_Epoller _epoller; // epoll
bool _bTerminate; // 停止标志
TC_Epoller::NotifyInfo _notify; // 通知epoll
ConnectionList _list; // 管理的连接链表
send_queue _sbuffer;// 发送队列
bool _bEmptyConnAttackCheck;
int _iEmptyCheckTimeout; // 空连接超时时间,单位是毫秒,默认值2s,该时间必须小于等于adapter自身的超时时间
size_t _nUdpRecvBufferSize;// udp连接时接收包缓存大小,针对所有udp接收缓存有效
bool _notifySignal = false; //通知信号
};
1.12 BindAdapter(TC_EpollServer的内部类及友元类)
1.13 TC_Endpoint
1.14 ServantHelperManager
1.15 NotifyObserver
1.16 PropertyReport
1.17 DataQueue
struct DataQueue
{
recv_queue _rbuffer;//接收的数据队列
TC_ThreadLock _monitor;//锁
};
typedef TC_ThreadQueue<shared_ptr<RecvContext>> recv_queue;
接受队列 BindAdapter中有接受队列的集合_threadDataQueue,搜索 TARS基金会CPP服务器文章链接的关键词“接收队列”
1.18 TC_ThreadQueue【线程安全队列】
template<typename T, typename D = deque<T> >
class TC_ThreadQueue
{
public:
TC_ThreadQueue():_size(0){};
public:
typedef D queue_type;
T front();//从头部获取数据, 没有数据抛异常
bool pop_front(T& t, size_t millsecond = 0, bool wait = true);// 从头部获取数据, 没有数据则等待.
bool pop_front();// 从头部获取数据.
void notifyT();// 通知等待在队列上面的线程都醒过来
void push_back(const T& t, bool notify = true);// 放数据到队列后端.
void push_back(const queue_type &qt, bool notify = true); // 放数据到队列后端.
void push_front(const T& t, bool notify = true);// 放数据到队列前端.
void push_front(const queue_type &qt, bool notify = true);// 放数据到队列前端.
bool swap(queue_type &q, size_t millsecond = 0, bool wait = true);// 交换数据
size_t size() const;// 队列大小.
void clear();// 清空队列
bool empty() const;// 是否数据为空.
protected:
TC_ThreadQueue(const TC_ThreadQueue&) = delete;
TC_ThreadQueue(TC_ThreadQueue&&) = delete;
TC_ThreadQueue& operator=(const TC_ThreadQueue&) = delete;
TC_ThreadQueue& operator=(TC_ThreadQueue&&) = delete;
protected:
queue_type _queue; // 队列
size_t _size; // 队列长度
std::condition_variable _cond; //条件变量
mutable std::mutex _mutex; //锁
};
1.19 RecvContext【接收包的上下文】
class RecvContext : public std::enable_shared_from_this<RecvContext> // 接收包的上下文
{
public:
RecvContext(uint32_t uid, const string &ip, int64_t port, int fd, const BindAdapterPtr &adapter, bool isClosed = false, int closeType = EM_CLIENT_CLOSE)
: _uid(uid), _ip(ip), _port(port), _fd(fd), _adapter(adapter), _isClosed(isClosed), _closeType(closeType), _recvTimeStamp(TNOWMS)
{
}
uint32_t uid() const { return _uid; }
const string &ip() const { return _ip; }
uint16_t port() const { return _port; }
vector<char> &buffer() { return _rbuffer; }
const vector<char> &buffer() const { return _rbuffer; }
int64_t recvTimeStamp() const { return _recvTimeStamp; }
bool isOverload() const { return _isOverload; }
void setOverload() { _isOverload = true; }
bool isClosed() const { return _isClosed; }
int fd() const { return _fd; }
BindAdapterPtr &adapter() { return _adapter; }
int closeType() const { return _closeType; }
void setCloseType(int closeType) { _closeType = closeType;}
shared_ptr<SendContext> createSendContext() { return std::make_shared<SendContext>(shared_from_this(), 's'); }
shared_ptr<SendContext> createCloseContext() { return std::make_shared<SendContext>(shared_from_this(), 'c'); }
protected:
uint32_t _uid; /**连接标示*/
string _ip; /**远程连接的ip*/
uint16_t _port; /**远程连接的端口*/
int _fd; /*保存产生该消息的fd,用于回包时选择网络线程*/
BindAdapterPtr _adapter; /**标识哪一个adapter的消息*/
vector<char> _rbuffer; /**接收的内容*/
bool _isOverload = false; /**是否已过载 */
bool _isClosed = false; /**是否已关闭*/
int _closeType; /*如果是关闭消息包,则标识关闭类型,0:表示客户端主动关闭;1:服务端主动关闭;2:连接超时服务端主动关闭*/
int64_t _recvTimeStamp; /**接收到数据的时间*/
};
1.20 SendContext【发送包的上下文,由RecvContext创建出来】
class SendContext // 发送包的上下文,由RecvContext创建出来
{
public:
SendContext(const shared_ptr<RecvContext> &context, char cmd) : _context(context), _cmd(cmd)
{
_sbuffer = std::make_shared<TC_NetWorkBuffer::Buffer>();
}
const shared_ptr<RecvContext> &getRecvContext() { return _context; }
const shared_ptr<TC_NetWorkBuffer::Buffer> & buffer() { return _sbuffer; }
char cmd() const { return _cmd; }
uint32_t uid() const { return _context->uid(); }
int fd() const { return _context->fd(); }
const string &ip() const { return _context->ip(); }
uint16_t port() const { return _context->port(); }
friend class RecvContext;
protected:
shared_ptr<RecvContext> _context;
char _cmd; /**send包才有效, 命令:'c',关闭fd; 's',有数据需要发送*/
shared_ptr<TC_NetWorkBuffer::Buffer> _sbuffer; /**发送的内容*/
};
1.21 send_queue
typedef TC_ThreadQueue<shared_ptr<SendContext>> send_queue; // 发送队列
发送队列,send_queue _sbuffer;--发送队列,在D:\005-02-代码\016-TARS\TARS\TarsFramework\tarscpp\util\include\util\tc_epoll_server.h文件中的NetThread类中
NetThread类中有发送队列,搜索 TARS基金会CPP服务器文章链接的关键词“发送队列”
1.22 recv_queue
typedef TC_ThreadQueue<shared_ptr<RecvContext>> recv_queue; // 接受队列
// 数据队列
struct DataQueue
{
recv_queue _rbuffer;// 接收的数据队列
TC_ThreadLock _monitor;// 锁
};
/**
* 每个线程都有自己的队列
* 0: 给共享队列模式时使用
* 1~handle个数: 队列模式时使用
* Every thread has its own queue.
* 0: Use when sharing queue mode
* 1~handle count: Use when queue mode
*/
class BindAdapter : public TC_HandleBase{
...
vector<shared_ptr<DataQueue>> _threadDataQueue;
...
}
1.23 ServantHandle
class ServantHandle : public TC_EpollServer::Handle
{
public:
enum{ HEART_BEAT_INTERVAL = 10, /**定义常量,心跳间隔时间**/};
ServantHandle(Application *application);// 构造
~ServantHandle();// 析构
virtual void run();// 线程处理方法
CoroutineScheduler* getCoroSched() { return _coroSched; }// 获取协程调度器
Application *getApplication() { return _application; } // get Application
protected:
virtual void handleRequest();// 处理接收请求的协程函数
virtual void handleRecvData(const shared_ptr<TC_EpollServer::RecvContext> &data);// 处理请求的协程函数
protected:
void initialize();// 线程初始化
virtual void handle(const shared_ptr<TC_EpollServer::RecvContext> &data);// 逻辑处理
virtual void handleTimeout(const shared_ptr<TC_EpollServer::RecvContext> &data);// 超时处理
virtual void handleOverload(const shared_ptr<TC_EpollServer::RecvContext> &data);// 处理
virtual void handleClose(const shared_ptr<TC_EpollServer::RecvContext> &data);// 事件处理
virtual void handleAsyncResponse();// handleFilter拆分的第一部分,处理异步调用队列
virtual void handleCustomMessage(bool bExpectIdle = false);// handleFilter拆分的第二部分,处理用户自有数据,非游戏逻辑可忽略bExpectIdle参数
virtual void heartbeat();// 心跳
virtual bool allFilterIsEmpty();// 检查servant有没有resp消息待处理
CurrentPtr createCurrent(const shared_ptr<TC_EpollServer::RecvContext> &data);// 创建上下文
CurrentPtr createCloseCurrent(const shared_ptr<TC_EpollServer::RecvContext> &data);// 创建闭连接时的关上下文
void handleTarsProtocol(const TarsCurrentPtr ¤t);// 处理Tars协议
void handleNoTarsProtocol(const TarsCurrentPtr ¤t);// 处理非Tars协议
#ifdef TARS_OPENTRACKING
void processTracking(const TarsCurrentPtr ¤t);//处理TARS下的调用链逻辑
void finishTracking(int ret, const TarsCurrentPtr ¤t);
#endif
bool processDye(const CurrentPtr ¤t, string& dyeingKey);// 处理TARS下的染色逻辑
bool processCookie(const CurrentPtr ¤t, map<string, string> &cookie);// 处理cookie
bool checkValidSetInvoke(const CurrentPtr ¤t);// 检查set调用合法性
protected:
Application *_application = NULL;// application
unordered_map<string, ServantPtr> _servants;// 处理对象
CoroutineScheduler *_coroSched;// 协程调度器
#ifdef TARS_OPENTRACKING
map<int,std::unique_ptr<opentracing::Span>> _spanMap;
#endif
};
1.24 Handle(TC_EpollServer的嵌套类)
/**
* 服务的逻辑处理代码
* Logical Processing Code for Services
*/
class Handle : public TC_Thread, public TC_HandleBase
{
public:
Handle();//构造, 默认没有请求, 等待10s
virtual ~Handle();// 析构函数
TC_EpollServer* getEpollServer() const { return _pEpollServer; };// 获取服务
BindAdapter *getBindAdapter() const { return _bindAdapter; } // 获取adapter
uint32_t getHandleIndex() const { return _handleIndex; } // 获取Handle的索引(0~handle个数-1)
void setNetThread(NetThread *netThread);// 设置网络线程
NetThread *getNetThread() { return _netThread; } // 获取网络线程
void process(shared_ptr<RecvContext> data); // 处理
virtual void run(); // 线程处理方法
public:
void sendResponse(const shared_ptr<SendContext> &data); // 发送数据
void close(const shared_ptr<RecvContext> &data); // 关闭链接
void setWaitTime(uint32_t iWaitTime); // 设置等待时间
virtual void initialize() {}; // 对象初始化
virtual void notifyFilter(); // 唤醒handle对应的处理线程
virtual void heartbeat() {} // 心跳(每处理完一个请求或者等待请求超时都会调用一次)
protected:
virtual void handleImp(); // 具体的处理逻辑
virtual void handle(const shared_ptr<RecvContext> &data) = 0; // 处理函数
virtual void handleTimeout(const shared_ptr<TC_EpollServer::RecvContext> &data); // 处理超时数据, 即数据在队列中的时间已经超过
virtual void handleClose(const shared_ptr<TC_EpollServer::RecvContext> &data);// 处理连接关闭通知(具体看源码)
virtual void handleOverload(const shared_ptr<TC_EpollServer::RecvContext> &data);// 处理overload数据 即数据队列中长度已经超过允许值
virtual void handleAsyncResponse() {} // 处理异步回调队列
virtual void handleCustomMessage(bool bExpectIdle = false) {} // handleFilter拆分的第二部分,处理用户自有数据
virtual void startHandle() {} // 线程已经启动, 进入具体处理前调用
virtual void stopHandle() {} // 线程马上要退出时调用
virtual bool allAdapterIsEmpty(); // 是否所有的Adpater队列都为空
virtual bool allFilterIsEmpty(); // 是否所有的servant都没有resp消息待处理
void setEpollServer(TC_EpollServer *pEpollServer); // 设置服务
void setBindAdapter(BindAdapter* bindAdapter); // 设置Adapter
void setHandleIndex(uint32_t index); // 设置index
void wait();// 等待在队列上
bool popRecvQueue(shared_ptr<RecvContext> &recv);// 从队列中获取数据
friend class BindAdapter;// 友元类
protected:
TC_EpollServer *_pEpollServer;// 服务
NetThread *_netThread = NULL;// handle对应的网路线程(网络线程和handle线程合并的情况下有效)
BindAdapter* _bindAdapter;// 所属handle组
uint32_t _iWaitTime;// 等待时间
uint32_t _handleIndex;// Handle的索引
};
1.25 Servant
class Servant : public BaseNotify
{
public:
Servant(); // 构造函数
~Servant();// 析构函数
void setName(const string &name);// 设置名称
string getName() const;// 名称
void setHandle(TC_EpollServer::Handle* handle);// 设置所属的Handle
void setApplication(Application *application);// 设置全局的应用
Application* getApplication() const;// 获取应用
TC_EpollServer::Handle* getHandle();// 获取所属的Handle
virtual void initialize() = 0;// 初始化
virtual void destroy() = 0;// 退出
public:
virtual int dispatch(CurrentPtr current, vector<char> &buffer);// 分发收到的请求
virtual int onDispatch(CurrentPtr current, vector<char> &buffer) { return -1; }// 分发并处理请求
public:
virtual int doRequest(CurrentPtr current, vector<char> &buffer) { return -1; }// 普通协议的请求,没有方法名,不需要Dispatch
virtual int doResponse(ReqMessagePtr resp) { return -1; }// 作为客户端访问其他server时,成功返回的响应接口
virtual int doResponseException(ReqMessagePtr resp) { return -1; }// 作为客户端访问其他server时,返回其他异常的响应接口
virtual int doResponseNoRequest(ReqMessagePtr resp) { return -1; }// 作为客户端访问其他server时,如果resp没有找到request,则响应该接口
virtual int doCustomMessage(bool bExpectIdle) { return -1; }// 处理消息
virtual int doCustomMessage() { return -1; }// doCustomMessage() 不带参数的是为了兼容老版本。尽量用带参数的函数
virtual int doClose(CurrentPtr current){ return -1; }// 客户端关闭连接时的处理
TC_CasQueue<ReqMessagePtr>& getResponseQueue();// 获得响应的数据队列
protected:
string _name;// 名字
Application *_application;// 应用
TC_EpollServer::Handle* _handle;// 所属的Handle
TC_CasQueue<ReqMessagePtr> _asyncResponseQueue;// 异步响应队列(详情看源码)
};
1.25 Current
/**
* 当前请求的上下文
*/
class Current : public TC_HandleBase
{
public:
typedef std::map<string, string> TARS_STATUS;
typedef std::vector<char> TARS_BUFFER;
Current(ServantHandle *pServantHandle);// 构造函数
~Current();// 析构
const string &getIp() const;// 获取IP
const string &getHostName() const;// get host name
int getPort() const;// 获取端口
uint32_t getUId() const;// 获取uid
int getFd() const { return _data->fd(); }// 获取fd
bool isResponse() const;// 是否函数返回时发送响应包给客户端
void setCloseType(int type);// 设置连接的关闭类型,详情参看TC_EpollServer::EM_CLOSE_T
int getCloseType() const;// 获取连接关闭类型,详情请参考TC_EpollServer::EM_CLOSE_T类型
void setResponse(bool value) { _response = value; }// 设置是否自动回响应包
void setResponseContext(const map<std::string, std::string> & context){_responseContext = context;}// 设置返回的context(仅TARS协议有效)
const map<std::string, std::string> & getResponseContext() const {return _responseContext;}//获取返回的context(仅TARS协议有效)
void close();// 关闭当前连接
ServantHandle* getServantHandle();// 获取所属的ServantHandle
TC_EpollServer::BindAdapter* getBindAdapter();// 获取来源的Adapter
const vector<char> &getRequestBuffer() const; // 获取请求buffer
string getServantName() const;// 获取服务Servant名称
short getRequestVersion() const;// 请求的协议的版本号(仅TARS协议有效)
map<string, string>& getContext();// 扩展map(仅TARS协议有效)
const map<string, string>& getRequestStatus() const;// 获取保存状态信息,比如染色等(仅TARS协议有效)
string getFuncName() const;// 获取函数名称(仅TARS协议有效)
uint32_t getRequestId() const;// 请求ID(仅TARS协议有效)
char getPacketType() const;// 获取包类型(仅TARS协议有效)
Int32 getMessageType() const;// 获取消息类型(仅TARS协议有效)
struct timeval getRecvTime() const; // 获取接收到请求的时间
void setReportStat(bool bReport);// 设置是否上报状态报告
void sendResponse(int iRet);// taf协议的发送响应数据(仅TAF协议有效)
void sendResponse(int iRet, tars::TarsOutputStream<tars::BufferWriterVector>& os);// taf协议的发送响应数据(仅TAF协议有效), 直接swapbuffer , 这样可以不用copy 数据
void sendResponse(int iRet, tup::UniAttribute<tars::BufferWriterVector, tars::BufferReader>& attr);// taf协议的发送响应数据(仅TAF协议有效), 直接swapbuffer , 这样可以不用copy数据
void sendResponse(int iRet, const vector<char> &buff); // taf协议的发送响应数据(仅TAF协议有效)
void sendResponse(const char* buff, uint32_t len);// 普通协议的发送响应数据(非TAF协议有效)
void sendResponse(int iRet, ResponsePacket &response, const map<string, string>& status, const string& sResultDesc);// 发送响应数据
protected:
friend class ServantHandle;
friend class Application;
void initialize(const shared_ptr<TC_EpollServer::RecvContext> &data); // 初始化
void initializeClose(const shared_ptr<TC_EpollServer::RecvContext> &data);// 初始化
void initialize(const vector<char> &sRecvBuffer); // 初始化
void reportToStat(const string & sObj); // 服务端上报状态,针对单向调用及WUP调用(仅对TAF协议有效)
void setCookie(const map<string, string> &cookie); // 设置cookie
map<string, string> & getCookie(); // 获取cookie
protected:
ServantHandle* _servantHandle; // 操作类指针
shared_ptr<TC_EpollServer::RecvContext> _data; // 接收到的数据
RequestPacket _request; // 客户端请求包
bool _response; // 响应
int _ret; // 接口处理的返回值
bool _reportStat; // 是否上报stat
map<std::string, std::string> _responseContext;// 设置额外返回的内容
map<string, string> _cookie; // cookie
};
2. 类间关系
2.1 网络模块
图中的BindAdapter中的_rBufQueue在我的2.4.14版本中已经变成了vector<shared_ptr<DataQueue>> _threadDataQueue;
2.2 业务模块