审核Java中的gRPC调用

时间:2019-09-26 15:02:57

标签: java grpc grpc-java

我正在尝试创建ServerInterceptor来审核对gRPC API的所有调用。我想用一个如下所示的API调用对象构成一个对象。这些被称为一元调用的简单请求和响应。

public class ApiAudit {

    private Map<String, String> headers;
    private long processTime;
    private String api;
    private String protocol;
    private String requestBody;
    private String responseBody;
    private int responseCode;
    private String errorMessage;
    private boolean isDeprecated;
}

我的挑战是,似乎没有一个地方可以收集这些信息。例如,如果这是REST API,我可以创建一个过滤器,该过滤器可以访问请求和响应对象,其中包含所有标头等,并且可以将过滤器链调用包装在try / catch中,以确定是否存在错误等。但是,使用gRPC时,所有这些不同的部分都是脱节的。标头是通过ServerInterceptor#interceptCall方法接收的,如果我创建了SimpleForwardingServerCallListener并覆盖了onMessage方法,则可以访问请求对象,如果我创建了{{1},则可以访问响应对象}并覆盖SimpleForwardingServerCall对象,然后我可以覆盖sendMessage中的onHalfComplete方法,并将调用包装在try / catch中,以确定调用是否成功。如何将所有这些信息放到一个对象中,以单行形式写入日志或存储在审核数据库中?

1 个答案:

答案 0 :(得分:0)

您应该覆盖您感兴趣的每个呼叫,复制出所需的数据。然后在onComplete() / onCancel()中将数据存储到数据库。 onComplete() / onCancel()始终是RPC的结尾(尽管意识到发送可以在取消之后发生,因为处理取消很不明智; onCancel()之后的所有内容都被grpc丢弃)。 / p>

您将创建一个(转发)ServerCall和一个(转发)ServerCall.Listener。要将数据存储在“一个地方”,您可以简单地让您的一个对象引用另一个对象(例如,嵌套类)。

请注意,制作Metadata的完整副本非常重要,因为它不是线程安全的对象。

Metadata copy = new Metadata();
copy.merge(headers);
next.interceptCall(call, headers);