增加Servicestack并发进程

时间:2018-03-05 08:30:08

标签: servicestack

我有以下服务:

public class ServerApp : AppHostHttpListenerPoolBase
{
    public ServerApp() : base("Server", 500,
            typeof(TestService).Assembly)
        {

        }

        public override void Configure(Container container)
        {
            ThreadsPerProcessor = 50;
        }
    }

    public class TestService : Service
    {
        private readonly Logger _logger = LogManager.GetCurrentClassLogger();

        public object Any(Hello hello)
        {
            _logger.Info("Received: " + hello.Name);
            var waitingMinutes = new Random().Next(1, 10);

            Thread.Sleep(TimeSpan.FromMinutes(waitingMinutes));

            _logger.Info("Response: " + hello.Name);
            return new GoodBye(){Message = "Bye Bye " + hello.Name};
        }
    }
}

我有一个简单的测试项目来将并行请求推送到服务(并且推送一切正常),但Service一次只处理2个请求。处理完请求后,应处理下一个请求。

如何增加并发流程?

1 个答案:

答案 0 :(得分:0)

ServiceStack的AppHostHttpListenerPoolBase通过在新的ThreadPool线程上执行服务来同时执行Service。

为了证明这一点,我创建了一个独立的示例,该示例执行50个并发请求,这些请求在30-60秒之间休眠,根据ConcurrencyTest.cs调用此服务的示例调用独立测试:

public class SleepTest : IReturn<SleepTestResponse>
{
    public string Name { get; set; }
    public int WaitingSecs { get; set; }
}

public class SleepTestResponse
{
    public string Message { get; set; }
    public ResponseStatus ResponseStatus { get; set; }
}

public class TestConcurrencyService : Service
{
    public object Any(SleepTest request)
    {
        var sw = Stopwatch.StartNew();

        Thread.Sleep(TimeSpan.FromSeconds(request.WaitingSecs));

        return new SleepTestResponse
        {
            Message = $"{request.Name} took {sw.Elapsed.TotalSeconds} secs",
        };
    }
}

使用此客户端负载测试执行,在30-60秒之间执行50个并发请求:

var rand = new Random();
var client = new JsonHttpClient(Config.AbsoluteBaseUri);
client.GetHttpClient().Timeout = TimeSpan.FromMinutes(5);
long responsesReceived = 0;
long totalSecondsWaited = 0;
var sw = Stopwatch.StartNew();
const int ConcurrentRequests = 50;

ConcurrentRequests.Times(i =>
{
    Interlocked.Increment(ref responsesReceived);
    ThreadPool.QueueUserWorkItem(async _ => {
        var request = new SleepTest {
            Name = $"Request {i+1}",
            WaitingSecs = rand.Next(30, 60),
        };
        Interlocked.Add(ref totalSecondsWaited, request.WaitingSecs);

        log.Info($"[{DateTime.Now.TimeOfDay}] Sending {request.Name} to sleep for {request.WaitingSecs} seconds...");

        try
        {
            var response = await client.GetAsync(request);
            log.Info($"[{DateTime.Now.TimeOfDay}] Received {request.Name}: {response.Message}");
        }
        catch (Exception ex)
        {
            log.Error($"[{DateTime.Now.TimeOfDay}] Error Response: {ex.UnwrapIfSingleException().Message}", ex);
        }
        finally
        {
            Interlocked.Decrement(ref responsesReceived);
        }
    });
});

等待所有线程完成:

while (Interlocked.Read(ref responsesReceived) > 0)
{
    Thread.Sleep(10);
}

log.Info($"Took {sw.Elapsed.TotalSeconds} to execute {ConcurrentRequests} Concurrent Requests waiting a total of {totalSecondsWaited} seconds.");

结果是:

  

INFO:执行246.4556327执行50个并发请求,总共等待2228秒。

,如果请求没有同时执行,那么就会少得多。

显示请求的full log for all requests执行时间略长于请求服务器等待的时间。

您指出的2并发限制表明它是每个域的http客户端连接限制。您应该确保使用的负载测试工具没有wrkapacahe bench这些限制。

使用.NET Core获得最佳性能

请注意,如果您想要自助托管ServiceStack服务的最大吞吐量,我们建议running ServiceStack on .NET Core,最好是在.NET Core运行时,但如果需要,您还可以运行ServiceStack ASP.NET Core on the .NET Framework