java—如何在长的方法调用链上共享内存?

t0ybt7op  于 2021-07-09  发布在  Java
关注(0)|答案(2)|浏览(429)

我需要找出一种有条件地保存和记录方法请求和响应的方法,条件是顶级方法的延迟超过p50延迟。调用可视化如下:

topLevel() -> method1() -> method2() -> ... -> makeRequest()

在makerequest中,我需要记录请求和对该请求的响应。
但我只知道在备份调用堆栈的过程中是否需要记录这些内容—如果顶级方法花费的时间太长。
所以对我来说,唯一的选择就是将请求和响应保存在makerequest中,不管发生什么,并使其可用于顶级方法。顶层方法将检查延迟是否高于p50,并有条件地记录请求和响应。
这一切都引出了一个有名无实的问题:如何在长的方法调用链上共享内存?
我不想通过多个方法调用将对象传递回去,从而污染函数签名。
最好的样式是什么?也许使用本地缓存保存请求和响应,然后在顶层检索它?有面向方面的方法来解决这个问题吗?

km0tfn4u

km0tfn4u1#

只要你能控制代码的顶层和底层就可以了 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();
}

尽管泽西岛提供了一些奇特的注解( @Context 以此类推),这里没有真正意义上的可区分的设计模式—您只是传递请求对象并返回响应。
当然,您也可以维护缓存并将其传递到调用堆栈,或者实际上只是请求和响应的 Package 器对象,但这与传递请求非常相似。

wlsrxk51

wlsrxk512#

这种类型的功能最好使用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} );
        }
    }

相关问题