0

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

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

我的第一个倾向是认为 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);
            }
        }
    }
4

1 回答 1

1

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

我要检查的第一件事(除非 Windows 服务具有正确的日志记录)是否存在正确设置的 Windows 服务依赖项 - 在 MSMQ 服务本身完全启动之前,您不希望您的旧服务完全启动。

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

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

希望这可以帮助

于 2013-04-12T16:36:05.363 回答