如何确保 asmx Web 服务一次只被调用一次?

发布于 2024-08-24 08:41:13 字数 238 浏览 4 评论 0原文

我有一个 asmx Web 服务,应该只允许一次响应 1 个客户端。

换句话说,如果服务被客户端 A 调用,而服务器 B 调用,我希望 B 挂起直到 A 完成,然后 B 才能得到服务。

如果这太复杂,那么在 A 使用服务期间,来自 B 的调用至少会失败并出现用户定义的错误。

原因是该服务严重依赖 IO 操作和 XML 序列化,因此该服务不能被超过 1 个客户端同时调用,这一点至关重要。

提前致谢

I have an asmx web service that should only be allowed to respond to 1 client at once.

In otherwords if the service is getting called by client A, and server B calls, I would like B to pend until A is finished then B can get serviced.

If this is too complicated then at bare minimum calls from B should fail with a user defined error during the time A is engaging the service.

The reason is that the service relies heavily on IO operations and XML serialization, so it is crucial that the service does not get called simultaneously by more than 1 client.

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

魄砕の薆 2024-08-31 08:41:14

我不知道你为什么要这样做,但无论如何,这可能是一个有效的场景。尝试看看 Linux 的 APT 包管理器如何获取锁:

为了防止包管理器产生多个实例,包管理器要运行,需要锁定锁文件并将其 PID 写入其中。

同样,您可以在虚拟主机的根目录中创建一个文件。当客户端连接时,锁定该文件,即在其中写入一些内容。完成后,将文件清空。在尝试锁定它之前,请尝试查看里面是否有东西。如果是,则返回错误信息给客户端。

I don't know why you want to do so, but anyway, that can be a valid scenario. Try to look how Linux's APT package manager acquires lock:

To prevent multiple instances of package manager from spawning, for a package manager to function, it needs to lock the lock file and write it's PID in it.

Similarly, you can create a file in the Virtual Host's root. When a client is connected, lock that file, i,e write something in it. When, it finishes, make the file empty. Before trying to lock it, try to see if something is there inside. If yes, then return back the error message to the client.

上课铃就是安魂曲 2024-08-31 08:41:13
static object _LockObject = new object();

void WebServiceCall()
{
    lock(_LockObject)
    {
        // Do work...
    }
}

创建一个调用 lock() 上。 lock() 语句将阻止其他调用执行其中的代码,直到获得锁的第一次执行完成。

请注意,根据您的超时设置,B 可能会因超时而失败,具体取决于 A 完成所需的时间。

更新:是的,您可以使用 Monitor 类代替 lock()。您可以使用 Monitor.TryEnter() 方法来检查对象是否已经锁定(即:是否想返回错误而不是等待)。

更多详细信息:

来自 http://msdn.microsoft.com/en-us/library/aa664735(VS.71).aspx

以下形式的锁定语句

lock (x) ...

其中 x 是引用类型的表达式,完全等同于

System.Threading.Monitor.Enter(x);
try {
   ...
}
finally {
   System.Threading.Monitor.Exit(x);
}

From http://msdn.microsoft.com/en-us/library/de0542zz.aspx

使用 Enter 获取作为参数传递的对象上的监视器。如果另一个线程已经对该对象执行了 Enter,但尚未执行相应的 Exit,则当前线程将阻塞,直到另一个线程释放该对象。

因此,代码知道阻塞而不知道阻塞只是设计使然跳过。如果您愿意,可以使用 Monitor.TryEnter() 方法跳过。

static object _LockObject = new object();

void WebServiceCall()
{
    lock(_LockObject)
    {
        // Do work...
    }
}

Create a static object that you call lock() on. The lock() statement will prevent other calls from executing the code inside until the first execution that got the lock completes.

Note that depending on your timeout settings B might fail with a timeout depending on how long A takes to complete.

Update: Yes you can use the Monitor class in place of lock(). You could use the Monitor.TryEnter() method to check if the object is already locked or not (ie: if you wanted to return an error instead of waiting).

More details:

From http://msdn.microsoft.com/en-us/library/aa664735(VS.71).aspx:

A lock statement of the form

lock (x) ...

where x is an expression of a reference-type, is precisely equivalent to

System.Threading.Monitor.Enter(x);
try {
   ...
}
finally {
   System.Threading.Monitor.Exit(x);
}

From http://msdn.microsoft.com/en-us/library/de0542zz.aspx:

Use Enter to acquire the Monitor on the object passed as the parameter. If another thread has executed an Enter on the object, but has not yet executed the corresponding Exit, the current thread will block until the other thread releases the object.

So it's just by design that the code knows to block and not skip. You could skip if you wanted by using the Monitor.TryEnter() method.

等你爱我 2024-08-31 08:41:13

我不知道它是如何在.net中实现的,但我猜你想实现一个锁对象,该对象在服务时由请求“拥有”,并且一次不能提供给多个请求。在 Java 中,我可能会在某些全局对象上进行同步。

但要小心,注意常见的并发问题......比如说一个简单的实现,一个请求检查锁并发现它可用,然后休眠,第二个请求检查锁并获取它,然后第一个请求唤醒,认为锁是免费的并且坏事情发生了)。还要确保处理请求处理崩溃而将锁留在原处的情况。

由于制作非并发的基于 Web 的系统的使用模式(当然在 Java servlet 世界中)被认为是一种不好的做法,因此我建议您在服务已在使用的情况下抛出错误,而不是阻止,因为可能很难判断阻止的影响。

I don't know how it's implemented in .net, but I guess you want to implement a lock object which is 'owned' by a request when it is being serviced and cannot be given to more than one request at a time. In Java, I might synchronize on some global object.

Be careful though, watch for the usual concurrency issues... say for a naive implementation, one request checks for the lock and finds it available, then sleeps and a second request checks for the lock and takes it, then the first request wakes, thinking the lock is free and bad things happen). Also make sure you handle the case that request processing crashes leaving the lock in place.

As the usage pattern of making a non-concurrent web-based system is taken (certainly in the Java servlets world) as a bad practise, I'd suggest you throw an error back in the case where the service is already in use rather than block as it might be difficult to judge the impact of blocking.

以往的大感动 2024-08-31 08:41:13

我理解一次只处理一个请求的要求,但我不认为一次只允许一个请求就是答案。

一些答案建议阻止该请求。尽管这在小规模上可行,但这会导致诸如超时扩展到更多服务器的能力等问题。

另一种方法是,您在每个请求进来时对其进行处理,并将其放入队列中以供稍后处理。该队列一次可以处理一项任务(或者取决于服务器的繁忙程度)。

可以通过多种方式通知原始请求者完成任务。一种方法是轮询以查看原始请求是否已完成,或者是否仍在队列中等待处理,可能使用生成的令牌(例如 GUID)。

I understand the requirement to only process one request at a time but I don't think only allowing one request at a time is the answer.

Some of the answers suggested blocking the request. Although this will work on a small scale, this will result in problems such as time-outs and the ability to scale to more servers.

An alternative ist that you service each request as they come in and place it on a queue for later processing. This queue can be processed one task at a time (or depending on how busy your server is).

The original requesters can be notified in a couple of ways off completion. One way would be to poll to see if the original request has completed or if it still in the queue for processing, perhaps using a generated token (such as GUID).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文