通俗易懂的生产环境Web应用架构介绍

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 在我职业生涯的早期,我曾在一家工作内容为构建Web内容管理系统的公司工作。他们的产品帮助营销部门可以自己管理网站的内容,而不是依靠开发人员来管理网站。该产品帮助他们的客户降低了运营成本,并帮助我学习如何构建Web应用程序。虽然产品本身有一个非常普通的用途,但其客户缺倾向于使用它来解决非常特殊的问题。这些问题以各种眼花缭乱的方式将对产品的要求推到了极限,并且要求该产品必须提供解决方案。在这种环境中工作了十多年,让我对生产环境下的Web应用程序有了全面的了解,其中一些我们将在本文中讨论。


正文



在我职业生涯的早期,我曾在一家工作内容为构建Web内容管理系统的公司工作。他们的产品帮助营销部门可以自己管理网站的内容,而不是依靠开发人员来管理网站。该产品帮助他们的客户降低了运营成本,并帮助我学习如何构建Web应用程序。

虽然产品本身有一个非常普通的用途,但其客户缺倾向于使用它来解决非常特殊的问题。这些问题以各种眼花缭乱的方式将对产品的要求推到了极限,并且要求该产品必须提供解决方案。在这种环境中工作了十多年,让我对生产环境下的Web应用程序有了全面的了解,其中一些我们将在本文中讨论。

这些年我学到的经验之一是,对于开发Web应用程序,个别工程师倾向于非常深入地了解他们感兴趣的东西,对于不感兴趣但必要的组件缺只学习皮毛,这其实是非常“危险”。这对于具有良好沟通的工程师团队来说非常有效,因为这些组合知识将重叠以填补任何个人的局限。然而,这对于独立工程师或者在这方面经验不足的团队,就显得“危险”。

如果你是在这样的环境中开始,然后开始从头开始构建和部署整个Web应用程序,你可能很快就会理解我说的“危险”的意思。

业界已经提供了许多旨在解决这个问题的解决方案:托管Web应用程序(Beanstalk,AppEngine等),托管容器管理(Kubernetes,ECS等等)以及许多其他解决方案。一旦你启动并运行它们,它们就可以正常工作,我认为它们在解决问题方面做得很好。它们隐藏了启动和运行Web应用程序所需的大量复杂性,并且它们倾向于“刚好能工作”。

不幸的是,当它不是“刚好能工作”,或者当你需要完成一些特殊的业务时,你可能会发现自己会希望更多地了解那个不祥的黑盒子。

在这篇文章中,我将采用一个不可靠的系统,并将其演变为具有合理可靠性的系统。沿途的每一步都将使用现实中会遇到的问题作为进入下一步的目的。我没有讨论一个最终设计的每一部分,而是使用这种增量方法有助于读者了解自己的需求,以及自己目前处于哪一步。我们将从头开始构建托管Web应用程序托管服务所提供的基本结构,并希望能够详细介绍每个部分存在的意义。


让我们开始



让我们假设你有一年500美元的托管预算,因此你决定从Amazon AWS租用一台t2.medium服务器。 在撰写本文时,每年仅花费约400美元。

你事先知道你需要设计登录系统,并且你需要存储用户信息,因此你需要一个数据库。 由于预算有限,让我们在我们唯一的服务器上托管它。 最终得到的结构如下:

看起来足够了,哈哈。 事实上,它可能会稳定工作很长一段时间。因为你网站的体量还很小。 此时,你可能每天最多只能处理10次访问。 一个小实例可能已经足够了,但由于你对公司的发展持乐观态度,因此你使用t2.medium实例做出了不错的选择。

你的业务价值存储在该数据库中,因此非常重要。你应该确保就算该服务器发生故障,不会导致你的数据丢失。所以最好去确保下你没有将数据库内容存储在临时磁盘上,不然的话,如果实例被删除,你将丢失所有数据。这会非常可怕。

此外,你还应确保将备份转到外部存储。AWS S3似乎是一个放置这些的好地方,它相对便宜,所以让我们设置它。而且你肯定应该通过每隔一段时间做一次数据备份来测试它是否正常工作。

你的结构现在应该如下所示:

在这时,你已经提高了数据库的可靠性,接下来,你想通过对服务器运行负载测试来为可能到来的大规模的黑客新闻流量(译者注:原文为Hacker News,一个信息源资讯网站)峰值做好准备。一切似乎进展顺利,直到500错误开始出现,然后是404流,所以你要调查弄清楚发生了什么。

事实证明,你没有任何线索来得知网站崩溃到底是因为什么原因,因为你把日志写到控制台,而没有将控制台输出传递到日志文件中。你还看到该进程未运行,因此你默认了这就是你获得404的原因。你脸上的紧张情绪稍稍缓解了点,并且庆幸还好自己没有直接将你的网站登记到Hacker News上。

你创建了一个运行Web服务器的systemd服务来保证你的服务会在崩溃后自动重启。此外,你最终解决了日志记录问题。然后你运行另一个负载测试,以确保你已经解决了所有问题。

你又看见了500错误(幸好没有404),你检查日志以查看出错的地方。你发现数据库连接池已经饱和,该连接池设置为10。你更新了参数,重新启动数据库,然后再次运行负载测试。一切顺利,所以你决定在Hacker News上推广你的网站。


发布日



我得到了404,所以我必须检查页面的存档版本。如果有人需要,这是链接:...

妈的空白页啊!我禁用了Javascript,为什么网站作者会觉得我会取读取你的2 MB Javascript文件 ...

你的主页需要4秒钟才能加载。我居住在澳大利亚,Traceroute显示服务器托管在德克萨斯州的某个地方。另外,为什么你的网页需要2 MB的Javascript?

在混乱中,你被迫在服务器上设置了Nginx作为应用程序的反向代理,并将其配置为服务器静态404页面。 还将静态文件推送到AWS S3,这样做是为了让CloudFront CDN能够起作用,来减少澳大利亚用户的访问时间。

这时候你已经解决了当前的问题,这之后,你可以随时访问服务器并查看日志。 但你慢慢发现,你的SSH连接非常迟钝。经过检查,你发现你的日志文件已经完全耗尽了你的磁盘空间,这会使你的进程崩溃并阻止它再次启动。你创建一个更大的磁盘并在其上挂载日志。 你还设置了滚动日志来防止日志文件再次变得非常巨大。


性能问题



几个月过去了。你的用户群在慢慢增长。你的网站开始变慢。你在CloudWatch监控中注意到,这似乎只发生在中午和晚上。由于变慢的开始和结束时间每天都相同,你猜测这是由于服务器上的计划任务造成的。你检查了你的crontab,看见了你自己在午夜安排了一份工作:备份数据库。果然,你的备份需要12个小时,并且备份程序使数据库过载了,导致了网站访问极慢。

发现了这个问题后,你决定新建一个从数据库,并在从数据库上运行备份。 所以你创建了一个从数据库。在同一台服务器上运行从数据库没有多大意义,你决定,是时候扩展了!你创建两个新服务器:一个用于master数据库,另一个用于slave数据库。 你将备份更改为在从属数据库中定时运行。


组建团队

一切都运行平稳了一段时间,几个月过去了,你聘请了一个更大的开发团队,其中一位新开发人员发现了一个bug,这个bug会导致生产服务器的崩溃。此位程序员觉得是由于开发环境与生产不同导致的。他说的话有些道理,你听起来觉得很对,所以你决定把这个问题解决。

你构建了更多不同的环境:Staging,QA和生产环境。幸运的是,你从写这个项目第一天开始就搭建了自动基础架构,因此环境的增加很容易。并且从第一天起,你就使用了良好的持续交付机制,因此你可以轻松地从管道构建新分支。

在这之后,营销部门希望推出v2.0版本。你不确定v2.0版本是什么,但无论如何你还是决定做了。是时候准备另一次流量的飙升了。在Web服务器上运行的服务已经接近服务器的峰值利用率,因此你决定开始对流量进行负载平衡。亚马逊ELB能够让你轻松上手。在这个时候,你还发现博客文章中的分层图表应该从上到下而不是从左到右显示图层。:)

你再次将你的网站发布到Hacker News。 它撑住了巨大的流量,取得了极大的成功!

这一切似乎都很棒,直到有一天,你去检查了你的日志。 这时你才发现,检查一次日志,需要一个小时,因为要检查12台服务器(每个环境中有4台服务器),这显得很麻烦。幸运的是,你的公司现在已经赚了足够的钱来实现ELK堆栈(ElasticSearch,LogStash,Kibana),你构建了一个ELK环境并将它用在了所有环境中。

这样一来,你可以轻松地查看日志了,你发现,有很多奇怪的东西混在了日志里。

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有关的服务,这非常令人担忧。 你注意到数据库服务器上也有类似的可疑日志,现在你很想问自己为什么将它们的端口暴露在了外网上,是时候区分公共和私人子网了。

OK,你又开始检查你的日志。黑客还是可以攻击你,但现在它们仅限于负载均衡器上的端口80,因为你的应用程序服务器,数据库服务器和ELK堆栈不再暴露在互联网上,这下你舒坦了。

尽管进行了集中式日志记录,但你还是不得不通过手动检查日志来发现中断。 你可以使用Amazon CloudWatch设置磁盘,CPU和网络警报,以便在达到80%容量时向你发送电子邮件。还能说什么,简直完美。


一帆风顺


开玩笑!没有一帆风顺的事情,总有事情会出错。幸运的是,你有很多工具可以更轻松地处理这些问题。

我们构建了一个可扩展的Web应用程序,包括备份,回滚,集中式日志记录,监控和警报。这是一个很好的总结时刻,因为这里的增长往往取决于特定应用的需求。

业界提供了许多托管选项,可以为你处理大部分内容。你可以依靠Beanstalk,AppEngine,GKE,ECS等,而不是自己构建所有这些服务。大多数这些服务都会自动设置合理的权限,负载均衡器,子网等。他们需要花费很多麻烦才能使应用程序快速启动并运行,这样可以确保你的站点长时间运行所需的可靠性。

无论如何,我认为了解这些平台提供的功能以及提供它们的原因是有用的。它可以根据你自己的需求更轻松地选择平台。一旦你在平台上运行了所有东西,你就已经弄清楚了这个工具的这些重要方面是如何工作的。当出现问题时,有助于了解你拥有解决问题的必要工具。


总结



这篇文章跳过了很多细节问题。它不包括如何自动创建基础结构,如何配置服务器或如何配置服务器。它不包括如何创建开发环境,如何设置连续交付管道,或如何执行部署或回滚。它不包括网络安全,秘密共享或最小特权原则。它不包括不可变基础架构或无状态服务器或迁移的重要性。这些主题中的每一个都需要自己的帖子。

本文的目的主要是提供一个合理的生产Web应用程序应该是什么样子的高级概述。 未来的帖子可以参考这个并扩展它。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1天前
|
SQL 缓存 搜索推荐
后端技术在现代Web开发中的应用与挑战
本文将深入探讨后端技术在现代Web开发中的重要性,涵盖从基础架构到性能优化的多个方面。通过分析当前主流后端技术的优缺点,并提供一些实用的解决方案和建议,帮助开发者更好地应对日常开发中的挑战。
10 1
|
6天前
|
存储 搜索推荐 数据库
MarkLogic在微服务架构中的应用:提供服务间通信和数据共享的机制
随着微服务架构的发展,服务间通信和数据共享成为关键挑战。本文介绍MarkLogic数据库在微服务架构中的应用,阐述其多模型支持、索引搜索、事务处理及高可用性等优势,以及如何利用MarkLogic实现数据共享、服务间通信、事件驱动架构和数据分析,提升系统的可伸缩性和可靠性。
16 5
|
6天前
|
机器学习/深度学习 测试技术 数据处理
KAN专家混合模型在高性能时间序列预测中的应用:RMoK模型架构探析与Python代码实验
Kolmogorov-Arnold网络(KAN)作为一种多层感知器(MLP)的替代方案,为深度学习领域带来新可能。尽管初期测试显示KAN在时间序列预测中的表现不佳,近期提出的可逆KAN混合模型(RMoK)显著提升了其性能。RMoK结合了Wav-KAN、JacobiKAN和TaylorKAN等多种专家层,通过门控网络动态选择最适合的专家层,从而灵活应对各种时间序列模式。实验结果显示,RMoK在多个数据集上表现出色,尤其是在长期预测任务中。未来研究将进一步探索RMoK在不同领域的应用潜力及其与其他先进技术的结合。
29 4
|
6天前
|
运维 Cloud Native Devops
云原生架构的崛起与实践云原生架构是一种通过容器化、微服务和DevOps等技术手段,帮助应用系统实现敏捷部署、弹性扩展和高效运维的技术理念。本文将探讨云原生的概念、核心技术以及其在企业中的应用实践,揭示云原生如何成为现代软件开发和运营的主流方式。##
云原生架构是现代IT领域的一场革命,它依托于容器化、微服务和DevOps等核心技术,旨在解决传统架构在应对复杂业务需求时的不足。通过采用云原生方法,企业可以实现敏捷部署、弹性扩展和高效运维,从而大幅提升开发效率和系统可靠性。本文详细阐述了云原生的核心概念、主要技术和实际应用案例,并探讨了企业在实施云原生过程中的挑战与解决方案。无论是正在转型的传统企业,还是寻求创新的互联网企业,云原生都提供了一条实现高效能、高灵活性和高可靠性的技术路径。 ##
16 3
|
6天前
|
人工智能 关系型数据库 数据安全/隐私保护
后端技术在现代Web开发中的应用与挑战
本文将深入探讨后端技术在现代Web开发中的重要性,通过分析其在数据处理、业务逻辑实现和安全性保障方面的应用,揭示后端技术的核心价值。同时,本文还将讨论当前后端开发面临的主要挑战,如高并发处理、数据安全、微服务架构的复杂性等,并给出相应的解决方案。无论是后端开发者还是对后端技术感兴趣的读者,都可以通过这篇文章获得启发和指导。
|
14天前
|
前端开发 安全 JavaScript
构建高效Web应用:前后端分离架构的实践
【9月更文挑战第4天】在数字时代,Web应用已成为企业与用户互动的主要平台。本文将介绍如何通过前后端分离的架构设计来构建高效的Web应用,探讨该架构的优势,并分享实现过程中的关键步骤和注意事项。文章旨在为开发者提供一种清晰、高效的开发模式,帮助其在快速变化的市场环境中保持竞争力。
|
14天前
|
传感器 Cloud Native 物联网
Micronaut在物联网中的应用探索:轻盈架构赋能万物互联新时代
【9月更文挑战第6天】Micronaut是一个现代、轻量级的Java框架,以其高效、易用及对云原生环境的支持,在物联网开发中展现出独特优势。它通过AOT编译技术优化应用,减少内存消耗,适合资源受限的设备。Micronaut支持反应式编程和HTTP/2,提升并发处理能力和网络传输效率。本文通过一个温度传感器数据收集服务的例子,展示了如何利用Micronaut简化物联网应用开发,使其成为该领域的理想选择。
31 3
|
18天前
|
中间件 编译器 数据处理
在web开发中应用管道过滤器
【9月更文挑战第1天】本文介绍管道-过滤器架构将数据处理流程分解为一系列独立组件,通过管道连接,适用于数据流处理如图像处理、编译器设计等。通过具体实例说明了Gin如何有效支持管道-过滤器风格的设计,构建高性能Web服务。
32 9
|
16天前
|
设计模式 存储 SQL
在web框架中实现解释器架构
【9月更文挑战第3天】解释器架构风格基于解释器设计模式,通过将问题建模为特定语言或指令集并逐条解析执行。然而,解释器风格也可能面临性能问题和扩展性限制。
17 1
|
2天前
|
缓存 负载均衡 数据管理
深入探索微服务架构的核心要素与实践策略在当今软件开发领域,微服务架构以其独特的优势和灵活性,已成为众多企业和开发者的首选。本文将深入探讨微服务架构的核心要素,包括服务拆分、通信机制、数据管理等,并结合实际案例分析其在不同场景下的应用策略,旨在为读者提供一套全面、深入的微服务架构实践指南。**
**微服务架构作为软件开发领域的热门话题,正引领着一场技术革新。本文从微服务架构的核心要素出发,详细阐述了服务拆分的原则与方法、通信机制的选择与优化、数据管理的策略与挑战等内容。同时,结合具体案例,分析了微服务架构在不同场景下的应用策略,为读者提供了实用的指导和建议。