代码之家  ›  专栏  ›  技术社区  ›  JL. Hans Passant

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

  •  5
  • JL. Hans Passant  · 技术社区  · 14 年前

    我有一个ASMX Web服务,应该只允许一次响应一个客户机。

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

    如果这太复杂,那么在A启动服务期间,从B发出的最低限度的调用应该失败,并出现用户定义的错误。

    原因是该服务严重依赖于IO操作和XML序列化,因此不由多个客户端同时调用该服务至关重要。

    提前谢谢

    4 回复  |  直到 14 年前
        1
  •  4
  •   Cory Charlton    14 年前
    static object _LockObject = new object();
    
    void WebServiceCall()
    {
        lock(_LockObject)
        {
            // Do work...
        }
    }
    

    创建您调用的静态对象 lock() 在。这个 lock() 语句将阻止其他调用在完成获取锁的第一次执行之前在内部执行代码。

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

    更新: 是的,您可以使用 Monitor 班级代替 锁定() . 你可以用 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);
    }
    

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

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

    因此,只有在设计上,代码才知道要阻塞而不是跳过。如果需要,可以使用monitor.tryenter()方法跳过。

        2
  •  2
  •   brabster    14 年前

    我不知道它是如何在.NET中实现的,但我想您希望实现一个锁对象,当一个请求正在被服务时,它是由该请求“拥有”的,并且一次不能给多个请求。在爪哇中,我可能会同步一些全局对象。

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

    由于使用非并发的基于Web的系统的使用模式(当然在Java Servlet World中)是一个糟糕的实践,我建议您在服务已经使用而不是阻塞的情况下抛出一个错误,因为它很难判断阻塞的影响。

        3
  •  2
  •   Philip Fourie    14 年前

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

    一些回答建议阻止请求。虽然这将在小范围内起作用,但这将导致诸如 暂停时间 以及 扩展能力 到更多服务器。

    另一个IST,当每个请求进入并放置在 队列 供以后处理。这个队列可以一次处理一个任务(或者取决于服务器有多忙)。

    原始请求者可以通过两种方式通知完成。一种方法是轮询,查看原始请求是否已完成,或者它是否仍在队列中进行处理,可能使用生成的令牌(如guid)。

        4
  •  0
  •   Manish Sinha    14 年前

    我不知道你为什么要这样做,但不管怎样,这可能是一个有效的方案。尝试查看Linux的apt包管理器如何获取锁:

    为了防止包管理器的多个实例产生,要使包管理器正常工作,它需要锁定锁定文件并在其中写入它的PID。

    同样,您可以在虚拟主机的根目录中创建一个文件。当连接到客户机时,锁定该文件,即在其中写入内容。完成后,将文件设为空。在试着锁上它之前,试着看看里面有没有什么东西。如果是,则将错误消息返回给客户机。