一个合理的生产环境的 Web 应用程序应该是什么样子的
好的工具的产生使开发与部署变得十分容易,作为一个曾经的云服务从业人员,鼓励大家拥抱云服务。拥抱这些现成的技术栈。
这是我在 stephenmann.io 上看到的一篇文章,对于 Web 应用程序架构演进的过程讲解的十分通俗易懂,所以就把它翻译了出来。
原载:stephenmann.io
译者:展小白
一个产品的规划可能会是迎合最普遍的需求,但是很多情况客户希望解决具体的问题,这些问题可能将程序变得无限复杂,就必须提出有效的解决方案。
在过去的经验教训中,一些工程师倾向于深入了解各项技术,足以解决任何问题。对于有着良好沟通的团队,这是非常好的。这些综合的知识有效的填补了团队个人的薄弱点。但对于行业或者经验不足的工程师团队,这些几乎是不可能的。
如果你是在一个薄弱的技术团队,然后从头开始构建和部署整个 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 应用程序应该是什么样子的。
感谢你的阅读!
关注公众号「展白说」,获取更多有价值的信息。
一个合理的生产环境的 Web 应用程序应该是什么样子的相关推荐
- securecrt连接mysql_使用SecureCRTP 连接生产环境的web服务器和数据库服务器
一.使用SecureCRTP 连接生产环境的web服务器 首先,需要知道以下参数信息: 1.web服务器的ip地址 2.服务器的端口号 3.会话连接的用户名和密码 4.服务器的用户名 ...
- 一个奇怪的生产环境配置ldap服务引起的故障及解决过程分享
ldap服务已应用几年了.当初自己部署时 都很顺利的(都是脚本统一处理的). 服务器部署时都是统一模版直接推过去就好了. 如今,新增一批服务器要部署ldap 客户端统一认证,这次安排下属去搞,他部署完 ...
- vue 属性是变量_手把手教你如何在生产环境检查 Vue 应用程序
本已经过原作者 Damian Mullins 授权翻译. 在开发环境中,Vue devtools 是很有用. 但是,一旦部署到生产环境,它就不再可以访问我们所编写的代码. 那么发布到生产环境时,我们 ...
- 如何把手变成手控_手把手教您如何在生产环境直接web级设计图形报表
相信很多从事数据分析的兄弟姐妹,对于数据报表的设计,图形化的设计等等,都是停留在后台进行模板设计,设计好模板后,再上传到前台,发布进行显示,这也是目前绝大多数工具的模式.也难怪,因为目前国内数一数二的 ...
- 通俗易懂的生产环境Web应用架构介绍
前言 看见一篇非常通俗易懂且适合新手阅读的Web应用架构文章,我将其手工翻译了出来,分享给大家. 也可以去阅读英文原文,标题为,贴出链接: stephenmann.io/post/whats-- 英文 ...
- python实现第一个web_使用Python的Flask框架来搭建第一个Web应用程序
1.初始化在这章,你将学到Flask应用程序的不同部分.同时,你将编写和运行你的第一个Flask web应用程序. 所有的Flask应用程序都必须创建一个 应用程序实例 .使用web服务器网关接口协议 ...
- 上 k8s 生产环境的一些准备!
来源:公众号 | 运维开发故事(mygsdcsf) 在生产中运行应用程序可能很棘手.这篇文章提出了一个自以为是的清单,用于在 Kubernetes 上使用 Web 服务(即应用程序公开 HTTP AP ...
- 生产环境mysql安装规划及调优实践--mysql8.0.29为例
以前运维人员部署在生产环境的mysql又被扫描出安全漏洞,需要进行修补.这种事情本来应该是很简单的事儿,但如今执着于软件领域技术的人是越来越少,竟然没有人愿意去做去学,都想等着别人去处理,最终还是得老 ...
- 如何使用 Docker 部署一个基于 Play Framework 的 Scala Web 应用?
2019独角兽企业重金招聘Python工程师标准>>> 本文作者 Jacek Laskowski 拥有近20年的应用程序开发经验,现 CodiLime 的软件开发团队 Leader, ...
- 非易失性内存在阿里生产环境的首次应用:Tair NVM最佳实践总结
阿里妹导读:本文介绍了非易失性内存在阿里巴巴集团生产环境的首次应用:线上运行的情况:使用NVM遇到的问题和优化的过程:最后,总结性地给出了基于NVM构建缓存服务的设计要点,希望这些实践总结能对大家的工 ...
最新文章
- 【ES6】ES6编程规范 编程风格
- 支付宝和微信的支付流程图
- php获取页面的可视内容高度,网页制作技巧:获取页面可视区域的高度_css
- java的位置_Java中数据存放的位置
- Jconsole使用实例解说
- 今日头条的企业服务产品线
- 200以内的质数(python)
- Centos使用chrony做时间同步
- 物联网毕设(基于STM32的蓝牙检测心率+步数+手机APP)
- 快速搭建仓储管理系统
- 《Real-Time Rendering》第四版学习笔记——Chapter 9 Physically Based Shading(二)
- 物联网平台搭建的全过程介绍(三)阿里云物联网设备接入订阅发布之Android studio例程
- JVM面试题整理-Java内存区域与内存溢出异常、垃圾收集器和内存分配策略
- 美国服务器如何抵御黑客攻击
- Hcash:见证量子计算和后量子密码的“矛盾较量”
- DCIC2021数字中国创新大赛大数据赛道-城市管理大数据专题学习
- 织梦wap.php绑定域名,dedecms织梦配置手机wap站点,并绑定二级域名
- 深度学习之环境配置--配置d2lzh_pytorch包
- HBase RegionServer宕机恢复
- 相对定位和绝对定位的搭配使用
热门文章
- 更改远程桌面默认端口3389及删除远程桌面连接历史记录
- webbrowser只对浏览器外应用程序以及在_常用浏览器大盘点!
- mysql中grade字段降序排列_Mysql order by 多个字段排序
- 如何写出优质干净的代码,这6个技巧你不能错过
- PHP Error(不定时更新)
- [R语言绘图]气泡图symbols
- java map 容器_java容器-map的常用实现及原理
- 质量小的夸克之间,如何互换质量大的胶子
- O_RDONLY/O_NOATIME undeclared (first use in this function
- 不要安全要性能,禁用补丁提高CPU性能