中间件框架知识进阶

概述

近期从不同渠道了解到了一些中间件相关的新的知识,记录一下收获。涉及到的中间件包括RPC调用、动态配置中心、MQ、缓存、数据库、限流等,通过对比加深理解,方便实际应用时候更明确如何进行设计和技术选型。


一、RPC框架中间件系列

1、选型对比相关

目前主流的RPC中间件包括Dubbo、HSF、Thrift、GRPC、Spring Cloud等。结合自己的具体场景选择合适的框架。从性能、通信方式、序列化、语言、易用性、生态等方面对比分析如下:

名称语言支持底层通信方式序列化协议注册中心性能
Dubbojava开发TCP长连接hessian,json,java默认的序列化等ZK等**(还可以)
HSFjava为主,支持C++Netty框架,本质TCP长连接默认Hessian2ConfigServer等**(还可以)
Thrift通过IDL构建支持跨语言自定义的协议,在Tcp上层包装ThriftConsul等****(比grpc快2-5倍)
GRPC跨语言Http2.0Protobufetcd(go)等***(平均比Dubbo略好一点)
Spring Cloudjava开发HttpJackson、FastJson等Nacos等*(也够用)

2、Dubbo中比较核心的SPI的概念

SPI(Service Provider Interface),本质原理----策略模式+配置+反射:将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。我们需要搞清楚java的SPI和Dubbo的SPI区别:

java的SPI:

基本原理:Java的SPI|用来设计给服务提供商做插件使用的。基于策略模式来实现动态加载的机制。我们在程序只定义一个接口,具体的实现交个不同的服务提供者;在程序启动的时候,读取配置文件,由配置确定要调用哪一个实现。
实现过程:需要在 classpath 下创建一个目录,该目录命名必须是:META-INF/service2)在该目录下创建一个 文本文件,该文件需要满足以下几个条件文件名必须是扩展的接口的全路径名称文件内部描述的是该扩展接口的所有实现类文件的编码格式是 UTF-83)通过 java.util.ServiceLoader 的加载机制来加载服务。
工作流程:1)当调用 ServiceLoader.load(Class clz) 方法时,会到jar中中的目录 “META-INF/services/“ + clz.getName 进行文件读取,2)当在调用ServiceLoader.forEach()方法时,实际走的是LazyIterator,当在调用LazyIterator.hasNext() 时,在文件中读取到实际的服务实现类并把它们通过调用 Class.forName(String name, boolean initialize,ClassLoader loader)。
应用:javaSPI我们最熟悉的应用就是数据库驱动了,mysql和oracle驱动针对JDBC分别有自己的实现,这就有赖于java的SPI机制。

Dubbo的SPI:

基本原理:在dubbo中也有SPI机制,虽然都需要将接口全限定名配置在文件中,但是dubbo并没有使用java的spi机制,而是重新实现了一套功能更强的 SPI 机制, 支持了AOP与依赖注入,并且 利用缓存提高加载实现类的性能,同时 支持实现类的灵活获取。基于 SPI,我们可以很容易的对 Dubbo 进行拓展。例如dubbo当中的protocol,LoadBalance等都是通过SPI机制扩展。
实现过程:1)需要在 classpath 下创建一个目录,该目录命名可以是:META-INF/service/、META-INF/dubbo/、META-INF/dubbo/internal/2)在该目录下创建一个 文本文件,该文件需要满足以下几个条件文件名必须是扩展的接口的全路径名称文件内部描述的是该扩展接口的所有实现类,将服务实现类写成KV键值对的形式,Key是拓展类的name,Value是扩展的全限定名实现类。3)通过 org.apache.dubbo.common.extension.ExtensionLoader 的加载机制来加载服务
工作流程:两次SPI过程 1)我们首先通过 ExtensionLoader的 getExtensionLoader 方法获取一个接口的 ExtensionLoader 实例,然后再通过 ExtensionLoader 的 getExtension 方法获取拓展类对象 2)通过 ExtensionLoader.getExtensionLoader取到接口的加载器Loader之后,再通过 getExtension方法获取需要拓展类对象。
补充几个核心机制:服务发现机制 SPI、自适应机制 Adaptive、包装机制 Wrapper 与激活机制 Activate;参考https://juejin.cn/post/7112764945120362526?searchId=202401142324596D6049137EA11C7B3412
应用:例如dubbo的多协议的实现等。

区别点
(1)Java SPI在加载扩展点的时候,会一次性加载所有可用的扩展点,很多是不需要的,会浪费系统资源。
(2)dubboSPI有选择性地加载所需要的SPI接口。javaSPI配置文件中只是简单的列出了所有的扩展实现,而没有给他们命名。导致在程序中很难去准确的引用它们。而dubboSPI配置文件中以键值对的形式有别名,易于区分。
(3)SPI扩展如果依赖其他的扩展,javaspi做不到自动注入和装配,dubbo可以实现自动注入。
(4)javaSPI不提供类似于Spring的IOC和AOP功能,dubboSPI是支持的

以上参考链接:https://www.zhihu.com/question/389551161/answer/2615909871

3、几种调用方式的区分

同步调用

发起调用后线程阻塞住同步等待调用结果,适用耗时短的场景。Dubbo有容错机制,包括以下:FailoverClusterInvoker
(dubbo默认的容错机制)失败重试机制。失败自动切换,当出现失败,重试其它服务器。支持重试的,查询接口,支持幂等的写接口
FailsafeClusterInvoker
如果调用失败的化,不用抛出错误,直接打印一个异常log日志就可以了。一般来说,你要是写一些类似与远程日志数据,审计数据,或者是一些可有可无的,可以丢失的一些数据
ForkingClusterInvoker
就是会并行的调用几个服务,如果谁能先返回结果,就用谁的。cpu负载过高。
FailfastClusterInvoker
一旦调用的时候遇到了异常,直接抛出异常,不在进行重试了。
FailbackClusterInvoker
如果调用失败了,会把这个请求记录存储起来。后续根据时间轮的策略,再去隔一段时间去重试。默认是3次调用以后就会进行存储到失败列表中
BroadcastClusterInvoker
广播的形式的。所有的invoker服务实例都会接收到请求

异步RPC的实现:目前成熟的RPC框架​都会支持异步调用、异步监听、callback调用
https://blog.csdn.net/qq_34760272/article/details/123830970

Future阻塞等待结果

客户端发起请求之后,不必等待获取结果,第一次执行返回Null,随后通过Future.get()阻塞获取执行结果。

异步listener监听

有时候我们发起一个调用请求之后,并不想通过Future的get获取结果,因为get的时候是阻塞的,而是希望调用请求之后可以去做其他事情,通过一个监听去监测,当有结果返回的时候直接获取结果,然后进行逻辑处理。

异步callback回调

callback回调支持同步/异步方式,观察者模式可以伴随异步监听或者回调。
RPC是以TCP全双工的协议进行通信的,基于长连接,服务端便具备了可以“调用”客户端callback函数的能力。如果在服务端接口里面完成一个业务逻辑功能有3个过程,那么这3个过程中可以分别调用callback方法,形成“一次调用,多次通知”的机制,这一点在异步监听中是没有办法实现的,异步回调更像是“一次性买卖”。在高并发场景下建议使用异步监听的方式,因为callback方式客户端会对Callback实例的个数有限制。

参考文章地址:https://blog.csdn.net/qq_34760272/article/details/123830970

补充一个异步注解@Async
https://blog.csdn.net/weixin_47872288/article/details/125512173?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-5-125512173-blog-51165251.235v40pc_relevant_anti_vip&spm=1001.2101.3001.4242.4&utm_relevant_index=8

以上内容参考:
https://blog.csdn.net/asdcls/article/details/121661651
https://zhuanlan.zhihu.com/p/458254270
https://www.zhihu.com/question/389551161?utm_id=0

二、HTTP/TCP 长短连接/长短轮询

1.TCP长短连接

HTTP协议是基于请求/响应模式的,因此只要服务端给了响应,本次HTTP连接就结束了,或者更准确的说,是本次HTTP请求就结束了,根本没有长连接这一说,那么自然也就没有短连接这一说了;网上所说的长连接、短连接,本质其实说的是TCP连接。TCP连接是一个双向通道,它是可以保持一段时间不关闭,因此TCP才有正真的长连接、短连接 。Http1.1以前是短连接,单次请求后关闭连接,下次重新TCP三次握手建立连接。长连接回保持TCP连接,使得多个HTTP请求可以复用同一个TCP连接。
短连接的操作步骤是:
建立连接——数据传输——关闭连接…建立连接——数据传输——关闭连接
长连接的操作步骤是:
建立连接——数据传输…(保持连接)…数据传输——关闭连接
优缺点:长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。在长连接的应用场景下,client 端一般不会主动关闭它们之间的连接,Client与server之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候。
应用场景:一般用于实时通信,比如Dubbo和HSF框架的注册中心和服务的发布与订阅者之间的通信。以及RocketMQ(MetaQ支持推push与拉poll模型)的NameServer和Broker与生产者、消费者之间的通信。
参考:https://www.jianshu.com/p/f36f83684f93
https://www.cnblogs.com/zhaozl/p/11168185.html

2.HTTP长短轮询

短轮询由客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接;即在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客户端的浏览器(可以理解为TCP连接不复用)。
长轮询:请求进来,有数据就返回,没有就hang住(先不把请求响应给前端),直到有数据或者超时再返回(然后立即再发起一个请求过来)。客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
轮询:客户端每隔一段时间ajax
长轮询:客户端请求1——服务端hold——服务端返回——客户端请求2
优缺点:短轮询实现容易,当请求中有大半是无用,难于维护,浪费带宽和服务器资源;响应的结果没有顺序(因为是异步请求,当发送的请求没有返回结果的时候,后面的请求又被发送。而此时如果后面的请求比前面的请 求要先返回结果,那么当前面的请求返回结果数据时已经是过时无效的数据了)。长轮询在无消息的情况下不会频繁的请求,耗费资源小,HTTP连接都不会复用TCP连接。
应用场景:动态配置中心,大量客户端请求,但是更新不频繁的请求与推送场景。比如Diamond持久化配置中心的动态更新通知,支持基于HTTP短轮询的“拉模型”和基于HTTP长轮询的“推模型”。

这里做简要解释,长连接是基于传输层的TCP连接通道,具备实时的双向传输能力,建立连接的过程中,就算server不回应,client也可以源源不断的向server发消息,连接不能“挂起”,需要一直保持连接状态,TCP连接多了,会对server造成很大连接负担。
长轮询是基于HTTP的连接,必须是请求—响应模式的,server可以不做出响应,将HTTP连接“挂起”,去处理其他的HTTP连接,对服务器的负担较小,因为server可以处理其他的HTTP请求,不用一直关注被“挂起”的HTTP连接。
实质上Diamond即支持由server向client动态的推送最新的配置,也支持client如果有需要可以主动从server拉最新的配置,非常灵活,可以适应各种业务场景。

参考:https://blog.csdn.net/dddgg__/article/details/133251289
参考https://www.cnblogs.com/Joeris/articles/10999373.html
https://blog.csdn.net/H200102/article/details/107354799

从兼容性角度考虑,短轮询 > 长轮询 > 长连接SSE > WebSocket;
从性能方面考虑,WebSocket > 长连接SSE > 长轮询 > 短轮询。
https://blog.csdn.net/sugelachao/article/details/124490112

HTTP与TCP通信区别:
Http是无转态的连接,TCP是有状态的长连接。
传输内容上:HTTP超文本传输,包的大小比TCP大。tcp比http快,是因为发送同样的有效数据,http比tcp多封装一次,也就是硬件实际要发送的数据量更大,那么自然耗时更多。
RPC为什么比HTTP快:
假设
这里的RPC服务一般是指基于TCP/IP协议上开发的二进制协议服务
Http服务一般是指基于Http1.0 / Http1.1协议上开发的REST服务
对比
序列化方式:
RPC服务序列化是针对二进制协议(0/1)来做序列化和反序列化,所以性能高。
而Http服务是基于文本的序列化和反序列化,需要读一行一行的文本(比如json格式的),进行序列化和反序列化,所以性能低。
报文长度:
RPC服务是自定义的传输协议,传输的报文都是干货。
而Http服务里面包括很多没用的报文内容,比如Http Header里面的accept,referer等等
连接的复用:
RPC服务是基于TCP/IP协议的,是长连接。
而Http服务大都是短连接,虽然Http1.1支持长连接,但是这个也是要取决于服务端是否支持长连接,不太可控。
结论
在追求性能的场合,用RPC服务(基于TCP/IP传输协议)
在追求兼容性多语言的场合,用REST服务
企业内部一般微服务互相调用用基于TCP的高性能RPC,对外网关支持HTTP请求。
https://blog.csdn.net/u013531487/article/details/130337143
https://blog.csdn.net/hudmhacker/article/details/108375757

三、缓存与数据库

数据库分库分表:对比ShardingJDBC和MyCat的设计。
缓存的热点数据处理:基于集群分片多级缓存打散读请求,合并写请求。
分库分表的主键ID选择:为什么不推荐UUID 全局自增 雪花算法
https://blog.csdn.net/qq_43665821/article/details/123883614?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-123883614-blog-112151582.235%5Ev40%5Epc_relevant_anti_vip&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-123883614-blog-112151582.235%5Ev40%5Epc_relevant_anti_vip&utm_relevant_index=2
https://zhuanlan.zhihu.com/p/459357903

四、分布式锁实现与应用

常见的几种实现包括:基于Redis的SetNX、LUA脚本、Redission红锁框架、ZK的临时顺序节点创建&监听等。
主要区别:基于CAP和BASE理论,基于Redis的分布式锁是AP系统(集群数据同步机制是Gossip协议,会有短期的数据不一致问题),ZK的是CP系统(集群数据同步采用ZAB协议,会牺牲掉一部分的可用性)
在这里插入图片描述
关于分布式系统的一致性协议划分:
强一致性,保证系统改变提交以后立即改变集群的状态,有以下几个模型:Paxos、Raft、Zab
弱一致性,也叫最终一致性,不用保证提交立刻在集群内全部生效,但需要随着时间的推移生效,有以下几个模型:DNS系统、Gossip协议
协议介绍参考:https://zhuanlan.zhihu.com/p/617831925

关于是否支持可重入锁、支持公平/非公平锁:
其实Redisson和ZK都能实现,具体实现方式参考如下:
https://www.jianshu.com/p/cee3c8092aa5
https://blog.51cto.com/u_15162069/2806447

总结

本文总结了一些中间件框架的进阶知识,涉及到的中间件包括RPC调用、动态配置中心、MQ、缓存、数据库、限流等。主要通过对比的方式增强记忆和理解,方便实际应用过程中进行技术方案的设计和选择。

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

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

相关文章

华清远见作业第二十七天——网络编程(第二天)

思维导图&#xff1a; 在虚拟机实现客户端控制机械臂 代码&#xff1a; #include<stdio.h> #include<string.h> #include<stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <a.h> #define SER_PORT 8888 //服务端口 #d…

SpringBoot 启动优化实践!

背景 公司 SpringBoot 项目在日常开发过程中发现服务启动过程异常缓慢&#xff0c;常常需要 6-7 分钟才能暴露端口&#xff0c;严重降低开发效率。通过 SpringBoot 的 SpringApplicationRunListener 、BeanPostProcessor 原理和源码调试等手段排查发现&#xff0c;在 Bean 扫描…

Linux安装Rdkafka PHP 扩展(Kafka使用教程)

以是centos为例 #可以查看php版本 php -v#查看php安装的扩展库 php -m 1、首先&#xff0c;确保你已经安装了 PHP 和相关的开发工具。你可以使用以下命令来安装它们&#xff1a; sudo yum install php-devel 中间会问你是否ok&#xff0c;输入y回车&#xff0c;出现complete…

pycharm debug显示的变量过多

问题&#xff1a; https://blog.csdn.net/Hodors/article/details/117535731 解决方法&#xff1a; 把"Show console variables by default"前面的勾取消掉就行 参考&#xff1a; https://stackoverflow.com/questions/48969556/hide-console-variables-in-pychar…

数据结构——二叉树(先序、中序、后序及层次四种遍历(C语言版))超详细~ (✧∇✧) Q_Q

目录 二叉树的定义&#xff1a; *特殊的二叉树&#xff1a; 二叉树的性质&#xff1a; 二叉树的声明&#xff1a; 二叉树的先序遍历&#xff1a; 二叉树的中序遍历&#xff1a; 二叉树的后序遍历&#xff1a; 二叉树的层序遍历&#xff1a; 二叉树的节点个数&#xff1a; 二叉…

使用netdxf(C#)框架实现dxf文件读取与导出坐标

使用netdxf&#xff08;C#&#xff09;框架实现dxf文件读取与导出坐标 一、新建窗体应用程序DxfToolDemo&#xff0c;将默认的Form1重命名为FormDxfTool 窗体FormDxfTool.Designer.cs设计器源程序如下&#xff1a; namespace DxfToolDemo {partial class FormDxfTool{/// <…

x-cmd pkg | magic-wormhole - (魔法虫洞)文件传输工具

目录 简介首次用户功能特点竞品和相关作品进一步探索 简介 magic-wormhole 是一个用于在两台计算机之间安全传输文件的工具。它通过创建一个临时的点对点连接&#xff0c;允许用户将文件或文本从一台计算机发送到另一台计算机。 它使用 PAKE 这一系列的加密算法&#xff0c;通…

扫地机行业研究:预计2028年将达到78.51亿美元

吸尘器、扫地机器人、洗地机为清洁电器中最亮眼的三大品类。吸尘器主要用来吸尘&#xff0c;扫地机的主要作用也是用于除尘&#xff0c;具备扫拖一体功能的扫地机&#xff0c;干湿混合垃圾暂时做不到干净清理。洗地机集齐了“吸、拖、洗”三种功能为一体&#xff0c;并且具备自…

消息队列-RockMQ-定时延时发送消息

定时延时发送消息 任务需要延迟一段时间再进行处理。 生产者 public class Producer {public static void main(String[] args) throws Exception {DefaultMQProducer producer new DefaultMQProducer("producer_group");producer.setNamesrvAddr("ip:9876&q…

【Python 数据分析】数据预处理:z-score 标准化、min-max 归一化、数据缺失值处理、数据重复处理

目录 简述 / 前言1. z-score 标准化2. min-max 归一化3. 数据缺失值处理4. 数据重复处理 简述 / 前言 本篇文章分享数据分析中最重要的一个步骤&#xff1a;数据预处理。我们在做数据分析之前&#xff0c;都需要采集很多数据&#xff0c;这些数据可能是从官网下载的&#xff0…

【docker-compose】【nginx】内网环境https配置

目录 1、openssl生成自签名证书和私钥2、nginx.conf配置ssl3、docker-compose挂载 1、openssl生成自签名证书和私钥 在部署服务器上&#xff0c;新建cert目录&#xff0c;执行以下指令&#xff0c;然后生成.crt和.key文件 openssl req -newkey rsa:2048 -nodes -keyout rsa_pri…

linux yum仓库

yum是基于rpm包构建的软件更新机制&#xff0c;能够自动解决软件包之间的依赖关系。 常用命令 查询 yum list [软件名] 显示可用的安装包&#xff0c;如果不加软件名则显示所有的可用包 yum info [软件名] 显示安装包的详细信息 如果不加软件名是显示所有包…

2024年【上海市安全员B证】考试试卷及上海市安全员B证复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 上海市安全员B证考试试卷根据新上海市安全员B证考试大纲要求&#xff0c;安全生产模拟考试一点通将上海市安全员B证模拟考试试题进行汇编&#xff0c;组成一套上海市安全员B证全真模拟考试试题&#xff0c;学员可通过…

海外短剧APP小程序开发 随心随意畅享大片

随着智能手机的普及和网络的高速发展&#xff0c;短剧APP已经成为当今热门的观影方式。作为一种全新的观影体验&#xff0c;海外短剧APP以其丰富多样的内容吸引了大量用户。本文将为您介绍海外短剧APP开发的相关知识和其所带来的优势&#xff0c;以及市场前景和发展趋势。 海外…

jsonschema,一个超强的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个超强的 Python 库 - jsonschema。 Github地址&#xff1a;https://github.com/python-jsonschema/jsonschema JSON&#xff08;JavaScript Object Notation&#xff09;是…

MySQL 多版本并发控制 MVCC

MVCC出现背景 事务的4个隔离级别以及对应的三种异常 读未提交&#xff08;Read uncommitted&#xff09; 读已提交&#xff08;Read committed&#xff09;&#xff1a;脏读 可重复读&#xff08;Repeatable read&#xff09;&#xff1a;不可重复读 串行化&#xff08;Se…

.NET领域最硬核的gRPC 核心能力一把梭

前言&#xff0c;本文定位为.NET方向 grpc核心能力一把梭&#xff0c;全篇是姿势性和结论性的展示&#xff0c; 方便中高级程序员快速上手.NET Grpc。 有关grpc更深层次的前世今生、底层原理、困惑点释疑请听下回分解&#xff0c; 欢迎菜鸟老鸟们提出宝贵意见。 grpc宏观目标&…

跨平台进程/任务管理服务——Meproc的配置

配置 Meproc的配置非常简单&#xff0c;只有以下几个配置选项。 Conf [ip: 0.0.0.0,port: 8606,log_level: debug,log_dir: /tmp,web: [ip: 127.0.0.1,port: 8606,],bootstrap_cmd: , ];ip 是 Meproc 服务监听 HTTP 请求的地址。port 是Meproc服务监听HTTP请求的端口。log_l…

「Vue3面试系列」Vue 3.0中如果想实现一个 Modal组件应该怎么设计?

文章目录 一、组件设计二、需求分析三、实现流程目录结构组件内容实现 API 形式事件处理其他完善 一、组件设计 组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念&#xff08;组件&#xff09;来实现开发的模式 现在有一个场景&#xff0c;点击新增与编辑都弹框出来进…

51单片机学习总结(自学)

1、模块化编程 c语言模块化编程实现思路设计代码 具体的程序实现代码如下所示 1&#xff1a;程序的头文件 2&#xff1a;程序的函数文件 3&#xff1a;程序的主文件控制函数的实现 持续更新中......