本文概述
- Lojinha和戏剧!构架
- 不变性和缓存
- 内存消耗
- 异步支持
- 总结
【终极优化!数千个并发请求】无论如何, 我要争辩的是, 如果你使用适当的工具集并遵循良好的开发实践, 那么忽略可伸缩性并没有听起来那么糟糕。
如果使用适当的工具, 则忽略可伸缩性并不像听起来那样糟糕。
Lojinha和戏剧!构架 不久前, 我启动了一个名为Lojinha的项目(将其翻译成葡萄牙语的” 小商店” ), 我试图建立一个拍卖场。 (顺便说一下, 这个项目是开源的)。我的动机如下:
- 我真的很想卖掉一些我不再使用的旧东西。
- 我不喜欢传统的拍卖网站, 尤其是我们在巴西的拍卖网站。
- 我想和Play一起” 玩” !框架2(双关语意)。
上面的段落至少应该使一件事明确:创建Lojinha时, 我根本不必担心性能。
这正是我的观点:使用正确的工具具有强大的力量-可以使你保持正确轨道的工具, 可以鼓励你按照自己的构想遵循最佳开发实践的工具。
在这种情况下, 这些工具就是Play!框架和Scala语言, Akka进行了一些” 访客外观” 。
让我告诉你我的意思。
不变性和缓存 人们普遍认为, 最小化可变性是一种好习惯。简而言之, 可变性使推理代码变得更加困难, 尤其是当你尝试引入任何并行性或并发性时。
表演! Scala框架使你可以在大部分时间使用不变性, Scala语言本身也是如此。例如, 控制器生成的结果是不可变的。有时你可能会认为这种不变性” 令人讨厌” 或” 令人讨厌” , 但是这些” 良好实践” 之所以是” 良好” , 是有原因的。
在这种情况下, 当我最终决定进行一些性能测试时, 控制器的不变性绝对至关重要:我发现了一个瓶颈, 并且要解决它, 只需缓存此不变的响应即可。
通过缓存, 我的意思是保存响应对象并为所有新客户端按原样提供相同的实例。这使服务器不必重新重新计算结果。如果此结果是可变的, 则不可能向多个客户提供相同的响应。
缺点:在很短的时间内(缓存过期时间), 客户端可以接收过时的信息。仅在你绝对需要客户端访问最新数据且无延迟的情况下, 这才是问题。
作为参考, 以下是Scala代码, 用于在不缓存的情况下加载包含产品列表的起始页:
def index = Action { implicit request =>
Ok(html.index(body = html.body(Items.itemsHigherBids(itemDAO.all(false))), menu = mainMenu))
}
现在, 添加缓存:
def index = Cached("index", 5) {
Action { implicit request =>
Ok(html.index(body = html.body(Items.itemsHigherBids(itemDAO.all(false))), menu =mainMenu))
}
}
很简单, 不是吗?此处, “ 索引” 是要在缓存系统中使用的密钥, 而5是到期时间(以秒为单位)。
缓存后, 吞吐量高达每秒800个请求。对于不到两行代码, 这是超过4倍的改进。
为了测试此更改的效果, 我在本地运行了一些JMeter测试(包括在GitHub存储库中)。在添加缓存之前, 我实现了大约每秒180个请求的吞吐量。缓存后, 吞吐量高达每秒800个请求。对于不到两行代码, 这比以前提高了4倍。
文章图片
内存消耗 合适的Scala工具可以带来很大变化的另一个领域是内存消耗。在这里, 再次播放!将你推向正确(可扩展)的方向。在Java世界中, 对于使用Servlet API编写的” 普通” Web应用程序(即, 几乎所有的Java或Scala框架), 由于该API提供了易于操作的功能, 因此很容易在用户会话中放入大量垃圾允许你这样做的调用方法:
session.setAttribute("attrName", attrValue);
由于将信息添加到用户会话非常容易, 因此经常被滥用。结果, 由于可能没有充分原因而占用过多内存的风险同样很高。
随着玩!框架, 这不是一个选择-框架根本没有服务器端会话空间。表演!框架用户会话保存在浏览器cookie中, 你必须忍受它。这意味着会话空间的大小和类型受到限制:你只能存储字符串。如果你需要存储对象, 则必须使用我们之前讨论的缓存机制。例如, 你可能想在会话中存储当前用户的电子邮件地址或用户名, 但是如果需要存储域模型中的整个用户对象, 则必须使用缓存。
玩!使你处于正确的轨道上, 迫使你仔细考虑内存使用情况, 这将产生实际上适合集群使用的首过代码。
再次, 这乍看起来似乎很痛苦, 但实际上, 玩!使你处于正确的轨道上, 迫使你仔细考虑内存的使用情况, 这将产生实际上适合集群使用的首过代码-尤其是因为无需在整个集群中传播服务器端会话无限地容易。
异步支持 此剧的下一个!框架审查, 我们将研究如何玩!在异步(hronous)支持中也很出色。除了其本机功能, Play!允许你嵌入Akka, 这是用于异步处理的强大工具。
Altough Lojinha尚未充分利用Akka, 它与Play的简单集成!使其非常容易:
- 安排异步电子邮件服务。
- 同时处理各种产品的报价。
要异步发送电子邮件, 我首先创建适当的消息和参与者。然后, 我需要做的是:
EMail.actor ! BidToppedMessage(item.name, itemUrl, bidderEmail)
电子邮件发送逻辑是在参与者内部实现的, 消息告诉参与者我们想要发送哪封电子邮件。这是一劳永逸方案, 这意味着上面的行发送请求, 然后继续执行此后的所有操作(即, 它不会阻塞)。
有关Play!原生Async的更多信息, 请参阅官方文档。
总结 简介:我迅速开发了一个小型应用程序Lojinha, 能够很好地进行扩展和扩展。当我遇到问题或发现瓶颈时, 由于我使用的工具(Play!, Scala, Akka等)而使修复迅速且容易, 并且功劳颇丰, 这促使我遵循有关效率和效率的最佳实践。可扩展性。无需担心性能, 我便可以扩展到数千个并发请求。
在开发下一个应用程序时, 请仔细考虑你的工具。
推荐阅读
- 我如何通过Python视频流使Porn效率提高20倍
- Trie数据结构(被忽视的宝石)
- 深度学习教程(从感知器到深度网络)
- 测试|django管理后台--models 模型层
- 创建在类路径资源[applicationcontext]中定义名为“工厂”的bean时出错。:在设置bean属性“dataSource”时,无法解析对bean“dataSource”的引用;嵌套异常是
- parsing XML document from class path resource [applicationtext.xml]; nested exception is java.io.Fil
- android 创建view间关系
- 如何将Azure DevOps中的代码发布到Azure App Service中
- android绘制流程