微服务--分布式基础

本篇笔记记录微服务的基础,都是基础概念,实现方案会记录在后续的笔记

我们先来看看常见的架构和概念

这是企业常用的搭配方案,这里先放一张图,学到最后我相信我们再看肯定懂

本篇笔记的核心内容:

注意:本篇知识需要你有实际项目部署的经验,有相关云服务的经验才好理解接下来的内容
接下来的例子都是以简单的商城应用以及相关服务的部署做例子

接下来我们正式开始

单体架构(ALL IN ONE)

这种架构就是指所有功能模块都在一个项目中

先从服务的基础部署讲起吧:

我们的后端应用和数据库都需要部署在各自的服务器(后续称作"节点") 上,这样他们可以通过"内网"来实现互相通信,我们服务就算部署完成。

但是服务都在内网 ,其他用户就无法访问了,于是我们需要在云服务平台购买"公网IP "

这样其他用户如果想要访问我们的后端服务,只需要输入我们购买的公网IP地址即可访问

但是直接输入公网IP去访问太难记了,于是开发者都会去购买"域名"(就是我们现在上网输入的网址) ,域名绑定公网IP,这样用户就可以通过域名访问我们的服务

(因此,所有的网站访问本质上都是在访问公网IP地址)

至此,单体架构的服务就部署完成

它的优缺点都很明显:

优点:应用/数据库都各自只部署在了一个服务器(后续称作"节点") 上,部署很简单,相应的网络连接也简单

缺点:就是因为他们的服务都各自部署在一个节点上,每个节点承载请求的能力是很有限的,若应对高并发场景,节点会承载不住,用户体验会非常差

由此引出下一个架构

集群架构

有了上面单体架构部署的基础,下面我们来讲解一些集群的基本概念:

集群

上面单体架构应对高并发很容易垮,因此我们常常会给之前工作的节点多复制几个"复制品"--"副本",这些副本节点和原来的节点一起工作,这种工作就叫集群

看图就很好了解,多个节点一起工作就叫"集群",因此后续我们所学习的"分布式架构"的工作方式也是"集群"工作

网关

如果就像上面那样单纯的设置集群来实现服务,这样用户在访问的时候还是智能化访问某一个节点,还是没有解决高并发问题(如下图)

因此,如果我们想要让用户的请求"分布式"的发送到各个节点以此来减轻服务器的压力,我们就必须要用到"网关"

企业中常常会使用Nginx作为网关,将Nginx部署在一个服务器上,让用户发来的请求打到Nginx上,再由Nginx转发到各个后端节点上,像这样的"转发"在微服务中就被称为"路由"

但是所谓的"转发"肯定不能乱转发,因此对于"路由"这样的转发**,我们通常会用"负载均衡"这样的算法去限制** ,让这种转发能够均衡的转发给下面的服务节点,让每一个节点所接收的请求量都差不多

集群架构总览:

集群架构虽然解决了单体架构的服务器过载问题,但是它本质上还是单体架构的衍生,因此还会有之前我们没有提及的一些单体架构的问题

1.模块化升级 :如果服务的某一项功能进行了升级或者改写,那么整一个服务又得重新打包再上传到服务器中

2.多语言团队:一个完整的项目有可能不止一种编程语言来实现,比如说想要新增"直播功能",Java对于"直播"这种技术并不擅长,需要用到C++才行,C++是无法"打包"的,但是项目整体又是Java语言,像上传到服务器就得打成jar包,这样C++实现的功能就上传不了了

分布式架构

微服务

之前单体架构以及它的衍生集群架构的所有功能都是部署在同一个项目中,如果新增功能或者多语言团队这种问题就非常难处理

为了解决上述问题,我们把一个项目中的功能进行拆分,把每一个功能拆分为一个个小应用

像这样被拆出来的"小应用"就被称作"微服务",每一个"微服务"都可以独立部署

因此,独立部署就解决了之前的"模块化升级"和"多语言团队"的问题

每个功能可以被拆分为微服务,同理,数据库也可以做相应的拆分 ,数据库可以根据拆分的微服务做拆分,每个微服务都对应一个个小数据库,这样就实现了**"数据隔离"**,每个功能的数据不会互相干扰

因此,在服务部署上我们就可以这么操作:

每一个服务器部署一些微服务

比如"商品"这个微服务用到的比较多,那么我们可以给"商品"添加"副本",然后多部署在其他的服务器中

看到这里,你是否会想:能否把多个微服务部署在同一个服务器呢?

单点故障

答案肯定不行,这就会出现"单点故障"问题,其实很好理解,多个同种类微服务(拿刚刚举例的"商品"微服务来说)假设都部署在同一个服务器,若该服务器挂了,那么该服务就会直接不可用了

因此,实际开发中我们要避免这种单点故障问题,即"鸡蛋不要放在同一个篮子里"

远程过程调用(RPT:Remote procedure call)

微服务的服务项目不可能都部署在同一个服务器中,肯定会出现不同微服务部署在不同的服务器当中

想象一个场景:用户在"用户界面"想查看自己的"订单"是什么,但是我们的"用户"微服务和"订单"微服务并不在同一个服务器中要怎么办?

这时就可以用到"远程调用","用户"这个微服务向"订单"微服务发送HTTP请求,让订单返回相应格式的JSON数据 即可在不同服务器也能实现互相使用

远程调用有很多种形式,HTTP+JSON只是其中的一种方式

但是这远程调用又引出一个问题:

"用户"这个微服务要怎么知道"订单"微服务在哪个服务器中,假设0.6服务器的微服务挂了,"用户"微服务能否知道要去0.5服务器来远程调用呢

注册中心

注册中心包含了服务注册和服务发现两个功能,很好的解决了上面远程调用的问题

服务注册

每当项目中的某一个微服务上线/下线,都需要给注册中心发送"该服务上下线"的消息,注册中心收到这些消息就会在注册中心的"服务-IP清单列表"标明某个服务上线了,他所在的服务器在哪

这整个过程就叫"服务注册"

因此,上线了的微服务就会在清单列表中,下线的微服务就会消失在清单列表,与"服务发现"配合,就解决了上文提及的"要去哪个服务器调用微服务"的问题

服务发现

服务注册完,在远程过程调用之前,微服务都会先向注册中心"询问""服务-IP列表"的内容,注册中心返回这些内容,这个过程就叫"服务发现"

最后微服务根据内容再进行远程过程调用

并且,远程过程调用的过程中,还可以用到"负载均衡"算法,比如图中的"订单"再0.5、0.6服务器都有部署,则负载均衡算法可以让"用户"微服务的调用均衡,一次0.5,一次0.6

配置中心

前文提及微服务把便捷了项目的模块化部署,但是如果项目的模块(也就是微服务)仅仅是配置文件需要改动,那我们还得把该微服务下线然后重新打包再上线吗?这显然是很麻烦的,因此注册中心里还包含了"配置中心"这个部分

配置中心统一管理所有微服务的配置文件,因此修改配置文件无需一个个下线微服务然后改配置文件再统一上线,只需要再配置中心直接修改相应微服务的配置文件即可

服务熔断(快速返回错误)

先来看下面这个场景:

在"直播--订单--支付"这条调用链中,假设"订单--支付"这条调用链损坏,(也就是订单调用支付微服务却迟迟拿不到结果,一直在等待),那么相应的,"直播"也会一直等待"订单"的结果,那这条调用链就会一直卡死。

同样的,若面对高并发对"直播--订单--支付"调用链的请求(比如数千万条请求),则这数千万条请求都会因为"订单--支付"这里一直卡死,请求没有完成,资源就不会释放,那么请求就会一直占用服务器资源数千万请求占用这些服务器资源就会导致"涉及到该调用链的服务器"的其他微服务功能无法拿到服务器资源,这就间接的导致了其他微服务的不可用 ,其他若微服务不可用的多了,那整个应用就没有可以用的地方了。这就导致了**"服务雪崩"**

面对这种情况,我们就需要引入"熔断机制",既然发生了卡顿等待,我们干脆就不等了,直接返回一个错误信息或者页面给用户,这样调用链链路就不会发生卡顿等待占用服务器资源

至于"熔断"的具体实现,就等我们后续学习再说,这里只提及概念

分布式事务

来看下面的场景:

用户在商城完成消费了一定金额的订单,商城为了鼓励用户会给用户加优惠积分,以服务和数据库的层面来看,这很明显是一个"事务",即花钱和加积分必须是在一个事务中完成,不得花钱后加积分出现错误积分就不加了

但是我们分布式架构的数据库都是独立的,我们之前开发项目的服务器都是在一台数据库完成,因此可以直接用事务机制就完成

想要解决这个问题就要引入"分布式事务"来解决了(这里只引入概念,后续文章会给出具体实现方案)

分布式架构总览

补充

前面的介绍还少了一点东西,现在来补充:

分布式架构中每个节点独立来看都不是完整的应用,无法像我们之前随便选一个节点就可以完成用户的任意需求,比如用户想要使用"物流"功能,那在这种架构下网关要怎么知道把请求送往含有"物流"的服务器呢?

还记得我们前文提到的"路由"吗,我们说它是网关对服务器的选择,但是当时通过路由选择哪个服务器好像都无所谓,现在路由可以发挥它的作用了,它可以结合"注册中心"来根据用户打到网关的请求来决定该请求要送往哪个服务器当中

比如"用户想要访问物流功能",那么用户发送的请求中一定是含有"物流"字样的请求,网关通过注册中心来找含有"物流"字样的请求在哪些服务器中,然后通过路由选择把该请求送往相关服务器中

最后,本篇只是简单介绍有关于微服务的简单概念,并不涉及某些实际问题的具体解决方案

上面讲的基础概念的相关技术都可以在下图中找:

相关推荐
鹿角片ljp1 小时前
Prompt Cache、Token 成本与 Plan Compiler 的工程设计
java·python·算法
Wang's Blog2 小时前
Java 接入Redis: 五大数据类型与存储结构选型
java·服务器·redis
Wang's Blog2 小时前
Java 接入Redis: 字符串与哈希类型操作命令
java·服务器·redis
weixin_435247063 小时前
微服务开发规范模版
微服务·云原生
智慧物业老杨6 小时前
物业数字化落地思考:真正的转型,是底层数据秩序的重构
java·大数据·人工智能·微服务·系统架构
星空9 小时前
金蝶苍穹build.gradle配置
java·build.gradle
考虑考虑10 小时前
Springboot环境变量占位符语法
spring boot·后端·spring
步行cgn12 小时前
Spring 基于 XML 的自动装配:byName 详解
java·后端·spring
不会c+12 小时前
Day02 - 需求分析与用例建模
spring