前言:

当我们在部署web服务的时候,web容器通常都会记录来自客户端的访问日志。而当我们使用Thrift RPC服务的时候,Thrift服务则不会给我们自动记录客户端的访问日志。

通过这篇文章,你可以学习到如何使用在Thrift服务器端添加客户端的访问日志。

面临的问题:

要在Thrift服务器端添加客户端的访问日志,我们需要解决两个问题:

  1. 找到合适的拦截点记录信息
  2. 收集访问日志中需要的信息
寻找合适的拦截点:

我们都知道,Thrift协议为我们提供了thrift文件向各种编程语言转换的程序。通过观察,我们会发现Thrift将IDL中定义的每个方法抽象为一个类,即ProcessFunction类。

该类负责从输入中读取参数,调用用户编写的服务将响应写回到输出中。该类是如何发挥作用的,下面这张类图可以比较清晰地说明。

当我们使用Thrift.exe可执行程序处理IDL文件的时候,Processor会被自动创建出来。它负责把实际的方法实现和方法的key关联起来,放到Map中维护。

以TMultiplexedProcessor为例,TMultiplexedProcessor会将所有注册的Processor都存储到SERVICE_PROCESSOR_MAP中。

public boolean process(TProtocol iprot, TProtocol oprot) throws TException {
/*
先读取消息头
*/
TMessage message = iprot.readMessageBegin();
if (message.type != TMessageType.CALL && message.type != TMessageType.ONEWAY) {
// TODO Apache Guys - Can the server ever get an EXCEPTION or REPLY?
// TODO Should we check for this here?
throw new TException("This should not have happened!?");
}
// Extract the service name
int index = message.name.indexOf(TMultiplexedProtocol.SEPARATOR);
if (index < 0) {
throw new TException("Service name not found in message name: " + message.name + ". Did you " +
"forget to use a TMultiplexProtocol in your client?");
}
// 从message中读取serviceName
String serviceName = message.name.substring(0, index);
TProcessor actualProcessor = SERVICE_PROCESSOR_MAP.get(serviceName);
if (actualProcessor == null) {
throw new TException("Service name not found: " + serviceName + ". Did you forget " +
"to call registerProcessor()?");
}
// Create a new TMessage, removing the service name
TMessage standardMessage = new TMessage(
message.name.substring(serviceName.length()+TMultiplexedProtocol.SEPARATOR.length()),
message.type,
message.seqid
);
//由真实的处理器对输入信息进行处理
return actualProcessor.process(new StoredMessageProtocol(iprot, standardMessage), oprot);
}

actualProcessor的process过程如下,其具体的实现逻辑在TBaseProcessor中。

public boolean process(TProtocol in, TProtocol out) throws TException {
//读取消息头
TMessage msg = in.readMessageBegin();
//从方法集合中获取对应的方法处理类
ProcessFunction fn = processMap.get(msg.name);
if (fn == null) {
TProtocolUtil.skip(in, TType.STRUCT);
in.readMessageEnd();
TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'");
out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
x.write(out);
out.writeMessageEnd();
out.getTransport().flush();
return true;
}
//进行具体的处理,ProcessFunction对象是实际方法的装饰器,
//process内部会调用实际方法的处理逻辑
fn.process(msg.seqid, in, out, iface);
return true;
}

通过上面的分析,我们可以在ProcessFunction中添加有关的access日志。但是这其中有一个问题,就是经过ThriftServer对thrift请求的解析以及消息内容处理,在到达ProcessFunction::process方法的时候,我们已经无法获取到客户端的远程IP地址了。

接下来,我们就要考虑如何收集访问日志需要的信息了。

如何收集访问日志需要的信息:

从上面ProcessFunction中的process方法中,我们可以看出将客户端的IP地址保存到iprot中,是一个不错的选择。

那么,接下来我们需要找到iprot这个对象参数是在什么地方被创建的,以及在合适的地方将客户端的IP地址写入到这个对象中。

经过分析,我们会发现TNonblockingServer是NIO服务器的实现,它通过Selector来检查IO就绪状态,进而调用相关的Channel。

就方法调用而言,它处理的是读事件,用AbstractNonblockingServer的handelRead()来进一步处理。

protected void handleRead(SelectionKey key) throws IOException {
FrameBuffer buffer = (FrameBuffer) key.attachment();
if (!buffer.read()) {
cleanupSelectionKey(key);
return;
}
// if the buffer's frame read is complete, invoke the method.
if (buffer.isFrameFullyRead()) {
if (!requestInvoke(buffer)) {
cleanupSelectionKey(key);
}
}
}

SelectionKey中有客户端的IP地址,FrameBuffer则是处理方法调用的缓冲区对象,其内部的invoke方法会对Processor中的方法进行实际调用。

因此,在handleRead方法中添加两行代码将客户端的IP地址写入inProt_中就可以带入ProcessFunction中了。

SocketChannel socketChannel = (SocketChannel)key.channel();
buffer.inProt_.setClientAddr(socketChannel.getRemoteAddress().toString());

Thrift RPC添加access log的更多相关文章

  1. netstat--查看服务器[有效]连接数--统计端口并发数--access.log分析

    简介 Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Member ...

  2. JMeter学习(三十一)Access Log Sampler

    前提: 在tomcat\conf\server.xml默认情况下,会有一段代码: <Valve className="org.apache.catalina.valves.Access ...

  3. Tomcat access log配置

    在tomcat的access中打印出请求的情况可以帮助我们分析问题,通常比较关注的有访问IP.线程号.访问url.返回状态码.访问时间.持续时间. 在Spring boot中使用了内嵌的tomcat, ...

  4. 【转载】netstat--查看服务器[有效]连接数--统计端口并发数--access.log分析

    简介 Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Member ...

  5. springboot中配置tomcat的access log

    在tomcat的access中打印出请求的情况可以帮助我们分析问题,通常比较关注的有访问IP.线程号.访问url.返回状态码.访问时间.持续时间. 在Spring boot中使用了内嵌的tomcat, ...

  6. nginx关闭全局access.log,error.log

    如果nginx的server里没配置access.log,nginx会默认将server的访问日志记录到access.log, 关闭方法: 在nginx.conf配置文件中, 在全局配置中添加 err ...

  7. Tomcat access log配置(二)

    前次讨论了spring boot 中添加Tomcat access log 是轻松愉快,配置文件中添加server.tomcat.accesslog即可,那么如果是外置的Tomcat容器又该如何配置呢 ...

  8. 在nginx日志access log可以记录POST请求的参数值

    1)      在nginx日志access log可以记录POST请求的参数值 实现程度:日志中可以显示POST请求所提交的参数值 问题: 日志中文显示十六进制(在配置文件中配置中文也无效) 没有对 ...

  9. 利用logrotate切割nginx的access.log日志

    一.新建一个nginx的logrotate配置文件 /var/log/nginx/access.log { daily rotate compress delaycompress missingok ...

  10. Thrift RPC实战(三) thrift序列化揭秘

    本文主要讲解Thrift的序列化机制, 看看thrift作为数据交换格式是如何工作的? 1.构造应用场景: 1). 首先我们先来定义下thrift的简单结构. 1 2 3 4 5 namespace ...

随机推荐

  1. CentOS yum如何安装php7.4

    centos系统下使用yum安装php7.4正式版,当前基于WLNMP提供的一键安装包来安装 1.添加epel源 yum install epel-release 2.添加WLNMP一键安装包源 rp ...

  2. STM32F0单片机基于Hal库温控智能风扇

    一.项目概述 设计采用STM32F0系列单片机做主控芯片,通过DHT11采集温湿度,将温度显示在OLED 屏幕上.根据温度的不同,利用STM32对风扇进行调速,总体硬件设计如下图所示 1.效果展示 2 ...

  3. 记一次批量更新整型类型的列 → 探究 UPDATE 的使用细节

    开心一刻 今天,她给我打来电话 她:你明天陪我去趟医院吧 我:怎么了 她:我怀孕了,陪我去打胎 我:他的吗 她:嗯 我心一沉,犹豫了片刻:生下来吧,我养! 她:他的孩子,你不配养! 我:我随孩子姓 需 ...

  4. 邻接矩阵bfs

    #include<bits/stdc++.h> using namespace std; int a[11][11]; bool visited[11]; void store_graph ...

  5. AcWing 最短Hamilton距离 (状压DP)

    题目描述 给定一张 n 个点的带权无向图,点从 0∼n−1 标号,求起点 0 到终点 n−1 的最短 Hamilton 路径. Hamilton 路径的定义是从 0 到 n−1 不重不漏地经过每个点恰 ...

  6. 文盘Rust -- struct 中的生命周期

    最近在用rust 写一个redis的数据校验工具.redis-rs中具备 redis::ConnectionLike trait,借助它可以较好的来抽象校验过程.在开发中,不免要定义struct 中的 ...

  7. Bug改不完,迭代总延期,咋办?

    摘要:本文从流程上需要改进的地方进行讨论,分四个方面来分析产生这个问题的原因. 本文分享自华为云社区<Bug改不完,迭代总延期,咋办?>,作者: 华为云PaaS服务小智. 前言 随着互联网 ...

  8. vulnhub靶场之JANGOW: 1.0.1

    准备: 攻击机:虚拟机kali.本机win10. 靶机:JANGOW: 1.0.1,地址我这里设置的桥接,,下载地址:https://download.vulnhub.com/jangow/jango ...

  9. Kafka 之producer拦截器(interceptor)

    Kafka 之producer拦截器(interceptor) 一.拦截器原理 Producer拦截器(interceptor)是在Kafka 0.10版本被引入的,主要用于实现clients端的定制 ...

  10. 知识图谱-生物信息学-医学顶刊论文(Briefings in Bioinformatics-2021):MPG:一种有效的自我监督框架,用于学习药物分子的全局表示以进行药物发现

    6.(2021.9.14)Briefings-MPG:一种有效的自我监督框架,用于学习药物分子的全局表示以进行药物发现 论文标题:An effective self-supervised framew ...