2014-02-13 1 views
3

우선 영어는 제 첫 번째 언어가 아니므로 일부 분명한 실수를하거나 너무 명확하지 않은 경우 실례합니다. 질문 :AsyncContext.complete() 이후 처리 계속

최근 Jersey + Hibernate를 통해 일부 REST 서비스를 제공하는 Java EE 애플리케이션을 개발중인 새로운 프로젝트로 이동했습니다. 이전에는 Java SE에 대한 경험이 있었지만 이미 경험이있는 사람이 있었기 때문에 코드를 배우고 Google과 SO를 많이 사용했습니다.

문제는 REST 서비스 중에는 완료하는 데 많은 시간이 걸리는 서비스가 있으며, 팀은이를 비 차단 방식으로 구현하기로 결정했습니다. 우리는 두 가지 서비스를 정의 할 것입니다. 첫 번째 클라이언트가 처리 할 데이터를 보낸 다음 클라이언트가 승인을 반환하고 처리를 시작하면서 다른 작업을 계속할 수 있습니다. 두 번째 방법은 클라이언트가 작업이 완료되면 나중에 확인할 수있게합니다.

가능한 가장 좋은 방법을 구현하는 방법을 조사하면서, 앞서 언급 한 동료가 Servlets 3.0의 AsyncServlet 기능을 발견하고 도착하기 전에 개념 증명을 구현했습니다. 나중에 개념적으로 입증 된 것이 로컬로 작동하지만 (매우 더러운) 서비스 버전. 그는 서블릿 3.0이 우리가 작업하는 Jersey 버전과 호환되지 않았기 때문에 저지를 버려야한다고 말했고 최종적으로 일반 서블릿을 구현하기로 결정했습니다.

결국 그는 집과 메모리로 글을 쓰지 않아도됩니다. 어떤 큰 실수 내일 아침) :

doPost()의 새로운 요청과 doGet()의 검사 처리하는 서블릿 :

@WebServlet(asyncSupported = true) 

//... 

void doGet(HttpServletRequest req, HttpServletResponse res) { 

    /* 
    * ...  
    * We query the previous "job request" here in the DB 
    * ... 
    */ 

} 

void doPost(HttpServletRequest req, HttpServletResponse res) { 

    /* 
    * ... 
    * We convert the JSON request to an entity and then start the asynchronous 
    * "worker" thread 
    * ... 
    */ 

    AsyncContext ctx = req.startAsync(req, res); 
    ctx.start(new WorkerThread(ctx, someOtherDataFromRequest); 
} 

그리고 Runnable를 구현하고하는 첫번째 것은 ctx.complete()를 호출하는 것입니다 작업자 스레드를 구성에서 그에게 보낸 AsyncContext에 또는. 내 동료 추론이며, 노동자가 바로 그가 완료 부모를 통지하는 경우, 부모는 다시 클라이언트로 응답을 커밋하고 생성자에서 그에게 전달 된 다른 데이터와 자신의 처리를 시작할 수 있습니다

public class WorkerThread implements Runnable { 

    public WorkerThread(AsyncContext ctx, SomeOtherData data){ 

     //... 

    } 

    public void run() { 
     ctx.complete(); 

     // ... Now start doing the heavy processing with data 

    } 
} 

글쎄, 내가 말한 것처럼 로컬 테스트 서버 (Tomcat 7)에서 작동하지만 며칠 전 자신의 코드를 지우도록 요청 받았고 JBoss EAP 6.1이 설치된 컴퓨터에서 실행되었을 때, 부모 서블릿은 작업자가 죽을 때까지 응답을 저 지르지 않기 때문에 (예상되는대로 작동합니다. 생산 시스템이 새롭고 상위 서버가 어떤 서버를 아직 설치하지 않았으며 그들의 마음을 여러 번 변경했기 때문에 다른 서버를 가지고 있기 때문에, 관료 ...)

나는 많은 시도를했는데 청소하는 동안 비동기 처리의 핵심 요소를 제거하지 않았다고 확신한다. 내 버전이 제대로 컴파일되고 실행되기 때문이다. 마지막에는 작업자가 10 초간 잠자기 후 로그에 기록하는 테스트 사례가 있습니다. Tomcat에서 응답은 거의 즉시 클라이언트에 도달 한 다음 로그에 기록됩니다. JBoss에서는 응답을 받기 위해 클라이언트가 전체 10 초를 기다려야합니다.

그런 다음 필자는 AsyncServlet 기능을 조사하기 시작했으며 잘못된 생각을 갖고 있다고 생각합니다.이 기능은 비동기 내부 처리로 이동하는 것으로 보이지만 사용하지는 못하는 이유는 무엇입니까? 그것은 그의 Tomcat에서 작동합니다.complete() 방법의 JavaDoc을에서 나는 보스의 동작은 올바른 이해 :이 방법은 startAsync이 컨테이너에 돌아왔다라는 용기 시작 파견하기 전에 호출하면

다음 호출은하지 않습니다 컨테이너에서 시작한 디스패치가 컨테이너으로 반환 될 때까지 이 적용될 때까지 (AsyncListener # onComplete (AsyncEvent)의 모든 호출이 지연됩니다).

그래서, 내 질문 (그들은 저지와 호환되는 경우 보너스 포인트) 우리의 원하는 동작을 얻을 수있는 다른 청소기 방법이있는 경우, 그렇지 않은 경우는 AsyncServlet 기능은 우리의 사용 사례를 대상으로하는 경우이며, . 난 그냥 스레드를 산란과 전혀 asyncontext를 사용하지 않는에 대한 생각,하지만 매우 위험한 소리 ...

감사 및 텍스트

답변

0

의 벽에 대한 유감이 응답은 너무 조금 늦게 될하지만있을 수있어 당신이 저지 2.0

또한

https://jersey.java.net/documentation/latest/async.html

을 제공 AsyncResource를 사용하여 보았다, 당신은 "노동자가 사망 할 때까지 부모 서블릿이 응답을 범하지 않는다"고 말했다. 어떻게 증명 했니? 아마도 Tomcat 서버와 Jboss 서버에 대한 설정이 다를 것입니다. (스레드 풀 크기/연결 수에 차이가 있습니까?)

또한 SomeOtherData에서 필요한 모든 것이있는 것처럼 보입니다. 따라서 ExecutorService를 대신 사용하여 생성자에서 SomeOtherData를 취하는 실행 파일을 추가하고 작업자에서 수행하지 않고 doPost 자체의 컨텍스트에서 즉시 complete를 호출 할 수 있습니다.

관련 문제