我有一个基于GWT的Java Web应用程序部署到Google App Engine,其中servelet读取和更改内存中保存的状态。客户端代码可能会发送更改此状态的请求,并随后更改或读取相同的状态。因此,来自客户端页面的同一实例的所有请求都必须转到应用程序版本的同一个实例。
由于我不期望有大量流量,我不介意将最大实例数限制为1.但我希望这个实例或多或少永久存在。 (如果用户在请求之间花费的时间超过一小时,我不介意他们的数据是否丢失。)
详细地说,我管理状态的方式是我有一个指向哈希表的静态变量,哈希表将字符串映射到状态。在客户端的第一个请求中,将创建一个新的唯一字符串,并在哈希表中创建一个新状态和一个新条目。字符串在响应中返回。在后续请求中,客户端发送字符串,以便servelet可以找到它需要变异或读取的状态。我无法将状态保存在数据库中,因为它非常复杂,并且根本不可序列化。
有哪些方法可以确保来自给定客户端实例的所有请求都转到同一服务器实例?
答案 0 :(得分:3)
有哪些方法可以确保来自给定客户端实例的所有请求都转到同一服务器实例?
没有办法,按设计。如果要在请求之间可靠地保持状态,请使用数据存储区,并将memcache作为缓存。
添加:如果您的数据存储空间不足,您也可以使用Cookie,根据需要对其进行模糊处理/加密。
App Engine假定应用程序在请求之间不存在基本状态。这使得启动/关闭实例成为非问题。
答案 1 :(得分:1)
我第二个戴夫的回答,GAE并不适合你想要的东西。
然而,可以解决它,但仅限于几个特定情况:如果您使用标准GAE环境进行手动扩展,后续请求始终基于嵌入的URL在对先前请求的回复中。
您可以根据目标路由规则在请求响应中制作URL,以便后续请求命中同一个实例。来自Targeted routing:
- 如果您仍在使用backends或manually-scaled services,则可以通过以下方式定位并向实例发送请求 包括实例ID。实例ID是范围内的整数 从0到正在运行的实例总数,并且可以 具体说明如下:
向特定实例中的特定服务和版本发送请求:
https://INSTANCE_ID-dot-VERSION_ID-dot-SERVICE_ID-dot-MY_PROJECT_ID.appspot.com http://INSTANCE_ID.VERSION_ID.SERVICE_ID.MY_CUSTOM_DOMAIN
注意:在配置为自动缩放或基本缩放的服务中不支持定位实例。实例ID必须是 一个整数,范围从0到最大实例总数 运行。无论您的缩放类型还是实例类,它都不是 可以在不指定的情况下向特定实例发送请求 该实例中的服务或版本。
要确定您可以使用the modules API的实例ID,例如:
// Get the instance handling the current request.
int currentInstance = modulesApi.getCurrentInstance();
请注意,如果目标实例出现故障,您将永久收到错误(该实例将不会再返回),因此您可能需要考虑使用后备解决方案以某种方式访问基于非实例的页面从那里你可以在另一个实例上搭便车。
但是这种解决方案在GAE flex环境中不可用。来自Targeted routing:
注意:在灵活的环境中,不支持定位实例。无法直接向特定请求发送请求 实例