一个合理的生产环境的 Web 应用程序应该是什么样子的

好的工具的产生使开发与部署变得十分容易,做为一个曾经的云服务从业人员,鼓励你们拥抱云服务。拥抱这些现成的技术栈。php

这是我在 stephenmann.io 上看到的一篇文章,对于 Web 应用程序架构演进的过程讲解的十分通俗易懂,因此就把它翻译了出来。数据库

原载:stephenmann.io缓存

译者:展小白安全

一个产品的规划可能会是迎合最广泛的需求,可是不少状况客户但愿解决具体的问题,这些问题可能将程序变得无限复杂,就必须提出有效的解决方案。bash

在过去的经验教训中,一些工程师倾向于深刻了解各项技术,足以解决任何问题。对于有着良好沟通的团队,这是很是好的。这些综合的知识有效的填补了团队我的的薄弱点。但对于行业或者经验不足的工程师团队,这些几乎是不可能的。服务器

若是你是在一个薄弱的技术团队,而后从头开始构建和部署整个 Web 应用程序,你可能很快意识到要深刻了解每项技术,是很难的一件事情。网络

业界其实已经提供了不少旨在解决这些问题的方案:Web 托管服务(Beanstalk,AppEngine 等),容器管理服务(Kubernetes, ECS 等)以及其它不少解决方案。一旦你启动并运行它们,即可以很好的正常进行工做,这种解决方案很是好,由于它规避了启动和运行 Web 程序过程当中大量复杂的操做,并且最终目的是为了使程序正常工做。架构

这里可能须要下功夫的是,在你决定用哪一种方案时,你须要更多的了解这些解决方案。负载均衡

在这篇文章中,将介绍一个不靠谱的系统到具备合理可靠性的系统的过程。这里不会介绍每一部分的具体细节,而是经过演进的过程,让你拥有在什么时候应该采用哪些决策的良好背景。工具

入门

最基本的你须要购买一台服务器,好比能够从亚马逊购买中配的服务器。

你知道你的程序须要用户登陆,你须要存储用户信息。所以你须要一个数据库。因为预算有限,直接在你的服务器上进行建立。最终获得的架构以下:

这应该足够了,事实上,使用这个架构,能够保障你的程序运行很长时间而没有瓶颈。此时,你可能天天只须要处理 10 次访问请求。其实一个最低配的服务器已经足够了,可是你的公司可能对业务持增加态度,因此选择了中配的服务器。

如今,你将有价值的业务数据存储在实例中的数据库中,若是服务器发生故障,或者实例被删除,极可能致使数据丢失,这是很可怕的。你应该确保数据备份到外部存储。好比:S3 服务。因此让咱们设置它。你应该经过每隔一段时间恢复一次备份的方式来确保它正常运行。

你的架构应该以下所示:

你已经提升了数据库的可靠性,那么你决定经过对服务器进行负载测试来检验是否能够应对大规模的流量访问。一切彷佛进展顺利,直到 500 错误出现,继而是 404,因此你要排查是什么缘由形成的。

但实际上,你并不知道是什么缘由致使的,由于你把日志写到了控制台,并无写入到日志文件中。你看到该进程并无运行,所以你假设是这个缘由致使了 404。

你能够经过建立 systemd 运行 Web 服务器服务来解决自动启动的问题,并解决你的日志记录问题。而后再进行新一轮的负载测试,以确保解决了全部的问题。

再一次,你看到了 500 错误,庆幸的是没有 404,你检查日志看是哪里出错了。你发现数据库的链接池已经饱和,该链接池设置了 10 个链接的限制。你更新了限制,重启数据库,而后再次运行负载测试。一切顺利。因此你决定对你的网站进行推广。

发布日

哇!你的服务很受欢迎,在 30 分钟内就得到了 5000 次的点击,你看到有评论进来。他们怎么说?

我访问 404 了,因而我检查我存储的地址是否正确,居然换地址了,若是有人须要,这是新的连接:……

……

什么也没有显示,也许是由于我禁用了 JavaScript,可是,谁会须要 2MB 那么大的 JS 文件 ……

……

大家的主页须要 4s 才能加载,并且访问到的是离我很远的一个地区的地址,另外,为何要加载 2MB 的 JS 文件?

因而你拼命的进行了优化,你在服务器经过 Nginx 设置了跳转你应用程序的反向代理,你将静态文件进行了剥离,上传到了 S3,这是颇有效的,你能够经过 CDN 帮助加速你网站在不一样地区的访问。

如今,你已经解决了当前的问题,那么你能够经过访问服务器查看日志。你发现 SSH 链接很是慢,通过一番检查,你发现你的日志文件已经耗尽了你的磁盘空间,这会使你的进程崩溃并阻止它再次启动。你建立更大的磁盘存储日志,而且设置 logrotate 防止日志文件再次变得如此巨大。

性能问题

几个月过去了,你的用户数持续增加,你的网站开始变得很慢。你在监控中注意到,这种状况彷佛只发生在午夜到中午之间。因为变慢开始和结束的时间比较固定,你猜想应该是服务器上的定时任务形成的。你检查 crontab 意识到你在午夜安排了备份任务。果真,你的备份过程须要持续 12 个小时,而且致使数据库超载,致使了站点访问明显拖慢。

你以为应该在从库进行数据库的备份,可是你记得,你并无建立从库,因此你须要建立一个。在同一台服务器运行从库没有太大的意义,所以,你决定对服务器进行扩展,建立了两个新的服务器:一个用于 master 数据库,另外一个用于 slave 数据库。你将备份改成依据从库运行。

发展团队

一切都很平稳,运行了一段时间。几个月过去了。你扩充了开发团队,其中一位新的开发人员为了检查一个错误,致使了生产服务器的故障。客户把错误归咎到了你没有对生产测试环境进行区分。你以为说的有道理,你是个虚心学习而且有追求的人,你把此次故障看作是一次学习的机会。

如今是到了构建规范的开发部署流程的时候了:分期开发,测试,而后部署。幸运的是,一开始你创建了良好的基础架构,所以这变得很容易。由于你从第一天起,就良好的践行了持续交付,你能够轻松的在一个新的分支进行构建。

业务部门但愿推出 2.0 版本,但并无具体的业务需求,可是你仍是去作了。你以为是时候进行一次性能的改造。你的 Web 服务器的运行如今已经接近峰值的利用率,所以你决定对流量进行负载均衡。而亚马逊 ELB 使你很容易上手。与此同时你以为你的架构图应该是这样的:

另外还能够经过 Redis 等作一些缓存策略。相信你的优化可以承担更大的负载,因此你再次对你的网站进行了大力推广,不出所料,流量飙升,但运行很稳定。

一切看起来都那么好,直到你须要去检查日志。这花费了你一个小时,由于要检查 12 台服务器(每一个环境有 4 台服务器)。那是一件麻烦事,幸运的是,你如今已经赚了足够的钱能够实现 ELK 堆栈(ElasticSearch,LogStash,Kibana)。新的架构图:

如今,你能够再次阅读你的日志了,你发现了一些奇怪的状况。里面充满了:

GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
复制代码

你并无运行 PHP 或 WordPress,因此很使人担心。你在数据库服务器上注意到相似的可疑日志,你想怎么把他们暴露在公网上了。因此是时候进行公网和本地访问的隔离了。

再次,你检查了日志,虽然仍然可能被黑客攻击,可是仅限于负载均衡服务器上的 80 端口,而你的应用服务器,数据服务器和 ELK 堆栈再也不暴露在公网上。你能够轻松许多了。

虽然对日志进行了集中式的记录管理,可是还不得不手动检查日志。这时候使用服务器提供商的监控,设置磁盘、CPU 和 网络报警,以便在达到 80% 的使用率时经过邮件等途径通知你,是个不错的选择。

一路顺风

开玩笑,没有哪一个程序的运行是一路顺风的,总有事情会发生,幸运的是,你有不少工具能够处理这些问题。

如今,咱们已经构建了一个可扩展的 Web 应用程序,包括备份,回滚,集中式日志记录管理,监控和警报。能够告一段落了,由于下面的改变每每取决于特定应用的需求。

业界提供了许多托管选项,能够为你处理大部份内容。你能够依靠 Beanstalk,AppEngine,GKE,ECS 等而不是本身构建全部这些服务。大多数这些服务都会自动设置合理的权限,负载均衡,子网等。能够确保你的站点能够长时间运行。

了解这些平台提供的功能以及何时使用它们是很是有用的,这样,你能够根据你的须要轻松选择平台。一旦你在相关平台上运行了你的程序,你应该了解这些工具的工做原理,这是很重要的,有助于在遇到问题时,快速解决问题。

结尾

这篇文章省略了不少细节,不包括如何自动建立基础架构,如何配置服务器。不包括任何开发环境的建立,如何实践持续交付,如何执行部署和回滚。不包括网络安全,私密共享或最小权限原则。它不涵盖不可变基础架构,无状态服务以及迁移的重要性。其实每一个主题均可以独立开辟一篇文章。

本文的主要目的是提供一个合理的生产环境的 Web 应用程序应该是什么样子的。

感谢你的阅读!


关注公众号「展白说」,获取更多有价值的信息。

相关文章
相关标签/搜索