[java] Java Jersey에서 요청 처리시 처리 시간 측정하는 방법은?

Jersey는 Java로 구현된 RESTful 웹 서비스 프레임워크입니다. 이 중에서도 요청의 처리 시간 측정은 매우 중요한 기능 중 하나입니다. 이를 통해 애플리케이션의 성능을 모니터링하거나 병목 현상을 발견할 수 있습니다.

Java Jersey에서 요청 처리 시간을 측정하는 방법은 다음과 같습니다:

  1. 필터를 사용하는 방법:
    • ContainerRequestFilterContainerResponseFilter 인터페이스를 구현하는 필터 클래스를 생성합니다.
    • ContainerRequestFilter에서 ContainerRequestContext 객체를 통해 요청 시작 시간을 기록합니다.
    • ContainerResponseFilter에서 ContainerRequestContext 객체를 통해 요청 종료 시간을 기록하고, 두 시간을 빼서 처리 시간을 계산합니다.
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Response;
import java.io.IOException;

public class TimingFilter implements ContainerRequestFilter, ContainerResponseFilter {

    private static final String START_TIME = "startTime";

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        requestContext.setProperty(START_TIME, System.currentTimeMillis());
    }

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        long startTime = (long) requestContext.getProperty(START_TIME);
        long endTime = System.currentTimeMillis();

        long elapsedTime = endTime - startTime;

        Response.ResponseBuilder builder = Response.fromResponse(responseContext.getResponse());
        builder.header("X-Processing-Time", elapsedTime);
        responseContext.setResponse(builder.build());
    }
}
  1. Interceptor를 사용하는 방법:
    • ReaderInterceptorWriterInterceptor 인터페이스를 구현하는 인터셉터 클래스를 생성합니다.
    • ReaderInterceptor에서 ReaderInterceptorContext를 통해 요청 시작 시간을 기록합니다.
    • WriterInterceptor에서 WriterInterceptorContext를 통해 요청 종료 시간을 기록하고, 두 시간을 빼서 처리 시간을 계산합니다.
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class TimingInterceptor implements ReaderInterceptor, WriterInterceptor {

    private static final String START_TIME = "startTime";

    @Override
    public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
        context.setProperty(START_TIME, System.currentTimeMillis());
        return context.proceed();
    }

    @Override
    public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
        long startTime = (long) context.getProperty(START_TIME);
        long endTime = System.currentTimeMillis();

        long elapsedTime = endTime - startTime;

        MultivaluedMap<String, Object> headers = context.getHeaders();
        headers.add("X-Processing-Time", elapsedTime);

        context.proceed();
    }
}
  1. 어노테이션을 사용하는 방법:
    • @NameBinding 어노테이션을 사용하여 자신만의 어노테이션을 생성합니다.
    • 해당 어노테이션을 필터나 인터셉터에 적용하여 처리 시간을 측정합니다.
import javax.ws.rs.GET;
import javax.ws.rs.NameBinding;
import javax.ws.rs.Path;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;

@NameBinding
public @interface TimingMeasurement {
}

@Path("/example")
public class ExampleResource {

    @GET
    @TimingMeasurement
    public Response exampleMethod() {
        // 처리할 로직
        return Response.ok().build();
    }
}

@Provider
public class TimingFeature implements DynamicFeature {

    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {
        if (resourceInfo.getResourceMethod().isAnnotationPresent(TimingMeasurement.class)) {
            context.register(TimingFilter.class);
        }
    }
}

이렇게 하는 것으로 Java Jersey에서 요청 처리 시간을 측정할 수 있습니다. 성능 모니터링 및 병목 현상 분석에 유용하게 사용할 수 있습니다.

참고 자료: