php视频网站开发实战,优秀品牌策划公司,湛江网站建设公司,神马快速排名优化工具RPC通信原理
RPC的概念
如果现在我有一个电商项目#xff0c;用户要查询订单#xff0c;自然而然是通过Service接口来调用订单的实现类。 我们把用户模块和订单模块都放在一起#xff0c;打包成一个war包#xff0c;然后再tomcat上运行#xff0c;tomcat占有一个进程用户要查询订单自然而然是通过Service接口来调用订单的实现类。 我们把用户模块和订单模块都放在一起打包成一个war包然后再tomcat上运行tomcat占有一个进程这个项目也是在这个进程中运行的模块之间的调用也是在进程的本地进行调用那么如果我是一个分布式项目该怎么解决呢 现在用户和订单模块部署在两台服务器上这时候用户模块就不能直接调用订单模块了只能够通过网络来进行调用而RPC就是用来干这个事情的通过RPC来进行服务之间的远程调用。 特点 把远程实现搬到了本地效果上远程调用和本地调用没区别这里的搬运到了本地不是真的把代码CV到调用者本地而是RPC的一种无侵入式的抽象调用者可以像调用本地服务一样去调用远程的服务其中的网络协议数据传输等实现细节被RPC屏蔽掉。使用CS模式客户端发起请求并传递参数服务端接收参数后执行并将执行结果返回底层网络通信细节对上层开发者屏蔽上层开发者无需为这一交互过程做额外的编码做到应用无侵入 RPC的应用场景有哪些 需要远程通信的各类场景 小结 RPC中的关键技术点 调用过程如下 调用流程总结 首先客户端要远程调用这个接口这个接口会由RPC底层动态代理实现远程调用然后通过序列化数据以及使用互相通信的协议编码通过网络传输到对端服务器上服务器从网络模块拿到数据经过解码、反序列化一系列操作之后调用这个函数的实现方法把结果再次经过序列化和协议编码处理之后发送给客户端客户端进行协议解码和反序列化得到数据。
小结 RPC中的高级特性
动态感知并且自动切换 当服务器压力小的时候可以减少RPC集群数量当服务器压力大的时候可以增加RPC集群节点这一过程都是自动完成的这一功能依赖于注册中心。 服务发现模块会监听注册中心看注册中心时候发送消息给服务发现模块当注册中心的配置发生变化之后注册中心会像服务发现模块发送消息告知它配置已经发生了修改然后去重写拉取配置写入本地缓存当中。 小结 RPC的优势 Zookeeper的注册原理及存储结构 Zookeeper是一个树形结构通过路径节点来标识一个节点。 https://www.runoob.com/w3cnote/zookeeper-tutorial.html 注册中心Dubbo会记录有哪些远程调用的接口及其生产者和消费者对于远程调用的接口是一个持久节点会一直存在而生产者和消费者却是临时节点这是因为 容错与自动摘除 当提供服务的生产者因为故障或正常关闭时Zookeeper上的临时节点会自动删除。这样消费者Consumer从Zookeeper获取的服务列表中将不再包含已下线的服务提供者实现了服务列表的自动更新和失效剔除。 服务实例生命周期管理 临时节点的存在与Zookeeper客户端会话绑定当服务提供者的Zookeeper客户端会话中断例如进程退出、网络断开等情况时对应的临时节点就会被清理这与服务提供者的生命周期保持一致。 负载均衡与集群伸缩性 使用临时节点可以方便地支持集群环境下的动态扩容与缩容新的服务提供者上线或者旧的提供者下线都能迅速反映到服务注册中心进而使得消费者能及时感知并调整访问策略。
Dubbo协议异步单一长连接原理与优势
2. 异步单一长连接原理
2.1 异步通信
Dubbo协议采用异步通信模型即客户端发送请求后不需要等待服务端响应可以立即进行其他操作。这种模型的核心在于使用了NIONon-blocking I/O技术通过事件驱动和回调机制来实现请求的并发处理。
具体来说客户端在发送请求后将请求信息注册到事件多路复用器上。当服务端响应到达时事件多路复用器会触发相应的回调函数进行处理。这样一来客户端就可以异步地处理多个请求提高了系统的并发能力和吞吐量。
2.2 单一长连接
Dubbo协议使用单一长连接的方式来进行通信。所谓单一长连接就是指客户端与服务端之间只建立一个TCP连接并保持长时间的有效性。
这种设计方案有以下几个优势
2.2.1 连接复用
由于只有一个TCP连接不需要频繁地建立和关闭连接避免了TCP连接的三次握手和四次挥手的开销。同时连接的复用还可以减轻网络设备的负担提高网络的利用率。
2.2.2 减少资源消耗
每个TCP连接都会占用一定的系统内存和CPU资源如果每个请求都需要建立新的连接那么系统资源开销将会非常大。而采用单一长连接的方式可以大幅度降低资源的消耗提高系统的稳定性和可伸缩性。
2.2.3 保证顺序性
由于Dubbo协议仅使用一个连接发送的请求和接收的响应不会交错。这意味着请求和响应可以按照发送的顺序进行处理不会出现乱序的情况。这在一些有序性要求较高的场景中非常重要。
3. 异步单一长连接的优势
异步单一长连接作为Dubbo协议的核心设计具有以下几个显著的优势
3.1 减少网络开销
采用异步通信模型和单一长连接方式可以减少网络的开销避免了频繁地建立和关闭连接带来的额外开销。这对于海量请求的场景尤为重要可以提升系统的性能和吞吐量。
3.2 提高系统的稳定性和可伸缩性
由于单一长连接减少了资源消耗系统的稳定性和可伸缩性得到了提高。在高并发情况下系统能够更好地承受请求的压力同时也降低了系统崩溃的风险。
3.3 简化系统维护和监控
采用单一长连接的方式简化了系统的维护和监控工作。只需要关注一个TCP连接的状态和性能指标而不需要管理多个独立的连接。这有助于提高运维效率和降低维护成本。
3.4 保证请求顺序性
由于异步通信模型和单一长连接的特性Dubbo协议能够保证请求和响应的顺序性。这对于某些有序性要求的业务场景非常重要例如金融交易系统中的订单处理。
长链接中断的情况
服务端或客户端主动断开连接。网络故障导致连接中断。客户端如消费方应用或者服务端进程终止。
代理技术 JDK Proxy原理
//JDK的动态代理
public class JdkProxyTest {public static void main(String[] args) {//会将生成的class保存在工程根目录下的 com/sun/proxy 目录里面System.setProperty(sun.misc.ProxyGenerator.saveGeneratedFiles,true);BookService bookService(BookService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), //类加载器new Class[]{BookService.class}, //要动态代理实现的方法new Handler() //要调用的方法实现);Book bookbookService.findById(100);System.out.println(book);}static class Handler implements InvocationHandler{Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//发起远程网络调用System.out.println(模拟发起网络远程调用);Book booknew Book();book.setId(args[0].toString());book.setName(斗破苍穹);book.setTitle(玄幻);book.setTag(玄幻);book.setContent(爽文);return book;}}
}查看其代理类 public final class $Proxy0 extends Proxy implements BookService {private static Method m1;private static Method m2;private static Method m0;private static Method m3;public $Proxy0(InvocationHandler var1) throws {super(var1);}public final boolean equals(Object var1) throws {try {return (Boolean)super.h.invoke(this, m1, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}public final String toString() throws {try {return (String)super.h.invoke(this, m2, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final int hashCode() throws {try {return (Integer)super.h.invoke(this, m0, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final Book findById(String var1) throws {try {return (Book)super.h.invoke(this, m3, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}static {try {m1 Class.forName(java.lang.Object).getMethod(equals, Class.forName(java.lang.Object));m2 Class.forName(java.lang.Object).getMethod(toString);m0 Class.forName(java.lang.Object).getMethod(hashCode);m3 Class.forName(BookService).getMethod(findById, Class.forName(java.lang.String));} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}对上述代码精简一下
public final class $Proxy0 extends Proxy implements BookService {private static Method m1;private static Method m2;private static Method m0;private static Method m3; //findById方法public $Proxy0(InvocationHandler var1) throws {super(var1);}public final Book findById(String var1) throws {try {return (Book)super.h.invoke(this, m3, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}static {try {m1 Class.forName(java.lang.Object).getMethod(equals, Class.forName(java.lang.Object));m2 Class.forName(java.lang.Object).getMethod(toString);m0 Class.forName(java.lang.Object).getMethod(hashCode);m3 Class.forName(BookService).getMethod(findById, Class.forName(java.lang.String));} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}super(var1);//查看一下这个函数如下protected InvocationHandler h;protected Proxy(InvocationHandler h) {Objects.requireNonNull(h);this.h h;}public final Book findById(String var1) throws {try {return (Book)super.h.invoke(this, m3, new Object[]{var1}); //这里的h就是我们传递过来的Handler方法也就是直接调用我们自己实现的handler方法} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}其他动态代理的解决方案 小结