读构建可扩展分布式系统:方法与实践04应用服务

news2024/11/15 17:26:57

1. 应用服务

1.1. 任何系统的核心都在于实现应用需求的特定业务逻辑

1.2. 服务是可扩展软件系统的核心

  • 1.2.1. 它们将契约定义为一个API,向客户端声明它们的能力

1.3. 应用服务器高度依赖于编程语言,但通常都会提供多线程编程模型,允许服务同时处理许多请求

1.4. 多服务配置意味着应用程序可以容忍单个实例的故障

1.5. 无状态服务允许负载均衡器简单地将请求重新发送到响应目标,从而轻松实现扩展并简化故障场景

1.6. 大多数负载均衡器采用被称为粘性会话的特性来支持有状态服务,但有状态服务会使得负载均衡和处理故障更加复杂

  • 1.6.1. 不建议在高度可扩展的系统中采用有状态服务

1.7. Java企业版(JEE)是一种成熟且被广泛部署的服务器端技术,它在不同范围提供了高度抽象的规范,可用于构建丰富而强大的服务

2. 服务设计

2.1. API

  • 2.1.1. Application Programming Interface,应用程序编程接口

  • 2.1.2. 定义了客户端与服务器之间的契约

  • 2.1.3. 指定了可能的请求类型、请求所需携带的数据以及请求所将获得的结果

  • 2.1.4. 主要风格还是基于HTTP的,它们通常被归类为RESTful

    • 2.1.4.1. REST是Roy T. Fielding在他的博士论文中定义的一种架构风格

    • 2.1.4.2. HTTP中API的创建、读取、更新和删除(简称CRUD)模式

      2.1.4.2.1. 有效利用了四个HTTP动词,即POST、GET、PUT和DELETE

    • 2.1.4.3. HTTP PATCH动词来更新资源的各个属性

      2.1.4.3.1. PATCH允许对一个资源的部分属性进行修改,而PUT则是将一个资源完整地替换成新的资源

    • 2.1.4.4. 有效负载通常被格式化成JSON,当然XML和其他格式也是有可能的

    • 2.1.4.5. HTTP动词与URI组合在一起定义了API操作的语义

      2.1.4.5.1. 用URI表示的资源在概念上类似于面向对象设计(OOD)中的对象或实体关系模型(ER模型)中的实体

  • 2.1.5. HTTP API可以采用OpenAPI来声明

    • 2.1.5.1. SwaggerHub工具是OpenAPI中声明API的事实标准

    • 2.1.5.2. 该规范是用YAML标记语言来定义的

  • 2.1.6. 一种常见的反模式是Chatty API,它使用多个API请求来执行一个逻辑操作

  • 2.1.7. 对传递大负载的HTTP API进行压缩

    • 2.1.7.1. 所有现代Web服务器和浏览器都支持采用Accept-Encoding和Content-Encoding的HTTP消息头的压缩内容

    • 2.1.7.2. 压缩可以将网络带宽和延迟减少50%甚至更多

    • 2.1.7.3. 要权衡的是压缩和解压缩内容过程中消耗的计算时间,与节省的网络传输时间相比一般都很小

2.2. 设计服务

  • 2.2.1. 应用服务器容器接收请求并将它们路由到适当的处理函数来处理请求

  • 2.2.2. Spring框架利用一组注解来简化服务代码,注解定义依赖关系和实现依赖注入

2.3. 状态管理

  • 2.3.1. 实现可扩展服务的底线是要避免存储会话的状态

  • 2.3.2. HTTP是无状态的协议

    • 2.3.2.1. 意味着每个请求都是独立执行的,对来自同一个客户端的早于它执行的请求一无所知

    • 2.3.2.2. 无状态意味着每个请求都需要是自包含的,不管客户端之前的行为如何,客户端要为Web服务器提供足够的信息来满足请求

  • 2.3.3. HTTP支持cookie,就是大家所知的HTTP状态管理机制

  • 2.3.4. HTTP/2支持流、压缩和加密,所有这些行为都需要状态管理

  • 2.3.5. 客户端和服务器之间底层的socket连接保持打开状态,这样可以分摊同一个客户端多个请求创建连接的开销

    • 2.3.5.1. HTTP/1及以上版本的默认行为
  • 2.3.6. 会话状态指的是在请求之间保留的所有信息,后续请求可以假定服务已保留有关先前交互的信息

    • 2.3.6.1. 如果你有多个客户端会话都要维护会话状态,这将占用可用的服务内存

      2.3.6.1.1. 占用的内存量将与服务所维护的客户端数量成正比

    • 2.3.6.2. 还必须注意保持会话状态的时长

      2.3.6.2.1. 如果你将此设置为较短的时长,客户端可能会出现非预期的会话状态丢失

      2.3.6.2.2. 如果你将会话超时期限设置得太长,则可能会因为资源不足而降低服务性能

  • 2.3.7. 无状态服务不会假定之前调用的任何会话状态已被保留

    • 2.3.7.1. 服务不应该维护来自之前请求的任何信息,每一个请求都可以独立处理

    • 2.3.7.2. 无状态服务要求客户端提供所有必要的信息,以便服务处理请求并提供响应

  • 2.3.8. 任何可扩展的服务都基于无状态的API

  • 2.3.9. 最重要的设计准则是,对于需要保留与客户端会话相关的状态的服务,状态必须存储在服务的外部,即外部数据存储

3. 应用服务器

3.1. 应用服务器是可扩展应用程序的核心,它托管了组成应用程序的业务服务

3.2. 其基本作用是接收来自客户端的请求,将程序逻辑应用于请求,并将请求结果返回给客户端

3.3. Tomcat是JEE平台的一个技术子集的开源实现,即Java servlet、Java Server Page(JSP)、Java Expression Language(EL)和Java WebSocket技术

3.4. 如果收到的请求多于服务器可以排队和处理的请求,那么新的TCP/IP连接将被拒绝,客户端将看到一些错误

  • 3.4.1. 最终,超负荷的服务器可能会因为资源耗尽而抛出异常并崩溃

  • 3.4.2. 花时间调整配置参数以有效处理预期负载是值得的

  • 3.4.3. 系统在达到100%利用率之前往往会降低性能

    • 3.4.3.1. 一旦任何资源(CPU利用率、内存使用、网络、磁盘访问等)接近100%利用率,系统就会表现出难以预测的性能问题

4. 水平扩展

4.1. 扩展系统的核心原则是能够轻松添加新的处理能力来处理增加的负载

4.2. 部署多个无状态服务器资源实例,使用负载均衡器在实例之间分配请求

4.3. 无状态服务副本和负载均衡器都是水平扩展所必需的

4.4. 服务副本部署在它们自己的(虚拟)硬件上

  • 4.4.1. 增加的处理能力使系统能够处理增加的负载

  • 4.4.2. 水平扩展的目的是创建一个系统,它的处理能力是所有可用资源的总和

  • 4.4.3. 服务器需要是无状态的,任何请求都可以发送到任何服务副本来处理

  • 4.4.4. 发送到哪个服务副本是由负载均衡器决定的,它可以使用各种策略来分发请求

  • 4.4.5. 如果负载均衡器可以使每个服务副本保持同样繁忙,那么我们就能有效地利用服务副本提供的处理能力

4.5. 如果我们的服务是有状态的,那么负载均衡器需要始终将来自同一服务器的请求路由到同一个服务副本

  • 4.5.1. 由于客户端会话的持续时间是不确定的,这就可能导致某些服务副本的负载比其他副本高得多

4.6. 水平扩展也提高了可用性

  • 4.6.1. 单服务实例如果失效了,服务就不可用了

    • 4.6.1.1. 单点故障(SPoF)

    • 4.6.1.2. 在任何可扩展的分布式系统中都应避免的一个问题

  • 4.6.2. 多个副本提高了可用性。如果一个副本失败,可以将请求定向到其他任何副本

5. 负载均衡

5.1. 负载均衡旨在有效利用服务集合的容量来优化每个请求的响应时间

5.2. 目的是避免某些服务超载而其他的服务利用不足

5.3. 客户端向负载均衡器的IP地址发送请求,负载均衡器将请求重定向到目标服务,并将结果转发回客户端

  • 5.3.1. 客户端永远不会直接与目标服务通信,这也有利于安全,因为服务可以存在于安全边界之后并且不会暴露在互联网上

5.4. 负载均衡器可以是网络级别或应用级别的,通常被称为四层和七层负载均衡器,分别对应开放系统互连(OSI)参考模型中第4层的网络传输层和第7层的应用层

  • 5.4.1. 网络级别的负载均衡器在网络连接级别分发请求,对单个TCP或UDP数据包进行操作

    • 5.4.1.1. 路由决策是根据客户端IP地址做出的

    • 5.4.1.2. 负载均衡器就会使用一种被称为网络地址转换(NAT)的技术,将客户端请求数据包中的目标IP地址从负载均衡器的地址更改为所选目标的地址

    • 5.4.1.3. 当收到来自目标服务的响应时,负载均衡器将记录在数据包头中的源地址从目标服务的IP地址更改为自己的IP地址

    • 5.4.1.4. 除了选择目标服务和执行NAT功能之外,它们提供的功能很少

  • 5.4.2. 应用级别的负载均衡器会重新组装整个HTTP请求,并根据HTTP头的值和消息的实际内容做出路由决策

    • 5.4.2.1. 应用负载均衡器是复杂的反向代理

    • 5.4.2.2. 意味着它们比网络负载均衡器稍微慢一些,但它们提供的强大功能可以用来弥补所产生的开销

5.5. 负载分配策略

  • 5.5.1. 决定了负载均衡器如何选择目标服务来处理请求

  • 5.5.2. 循环

    • 5.5.2.1. 负载均衡器以循环(round robin)方式将请求分发到可用的服务器
  • 5.5.3. 最少连接数

    • 5.5.3.1. 负载均衡器将新请求分发到打开连接数最少的一个服务器
  • 5.5.4. HTTP头字段

    • 5.5.4.1. 负载均衡器根据特定HTTP头字段的内容来引导请求
  • 5.5.5. HTTP操作

    • 5.5.5.1. 负载均衡器根据请求中的HTTP动词来引导请求
  • 5.5.6. 负载均衡器还可以为服务分配权重

5.6. 健康检测

  • 5.6.1. 负载均衡器会定期给负载均衡池中的每个服务发送ping命令并尝试连接以测试服务的健康状况

    • 5.6.1.1. 这些测试就被称为健康检查
  • 5.6.2. 如果与服务的连接只是发生暂时性故障,负载均衡器将会在服务变为健康可用后重新添加进来

5.7. 弹性

  • 5.7.1. 请求负载急剧增加会导致负载均衡器的服务容量达到饱和,导致更长的响应时间,并最终导致请求和连接失败

  • 5.7.2. 弹性指的是应用动态地提供新的服务容量以处理新增请求的一种能力

  • 5.7.3. 随着请求负载的增加,新的服务副本会被启动,负载均衡器将请求定向到新的副本

  • 5.7.4. 随着负载的减少,负载均衡器则会停止不再需要的服务副本

  • 5.7.5. 弹性要求负载均衡器与应用监控紧密集成,以便定义扩展策略来确定何时增加和减少服务容量

  • 5.7.6. AWS Auto Scaling组是弹性负载均衡的一个实例

    • 5.7.6.1. 定义了集合中服务实例数量的最大值和最小值

    • 5.7.6.2. 负载均衡器将确保组中始终具有最小数量的可用服务,并且永远不会超过最大数量

    • 5.7.6.3. 有两种方法可以控制一个组中的副本数量

      5.7.6.3.1. 一种是基于时间计划表,相关用例的请求负载的增加和减少是可预测的

      5.7.6.3.2. 如果无法预测增加的负载峰值,则可以根据应用指标(例如平均CPU和内存使用率以及队列中的消息数量)定义扩展策略来动态控制

      5.7.6.3.2.1. 如果超过策略的上限阈值,那么负载均衡器将启动一个或多个新的服务实例,直至性能下降到指标阈值以下

  • 5.7.7. 弹性是一个非常关键的特性,它允许服务随着需求的增长而动态扩展

    • 5.7.7.1. 对于负载频繁波动的高度可扩展系统,它几乎是一种以最低成本提供所需容量的必备能力

5.8. 会话保持(session affinity)

  • 5.8.1. 会话保持或粘性会话(sticky session)是有状态服务的负载均衡器特性

  • 5.8.2. 使用粘性会话,负载均衡器会将来自同一客户端的所有请求发送到同一服务实例

  • 5.8.3. 对于高度可扩展的系统来说,粘性会话可能会有问题

    • 5.8.3.1. 它们会导致负载不均衡的问题,随着时间的推移,客户端不会在服务之间均匀分布

    • 5.8.3.2. 发生负载不均衡的原因是客户端会话保持的时间不同

      5.8.3.2.1. 在一个拥有百万级会话的系统中,持续不断地创建和销毁会话,负载不均衡是不可避免的

      5.8.3.2.2. 这将导致一些服务副本不能被充分利用,而另一些则不堪重负,并可能由于资源耗尽而失败

  • 5.8.4. 通常,有状态服务器会产生在大规模系统中难以设计和管理的问题

  • 5.8.5. 如果服务由于短暂的网络中断而变慢,负载均衡器会将其从服务组中取出,直到它通过健康检查或失败

  • 5.8.6. 无状态服务提升了可扩展性,简化了故障场景,并减轻了服务管理的负担

5.9. 通过负载均衡扩展一组服务可能会导致负载均衡服务所依赖的下游服务或数据库不堪重负

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2138243.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu系统使用Docker部署Jupyter Notebook并实现笔记云同步

文章目录 前言1. 选择与拉取镜像2. 创建容器3. 访问Jupyter工作台4. 远程访问Jupyter工作台4.1 内网穿透工具安装4.2 创建远程连接公网地址4.3 使用固定二级子域名地址远程访问 前言 本文主要介绍如何在Ubuntu系统中使用Docker本地部署Jupyter Notebook,并结合cpol…

Netty(零散记录)

Netty: 1、Netty三种IO 2、Netty和Reactor的 1、Netty对Reactor的支持 Netty的线程模型时基于Reactor模型实现的,Netty对Reactor三种模式都有非常好的支持,并做了一定的改善,一般情况下,在服务端会采用主从架构模型…

Leetcode面试经典150题-739.每日温度

应读者私信要求,本题协商题目的具体内容 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0…

计算机毕业设计 二手闲置交易系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

【目标检测数据集】厨房常见的水果蔬菜调味料数据集4910张39类VOC+YOLO格式

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):4910 标注数量(xml文件个数):4910 标注数量(txt文件个数):4910 标注…

SSH公私钥后门从入门到应急响应

目录 1. SSH公私钥与SSH公私钥后门介绍 1.1 SSH公私钥介绍 1.1.1 公钥和私钥的基本概念 1.1.2 SSH公私钥认证的工作原理(很重要) 1.2 SSH公私钥后门介绍 2. 如何在已拿下控制权限的主机创建后门 2.1 使用 Xshell 生成公钥与私钥 2.2 将公钥上传到被需要被植入后门的服务…

Qt_显示类控件

目录 一、QLabel 1、QLabel属性介绍 2、textFormat文本格式 3、pixmap标签图片 3.1 resizeEvent 4、QFrame边框 5、alignment文本对齐 6、wordWrap自动换行 7、indent设置缩进 8、margin设置边距 9、buddy设置伙伴 二、QLCDNumber 1、QLCDNumber属性介绍 2、实…

再次探讨最小生成树Prim算法

二次复习Prim算法时得到了一些新的启示。正常初次学算法时都特别注意代码,但是慢慢的发现,随着代码能力的增强,代码反而不是这么重要,重要的是算法的思路。既在自己的脑子中能有这个算法的图解。 下面展示一下二次学习的思路&…

秋韵虫趣.

文章目录 虫鸣概览虫坛文化蟀种纷呈中华蟋蟀宁阳蟋蟀刻点铁蟋长颚斗蟋 油葫芦棺头蟋中华灶蟋小素蟋树皮蟋蟀 花生大蟋斑腿针蟋其他鸣虫树蟋,又名竹蛉、邯郸梨片蟋,又名金钟、天蛉、绿蛣蛉、银琵琶凯纳奥蟋,又名石蛉,鳞蟋黄蛉蟋&am…

基于A2C与超启发式的航天器星载自主任务规划算法-笔记

1. Actor-Critic 模块 主要文件:AC.py, PolicyNet.py, ValueNet.py作用:该模块实现了 A2C(Advantage Actor-Critic)强化学习算法。其中,ActorCritic 类是核心,它同时管理策略网络(Actor&#x…

misc合集(1)

[Week3] 这是一个压缩包 有密码,提示QmFzZUNURj8/Pz8/P0ZUQ2VzYUI base64解密是BaseCTF??????FTCesaB 猜测这应该是⼀个轴对称的密码 python ⽣成了密码字典,再通过 ARCHPR 进⾏字典爆破 lowercase abcdefghijklmnopqrstuvwxyz uppercase l…

Vue生命周期;Vue路由配置;vue网络请求;vue跨域处理

一&#xff0c;Vue生命周期 <template><div > <h1 click"changeText">{{ info }}</h1></div> </template><script> export default {name: HelloWorld,data(){return{info:"介绍组件生命周期"}},methods:{chang…

Android源码导入Android Studio

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 前言 需要先把 Android 源码编译一遍 然后执行下面指令就可以导入android源码了 关于 Android 源码编译可以参考这篇文章【LineageOS源码下载和编译&#xf…

GitLab CI_CD 从入门到实战笔记

第1章 认识GitLab CI/CD 1.3 GitLab CI/CD的几个基本概念 GitLab CI/CD由以下两部分构成。 &#xff08;1&#xff09;运行流水线的环境。它是由GitLab Runner提供的&#xff0c;这是一个由GitLab开发的开源软件包&#xff0c;要搭建GitLab CI/CD就必须安装它&#xff0c;因…

搜索二叉树BSTree的原理及实现

目录 一、简介 二、功能的实现 节点的实现 这里为什么模板参数采用的是K而不是T呢&#xff1f; 树体的实现 非递归版本 Insert函数 Find函数 Erase函数 递归版本 中序遍历 FindR InsertR EraseR 构造函数 析构函数 拷贝构造 赋值重载 一、简介 BSTree&#x…

Python 数学建模——Prophet 时间序列预测

文章目录 前言原理使用方法&#xff08;初级&#xff09;代码实例Prophet 高级应用add_seasonality 添加自定义周期性add_regressor 添加外生变量交叉检验 前言 Prophet 是 Facebook 团队开发的一个时间序列分析工具&#xff0c;相比传统的 ARMA 时间序列分析&#xff0c;能够综…

nodejs 007:错误npm error Error: EPERM: operation not permitted, symlink

完整错误信息 npm error Error: EPERM: operation not permitted, symlink npm warn cleanup Failed to remove some directories [ npm warn cleanup [ npm warn cleanup C:\\Users\\kingchuxing\\Documents\\IPFS\\orbit-db-set-master\\node_modules\\ipfs-cli, npm…

岭回归:带示例的分步介绍

由 AI 生成&#xff1a;DNA、基因组、摘要、岭回归 一、说明 岭回归是一种在独立变量高度相关的情况下估计多元回归模型系数的方法。 [ 1 ]它已用于计量经济学、化学和工程学等许多领域。[ 2 ]也称为Tikhonov 正则化&#xff0c;以Andrey Tikhonov命名&#xff0c;是一种解决不…

Lombok:Java开发者的代码简化神器【后端 17】

Lombok&#xff1a;Java开发者的代码简化神器 在Java开发中&#xff0c;我们经常需要编写大量的样板代码&#xff0c;如getter、setter、equals、hashCode、toString等方法。这些代码虽然基础且必要&#xff0c;但往往占据了大量开发时间&#xff0c;且容易在属性变更时引发错误…

【Linux取经之路】编译器gcc/g++的使用 调试器gdb的使用

目录 背景知识 编译器gcc/g的安装 编译器gcc/g的使用 调试器gdb的使用 cgdb 条件断点 背景知识 子曰&#xff1a;“温故而知新”。在谈gcc/g的使用之前&#xff0c;我们先来复习编译的4个阶段&#xff0c;也算是为下面的内容做一些铺垫&#xff0c;请看思维导图。 编译…