2011-09-19 60 views
1

问:从AppEngine的Servlet调用Web服务(每秒0.5-1.5秒)的最佳方式是什么?阻止呼叫在AppEngine环境中是否可扩展?从AppEngine的Servlet调用Web服务

上下文:我正在开发一个使用AppEngine和J2EE的Web应用程序。这些应用程序调用Amazon Web服务来为用户获取一些信息。从我的asp.net经验来看,完成这些调用的最好方法是使用异步http处理程序来防止在IIS线程池中出现饥饿。对于Servlet 2.5规范的J2EE(3.0 is planned),此功能不适用。

现在我正在考虑让我的控制器(和servlets)线程安全并请求作用域。我还能做些什么吗?这是J2EE + AppEngine环境中的问题吗?编辑:我知道AppEngine和JAX-WS的异步调用支持,但我不确定它如何与servlet环境一起玩。编辑:我知道AppEngine和JAX-WS的异步调用支持,但我不确定它如何与servlet环境一起玩。据我了解,要完成servlet请求,代码仍然应该等待异步WS调用完成(回调或其他)。 我假设使用同步原语做它会阻塞当前工作线程。

因此,就线程被阻塞而言,为了服务另一个用户请求,servlet容器需要在线程池中分配新线程,为堆栈分配新内存并浪费时间进行上下文切换。而且,当线程池中的线程用完时,请求可能会阻塞整个服务器。这个假设基于ASP.Net和IIS线程模型。它们适用于J2EE环境吗?

回答:在研究Apache和GAE文档后,线程池中线程的匮乏似乎不是真正的问题。 Apache默认情况下有200个线程池的线程(与asp.net和IIS中的25个线程相比)。基于此,我可以推断出线程在JVM中相当便宜。

如果真的需要异步处理,或者servlet容器将耗尽线程,可以重新设计应用程序以通过google channel API发送响应。 的工作流程是这样的:

  1. 使同步请求与Servlet
  2. 的Servlet使得对background工人创造了异步回复和队列任务通道
  3. 的Servlet返回响应客户
  4. [服务其他请求]
  5. 后台工作人员通过处理并将数据推送到客户端channel api
+1

Web服务结果是否需要显示给用户?你不能将ws调用转移到后台任务队列吗? – systempuntoout

+0

是的。用户调用搜索请求,并且WS执行实际搜索。但为此实施一种共享方案是一个好主意! –

回答

1

当你观察,servlets的不要” t支持使用单个线程来服务多个并发请求 - 每个请求需要一个线程。执行HTTP调用的最佳方式是使用异步urlfetch,并在需要结果时等待该调用完成。这将阻止请求的线程,但是不能避免 - 线程专用于当前请求,直到它终止,无论您做什么。

如果您不需要来自API调用的响应来满足用户的请求,则可以使用任务队列离线执行工作。

0

使用fetchAsync不行吗?

+0

我不太明白,如何将它整合到servlet执行中。为了完成请求,servlet应该等待完成异步操作,占用工作者线程。 –

+0

我想你希望异步调用的结果在响应中,我加入到Nick Johnsons的答案中。我认为一个可能的问题可能是,当你有两种类型的请求时:等待和提示。假设您池中的线程数量有限,并且您会遇到很多等待请求。这会使提示请求也等待,因为不会有空闲的线程来为它们服务。所以我建议为等待请求设置一个单独的池,就是这样。 – bpgergo

0

着眼于这一点,这可能帮助

http://today.java.net/pub/a/today/2006/09/19/asynchronous-jax-ws-web-services.html

我不知道,如果你能准确地复制你点网做什么,这是你可以做什么可能是模拟它页负载

  1. 提交一个Ajax请求使用Java脚本体的onload
  2. 在控制器控制器启动异步任务,并发送回响应用户,并使用一个会话令牌,以保持跟踪任务的
  3. 您可以查询控制器(添加另一种方法,以请求任务的更新,因为你有会话令牌来跟踪任务),直到你得到的回应
  4. 你可以做到这一点无论在等待响应,保持轮询控制器页面或隐框
  5. 一旦你有你正在寻找如果你想这样做,这将是最好的选择,而不是投票将是理想的去除会话令牌

响应这种情况下Reverse Ajax /服务器推送

编辑:现在我明白你的意思了,我认为你可以让你的代码执行异步任务,而不是等待异步本身的响应,只是将响应发回给用户。我有简单的线程,我将启动,但会等待它完成,因为我发送响应返回给用户,并同时使用会话令牌来跟踪请求

@Controller 
@RequestMapping("/asyncTest") 
public class AsyncCotroller { 
@RequestMapping(value = "/async.html", method = RequestMethod.GET) 
public ModelAndView dialogController(Model model, HttpServletRequest request) 
{ 
    System.err.println("(System.currentTimeMillis()/1000) " + (System.currentTimeMillis()/1000)); 
    //start a thread (async simulator) 
    new Thread(new MyRunnbelImpl()).start(); 
    //use this attribute to track response 
    request.getSession().setAttribute("asyncTaskSessionAttribute", "asyncTaskSessionAttribute"); 
     //if you look at the print of system out, you will see that it is not waiting on //async task 
    System.err.println("(System.currentTimeMillis()/1000) " + (System.currentTimeMillis()/1000)); 
    return new ModelAndView("test"); 
} 

class MyRunnbelImpl implements Runnable 
{ 

    @Override 
    public void run() 
    { 
     try 
     { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

} 
} 
+0

Prasanna,谢谢你的建议。我意识到对JAX和内部GAE fetchAsync的异步支持。问题是 - 我不明白如何将其整合到sevlet生命周期中。请参阅我的原始问题的编辑。 –

+0

感谢您的完整示例,但我需要将WS调用的结果返回给用户。 以下是来自.net的示例:http://msdn.microsoft.com/en-us/magazine/cc163725。aspx来澄清我在说什么: 异步请求在Page_Load方法中启动。之后,工作线程可以自由地提供另一个请求。只有当异步操作完成时,线程才会回到处理页/ servlet生命周期的其余部分(预渲染等)。 –

+0

我编辑我的答案与控制器的例子。 –