2016-01-13 29 views
5

Tôi có hai tác vụ mà tôi cần thực hiện nói task1task2 là một phần của cùng một quy trình nghiệp vụ. Tôi phải trả lời cho người dùng cuối khi hoàn thành task1 để thời gian đáp ứng của nó phải được giảm thiểu.Cách đúng để sử dụng các phương pháp không đồng bộ EJB

Cách tiếp cận hiện tại của tôi là thực hiện task1 và ngay sau khi task1 kết thúc, hãy gọi phương thức task2 không đồng bộ. task2 phức tạp và thời gian phản hồi nằm ngoài tầm kiểm soát của tôi vì nó có một số phụ thuộc bên ngoài.

@Stateless 
public class SessionBean1 { 

    @Inject 
    SessionBean2 sessionBean2; 

    public void doTask1(){ 
     // task one stuff 
     sessionBean2.doTask2(); 
    } 

} 



@Stateless 
public class SessionBean2 { 

    @Asynchronous 
    public void doTask2(){ 
     // do task2 stuff 
    } 

} 

Trong websphere 8.0 (EJB container đang sử dụng) phương pháp đồng bộ và phương pháp không đồng bộ được điều hành bởi các nhóm luồng khác nhau.

Giả định ban đầu của tôi là ngay cả khi task2 đang hoạt động kém, task1 sẽ không có tác động, nhưng đáng buồn là điều đó không đúng.

Nếu task2 đang hoạt động kém, tất cả các chuỗi từ nhóm chủ đề không đồng bộ sẽ bị chiếm đóng. Điều này sẽ gây ra task1 để chờ các chuỗi không đồng bộ được miễn phí và do đó task1 có tác động.

Thông điệp trong nhật ký máy chủ websphrere: The request buffer for thread pool WorkManager.WebSphere_EJB_Container_AsynchMethods_Internal_WorkManager has reached its capacity

Câu hỏi của tôi là những gì sẽ là một cách thích hợp để đạt được những gì tôi đang cố gắng để đạt được ở đây.

+0

Nếu bạn đang sử dụng Java EE 7, bạn có thể sử dụng chú thích @AccessTimeout (value = xx), nhưng tôi nghĩ Websphere là Java EE 6? – rjdkolb

+0

@mattfreake: Như trong [image] được liên kết (http://2.1m.yt/itzn6So.jpg), không có yêu cầu phương thức async bị giới hạn và phụ thuộc vào số lượng các chủ đề không đồng bộ. Tôi có thể tăng không có chủ đề nhưng ngay cả khi trong một vài phút task2 thực hiện xấu, task1 của tôi vẫn sẽ phải chờ đợi. Ngoài ra, không có chủ đề nào bị giới hạn bởi cấu hình phần cứng. – ares

+1

Ý tưởng về việc sử dụng hàng đợi JMS được đề xuất bởi @rjdkolb là một ý tưởng tốt hơn nhiều nếu việc định kích thước nhóm luồng là vấn đề. –

Trả lời

2

Một lựa chọn khác sẽ là tăng cường hàng đợi "Yêu cầu công việc kích thước "của" cài đặt yêu cầu phương thức không đồng bộ EJB "trong Bảng điều khiển dành cho quản trị viên. Đây là hàng đợi, trước hồ bơi chủ đề thực sự, vì vậy điều này có thể giúp bạn có thêm thời gian.

Lý tưởng nhất nên sử dụng kết hợp này với thời gian chờ được đề xuất ở trên.

+0

Điều đó có vẻ là một lựa chọn tốt. Theo mặc định nó được xử lý bởi thời gian chạy và phụ thuộc vào không có chủ đề được phân bổ nhưng tôi không thể tìm ra bao nhiêu. Dòng cuối cùng từ bảng điều khiển quản trị websphrere 'Thời gian chạy hiện có sử dụng lớn hơn 20 và giá trị của số lượng chủ đề tối đa.' có ý nghĩa gì không? – ares

+0

Nhìn vào hình ảnh của bạn, tôi lấy nó là "lớn hơn 15 hoặc 20", vì vậy trong trường hợp của bạn, nó phải là 20. Bạn có thể giữ kích thước tối đa 15 thread-pool, và tăng hàng đợi của bạn đến một cái gì đó lớn hơn nhiều. Tôi muốn * hy vọng * hàng đợi sẽ có một bộ nhớ nhỏ/bộ xử lý nhỏ, vì vậy nó có thể lưu trữ các yêu cầu chờ đợi của bạn cho task2, trong khi cho phép các kết thúc hiện có và giữ trong giới hạn phần cứng của bạn. Nhưng nếu task2s có thể mất một thời gian vô hạn để kết thúc, thì tôi nghĩ timeouts sẽ là con đường để đi –

2

Tôi nghĩ rằng @AccessTimeout là những gì bạn đang tìm kiếm. Tôi thấy ví dụ here Điều này sẽ giới hạn khoảng thời gian mà .doTask2() có thể chạy và tránh sự cố của bạn.

@Stateless 
public class SessionBean1 { 

    @Inject 
    SessionBean2 sessionBean2; 

    public void doTask1(){ 
     // task one stuff 
     sessionBean2.doTask2(); 
    } 

} 

SessionBean2

@Stateless 
public class SessionBean2 { 
    @AccessTimeout(60000)//default timeunit is TimeUnit.MILLISECONDS 
    @Asynchronous 
    public void doTask2(){ 
     // do task2 stuff 
    } 

} 

Là một thay thế:

Để hạn chế thời gian quá trình async có thể mất, sử dụng handle.get (xx, TimeUnit.xx); phương pháp. Bạn cũng sẽ cần phải trả về Tương lai và không chỉ mất hiệu lực để làm cho nó hoạt động.

Tôi hy vọng điều này phù hợp với trường hợp sử dụng của bạn như bạn sẽ cần phải gọi một .get

@Stateless 
public class SessionBean1 { 

    @Inject 
    SessionBean2 sessionBean2; 

    public void doTask1(){ 
     // task one stuff 
     Future<Void> handle = sessionBean2.doTask2(); 
     // do other stuff 
     handle.get(10, TimeUnit.SECONDS);//If you want to block later 

    } 

} 

SessionBean2

@Stateless 
public class SessionBean2 { 

    @Asynchronous 
    public Future<Void> doTask2(){ 
     // do task2 stuff 
     new AsyncResult<Void>(Void); 
    } 

} 
+0

Tôi sẽ tải thử nghiệm sau khi thêm @AccessTimeout và cho bạn biết kết quả. Nhưng trong trường hợp khi cuộc gọi thực sự sẽ hết thời gian, nhiệm vụ 2 của tôi sẽ không được gọi. – ares

+1

Nếu bạn muốn nó không đồng bộ và luôn chạy, thay vì đặt thông điệp một hàng đợi JMS – rjdkolb

+0

... hoặc sử dụng bộ hẹn giờ EJB, có khả năng dễ sử dụng hơn. –

Các vấn đề liên quan