1.1 关于HTTP的概述
HTTP是超文本传输协议,工作在OSI七层模型中的应用层,是基于TCP/IP协议的应用层协议,通过C/S模式实现(客户端-服务端),早期计算机系统没有现代的计算机系统繁杂,只提供简单的人机交互,后来逐渐形成了图片、音频、视频等。HTTP协议包含但不限于WWW服务,还有FTP、SMTP、NNTP等。构成HTTP第一要素是明确的边界,即规定数据格式、编码和信号的等级(高低电平)。
1.2 HTTP 协议的关键组件
-
请求/响应模型:HTTP 遵循客户端-服务器模型,客户端向服务器发送请求,服务器用请求的数据或适当的状态代码进行响应。
-
统一资源标识符 (URI):URI 用于标识和定位 Web 上的资源。 它们包括 URL(统一资源定位符)和 URN(统一资源名称)。
-
方法:HTTP 定义了几种方法,这些方法指示要对已识别资源执行的所需操作。 常用方法包括 GET(获取资源)、POST(提交待处理数据)、PUT(更新资源)、DELETE(删除资源)等。
-
标头:HTTP 标头包含有关请求或响应的附加信息。 它们提供内容类型、内容长度、缓存指令、身份验证凭据等详细信息。
-
状态码:HTTP状态码是服务器发送的三位数字,表示请求的状态。 它们提供有关请求是否成功、重定向、遇到错误或其他相关条件的信息。
-
Cookies:Cookies 是由服务器发送并存储在客户端浏览器上的小块数据。 它们用于维护会话状态并启用用户身份验证、个性化和跟踪等功能。
-
缓存:HTTP支持缓存以提高性能和降低服务器负载。 缓存允许客户端或中间代理存储和重用以前检索到的资源,从而减少重复请求的需要。
-
安全通信:HTTP可以与TLS(安全传输层)或SSL(安全套接字层)结合使用,建立加密连接(HTTPS),实现数据的安全传输。
1.3 对比分析
简单对比 HTTP1、HTTP2、QVIC:
| 协议 | 优劣 |
|---|---|
| HTTP1 | 队头阻塞、传输效率低、明文传输不安全 |
| HTTP2 | 多路复用、头部压缩、二进制协议 |
| QVIC | UDP实现、优化算法、减少握手次数 |
2.1 分层设计
引用一句真理:“与其一开始设计实现复杂系统,不如从简单的系统开始实现”,这便是分层设计的原因,好的架构,是层次分明的,往往利于扩展和复用(因为模块具有通用性)。分层设计包含了应用层、中间件、路由层、协议层。
-
应用层:应用层是分层设计中的最顶层。 它包括直接与最终用户或客户交互的软件应用程序。 应用层的任务可以根据具体的应用程序而有所不同,但一般来说,它涉及处理用户界面、业务逻辑和特定于应用程序的功能。
-
中间件层:中间件层也称为业务逻辑层或服务层,充当应用层和下层之间的中介。它的主要任务是提供跨多个应用程序通用的服务和功能。 中间件层可能包括身份验证、授权、数据验证、会话管理、缓存和其他可重用业务服务等组件。
-
路由层:也称为通信层或传输层,处理不同组件或系统之间数据的路由和传递。它的主要任务是建立和管理网络中不同节点之间的通信通道。 路由层确保根据寻址和路由协议将数据包传送到适当的目的地。 它可以处理路由决策、负载平衡和网络拥塞控制等任务。
-
协议层:通常称为网络层或数据链路层,处理数据传输和网络协议的底层细节。 它侧重于数据包在网络中的格式化、打包和可靠传输。该层处理诸如将数据封装到数据包、寻址、错误检测和纠正、流量控制以及处理传输协议(如 TCP(传输控制协议)或 UDP(用户数据报协议))等任务。
2.2 应用层设计
合理设计应用层,应遵循如下几点:
-
易读性:易读性是指代码的清晰度和可读性。 一个设计良好的应用层应该有易于理解和维护的代码。 清晰的代码可以改善开发人员之间的协作,更容易识别和修复问题,并提高开发过程的整体效率。
-
简单性:设计上的简单性促进干净直接的解决方案。 通过保持应用层设计简单,可以更容易理解、修改和扩展代码库。 简单性降低了复杂性,提高了代码的可维护性,并降低了引入缺陷或错误的可能性。
-
冗余:应用层设计中的冗余是指有备份或替代机制来处理故障的做法。 通过合并冗余,例如冗余服务器、数据库或故障转移系统,应用层变得更具弹性,可以更好地处理意外事件或系统故障。
-
兼容性:兼容性确保应用层可以与它交互的其他组件或系统无缝地工作。 它涉及遵循行业标准、使用兼容协议并考虑与其他软件或平台的互操作性。 兼容的应用层设计可实现与现有系统的集成,并简化未来的增强或集成。
-
可测试性:可测试性对于保证应用层的可靠性和质量至关重要。 设计良好的应用层应该易于测试,允许开发人员编写全面的单元测试、集成测试和系统测试。 可测试性有助于及早发现问题,实现快速反馈,并支持高效的调试和维护。
-
可观察性:可观察性是指监视和理解系统内部状态和行为的能力。 通过在设计应用程序层时考虑到可观察性,跟踪和诊断问题、收集指标和日志以及深入了解系统性能变得更加容易。 可观察性增强了故障排除、性能优化和整体系统可靠性。
2.3 中间件设计
中间件设计的洋葱模型,也称为洋葱架构,是一种软件架构模式,强调模块化、关注点分离以及各个层或组件的独立性。 该设计采用同心层结构,类似于洋葱层,每一层都有特定的职责和依赖性。
洋葱模型通常由以下几层组成:
-
核心层:核心层形成洋葱的最内层。 它包含应用程序的核心业务逻辑和领域模型。 该层代表系统的核心,独立于任何外部框架或技术。
-
领域服务层:领域服务层围绕核心层,提供特定于应用程序领域的更高级别的服务和操作。 这些服务协调和编排核心层内领域模型之间的交互。
-
应用服务层:应用服务层包裹着领域服务层,充当领域层和表示层之间的接口。 它公开了特定于应用程序的服务和操作,这些服务和操作被表示层用来与底层领域模型进行交互。
-
基础设施层:基础设施层形成洋葱的最外层。 它处理技术问题,例如数据访问、外部集成和与基础设施相关的实施。 该层包括数据库、外部 API、文件系统和缓存机制等组件。 它封装了技术细节并为其上方的层提供抽象。
洋葱模型的关键原理是内层是独立的并且不知道外层。 这促进了松散耦合,并使代码库更易于维护、可测试和适应性强。 每一层都可以独立开发、测试和修改,从而在不影响整个系统的情况下更容易更换或添加组件。洋葱模型还支持依赖倒置原则,其中高层依赖于低层定义的抽象,而不是相反。 该原则可以灵活地交换实现,并促进使用接口或契约进行层间交互。
2.4 路由层设计
在实现路由层时,可以使用 OPTIONS 方法查询路由基础结构并获取支持的路由、HTTP 方法和相关处理程序或函数的列表。 通过向服务器或路由器发送 OPTIONS 请求,客户端可以收到包含有关可用端点和每个端点允许的方法的信息的响应。
OPTIONS 方法用于检索可用于特定资源或服务器的通信选项。它允许客户端查询允许的 HTTP 方法、标头和服务器支持的其他功能。在路由上下文中,OPTIONS 方法可用于获取有关路由树或可用端点的信息。
此外,在实现多处理功能时,可以使用 OPTIONS 方法获取有关可用服务器实例、负载平衡机制或与多处理和分布式处理相关的其他信息的详细信息。 它允许客户端收集有关服务器功能的信息,并就资源利用和负载分配做出明智的决策。
2.5 协议层设计
协议层设计抽象出一个合适的接口,可以使用阻塞 I/O (BIO) 或非阻塞 I/O (NIO) 机制来实现。 让我们简要探讨一下这些概念:
-
阻塞 I/O (BIO):阻塞 I/O 是一种传统的 I/O 模型,在该模型中,程序的执行会暂停,直到 I/O 操作完成。 在协议层的上下文中,BIO 涉及阻塞套接字和 I/O 操作。 当程序进行阻塞 I/O 调用时,它会等待直到收到请求的数据或操作完成。 BIO 使用起来相对简单,因为程序员不需要处理复杂的异步回调或多路复用。 但是,BIO 的一个缺点是它会限制可扩展性和响应能力,尤其是在具有大量并发连接的场景中。
-
非阻塞 I/O (NIO):非阻塞 I/O 是一种可供选择的 I/O 模型,它允许程序在等待 I/O 操作完成的同时执行其他任务。 在协议层设计中,NIO 通常采用异步 I/O 和事件驱动编程。 它涉及非阻塞套接字和操作,其中程序可以发起一个 I/O 操作并继续处理其他任务,而无需等待完成。 当 I/O 操作完成时,回调或事件通知程序。 NIO 非常适合处理大量并发连接,并且与 BIO 相比可以提供更好的可伸缩性和响应能力。 然而,实现基于 NIO 的系统需要仔细处理回调、事件循环以及管理缓冲区管理和同步。
协议层设计中的抽象合适接口提供了一个公共接口或抽象,可以使用 BIO 或 NIO 机制实现。 它允许开发人员根据他们的要求、性能目标以及他们的应用程序或系统的具体特征来选择合适的 I/O 模型。 通过将通用接口背后的I/O操作抽象出来,可以将协议层与底层I/O模型解耦,方便BIO和NIO之间的切换,甚至未来支持其他I/O模型。
BIO 和 NIO 之间的选择取决于多种因素,例如预期的并发连接数、应用程序的性质(例如,高 I/O 密集型或计算密集型)以及所需的可伸缩性和响应级别。