HTTPListenerContext响应错误的客户端

时间:2014-03-07 20:20:28

标签: c# multithreading http f#

我遇到了一个非常奇怪的场景,我使用HTTP构建的服务器应用程序总是开始错误地响应客户端请求。服务器是一个位于数据库顶部的简单程序,允许通过从查询/请求层次结构发送序列化对象来查询该数据库。

我使用F#编写的简单可重用HTTP服务器,使用邮箱处理器异步接收和服务请求:

type public HttpAgent (port:int, handler:System.Action<HttpListenerContext>) = 
    let tokenSource = new CancellationTokenSource()
    let processorBody (mailbox: MailboxProcessor<HttpListenerContext>) =         
        async {
            while true do
                let! context = mailbox.Receive()
                Async.Start(async { handler.Invoke(context) } )
        }

    let agent = new MailboxProcessor<HttpListenerContext>(processorBody, tokenSource.Token)

    member public x.Start () = // Starts the server listening on the specified port
        agent.Start()

        let server = async {
            use listener = new HttpListener()
            listener.Prefixes.Add(String.Format("http://*:{0}/", port))
            listener.Start()
            while true do
                let! context = listener.AsyncGetContext()
                agent.Post(context)
        }
        do Async.Start(server, cancellationToken = tokenSource.Token)

    member public x.Stop () = // Stops the Agent server
        tokenSource.Cancel()

正如您所看到的,为了运行服务器,您只需要为此类型提供一个Action,就可以为邮箱异步接收的每个请求上下文调用一个Action。

位于数据库顶部的实际服务器如下所示:

Func<QueryRequest, QueryResponse> tryQueryLookup = (request) => {
    if (request is RequestTypeA) {
        // attempt to retrieve from database
    } else if (request is RequestTypeB) {
        // attempt to retreive from database
    }

    // ... etc

    if (querySuccessful) {
        return new QueryResponse(databaseResults);
    } else {
        return new QueryResponse("Error");
    }
}

Action<HttpListenerContext> requestParser = (context) => {
    Action<QueryResponse> writeResponse = (response) => {
        try {
            using (StreamWriter streamWriter = new StreamWriter(context.Response.OutputStream)) {
                streamWriter.Write(response.ToXml());
            }
        } catch (Exception ex) {
            // write error message to event log
        }   
    };

    try {
        QueryRequest request = null;
        string requestBytes = new StreamReader(context.Request.InputStream).ReadToEnd();
        request = requestBytes.FromXml<QueryRequest>();
        writeResponse(tryQueryLookup(request));
    } catch (Exception ex) {
        writeResponse(new QueryResponse("Error"));
    }
};

m_HttpAgent = new HttpAgent(port, requestParser);
m_HttpAgent.Start()

这项服务在我们的开发环境中已经运行了好几个星期了,但是今天我遇到了一个错误,其中一个请求返回了与它无关的响应 - 它只能来自不同的请求服务器作为请求类型完全不同。

我已经设置了一个测试控制台应用程序,它为每个查询类型启动一个不同的线程,并无限地向服务发出请求。成千上万的这些成功返回,但最终总会收到来自服务器的消息,该消息是响应来自其他线程之一的请求类型而生成的。有时,服务器似乎进入故障状态,其中所有请求都将返回与交叉类型相对应的消息。

我想知道是否存在一些我遗漏的明显线程问题或者我不知道的HTTPListenerContext的行为,因为代码似乎通过在requestParser中使用闭包来保持每个HTTPListenerContext被隔离

0 个答案:

没有答案