问题:从 AppEngine 中的 servlet 调用 Web 服务(每次调用 0.5-1.5 秒)的最佳方式是什么?阻塞调用在 AppEngine 环境中是否可扩展?
上下文:我正在使用 AppEngine 和 J2EE 开发一个 Web 应用程序。应用程序调用 Amazon Web 服务来为用户获取一些信息。根据我的 asp.net 经验,执行调用的最佳方法是使用异步 http 处理程序来防止 IIS 线程池出现饥饿。此功能不适用于具有 Servlet 2.5 规范的 J2EE ( 3.0 is planned )。
现在我正在考虑使我的 Controller (和servlet)线程安全并限制请求范围。还有什么我可以做的吗?在 J2EE + AppEngine 环境中这甚至是一个问题吗?
编辑:我知道 AppEngine 和 JAX-WS 异步调用支持,但我不确定它如何在 servlet 环境中发挥作用。据我了解,要完成 servlet 请求,代码仍然应该等待异步 WS 调用完成(回调或其他)。 我假设使用同步原语执行此操作会阻塞当前工作线程。
因此,只要线程被阻塞,为了服务另一个用户请求,Servlet 容器需要在线程池中分配新线程,为堆栈分配新内存,并浪费时间进行上下文切换。此外,当我们用完线程池中的线程时,请求可能会阻塞整个服务器。此假设基于 ASP.Net 和 IIS 线程模型。它们适用于J2EE环境吗?
答案:在研究了 Apache 和 GAE 文档之后,线程池中的线程饥饿似乎并不是一个真正的问题。 Apache 默认情况下有 200 个线程池线程(而 asp.NET 和 IIS 中为 25 个)。基于此我可以推断 JVM 中的线程相当便宜。
如果确实需要异步处理或 servlet 容器将耗尽线程,则可以重新设计应用程序以通过 google channel api 发送响应。 工作流程如下所示:
- 向 servlet 发出同步请求
- Servlet 为 background 创建异步回复 channel 和队列任务 worker
- Servlet 将响应返回给客户端
- [处理其他请求]
- 后台工作人员进行处理并通过 channel api 将数据推送到客户端
最佳答案
正如您所观察到的,servlet 不支持使用单个线程来服务多个并发请求 - 每个请求需要一个线程。执行 HTTP 调用的最佳方法是使用异步 urlfetch,并在需要结果时等待该调用完成。这将阻塞请求的线程,但这是不可避免的 - 无论您做什么,线程都会专用于当前请求,直到它终止。
如果您不需要 API 调用的响应来满足用户的请求,则可以使用任务队列离线执行工作。
关于java - 在 AppEngine 中从 Servlet 调用 Web 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7471900/