ServiceStack注册Web服务性能下降
问题描述:
我们注意到服务堆栈Web服务中的一些性能瓶颈,特别是像(注册)Web服务这样的盒子。ServiceStack注册Web服务性能下降
我们跑了使用Visual Studio负载测试具有以下参数的负载测试:
- 1K并发用户。
- 持续1分钟。
- 测试迭代之间的5秒思考时间。
- 5秒采样率。
的结果是如此糟糕,他们实际上是阻止我们与客户去住:
19秒平均响应时间
环境规格有:
- 2在AWS Europe Region中使用c4.8xlarge EC2托管的Web前端(IIS)公开后面的实例(16GB-Ram & 8vCPU)包含负载平衡器。
- MySQL数据库在AWS RDS托管内运行(db.m4.4xlarge)EC2实例 (64GB内存,高网络流量,16个vCPU)
我们没有特殊的代码或特殊全局请求过滤器..只有默认配置..我们甚至尝试过连接池,但这并没有太大的帮助..
这种性能下降的原因是什么?感谢您的支持,因为我们处于客户对ServiceStack框架本身提出质疑的地步,即使我们热爱它的每一个方面,我们也开始怀疑这一点。
答
我们回到了最底层。经过几个小时的调试和分析注册/登录Web服务后,我们发现注册代码执行对db的重复查询(比如检查现有用户验证逻辑等)。甚至被Mini Profiler强调,但这仍然不是导致只有1K个并发用户触及服务的原因,与我们运行的环境规格相比,这是非常低的数量。
的原因是由于下面的代码获取调用两个注册/登录:
private static TUserAuth GetUserAuthByUserName(IDbConnection db, string userNameOrEmail)
{
var isEmail = userNameOrEmail.Contains("@");
var userAuth = isEmail
? db.Select<TUserAuth>(q => q.Email.ToLower() == userNameOrEmail.ToLower()).FirstOrDefault()
: db.Select<TUserAuth>(q => q.UserName.ToLower() == userNameOrEmail.ToLower()).FirstOrDefault();
return userAuth;
}
到.ToLower()
的调用被记到SQL较低函数获取调用而当这是同时运行在一个表,你有成千上万的行,这将导致数据库服务器的巨大CPU峰值导致所有的瓶颈。
该修复非常简单,只需在数据库中添加专用的降级用户名和电子邮件字段,更新UserAuth POCO以反映这些字段,最后将索引添加到新的数据库列并调整ormlite使用新列的条件。
如果没有一个可以看到的实际示例,您可能会遇到一些性能较差的代码,不正确的API使用情况或您的环境中存在的其他问题,这些信息无济于事,将带有基准的独立应用程序放在一起,问题,我们将看看, – mythz
嗨@mythz ..我们的自定义Web服务并没有受到影响,并提供了0.6 - 1.0秒的平均响应时间跨越1k并发调用..只有默认的'注册'和'身份验证'网站服务正在遭受..这些方法是否有任何基准?在编写它们的实现时考虑了性能?我们怀疑Fluent Validator部件,但这只是在黑暗中拍摄..你可以帮忙吗? –
@MohammadZekrallah注册服务需要执行验证并在注册的Auth提供程序中设置一个新用户+调用多个会话/身份验证回调。您可以检查[RegisterService](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Auth/RegisterService.cs)的impl以查看它的作用,例如,如果您未指定' ?AutoLogin = true'会更快。如果你担心perf,你应该考虑自定义RegisterService将用户直接插入UserAuth表格,否则不要在黑暗中拍摄,请剖析应用程序以查看瓶颈的位置 – mythz