如何防止一个网页被多次访问?
假设我有一个 Web 服务,我只想提供一次内容。提供服务后,对该 url 的任何其他访问都应生成错误消息。
我该如何去做这样的事情呢?如果 2 个客户端在同一时间访问该 url 会怎样?
Say I have a web service where I want to serve the content only once. After it is served any other access to that url should generate an error message.
How would I go about doing something like this? What if 2 clients access the url in the same exact moment?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我会使用数据库来管理内容服务。您可以使用事务来获取内容并将其设置为一步检索,这应该可以防止两个客户端同时访问服务的问题。
I would use a database to manage the content serving. You can use transactions to get the content and set it as retrieved in one step, which should prevent the problem of two clients accessing the service at the same instant.
您的要求与我的服务器缓存动态报告的情况非常相似,但相反。
我有需要很长时间才能生成的按需统计报告,因此如果有人已经请求该页面,则将提供缓存的页面而不是重新生成它。
您的情况是,一旦提供了一个页面,就不再提供它。
无论哪种方式,我们都需要在每个页面上有一个持久的标志或签名。该标志或签名必须位于持久数据存储上。
管理无数可能的页面
如果您必须像我一样管理无数的页面,因为按需 http 参数驱动的动态页面的数量是无限可能的页面数量,所以您不能拥有简单的单个持久标志。我有一个例程将 http post/get 请求参数压缩为唯一的签名。该签名被保留。这样,当请求传入时,http 参数将通过此签名生成器运行,并将生成的签名与持久数据存储进行比较,以搜索该签名是否已存在。
就我而言,如果签名存在,我将提供缓存的页面。在您的情况下,如果签名存在,您将显示一个错误页面。
受时间事件影响的先到先服务
但是,在我们的两种情况下,“首次提供的页面”可能会受到时间事件的影响。就我而言,当上传新数据时,该签名已过时。因此,我必须确保我的统计信息模式是基于时间的 - 数据加载时间或事件时间。因此签名有两个组成部分,http 参数签名和请求实体的事件/加载时间。如果签名匹配,但存储在数据库中的请求实体的最新时间大于签名中保存的时间,则意味着该请求被视为“新页面”。
您必须自己决定如何设计 http 参数,以帮助您生成尽可能短的签名,并决定哪些参数将使页面独一无二。
至于持久性存储,由于我已经使用 oracle 来存储统计信息,因此我也使用相同的 oracle 数据库来持久化签名。否则,我认为 hsqldb 可能是一个很好的解决方案。
签名策略
签名表由三个字段组成:事件日期时间、所有者信号量、唯一密钥参数。
其中,为了防止表增长超出当前签名,在签名比较期间会覆盖过时的签名。我还负责删除过时的签名。
通过放置带有空日期时间的 paramsig 可以非常简单地管理多用户访问。就我而言,我可以向自己保证请求日期时间是唯一的,因此我实际上使用请求日期时间作为所有者信号量。第一个幸运的人(但在我的例子中,第一个不幸的用户需要等待未缓存的报告)抢占表并创建唯一的 paramsig 将导致后续尝试被数据库系统抛出。空日期时间表明参数已被保留,稍后将被填充。对于您的情况,您也许可以跳过该步骤,只使用 paramsig、ownersemaphore。
但是,如果您处于多服务器环境中,则需要为 Ownersemaphore 设计一个组合键,例如服务器 ID + 请求时间。
我不确定 hsqldb 是否能够管理并发。我只在oracle和sqlserver上做过这个策略。
Your requirement is very similar, but opposite, to my case of server caching dynamic reports.
I had on-demand statistical reports that took a long time to generate, so that if someone had already requested for that page, the cached page would be served rather than re-generating it.
Your case is, once a page is served, do not serve it again.
Either way, we need a persistent flag or signature on each page. That flag or signature would have to sit on a persistent datastore.
Managing innumerable possible pages
If you have to manage an innumerable number of pages like I had to, since the number of on-demand http-parameter driven dynamic pages are of infinite possible number of pages, you cannot have simple single persistent flag. I had a routine to compress the http post/get request parameters into a unique signature. That signature is persisted. So that when a request comes in, the http parameters are run thro this signature generator and the resultant signature is compared against the persistent datastore to search if the signature is already existent.
In my case, if the signature is existent, I serve the cached page. In your case, if the signature is existent, you show an error page.
First-come-first-served affected by time events
However, in both our cases "page served for the first time" can be affected by time events. In my case, when new data is uploaded - that signature is stale. So, I have to ensure my statistical information schema is time-based - with the time of dataload or time of event. So that the signature has two components, the http parametric signature and the event/load time of the requested entity. If the signature matches, but that the latest time of the requested entity stored in the database is greater than the one persisted in the signature, that means the request is considered "a new page".
You have to decide for yourself how to design http parameters that would help you generate the shortest possible signature and decide what parameters would make a page unique.
As for the persistent store, since I was already using oracle to store the statistical info, I had as well used the same oracle database to persist the signatures. Otherwise, I think hsqldb might be a good solution.
Signature strategy
The signature table would consist of three fields: event datetime, ownersemaphore, unique key paramsig.
Where, to keep the table from growing beyond current signatures, a stale signature is overwritten during signature comparison. I also had a job deleting stale signatures.
Multi-user access is managed very simply by placing a paramsig with a null datetime. In my case, I could assure myself that request datetime is unique so that I actually used the request datetime as ownersemaphore. The first lucky person (but in my case the unlucky first user who needed to wait for an uncached report) to race to the table and create that unique paramsig would cause subsequent attempts to be thrown out by the database system. The null datetime is inform that a paramsig is being reserved and will be filled in later. In your case, you might be able to skip that step and just use paramsig, ownersemaphore.
However, if you are in a multiserver env, you need to devise a composite key for ownersemaphore, like server id + request time.
I'm not sure if hsqldb is able to manage concurrency. I have only done this strategy on oracle and sqlserver.