中间件框架知识进阶

概述

近期从不同渠道了解到了一些中间件相关的新的知识,记录一下收获。涉及到的中间件包括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.rhkb.cn/news/239334.html

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

相关文章

JavaWeb后端——Maven

maven主要服务于基于Java平台的项目构建、依赖管理和项目信息管理 maven项目对象模型简称POM, maven解决问题: 1. 添加第三方jar包,maven将 jar 包放在本地仓库中统一管理,使用时用坐标的方式引用即可 2. 解决 jar 包之间的依…

MIT 6s081 lab1:Xv6 and Unix utilities

Lab1: Xv6 and Unix utilities 作业网址:https://pdos.csail.mit.edu/6.828/2020/labs/util.html Boot xv6(easy) 下载,启动xv6系统 $ git clone git://g.csail.mit.edu/xv6-labs-2020 Cloning into xv6-labs-2020... ... $ cd xv6-labs-2020 $ git …

计算机网络——应用层(3)

计算机网络——应用层(3) 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 点对点(P2P)P2P网络一般用途优点缺点总结 套接字编程基本步骤UDP套接字TCP套接字基本步骤 二者对比 小程一言 我的计算机网络专栏,是自…

基于SSM的高校班级同学录网站的设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

maven导入无法拉取所需依赖

maven导入无法拉取所需依赖 1.原因2.解决搞定收工&#xff01; 1.原因 公司使用的是gradle&#xff0c;配置的私有云&#xff0c;maven里面配置私有云完全使用不了&#xff0c;无论配置国内还是国外的&#xff0c;导入的项目报错拉不到jar包。 <mirror><id>mirro…

倒计时1天|解锁「PolarDB开发者大会」正确打开方式

1月17日 9:30-16:30 北京嘉瑞文化中心 PolarDB开发者大会 明天就要和大家就见面啦&#xff5e; 大会参会指南现已出炉 各位开发者们&#xff0c;请查收~ &#x1f447;&#x1f447;&#x1f447; 点击 大会主页 or 扫描上方二维码 一键抵达大会官网&#x1f447; 查看…

微服务接口工具Swagger2

##1、什么是Swagger? # 官网 https://swagger.io/核心功能 生成接口说明文档生成接口测试工具 2、SpringBoot集成Swagger2 1&#xff09;、添加依赖 <!-- swagger2 --><!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --><depen…

数据绑定,defineProperty,v-on,事件处理

目录​​​​​​​ v-bind单向数据绑定 defineProperty 是v-on的简写 事件处理 v-bind单向数据绑定 从name绑定到v-bind到value单向数据绑定&#xff1a; <input type"text" :value"name"> <input type "text" v-model"na…

【GCC】6 接收端实现:周期构造RTCP反馈包

基于m98代码。GCC涉及的代码,可能位于:webrtc/modules/remote_bitrate_estimator webrtc/modules/congestion_controller webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc webrtc 之 RemoteEstimatorProxy 对 remote_bitrate_estimator 的 RemoteEstimato…

线性表的应用 | 线性表的合并

线性表的合并 #include <iostream> using namespace std;#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2typedef int Status;// 定义单链表 typedef struct LNode {int data;struct LNode *next; }LNode, *…

网络文件共享服务

一.存储类型 直连式存储&#xff1a;Direct-Attached Storage&#xff0c;简称DAS 存储区域网络&#xff1a;Storage Area Network&#xff0c;简称SAN&#xff08;可以使用空间&#xff0c;管理也是你来管理&#xff09; 网络附加存储&#xff1a;Network-Attached Storage&…

代码随想录 Leetcode18. 四数之和

题目&#xff1a; 代码&#xff08;首刷看解析 2024年1月15日&#xff09;&#xff1a; class Solution { public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> result;sort(nums.begin(), nums.end(…

mac上部署单体hbase

1. 简介 HBase 是一个开源的、分布式的、版本化的典型非关系型数据库。它是 Google BigTable 的开源实现&#xff0c;并且是 Apache 基金会的 Hadoop 项目的一部分1。HBase 在 Hadoop Distributed File System (HDFS) 上运行&#xff0c;作为一个列式存储非关系数据库管理系统…

响应式编程初探-自定义实现Reactive Streams规范

最近在学响应式编程&#xff0c;这里先记录下&#xff0c;响应式编程的一些基础内容 1.名词解释 Reactive Streams、Reactor、WebFlux以及响应式编程之间存在密切的关系&#xff0c;它们共同构成了在Java生态系统中处理异步和响应式编程的一系列工具和框架。 Reactive Streams…

查看Linux系统内存、CPU、磁盘使用率和详细信息

一、查看内存占用 1、free # free -m 以MB为单位显示内存使用情况 [rootlocalhost ~]# free -mtotal used free shared buff/cache available Mem: 11852 1250 8668 410 1934 9873 Swap: 601…

【Kotlin】协程的字节码原理

前言 协程是Koltin语言最重要的特性之一&#xff0c;也是最难理解的特性。网上关于kotlin协程的描述也是五花八门&#xff0c;有人说它是轻量级线程&#xff0c;有人说它是无阻塞式挂起&#xff0c;有人说它是一个异步框架等等&#xff0c;众说纷芸。甚至还有人出了书籍专门介…

Linux用户提权

新建用户 用root账户修改文件&#xff0c;添加信任用户 使用sudo提权&#xff0c;可以使用 **root删除新建账户**

各种版本对应关系:SpringCloudAlibaba——SpringCloud——SpringBoot——SpringFramework——JDK

SpringCloudAlibaba——SpringCloud——SpringBoot——SpringFramework——JDK 一般情况&#xff0c;在https://github.com/项目/wiki目录下有发布信息及对应的要求其他依赖的版本信息SpringCloudAlibaba——SpringCloud——SpringBootSpringBoot和SpringFramework的版本对应关…

Web3的应用发展及其影响

Web3&#xff0c;又被称为去中心化Web&#xff0c;是互联网发展的一个阶段&#xff0c;其核心特点是数据的去中心化和用户自主权。近年来&#xff0c;随着区块链技术的不断成熟&#xff0c;Web3的应用也得到了广泛的关注和发展。在这篇文章中&#xff0c;我们将深入探讨Web3目前…

vuex的初步使用-1

1. 介绍 Vuex 是一个 Vue 的 状态管理工具&#xff0c;状态就是数据。 简单讲&#xff1a;Vuex 就是一个插件&#xff0c;可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。相对于一个仓库&#xff1a;存放组件共享的数据。 2. 安装 vuex 安装vuex与vue-router类似&…