MSMQ,Windows服务和服务器重启

时间:2013-04-11 22:23:37

标签: windows-services msmq reboot

我正在使用遗留的Windows服务,它从私有MSMQ队列中读取消息处理它们(做一些数据库工作,发送一些电子邮件),然后等待下一条消息(PeekCompleted)

该服务存在问题 - 只要Windows Update需要重新启动服务器(几乎总是如此),服务就会以“已启动”状态重新启动,但必须手动重新启动,否则消息会堆积在队列中。

我的第一个倾向是认为OnStart处理程序中有一些东西在服务器恢复时没有被点击,而我正在尝试整理日志(另一个故事),但Windows服务和线程不是我的正常的域名,所以我希望有人可以指出我正确的方向....

下面是OnStart Handler和消息处理函数,剥离了无关紧要的东西。

问题:在OnStart中,MessageRecieved函数附加到PeekCompleted事件。 我假设OnStart在服务器恢复时触发,因此处理程序必须连接,但我不清楚是否(a)在重新启动时已经在队列中或(b)在重新启动期间到达的消息实际上会触发事件?

如果它应该还有其他我应该寻找的东西?

欢迎任何建议!

protected override void OnStart(string[] args)
    {
        try
        {
            _inProcess = false;
            _queueMessage = null;
            _stopping = false;
            _queue = ReadyQueue(_queueName);
            if (_queue == null)
            {
                throw new Exception(string.Format("'ReadyFormQueue({0})' returned null", _queueName));
            }
            _queue.PeekCompleted += new PeekCompletedEventHandler(MessageReceived);
            _queue.Formatter = new BinaryMessageFormatter();
            _queue.BeginPeek();
        }
        catch (Exception exception)
        {
            //do cleanup and other recovery stuff
        }
    }


    private void MessageReceived(object sender, PeekCompletedEventArgs e)
    {
        _currentMessage = null;
        _inProcess = false;
        try
        {
            _queueMessage = _queue.EndPeek(e.AsyncResult);
            _queueMessage.Formatter = new BinaryMessageFormatter();
            _currentMessage = (MyMessageType)_queueMessage.Body;
            _queue.ReceiveById(_queueMessage.Id);
            _inProcess = true;
            _helper = new MessageHelper();
            _currentMessage = _helper.Process(_currentMessage);  //sets global _inProcess flag
            if (_inProcess)
            {
                Thread.Sleep((int)(_retryWaitTime * 0x3e8));
                SendFormMessageToQueue(FailedQueueName, _currentMessage);
            }
            else
            {
                _queue.BeginPeek();
            }


        }
        catch (Exception exception)
        {
            _inProcess = false;
            //do other recovery stuff
            if (_currentMessage != null)
            {
                ReadyFormQueue(_poisonQueueName);
                SendFormMessageToQueue(_poisonQueueName, _currentMessage);
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

这个传统的Windows服务可以在排队基础设施启动并完全运行之前启动,在初始连接中必须失败,因此不处理消息。

我要检查的第一件事(除非Windows服务有正确的日志记录)是否有正确设置的Windows服务依赖项 - 您不希望您的旧服务完全启动,直到MSMQ服务自身完全开始了。

我认为遗留服务中没有问题,因为一旦你重新启动它,它似乎工作正常,我认为你有资源可用竞争类型的问题,消费者在资源之前启动并没有完全设计从那恢复。

我会:创建一个服务依赖项(可以在SCM中完成),然后重新启动服务器,看看你是否还有更多的MSMQ消息,我的猜测答案是否定的。

希望这有帮助