微服务架构及幂等性

微服务架构

微服务架构是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。它的主要作用是将功能分解到离散的各个服务当中,从而降低系统的耦合性,并提供更加灵活的服务支持。

和 微服务 相对应的,这种方式一般被称为 单体式开发(Monolithic)。既所有的功能打包在一个 WAR 包里,基本没有外部依赖(除了容器),部署在一个 JavaEE 容器(Tomcat,JBoss,WebLogic)里,包含了 DO/DAO,Service,UI 等所有逻辑。

单体应用的优缺点:

img

优点:

  • 开发简单,集中式管理
  • 基本不会重复开发
  • 功能都在本地,没有分布式的管理和调用消耗

缺点:

  • 效率低:开发都在同一个项目改代码,相互等待,冲突不断
  • 维护难:代码功能耦合在一起,新人不知道何从下手
  • 不灵活:构建时间长,任何小修改都要重构整个项目,耗时
  • 稳定性差:一个微小的问题,都可能导致整个应用挂掉
  • 扩展性不够:无法满足高并发下的业务需

微服务的优缺点:

img

优点:

  • 它解决了复杂问题。它把可能会变得庞大的单体应用程序分解成一套服务
  • 这种架构使得每个服务都可以由一个团队独立专注开发
  • 微服务架构模式可以实现每个微服务独立部署
  • 微服务架构模式使得每个服务能够独立扩展

缺点(挑战):

  • 微服务是一个分布式系统,其使得整体变得复杂。开发人员需要基于RPC或者消息实现微服务之间的调用和通信,而这就使得服务之间的发现、服务调用链的跟踪和质量问题变得的相当棘手。
  • 分区的数据库体系和分布式事务。更新多个业务实体的业务交易相当普遍。这些类型的事务在单体应用中实现非常简单,因为单体应用往往只存在一个数据库。但在微服务架构下,不同服务可能拥有不同的数据库。CAP原理的约束,使得我们不得不放弃传统的强一致性,而转而追求最终一致性,这个对开发人员来说是一个挑战。
  • 跨越多服务变更。在单体应用程序中,您可以简单地修改相应的模块、整合变更并一次性部署他们。相反,在微服务中您需要仔细规划和协调出现的变更至每个服务。
  • 部署基于微服务的应用程序也是相当复杂的
  • 测试

以上问题和挑战可大体概括为:

  • API Gateway
  • 服务间调用
  • 服务发现
  • 服务容错
  • 服务部署
  • 数据调用

目前流行的两种微服务框架解决方案(可以解决以上问题)

  • SpringBoot + SpringCloud
    • SpringBoot是 Spring 的一套快速配置框架,可以基于spring boot 快速开发单个微服务
    • Spring Cloud基于Spring Boot,为微服务体系开发中的架构问题提供了一整套的解决方案——服务注册与发现,服务消费,服务保护与熔断,网关,分布式调用追踪,分布式配置管理等路由网关
  • Dubbo + ZooKeeper
    • Dubbo是一个阿里巴巴开源出来的一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
    • ZooKeeper用来实现服务的注册与发现和进行负载均衡

基于微服务架构的应用是分布式系统,增加了系统设计和实现的难度,主要有以下方面:

  • 运行环境中,微服务实例的网络地址是动态分配的,微服务运行的实例是动态变化的,需要一套发现机制,使服务调用者可以获取正确的服务地址。
  • 服务之间存在着复杂的依赖关系,在高并发访问下,依赖的稳定性影响系统的可用性及性能,因此需要提供容错机制,当依赖的服务发生故障时,不会使调用方线程被长时间占用不释放,避免故障在系统中蔓延。
  • 需要一个高效的进程间通信机制支持微服务之间的交互
  • 服务实例的启停及流量的调度和分配需要一套负载监控和负载均衡组件来管理。

微服务架构的基本组件

  • 可持续交付的平台
  • 服务注册与发现组件(ZooKeeper)
  • 服务网关

一般微服务在系统内部,通常是无状态的,用户登入信息和权限管理最好有一个统一的地方维护管理(OAuth)。(类似SSO单点登入)

API网关 + 服务间通信

  • 一般在后台 N 个服务和 UI 之间一般会一个代理或者叫 API Gateway
    • 提供统一服务入口,让微服务对前台透明
    • 聚合后台的服务,节省流量,提升性能(PC、Android/IOS端只需记住API网关的IP,API网关会有一个后台服务IP列表)
    • 提供安全,过滤,流控等API管理功能
    • 其实这个 API Gateway 可以有很多广义的实现办法,可以是一个软硬一体的盒子,也可以是一个简单的 MVC 框架,甚至是一个 Node.js 的服务端

img

所有的微服务都是独立的 Java 进程跑在独立的虚拟机上,所以服务间的通信就是 IPC(Inter Process Communication),已经有很多成熟的方案。现在基本最通用的有两种方式

服务间通信

同步调用(阻塞)

服务间通信:网络中只有字符串可以穿透防火墙

  • REST(JAX-RS,Spring Boot):Http通信
RESTapiString json = /users/list;USer user = new USer();user.setId(json.getId());
  • RPC(Thrift, Dubbo):远程过程调用 User user = new RPCUser();

同步调用比较简单,一致性强,但是容易出调用问题,性能体验上也会差些,特别是调用层次多的时候。一般 REST 基于 HTTP,更容易实现,更容易被接受,服务端实现技术也更灵活些,各个语言都能支持,同时能跨客户端,对客户端没有特殊的要求,只要封装了 HTTP 的 SDK 就能调用,所以相对使用的广一些。RPC 也有自己的优点,传输协议更高效,安全更可控,特别在一个公司内部,如果有统一个的开发规范和统一的服务框架时,他的开发效率优势更明显些。就看各自的技术积累实际条件,自己的选择了。
(对外REST,对内RPC)

异步消息调用

  • Kafka
  • Notify
  • MessageQueue

异步消息的方式在分布式系统中有特别广泛的应用,他既能减低调用服务之间的耦合,又能成为调用之间的缓冲,确保消息积压不会冲垮被调用方,同时能保证调用方的服务体验,继续干自己该干的活,不至于被后台性能拖慢。不过需要付出的代价是一致性的减弱,需要接受数据 最终一致性;还有就是后台服务一般要实现 幂等性,因为消息送出于性能的考虑一般会有重复(保证消息的被收到且仅收到一次对性能是很大的考验);最后就是必须引入一个独立的 Broker(消息队列的中间服务器)

Broker.png

服务发现

在微服务架构中,一般每一个服务都是有多个拷贝,来做负载均衡。一个服务随时可能下线,也可能应对临时访问压力增加新的服务节点。服务之间如何相互感知?服务如何管理?

这就是服务发现的问题了。一般有两类做法,也各有优缺点。基本都是通过 Zookeeper 等类似技术做服务注册信息的分布式管理。当服务上线时,服务提供者将自己的服务信息注册到 ZK(或类似框架),并通过心跳维持长链接,实时更新链接信息。服务调用者通过 ZK 寻址,根据可定制算法,找到一个服务,还可以将服务信息缓存在本地以提高性能。当服务下线时,ZK 会发通知给服务客户端。

ZooKeeper实现了分布式锁,解决单点故障问题

服务注册

服务注册与发现.png

Dubbo是一个RPC通信框架;ZooKeeper服务注册与发现。此处两者结合使用。

  • 基于客户端的服务注册与发现

优点是架构简单,扩展灵活,只对服务注册器依赖。缺点是客户端要维护所有调用服务的地址,有技术难度,一般大公司都有成熟的内部框架支持,比如 Dubbo。
此处调用可以是Dubbo,服务注册为ZooKeeper

img

  • 基于服务端的服务注册与发现

优点是简单,所有服务对于前台调用方透明,一般在小公司在云服务上部署的应用采用的比较多。

LB为负载均衡服务器,由LB去查询注册中心,再去调用对应指定的服务

img

微服务需要考虑的问题:

  • API Gateway
  • 服务间调用
  • 服务发现
  • 服务容错
  • 服务部署
  • 数据调用

微服务幂等性

分布式系统中的幂等性概念:用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。

幂等场景:

可能会发生重复请求或消费的场景,在微服务架构中是随处可见的。

  • 网络波动:因网络波动,可能会引起重复请求
  • 分布式消息消费:任务发布后,使用分布式消息服务来进行消费

  • 用户重复操作:用户在使用产品时,可能无意地触发多笔交易,甚至没有响应而有意触发多笔交易
  • 未关闭的重试机制:因开发人员、测试人员或运维人员没有检查出来,而开启的重试机制(如Nginx重试、RPC通信重试或业务层重试等)

CRUD操作分析

  • 新增类请求:不具备幂等性

  • 查询类动作:重复查询不会产生或变更新的数据,查询具有天然幂等性

  • 更新类请求:
    • 基于主键的计算式Update,不具备幂等性,即UPDATE goods SET number=number-1 WHERE id=1
    • 基于主键的非计算式Update:具备幂等性,即UPDATE goods SET number=newNumber WHERE id=1
    • 基于条件查询的更新,不一定具备幂等性(需要根据实际情况进行分析判断)
  • 删除类请求:
    • 基于主键的Delete具备幂等性
    • 一般业务层面都是逻辑删除(即update操作),而基于主键的逻辑删除操作也是具有幂等性的

幂等性的重要性

针对一个微服务架构,如果不支持幂等操作,那将会出现以下情况:

  • 电商超卖现象
  • 重复转账、扣款或付款
  • 重复增加金币、积分或优惠券

超卖现象
​ 比如某商品的库存为1,此时用户1和用户2并发购买该商品,用户1提交订单后该商品的库存被修改为0,而此时用户2并不知道的情况下提交订单,该商品的库存再次被修改为-1这就是超卖现象。

​ 究其深层原因,是因为数据库底层的写操作和读操作可以同时进行,虽然写操作默认带有隐式锁(即对同一数据不能同时进行写操作)但是读操作默认是不带锁的,所以当用户1去修改库存的时候,用户2依然可以都到库存为1,所以出现了超卖现象。

​ 解决方案A:可以对读操作加上显式锁(即在select …语句最后加上for update)这样一来用户1在进行读操作时用户2就需要排队等待了。但问题来了,如果该商品很热门并发量很高那么效率就会大大的下降,如何解决呢?(解决方案B)

​ 解决方案B:我们可以有条件有选择的在读操作上加锁,比如可以对库存做一个判断,当库存小于一个量时开始加锁,让购买者排队,这样一来就解决了超卖现象。

解决方案

  • 全局唯一ID

如果使用全局唯一ID,就是根据业务的操作和内容生成一个全局ID,在执行操作前先根据这个全局唯一ID是否存在,来判断这个操作是否已经执行。如果不存在则把全局ID,存储到存储系统中,比如数据库、Redis等。如果存在则表示该方法已经执行。

使用全局唯一ID是一个通用方案,可以支持插入、更新、删除业务操作。但是这个方案看起来很美但是实现起来比较麻烦,下面的方案适用于特定的场景,但是实现起来比较简单。

  • 去重表

这种方法适用于在业务中有唯一标识的插入场景中,比如在以上的支付场景中,如果一个订单只会支付一次,所以订单ID可以作为唯一标识。这时,我们就可以建一张去重表,并且把唯一标识作为唯一索引,在我们实现时,把创建支付单据写入去重表,放在一个事务中,如果重复创建,数据库会抛出唯一约束异常,操作就会回滚。

  • 插入或更新

这种方法插入并且有唯一索引的情况,比如我们要关联商品品类,其中商品的ID和品类的ID可以构成唯一索引,并且在数据表中也增加了唯一索引。这时就可以使用InsertOrUpdate操作。

  • 多版本控制

这种方法适合在更新的场景中,比如我们要更新商品的名字,这时我们就可以在更新的接口中增加一个版本号,来做幂等:boolean updateGoodsName(int id,String newName,int version);

在实现时可以如下:update goods set name=#{newName},version=#{version} where id=#{id} and version<${version}

  • 状态机控制

这种方法适合在有状态机流转的情况下,比如就会订单的创建和付款,订单的付款肯定是在之前,这时我们可以通过在设计状态字段时,使用int类型,并且通过值类型的大小来做幂等,比如订单的创建为0,付款成功为100,付款失败为99。在做状态机更新时,我们就这可以这样控制:update goods_order set status=#{status} where id=#{id} and status<#{status}

以上就是保证接口幂等性的一些方法。

总结

幂等性设计不能脱离业务来讨论,一般情况下,去重表同时也是业务数据表,而针对分布式的去重ID,可以参考以下几种方式:

  • UUID
  • Snowflake
  • 数据库自增ID
  • 业务本身的唯一约束
  • 业务字段+时间戳拼接

分类: 分布式

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

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

相关文章

【Python学习】 - Matplotlib二维绘图 - plt.matshow()和plt.imshow()区别对比

给定一个8*8的数据&#xff0c;用两种方式分别进行输出。 xx np.zeros((8,8),dtype np.uint8) xx[0,0] 13im Image.fromarray(xx) plt.imshow(im)plt.matshow(xx) plt.show() 输出&#xff1a; 得出结论&#xff1a; 首先我不知道为啥两个窗口是不一样大的。 其次发现图…

【机器学习】 - 数据预处理之数据归一化(标准化)与实战分析,正则化

一、为什么要进行数据归一化 定义&#xff1a;把所有数据的特征都归到 [0,1] 之间 或 均值0方差1 的过程。原则&#xff1a;样本的所有特征&#xff0c;在特征空间中&#xff0c;对样本的距离产生的影响是同级的&#xff1b;问题&#xff1a;特征数字化后&#xff0c;由于取值…

【基于Python】 - 人工智能机器学习深度学习数据分析 - 常见问题,常用的套路与操作(持续更新)

20200221&#xff1b; 1.做分类问题的时候&#xff0c;给定你标签&#xff0c;你想知道每一类标签的出现频数&#xff0c;可以使用这个函数&#xff1a;np.bincount()。 如果想分析一下数据样本是否均衡的时候&#xff0c;可以考虑这种操作&#xff0c;代码十分简明。 2. 当…

Entity Framework 简介

转贴&#xff1a;链接https://www.cnblogs.com/davidzhou/p/5348637.html 侵删&#xff0c;谢谢 第一篇&#xff1a;Entity Framework 简介 先从ORM说起吧&#xff0c;很多年前&#xff0c;由于.NET的开源组件不像现在这样发达&#xff0c;更别说一个开源的ORM框架&#xff0…

【Python学习】 - pyecharts包 - 地图可视化

安装&#xff1a; https://pan.baidu.com/s/1vAlSjVbHt0EDJY6C_38oEA 提取码&#xff1a;t9be 在这个链接中下载对应的.whl文件&#xff0c;放到下图所示的目录中。 然后打开anaconda prompt 找到对应的目录&#xff0c;输入&#xff1a; pip install pyecharts-0.1.9.4-py…

【机器学习】 - 关于图像质量评价IQA(Image Quality Assessment)

图像质量评价&#xff08;Image Quality Assessment,IQA&#xff09;是图像处理中的基本技术之一&#xff0c;主要通过对图像进行特性分析研究&#xff0c;然后评估出图像优劣&#xff08;图像失真程度&#xff09;。 主要的目的是使用合适的评价指标&#xff0c;使得评价结果…

【机器学习】 - CNN

什么是卷积神经网络&#xff0c;它为何重要&#xff1f; 卷积神经网络&#xff08;也称作 ConvNets 或 CNN&#xff09;是神经网络的一种&#xff0c;它在图像识别和分类等领域已被证明非常有效。 卷积神经网络除了为机器人和自动驾驶汽车的视觉助力之外&#xff0c;还可以成功…

Asp.Net中WebForm与MVC,Web API模式对比

webform&#xff0c;web mvc和web api都是asp.net官方的三套框架&#xff0c;想对比下三者的关系&#xff0c;查了下资料&#xff0c;web api跟web mvc基本同属一脉&#xff0c;只是mvc多了一个视图渲染&#xff0c;网上有些博客介绍了webform和mvc底层源码实现的不同&#xff…

【机器学习】 - Keras学习 - TensorBoard模块 - 可视化模型训练过程神器

运行环境&#xff1a;Win10 anaconda3。 TensorFlow版本&#xff1a;2.0.0 import numpy as np import tensorflow as tf import tensorflow.keras from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense import matplotlib.pyplot as…

无废话SharePoint入门教程一[SharePoint概述]

一、前言 听说SharePoint也有一段时间了&#xff0c;可一直处在门外。最近被调到SharePoint实施项目小组&#xff0c;就随着工作一起学习了一下实施与开发。但苦于网上SharePoint入门的东西实在太少&#xff0c;导致自学入门很难&#xff0c;不知道SharePoint这东西到底能做什么…

SharePoint 站点结构及概念

简单的记录一下Sharepoint的结构与基本概念 一、服务器场 服务器场,即主机的集群.简单点说就是两台机器互相备份&#xff0c;两个或几台机器之间有心跳线&#xff0c;定时检测对端设备的情况&#xff0c;如果对端设备出现故障&#xff0c;一台机器就会接管出问题机器的受保护…

【Python学习】 - sklearn学习 - 自带数据集sklearn.datasets.x

sklearn 的数据集有好多个种 自带的小数据集&#xff08;packaged dataset&#xff09;&#xff1a;sklearn.datasets.load_可在线下载的数据集&#xff08;Downloaded Dataset&#xff09;&#xff1a;sklearn.datasets.fetch_计算机生成的数据集&#xff08;Generated Datas…

sharepoint 概念及认证方式介绍

3.SharePoint Web 应用程序 我个人的理解&#xff0c;SharePoint Web 应用程序&#xff08;SharePoint Web Application&#xff09;代表的是 SharePoint 网站&#xff08;集&#xff09;的物理容器。 SharePoint Web 应用程序需要指定内容数据库、宿主 IIS 应用程序池、应用…

我们可以用SharePoint做什么

前言 不知不觉作为一个SharePoint的开发人员若干年了&#xff0c;从SharePoint api 开始学习&#xff0c;到了解SharePoint的结构&#xff0c;逐渐一点点了解sharepoint的体系&#xff1b;从SharePoint 的2007到2010到2013到SharePoint Online都接触了一些。本文会从个人的视角…

SharePoint REST API - 确定REST端点URL

SharePoint REST端点URI的结构 在你能够通过REST访问SharePoint资源之前&#xff0c;首先你要做的就是找出对应的URI端点&#xff0c;如果你对Client API熟悉&#xff0c;有些时候也可以参考Client API去猜测构建&#xff0c;例如。 客户端对象模型的方法&#xff1a; List.G…

【机器学习】 - 各种人脸数据集下载地址及说明汇总

1. Olivetti Faces人脸数据集 由40个人组成&#xff0c;共计400张人脸&#xff1b; 每人的人脸图片为10张&#xff0c;包含正脸、侧脸以及不同的表情&#xff1b; 整个数据集就是一张大的人脸组合图片&#xff0c;下载地址&#xff1a;https://cs.nyu.edu/~roweis/data/olivet…

【机器学习】 - 激活函数与交叉熵Sigmoid, Softmax, binary_crossentropy, categorican_crossentropy区别

Content: 为什么需要激活函数&#xff1b;一个神经元在做什么&#xff1b;激活函数 SigmoidSoftmax 4. 交叉熵损失函数 Binary cross-entropyCategorican cross-entropy为什么需要激活函数&#xff1a; Ans: 为了引入非线性变换。 如下图所示的红线和蓝线&#xff0c;在这个…

SharePoint 2013 Farm 安装指南——Least Privilege

写过很多关于SharePoint 2013 安装&#xff0c;这是第四篇。可能你会觉得为什么如此简单的安装至于花那么多精力去折腾吗。我的答案是肯定的。知识的积累不是一蹴而就的&#xff0c;而是循序渐进的去学习&#xff0c;每一个阶段都有独立的思考&#xff0c;于是乎第四篇SharePoi…

【机器学习】 - 关于Keras的深入理解

1.keras中使用相同的loss与metrics&#xff0c;都指定为mse&#xff0c;为什么训练时每轮完成后它们数值不一样&#xff1f; 答&#xff1a; 此时的loss是指完成最后一个batch后得到的这轮epoch的loss的加权平均&#xff0c;权重就是每个batch的样本数&#xff0c;&#xff08…

SharePoint 2007 and 2010 的服务器场的端口

由于要把一台SharePoint Server放到外网去,就把IP改到DMZ区了,结果除了系统管理员,其他帐号都无法验证通过,肯定是一些端口没开. 网上一查,SharePoint所需要的端口还真多,不过Client和WFE之间的应该开放80和443就OK了,其余的都是SharePoint Server之间,或者和 公司网络环境的…