云原生应用架构-微服务开发最佳实践

第1章云原生时代下的微服务

微服务架构是一种将单个应用程序开发为一组小型服务的方法,每个服务在自己的进程中运行,并通过轻量级的通信机制(如HTTP API)进行交互。这些服务围绕业务功能构建,可以通过完全自动化的部署机制独立部署。服务可以使用不同的编程语言,并使用不同的数据存储,我们可以以一个非常轻量级的中心化管理方式来协调服务。

1.1.1 微服务架构的关键特性

1.服务组件化

2.基于业务能力构建系统

3.去中心化治理和数据分治

分散的服务带来的另一个特征就是去中心化。

一个应用所包含的各个业务需求必然是各不相同的,而不同的业务模型必然有最适合的技术方案。通过拆分,我们实现不同的服务时在技术方案上可以有不同的选择,这就是所谓的异构。使用合适的方案比使用统一的方案更重要,因为这样效率更高。例如,使用面向对象语言构建有复杂业务模型且适合建模的服务,使用Golang语言构建中间件服务。在数据层面也是如此,对于有级联关系的业务模型,使用MongDB这种文档化的存储方案更合适,对于大数据离线分析业务,使用列式数据仓库方案更合适。对于团队来讲,这种去中心化的构建方式也更加灵活。

4.基础设施自动化

5.面向失败设计和演进式设计

 将业务模块拆分成服务后,因为交互方式的改变,服务间的调用很有可能会因为各种原因而失败,比如网络抖动、上游服务不可用、流量过载、路由出错等。这就要求我们在构建微服务应用过程中充分考虑这些问题,想办法在失败时尽可能降低对用户的影响。很显然,这将增加开发负担,我们需要再应用中添加更多的非功能性需求,或者说控制逻辑,而这应该是微服务这种分布式架构之于单体应用最大的劣势。

为了解决微服务的这一问题,服务治理,以及通过服务网格技术更轻松地管理服务间的通信成了重要课题。当面对失败时,最重要的及时能够及时检测和发现故障并自动恢复。在云原生技术的加持下,实现面向失败设计变得不再困难,比如我们可以基于基础设施的探针和运行策略完成自动化重启,也可以通过日志、指标和追踪构建完善的服务监控能力。

简单来说,服务网格就是一个用来管理服务间通信的基础设施层,通过一组边车代理提供的能力,进行服务间流量的管理。如果将k8s称作云原生应用的操作系统,那么服务网格就是云原生应用的网络层,为微服务应用解决流量管理难题。随着服务的增多,微服务需要进行治理和管控,服务网格正是用来管理服务间通信的解决方案。

以服务网格为例,要实现上面的重试功能,应用本身不需要做任何代码层面的修改,只需要在服务网格的路由配置中增加与重试相关的配置即可,服务代理会根据这个配置在请求失败的时候自动进行重试。这就是云原生技术的能力,其理念是将非功能性需求下沉到基础设施,让应用只关注业务实现。

我们还以Spring Cloud为例,它是一个强大的微服务开发框架,提供了很多具有服务治理能力的组件。

框架几乎可以满足我们所有的需求,但本质上他还是以类库方式运行的。

微服务应用基于业务进行服务拆分,通过服务间的交互实现应用的整体功能。开发应用时,除了要考虑实现功能性需求,还要考虑实现非功能性需求。而在云原生架构中,非功能性需求通常交由基础设施负责。下沉非功能性需求可让开发人员只关注业务,这就是我们在前面提到的云原生技术愿景。因此,从这一宏观层面上来看,开发人员要有思想上的转变,在架构设计、技术选型等方面从云原生的理念出发,构建出面向未来的云原生应用。

利用k8s这一类基础设施完成应用的编排和调度管理,使大量的非功能性需求被剥离出来,交由k8s实现。

现代应用程序的构建趋势是“微服务+云原生”,即从微服务应用转变为云原生应用。

第2章 微服务的应用设计方法

2.1应用架构设计

架构描述的是在更高层次上将应用拆分为子系统(或模块)的方法,以及这些子系统之间的交互关系。开发过程中的一个基本问题是理解底层的软件架构,在考虑使用何种技术或工具前必须首先考虑总体的架构。

在分解复杂的软件系统时,最常用的设计手段就是分层。比如TCP/IP网络模型,上层使用下层定义的服务,下层对上层隐藏自己的实现细节。

20世纪90年代前后,两层结构是一种比较先进的设计,例如客户端/服务端架构。

使用两层结构经常要面对的一个问题是业务逻辑写在哪层。如果应用的数据操作是简单的增删改查,选择两层结构式合理的。一旦业务逻辑变得复杂,这些代码写到哪一层都不太合适。出现这一问题的原因是缺乏领域建模。

随着业务的变更和发展,最初设计的数据库表常常无法准确呈现出当前的业务状况,这时转到三层结构是更好的选择。通过引入一个中间层,可以解决业务逻辑的归属问题,我们可以将这一层称为领域层,或者业务逻辑层。

如果我们将展示层看作前端(与网页相关的部分),那么业务逻辑层和数据访问层就是后端。后端可以分为两层,不过一个更常见的分层方式是将后端也分为三层,比如下面这样。

接口层:或者应用层,负责与前端对接,完成从前端请求参数到业务数据对象编解码工作,处理通信层面的功能,调用下层真正的业务逻辑。构建这一层的目的是避免将非业务功能引入领域层,保证领域层中业务逻辑的纯粹性。这一层通常可以使用门面模式来构建,这样就可以对接不同的展示层,比如网页、移动端App等。

领域层:领域相关的业务逻辑部分,其中只包含相对纯粹的业务代码。

数据访问层:与数据源对接,将业务对象转换为存储数据并保存到数据库中,这个过程可简单理解为“对象-关系映射”(ORM)。

在讨论分层结构的时候,我们需要明确层的粒度问题。而我们讨论的主要是layer所代表的层,是基于代码层面的一种隔离。

对于微服务而言,服务发现的重要性不言而喻的。

通常一个服务发现系统有如下三个角色。

服务提供者:可以理解为一个Web服务(协议可以多样化),对外暴露一些API,有一个IP地址和端口作为服务地址。在微服务应用中可以认为服务提供者就是上游服务,即被调用的服务。

服务消费者:消费服务的一方,通过访问服务提供者的API来获取数据,实现功能。在微服务应用中可以认为服务消费者就是下游服务,即调用者。

注册中心:也叫注册表,可以理解为一个中心化的数据库,用来存储服务地址信息,是服务提供者和服务消费者之间的桥梁。

如果一个服务既要访问上游服务,又要提供API给下游服务,那么它既是服务的提供者,也是服务消费者。微服务应用中有很多服务都具有这样的特性。

服务发现机制的模式主要有两种。

1.客户端发现模式

在这种模式下,服务启动时会将自己的地址注册到注册中心,客户端访问注册中心获取要访问的服务地址,然后向服务提供者发起请求。

2.服务端发现模式

相对客户端发现模式而言,服务端发现模式最主要的变化是增加了一个中心化的代理,将服务信息的拉取、负载均衡集中到了一起。服务消费者发起的请求会由代理接管,代理从注册中心查询到服务提供者的地址,然后根据地址将请求发送给服务提供者。它带来的缺点是,因为引入了代理,请求会多转发一次,增加了服务响应的延迟。对于k8s为基础的云原生应用来说,使用默认的服务发现机制是首选策略,但如果你的应用是混合部署的,比如既有k8s集群内的服务,也有集群外的服务,且它们之间还需要交互,那么就要考虑服务发现的集成方案。比如Consul项目就可以与k8s集成。他提供的Helm Chart可以让你方便地在集群中安装Concul,并提供了k8s服务与Consul的自动同步机制。这些特性可以让应用很好地工作在跨集群或者异构的工作负载环境中,为服务间通信提供了便利。

  通信协议和格式

REST/HTTP

REST是一组架构设计的约束条件和原则,基于REST风格设计的API称为RESTful API。它以资源这个概念为核心,配合使用HTTP的方法,从而实现对资源数据的操作。比如下面的URL代表使用HTTP的GET方法来获取订单数据。

GET /orders/{id}

RESTful API有很多优点:简单易读,很容易设计测试方便,可以用curl之类的命令或工具直接测试;实现容易,只要构建一个Web服务器就可以使用;HTTP应用广泛,更容易集成。

当然,它也有缺点,比如工作在七层,需要多次交互才能建立连接,性能稍逊一筹;只支持一对一的通信,如果想在单一请求中获取多个资源,需要通过API聚合等方式实现。

尽管如此,RESTful API依然是构建Web应用的事实标准,对内负责前后端的请求和响应,对外负责定义API接口,供第三方使用。

RPC即远程过程调用,它的工作方式是使用一种接口定义语言(IDL)来定义接口和请求响应消息,然后渲染出对应的服务端和客户端桩(Stub)程序,客户端可以通过这个桩程序像调用本地方法一样去调用远端服务。

RPC一般包含传输协议和序列换协议。RPC比HTTP封装性更好,更符合面向领域建模理念。

使用RPC也很简单,并且因为具有很多语言SDK的支持,也可以认为它不会受到语言限制。另外,RPC通常优先选择二进制格式进行传输,虽然二进制数据不可读,但传输效率要高于HTTP/JSON这样的明文格式数据。RPC的通信机制也更丰富,不仅仅支持请求/响应这种一去一回的方式,比如gRPC还支持流式传输。

RPC更适合服务之间的调用,或者组织内部各个系统之间调用。对于需要暴露给外界的OpenAPI,还是要优先选择使用RESTful API。原因很简单,基于HTTP的RESTful API对调用方的技术栈是没有任何要求的,而RPC因为需要特定的IDL语言渲染出桩程序,调用方需要在自己的应用中引入桩程序,因此会产生依赖,另外,如果将IDL源文件共享给调用方,也会有安全方面的隐患。

3.基于服务网格的流量管理

微服务应用一般会有三种请求来源:来自外界的请求(比如对外提供的API)、来自组织内部其他存量系统的访问请求,以及微服务应用内部服务之间的请求。这些流量都需要管理,比如实现动态路由、按比例切分,或者添加超时、重试这些弹性能力。一些传统的基于公共库的解决方案(如Spring Cloud)已经提供了非常完善的流量管理功能,不过相对于服务网格这样的云原生解决方案还存在一些劣势。

 缓存

缓存是计算机软硬件系统广泛存在的一类组件和设计模式,存储层的典型代表是内存key-value型数据库,它比读写磁盘数据库快,可以作为中间件挡在主数据库的前面,产生以小硬件撬动大流量的杠杆效应。完全在内存中处理数据虽然快,但代价是机器停电或者进程重启会导致数据丢失。为了解决易失性问题,有些缓存(如Redis)也提供了数据持久化方案。

缓存的主要设计指标之一是命中率,命中率越高说明缓存的作用越大,另一方面也预示着缓存被击穿时对数据库的影响越大。缓存的另一个设计指标是流量分布的均衡性。如果某个key承载了过大的流量(热点),容易造成存储硬件(内存、网卡)的损坏,热点击穿甚至可能引发新的热点,造成系统雪崩。

应用要使用缓存,需要允许缓存中的数据和数据库的数据出现短暂的不一致。应用可以选择伴随写数据库的操作(之前、之后均可)更新缓存,也可以选择伴随数据库的操作来更新缓存并设置缓存的过期时间,甚至可以选择离线定期更新缓存,在线只读取缓存,未命中也不穿透到数据库。如果应用设置了缓存过期时间,还要小心处理在缓存过期到缓存更新的间隙中数据库的流量尖峰。

队列

队列作为先进先出的数据结构,是各种数据库系统的持久化、跨节点同步和共识机制的实现基础,保证了进入数据库的数据不丢失、不乱序。 

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

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

相关文章

单链表的基本操作--增删改查

增删改查 #include <stdio.h> #include <stdlib.h>#define OK 1 #define ERROR 0 typedef int Status; typedef char ElemType;typedef struct Lnode {ElemType data; //结点的数据域struct Lnode* next; //节点的指针域 }Lnode,*LinkList;初始化 Status InitLis…

【PCL】(二十八)超体素聚类分割点云

&#xff08;二十九&#xff09;超体素聚类分割点云 论文&#xff1a;Voxel Cloud Connectivity Segmentation - Supervoxels for Point Clouds supervoxel_clustering.cpp #include <pcl/console/parse.h> #include <pcl/point_cloud.h> #include <pcl/poin…

重启 explorer 进程的正确做法(二)

重启资源管理器进程的方法不唯一&#xff0c;但长期以来大家对实施方法用的不到位。 在上一篇中我认为&#xff1a;“我们往往使用 TerminateProcess 并传入 PID 和特殊结束代码 1 或者 taskkill /f /im 等方法重启资源管理器( explorer.exe )&#xff0c;其实这是不正确的。我…

21 卷积层里的多输入多输出通道【李沐动手学深度学习v2课程笔记】

目录 1. 多输入输出通道&相应代码实现 1.1 多输入 1.2 多输出 1.3 1x1 卷积层 1.4 小结 1. 多输入输出通道&相应代码实现 1.1 多输入 为了加深理解&#xff0c;我们实现一下多输入通道互相关运算。 简而言之&#xff0c;我们所做的就是对每个通道执行互相关操作&a…

CentOS 8启动流程

一、BIOS与UEFI BIOS Basic Input Output System的缩写&#xff0c;翻译过来就是“基本输入输出系统”&#xff0c;是一种业界标准的固件接口&#xff0c;第一次出现在1975年&#xff0c;是计算机启动时加载的第一个程序&#xff0c;主要功能是检测和设置计算机硬件&#xff…

题目:泡澡(蓝桥OJ 3898)

问题描述&#xff1a; 解题思路&#xff1a; 图解&#xff1a;&#xff08;以题目样例为例子&#xff09; 注意点&#xff1a;题目的W是每分钟最大出水量&#xff0c;因此有一分钟的用水量大于出水量则不通过。 补充&#xff1a;差分一般用于对一段区间每个元素加相同值&#x…

JZ76 删除链表中重复的结点

/*public class ListNode {int val;ListNode next null;ListNode(int val) {this.val val;} } */import java.util.*; public class Solution {public ListNode deleteDuplication(ListNode pHead) {//初步想想法&#xff1a; 弄一个hashmap 然后进行key存储起来。然后 如果存…

PHP将PDF转成多个PNG文件

1. 安装Imagick之前&#xff0c;您需要确保已安装PHP。如果您尚未安装PHP&#xff0c;请运行以下命令安装PHP及其常用扩展&#xff1a; sudo apt install php php-cli php-imagick 2. 安装Imagick PHP扩展&#xff1a; sudo apt install php-imagick 3.安装后&#xff0c;您…

python 查询json文件的某一行并 替换json 键值字符串右边的内容

在Python中处理JSON文件时&#xff0c;通常不需要按照行来查询和替换内容&#xff0c;因为JSON数据结构是键值对组成的&#xff0c;并且不以“行”为单位。你可以直接读取整个JSON文件&#xff0c;解析成字典对象&#xff0c;然后根据键名查找并修改对应的值。 以下是一个示例…

hibernate查询时会无限循环,然后报错:Exception in thread “main“ java.lang.StackOverflowError

遇到的情况有&#xff1a; 1、建表对应的时候“意外”添加了索引。解决&#xff1a;需要把索引删掉 2、打印查询到的单个实体信息时&#xff0c;使用了toString()方法。解决&#xff1a;不用就行了 3、多对多映射&#xff0c;查询到的整个实体集合时&#xff0c;直接打印这个…

web前端框架

目前比较火热的几门框架: React React是由Facebook(脸书)开发和创建的开源框架。React 用于开发丰富的用户界面&#xff0c;特别是当您需要构建单页应用程序时。它是最强大的前端框架。 弊端: 您不具备 JavaScript 的实践知识&#xff0c;则建议不要使用 React。同样&#x…

2024 年广东省职业院校技能大赛(高职组) “云计算应用”赛项样题①

2024 年广东省职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项样题① 模块一 私有云&#xff08;50 分&#xff09;任务 1 私有云服务搭建&#xff08;10 分&#xff09;任务 2 私有云服务运维&#xff08;25 分&#xff09;任务 3 私有云运维开发&#xf…

人工智能(AI)领域最流行的八大算法概括

人工智能&#xff08;AI&#xff09;领域最流行的八大算法概括&#xff01; 1. 卷积神经网络&#xff08;CNN&#xff0c;Convolutional Neural Network&#xff09; 2. 图神经网络&#xff08;GNN&#xff0c;Graph Neural Network&#xff09; 3. 循环神经网络&#xff08;RN…

蓝桥杯第一天

这题就是典型的位数贡献大于数量贡献&#xff0c; 1花的火柴更少&#xff0c;所以尽量用完10个1&#xff0c;然后其实就是简单的背包问题尽量拿最多的物品&#xff08;数字&#xff09;&#xff0c;限重为300&#xff0c;各物品&#xff08;数字&#xff09;的重量即为所需火柴…

vue2的常用指令

什么是vue的内置指令 内置指令的一些新颖而有吸引力的用法&#xff0c;可以让您在开发中能加速开发效率,降低维护成本。 v-bind和v-model v-bind&#xff1a; 使用 v-bind 可以动态地绑定一个或多个特性&#xff0c;或者一个组件 prop 到表达式。可以使用简化语法 : 来代替 …

php文件操作

一、文件读取的5种方法 1&#xff0c;file_get_contents: 将整个文件读入一个字符串 file_get_contents( string $filename, bool $use_include_path false, ?resource $context null, int $offset 0, ?int $length null ): string|false 可以读取本地的文件也可以用来打…

Python语言元素之变量

程序是指令的集合&#xff0c;写程序就是用指令控制计算机做我们想让它做的事情。那么&#xff0c;为什么要用Python语言来写程序呢&#xff1f;因为Python语言简单优雅&#xff0c;相比C、C、Java这样的编程语言&#xff0c;Python对初学者更加友好。 一、一些计算机常识 在…

【Apache的安装与目录结构】讲解

Apache的安装与目录结构 0. 前言1. 安装Apache1.1 在Ubuntu/Debian上安装Apache1.2 在CentOS/Red Hat/Fedora上安装Apache1.3 在Windows上安装Apache1.4 在Mac OS X上安装Apache 2. Apache目录结构 0. 前言 Apache HTTP Server&#xff0c;简称Apache&#xff0c;是一个开源的…

储能系统--户用储能欧洲市场(三)

五、户用市场地域分析 2022年以来&#xff0c;全球能源供需格局进入调整阶段&#xff0c;越来越多的国家将储能列为加速其清洁能源转型的必选项。根据中关村储能产业技术联盟 &#xff08;CNESA&#xff09;数据&#xff0c;2022年全球新增投运电力储能项目装机规模30.7GW&…

删除 PostgresSql 数据库 报错:有 N 个其它会话正在使用数据库 的解决方案

说明此时有两个客户端在连接此数据库&#xff0c;此时不能删除数据库。 如果确定要强制删除此数据库&#xff0c;那么执行如下命令&#xff1a; SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname‘VolteAna3G’ AND pid<>pg_ba…