Tars 的 cookie 功能
概念说明
tars cookie 是在服务调用链上传播的信息,业务可以在调用链的上游设置 cookie,并在调用链的下游获取 cookie
使用场景
透传命令字优先级
接入 Svr 在 cookie 中设置请求命令字 id 和请求命令字优先级,透传到后端,后端可以根据这些信息定制自己的过载保护策略(譬如优先拒绝低优先级请求)
透传 msgno 和 uid
接入 Svr 在 cookie 中设置消息序列号(msgno)和用户 id(uid), 后端服务可以取出 cookie,并将 msgno 和 uid 打印在日志头中(这一步可以通过封装日志宏来自动处理); 这样定位问题时,可以通过 uid 或者 msgno 来快速查找日志(譬如 A 调用 B 的场景,看到 A 的错误日志,则可以复制出 msgno,前往 B 服务快捷查找到该请求的日志); 业务也可以把日志上报到 elk 等检索平台,便于通过 msgno 查找到所有日志
和染色关系
- cookie 和染色类似,都可以在调用链上传播
- 染色从概念上来说,一般只针对少量请求;而 cookie 针对全量请求
- 染色会打印一份集中染色日志,而 cookie 不会
- cookie 和染色可以同时使用,既针对全量请求设置 cookie,针对小部分需要特殊处理的请求进行染色(并且如果日志中有打印 cookie 中 msgno 和 uid 的话,在集中染色日志查找一个请求的完整日志也会很方便)
- 使用全量请求染色也可以实现类似 cookie 的功能,但是这样相当于丢失了染色功能,只有 cookie 功能,而且此时磁盘 I/O 和使用容量会翻倍
- 设置/读取 cookie 的函数使用 map 参数,方便业务定制各种信息,使用起来更加友好
使用示例
设置 cookie
#include "servant/Cookie.h"
CookieOp cookieOp;
map<string, string> cookie;
cookie["msgno"] = "12345";
cookie["uid"] = "67890";
cookieOp.setCookie(cookie);
获取 cookie
从线程私有数据中获取 cookie
#include "servant/Cookie.h"
map<string, string> & cookie = CookieOp::getCookie();
TLOGDEBUG("cookie:" << TC_Common::tostr(cookie.begin(), cookie.end()) << endl);
TLOGDEBUG("msgno:" << cookie["msgno"] << endl);
从 current 对象中获取 cookie
map<string, string> & cookie = current->getCookie();
TLOGDEBUG("current cookie:" << TC_Common::tostr(cookie.begin(), cookie.end()) << endl);
TLOGDEBUG("msgno:" << cookie["msgno"] << endl);
具体应用
接入服务设置 cookie
接入服务在 RPC 调用之前,在 cookie 中设置 msgno 和 uid
#include "servant/Cookie.h"
CookieOp cookieOp;
map<string, string> cookie;
cookie["msgno"] = genMsgNo();
cookie["uid"] = uid;
cookieOp.setCookie(cookie);
UserInfoServantPrx->async_getUserInfo(cb, ...);
后端服务打印日志
后端服务使用如下定制的宏来打印日志,日志头会自动带上 msgno 和 uid
LOG_ERROR("call DBProxy.getUserInfo failed, ret:" << ret);
LOG_ERROR 宏定义如下
#define LOG_ERROR(msg) \
TLOGERROR(__FILENAME__ << ":" << __LINE__ << ":" << __FUNCTION__ << "|" << CookieOp::getCookie()["msgno"] << "|" << CookieOp::getCookie()["uid"] << "|" << msg << endl);
查看日志
查看每个后端服务的日志,可以看到每条日志上都带上了 msgno 和 uid, 同一个请求在所有服务中的日志,msgno 和 uid 相同,其中 af4686091585191682152580023 和 10001 分别为 msgno 和 uid
UserInfoSvr 的日志
2020-03-26 11:01:22|24209|DEBUG|UserInfoServantImp.cpp:1019:getUserInfo|af4686091585191682152580023|10001|call DBProxy.getUserInfo failed, ret:-1
DBProxySvr 的日志
2020-03-26 11:01:22|12359|DEBUG|DBProxyServantImp.cpp:720:getUserInfo|af4686091585191682152580023|10001|sql is: select * from t_user wehre uid = '10001'
2020-03-26 11:01:22|12359|ERROR|DBProxyServantImp.cpp:723:getUserInfo|af4686091585191682152580023|10001|access db timeout