我需要找出一种方法来有条理地保存和记录方法请求和响应,条件是顶级方法的延迟超过p50延迟。调用可视化为如下:
topLevel() -> method1() -> method2() -> ... -> makeRequest()
在makeRequest中,我需要记录对该请求的请求和响应。
但是我只知道在返回调用堆栈的过程中我是否需要实际记录那些 - 如果topLevel方法花费的时间太长。
所以对我而言,唯一的选择是在makeRequest中保存请求和响应,无论如何,并使topRevel方法可用。 topLevel方法将检查延迟是否高于p50并有条件地记录请求和响应。
这一切都导致了一个名义上的问题:如何通过长链方法调用共享内存?
我不希望通过多个方法调用传回对象,污染函数签名。
最好的模式是什么?也许使用本地缓存来保存请求和响应,然后在topLevel中检索它?是否有一种面向方面的方法来解决这个问题?
答案 0 :(得分:1)
只要您控制了顶级代码并且通过method1
和method2
,这真的不是那么难。
您只需要通过调用链传递请求,然后传回响应。
topLevel() -> method1(request) -> method2(request) -> ...
-> makeRequest(request) { ... return response; }
要将此与实际代码示例相关联,您可以查看jersey
框架的工作原理。
以下是注入请求并返回响应的方法示例。
@POST
@Consumes({MediaType.TEXT_XML})
@Produces({TEXT_XML_UTF_8})
public Response resource(@Context HttpServletRequest servletRequest) throws Exception {
ExternalRequest req = makeRequest(servletRequest.getInputStream());
ExternalResponse resp = externalGateway.doSomething(req);
return Response.ok(wrapResponse(resp)).build();
}
虽然Jersey提供了一些花哨的注释(@Context
等等),但这里没有任何明显的可区分设计模式 - 你只是传递请求对象并返回响应。
当然,您也可以维护缓存并将其传递给调用堆栈,或者实际上只是请求和响应的包装器对象,但它与简单地传递请求非常相似。
答案 1 :(得分:0)
此类功能最好使用ThreadLocals完成。您的makeRequest
会将请求和响应对象添加到ThreadLocal中,然后topLevel
将删除它们并在需要时记录它们。这是一个例子:
public class RequestResponseThreadLocal{
public static ThreadLocal<Object[]> requestResponseThreadLocal = new ThreadLocal<>();
}
public class TopLevel{
public void topLevel(){
try{
new Method1().method1();
Object[] requestResponse = RequestResponseThreadLocal.requestResponseThreadLocal.get();
System.out.println( requestResponse[0] + " : " + requestResponse[1] );
}finally{
//make sure to clean up stuff that was added to ThreadLocal otherwise you will end up with memory leak when using Thread pools
RequestResponseThreadLocal.requestResponseThreadLocal.remove();
}
}
}
public class Method1{
public void method1(){
new Method2().method2();
}
}
public class Method2{
public void method2(){
new MakeRequest().makeRequest();
}
}
public class MakeRequest{
public void makeRequest(){
Object request = new Object();
Object response = new Object();
RequestResponseThreadLocal.requestResponseThreadLocal.set( new Object[]{request, response} );
}
}