如何在Web API中维护请求的状态或队列

use*_*965 10 c# asp.net solr solrnet asp.net-web-api

我有情况,我必须在Web API方法中接收请求,排队这些请求,然后将批量发送到数据库(Solr实例).

我不确定如何维护来自多个来源的一批请求.现在我将每个请求数据以json格式写入磁盘上的文件,稍后我将有一个Windows服务,浏览文件夹读取所有文件,更新数据库并删除这些文件.

这是我在Web API中所做的事情

public void Post(LogEntry value)
{
    value.EventID = Guid.NewGuid();
    value.ServerTime = DateTime.UtcNow;
    string json = JsonConvert.SerializeObject(value);
    using(StreamWriter sw = new StreamWriter(value.EventID.ToString()))
    {
        sw.Write(json);
    }
}
Run Code Online (Sandbox Code Playgroud)

(这EventID是GUID)

这个过程看起来不正确,必须有一种维护请求队列的方法,但我不确定如何在多个请求期间维护队列.

我这样做的原因是,在solr实例中批量插入比通过SolrNet插入单个记录更快.我期望在Web API上每秒至少获得100个请求.我想创建一批1000个请求并每10秒更新一次solr实例.请不要认为我需要代码,只需知道我应采用什么策略来维护请求/状态队列.

Aag*_*age 15

如果您使用的是.NET 4.0或更高版本,则可以使用并发队列:

并发队列(MSDN)

这是一种使用队列的线程安全方式,然后可以在所需的时间访问该队列.

编辑:

例:

这将是队列的包装:

public static class RequestQueue
{
    private static ConcurrentQueue<int> _queue;

    public static ConcurrentQueue<int> Queue
    {
        get
        {
            if (_queue == null)
            {
                _queue = new ConcurrentQueue<int>();
            }

            return _queue;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样设置你的web api(这个例子为了简洁起见存储整数):

public class ValuesController : ApiController
{        
    public string Get()
    {
        var sb = new StringBuilder();
        foreach (var item in RequestQueue.Queue)
        {
            sb.Append(item.ToString());
        }

        return sb.ToString();
    }

    public void Post(int id)
    {
        RequestQueue.Queue.Enqueue(id);
    }        
}
Run Code Online (Sandbox Code Playgroud)

如果您使用此示例,您将看到队列保存多个请求中的值.但是,由于它存在于内存中,如果应用程序池被回收(例如),那些排队的项目将会消失.

现在,您可以检查队列何时保存10个项目,然后将这些项目保存到数据库,同时创建另一个队列来存储传入的值.

像这样:

public static class RequestQueue
{
    private static ConcurrentQueue<int> _queue;

    public static ConcurrentQueue<int> Queue
    {
        get
        {
            if (_queue == null)
            {
                _queue = new ConcurrentQueue<int>();
            }

            if (_queue.Count >= 10)
            {
                SaveToDB(_queue);
                _queue = new ConcurrentQueue<int>();
            }

            return _queue;
        }
    }

    public static void SaveToDB(ConcurrentQueue<int> queue)
    {
        foreach (var item in queue)
        {
            SaveItemToDB(item);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你需要稍微清理一下,但这种设置应该有效.此外,您可能需要一些锁定机制来绕过将队列转储到数据库并创建新实例.我会编写一个控制台应用程序,其中有多个线程可以访问此队列来测试它.


Vin*_*Y S 5

这是使用MSMQ的一个非常好的场景。对于每个请求,只需将项目发布到 MSMQ 队列。在同一个 web 应用程序或任何其他应用程序中,只需从队列中读取多个项目并将其发布到 solr。无论您的应用程序崩溃还是被回收,MSMQ 都会安全地保存您的数据,以便您稍后检索。

MSMQ 健壮、可靠且可扩展。它非常适合您的问题。