问题描述
看起来,让GAE Channel API在财务上可行的唯一方法是实施某种汇集机制(其中一位高级应用程序引擎产品经理甚至在我向他们发送关于高昂价格的电子邮件时告诉我这一点)重用渠道还没有过期。我一直在头脑风暴的方式来实现一个渠道池,但我想到的每种方法都有一些非常严重的缺点。 >
Servlet的静态内存 - 很好,但是当新的VM实例打开和/或客户端通过时,会丢弃相当多的开放通道从一个虚拟机到另一个虚拟机。
Memcache - 至少内存可以从全部虚拟机全局访问,但现在可以丢弃由于不活动和内存压力,可行渠道可能会更大。
后端实例 - 可能是可靠性方面的最佳选择,运行后端的费用会让你吃不消所有实现池的节省首先!
是否有一个更好的地点/方式来实现跨虚拟机的通道池,我错过了,或者我在这里不必要地挂上了我的选择的缺点?我真的很希望有,或者看起来我的应用程序将不得不恢复到投票(这在我的初步指标中看起来稍微便宜一些)。
解决方案这是我会做的(我实际上正考虑在看到你的问题后编写这个库,我也需要它):创建一个<$
client_id,token = taskpool.get(code> taskpool
)
#在客户端JS中设置心跳,可能是每分钟。
#每当客户端显示存在时也调用它
taskpool.ping(client_id)
taskpool.release(client_id)
执行:
client_id
和令牌
在一个实体中,其状态指示是否正在使用,最后一次ping时间和创建时间。让 client_id
成为关键。另请考虑使用。免费的memcaching。
get()
检查是否有未使用的标记并返回一个发现它。否则,创建一个新的,存储并返回它。
ping()
更新该令牌的最后ping时间。每隔[心跳]时间让客户端发送ping命令,而不是轮询。
release()
将令牌标记为未使用。
每[心跳]秒钟运行一次任务/ cron以查找尚未得到ping的令牌 - 并将它们设置为未使用。
当客户报告已关闭的令牌时,执行 get()
。
请记住,安全性的损失是任何类型令牌池的副产品。如果恶意客户端持有一个令牌并停止发送心跳,那么一旦该令牌被重新使用,它可能以后能够监听传递给新客户端的消息。如果你在一个完全公开的网站上,这并不是问题,但请记住它。
如果我写这篇文章的时候我会更新这个答案作为图书馆。
It seems the only way to make the GAE Channel API financially viable is to implement some kind of pooling mechanism (one of the senior app engine product managers even told me this when I emailed them about the exorbitant price) to reuse channels that have not yet expired.
I've been brainstorming ways (places) to implement a channel pool, but each method I think of has some pretty serious drawbacks.
Static memory of a Servlet -- Good, but will drop quite a bit of open channels when a new VM instance opens and/or a client gets passed from one VM to another.
Memcache -- At least the memory is globally accessible from all VMs, but now the possibility of dropping a very viable channel is possibly greater due to inactivity and memory pressure.
Backend Instance -- Probably the best option in terms of reliability, but now the expense of running the backend will eat up all the savings of implementing the pool in the first place!
Is there a better place/way of implementing a channel pool across VMs that I'm missing, or am I unnecessarily hung up on the drawbacks of my options here? I really hope there is, or it looks like my app will have to revert to polling (which is looking marginally cheaper in my preliminary metrics).
Here's what I'd do (I'm actually considering writing this library after seeing your question. I need it too):
Create a taskpool
module with the following API.
client_id, token = taskpool.get()
# Setup a heartbeat in the client JS, maybe every minute.
# Also call this every time the client indicates presence
taskpool.ping(client_id)
taskpool.release(client_id)
Implementation:
- Store the
client_id
andtoken
in an entity, with a status indicating whether it's being used, last ping time, and creation time. Let theclient_id
be the key. Also consider using NDB. Free memcaching.
get()
checks if there are unused tokens and returns one if it finds it. Otherwise create a new one, store and return it.
ping()
updates the last ping time for that token. Instead of polling, let the client send in a ping every [heartbeat] time.
release()
marks the token as unused.
Run a task / cron every [heartbeat] seconds to find the tokens which haven't gotten a ping in a while - and set them as unused.
When clients report a closed token, perform a get()
.
Keep in mind, though, that a loss in security is a by-product of any kind of token pooling. If a malicious client has held on to a token and stopped sending heartbeats, it might later be able to listen in on the messages being passed to the new client once the token is re-purposed. This isn't a problem if you're on a fully public site, but keep it in mind anyway.
I will update this answer if and when I write this up as a library.
这篇关于Google App Engine中最佳的渠道合并方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!