小凉学RPC

一、浅谈一下微服务

1. 集群

狭义的理解:对同一个操作进行水平的拆分,交由大家共同来完成。同一个业务,部署在多个服务器上(不同的服务器运行同样的代码,干同一件事)。

  • 通过多台计算机完成同一个工作,达到更高的效率。
  • 双机或多机内容、工作过程等完全一样。如果一台死机,另一台可以起作用。

2. 分布式

狭义的理解:对同一套整操作进行垂直的拆分,交由大家各自完成部分工作。一个业务分拆多个子业务,部署在不同的服务器上(不同的服务器,运行不同的代码,为了同一个目的)。

  • 模块之间独立,各做各的事,便于扩展,复用性高。
  • 高吞吐量。某个任务需要一个机器运行10个小时,将该任务用10台机器的分布式跑(将这个任务拆分成10个小任务),可能2个小时就跑完了。

3. SOA

狭义的理解:核心是自治,把系统按照实际业务,拆分成刚刚好大小的、合适的、独立部署的模块,每个模块之间相互独立。

  • 业务系统分解为多个组件,让每个组件都独立提供离散,自治,可复用的服务能力,通过服务的组合和编排来实现上层的业务流程。
  • 作用:简化维护,降低整体风险,伸缩灵活。

4. 微服务

狭义的理解:分布式+SOA

  • 架构设计概念,各服务间隔离(分布式也是隔离),自治(分布式依赖整体组合)其它特性(单一职责,边界,异步通信,独立部署)是分布式概念的跟严格执行SOA到微服务架构的演进过程。
  • 作用:各服务可独立应用,组合服务也可系统应用。

二、RPC基本原理

1. 远程过程调用

RPC 则是远程调用,其对应的是本地调用。
RPC(Remote Procedure Call):远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。
在这里插入图片描述

RPC的主要功能是让分布式更加容易,再提供强大的远程调用能力的同时而不损失本地调用的语义简洁性。为实现该目标,RPC框架需要提供一套透明的调用机制,使使用者不用显示的区分本地调用还是分布式调用。

同步调用,异步的话MQ。

2. Stub存根?

Stub可以理解为存根,开出票据或证明后留下来的底子,上面记载着与票据或证明同样的内容,以备查考。

存根将其方法、请求类型和响应类型转换为 RPC 系统使用的形式,接收到请求后负责将方法、入参等信息序列化(组装)成能够进行网络传输的消息体。客户端存根代替最终将被执行的目标函数,同时允许客户端调用存根,就好像它是目标实现一样。

客户端存根:存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。
服务端存根:接收客户端发送过来的消息,将消息解包,并调用本地的方法。

3. RPC核心技术

  • 动态代理:生成Client stub(客户端存根)和Server Stub(服务端存根)的时候需要用到java动态代理技术。
  • 序列化:在网络中,所有的数据都将会转化为字节进行传送,需要对这些参数进行序列化和反序列化操作。目前主流的开源序列化框架有Kryo、fastJson、Hessian、Protobuf等,一般在HTTP协议的RPC框架通信中,会选择JSON方式,因为JSON有较好的扩展性、可读性和通用性。
  • NIO通信:Java提供了NIO的解决方案,Java7也提供了更优秀的NIO.2支持。可以采用Netty或者mina框架来解决数据传输的问题。开源的RPC框架Dubbo就是采用NIO通信,集成netty、mina、grizzly。
  • 服务注册中心:通过注册中心,让客户端连接调用服务端所发布的服务。主流的注册中心组件:redis、Nacos、Zookeeper、Consul、Etcd。Dubbo采用的是ZooKeeper提供服务注册与发现功能。
  • 负载均衡:在高并发的场景下,需要多个节点或者集群来提升整体的吞吐能力。
  • 健康检查:健康检查包括,客户端心跳和服务主动探测两种方式。

三、常见的开源RPC框架

1. HttpClient

HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包。HTTP Client和浏览器有点像,都可以用来发送请求,接收服务端响应的数据。
但它不是浏览器,没有用户界面。HttpClient是一个HTTP通信库,只通过其API用于传输和接受HTTP消息。甚至可以理解为一个原生的http的调用方式。
HttpClient是客户端的http通信实现库,这个类库的作用是接收和发送http报文,使用这个类库,它相比传统的 HttpURLConnection,增加了易用性和灵活性,我们对于http的操作会变得简单一些。
这里提供 官网下载链接 感兴趣可以自行下载玩一下。

  • HTTP 请求:HttpClient 提供了 URIBuilder 通用类来创建或修改请求 URI。
URI uri = new URIBuilder()
    .setScheme("http")
    .setHost("www.google.com")
    .setPath("/search")
    .setParameter("q", "httpclient")
    .setParameter("btnG", "Google Search")
    .setParameter("aq", "f")
    .setParameter("oq", "")
    .build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI())
  • HTTP 响应:HTTP 响应是 HTTP 请求发送到服务端处理后响应到客户端的消息。响应包括协议与协议版本号,接着是数字状态码和一些文本信息。
  • HTTP 消息头:HTTP 消息头(header)包含多个消息描述的信息,例如:内容长度,内容类型等。HttpClient 提供的方法有检索,添加,删除和枚举等操作。
  • HTTP Entity:HTTP 消息能携带与请求或响应有关的实体内容,它只是可选的,能在有些请求或响应中找到。请求消息中使用实体是针对 entity enclosing request 的,HTTP 规范中定义了两个 entity enclosing request 方法:POST 和 PUT。
  • 确保底层资源的释放:为了确保系统资源的释放,必须关闭与实体相关的内容流或者 response 自身。
  • 消费实体内容:消费实体内容的推荐方式是使用 HttpEntity 的 getContent () 或 HttpEntity 的 writeTo (OutputStream) 方法。HttpClient 还配备了 EntityUtils 类,它提供了几个静态方法让读取实体内容与信息更容易,而不是直接读 java.io.InputStream。能通过 EntityUtils 的这些静态方法检索整个内容体到这符串 / 字节数组。不管怎样,强烈建议不要使用 EntityUtils,除非响应实体产生自一个可信的 HTTP 服务端并且知道是有限长度的。
  • 创建实体内容:HttpClient 提供了几个通过 HTTP connection 有效地流出内容的类。这些类的实例与 POST 和 PUT 这样的 entity enclosing requests 有关,为了把这些实体内容放进即将发出的请求中。HttpClient 提供的这几个类大多数都是数据容器,像字符串,字节数组,输入流和文件对应的:StringEntity,ByteArrayEntity,InputStreamEntity 和 FileEntity。
  • response 处理:处理 response 最简单,最方便的方式是使用 ResponseHandler 接口,它包含 handleResponse (HttpResponse respnse) 方法。这种方法让用户完全不用担心连接的管理。使用 ResponseHandler 时,HttpClient 将自动释放连接并把连接放回连接管理器中,不论请求执行成功还是失败。

2. gRPC

gRPC,google的开源框架,前面带了一个g,g有global的意思,意思是全球化的,是一个高性能、开源和通用的 RPC 框架,基于ProtoBuf(Protocol Buffers) 序列化协议开发,且支持众多开发语言。面向服务端和移动端,基于 HTTP/2 设计,带有诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特性。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。
在这里插入图片描述
gRPC 基于定义服务的想法,指定了可以用参数远程调用的方法和返回类型。在服务器方面,服务器实现此接口并运行 gRPC 服务器以处理客户端呼叫。在客户端方面,客户端有一个存根,该存根提供与服务器相同的方法。
在这里插入图片描述
上图即为gRPC的一个基本调用过程。

3. Dubbo

Dubbo框架支持dubbo、rmi、hessian、http、webservice、thrift、redis等多种协议,但是Dubbo官网是推荐我们使用Dubbo协议的(缺省),采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。
Hessian底层采用HTTP通讯(同步),采用Servlet暴露服务。适用于传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。

  • 缺省协议dubbo特性如下:
* 连接个数:单连接
* 连接方式:长连接
* 传输协议:TCP
* 传输方式:NIO 异步传输
* 序列化:Hessian 二进制序列化
* 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用 dubbo 协议传输大文件或超大字符串。
* 适用场景:常规远程服务方法调用
  • rmi:阻塞式短连接,同步TCP传输,Java 标准二进制序列化。
  • hessian:多个短连接,HTTP同步传输,Hessian二进制序列化。

4. RestTemplate

RestTemplate是Spring提供的使用Restful远程访问Http的模板,理解为 Spring 提供的一个调用Restful 服务的抽象层,它简化的同 Restful 服务的通信方式,隐藏了不必要的一些细节,让我们更加优雅地在应用中调用 Restful 服务 。但是在Spring 5.0 以后RestTemplate处于维护模式,不再进行新特性的开发,仅仅进行一些日常维护。

5. Feign

Feign默认封装了Ribbon(负载均衡)去调用注册中心的服务,是一个http请求调用的轻量级框架(客户端),封装了Http调用,简化流程,更适合面向接口化。Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,封装了http调用流程。
Feign / OpenFeign ?

FeignOpenFeign
Feign是Netflix公司写的,是SpringCloud组件中的一个轻量级RESTful的HTTP服务客户端,是SpringCloud中的第一代负载均衡客户端。OpenFeign是SpringCloud自己研发的,在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。是SpringCloud中的第二代负载均衡客户端。
Feign本身不支持Spring MVC的注解,使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
Feign不再维护。OpenFeign维护频繁,Feign不再维护。

6. 基于netty手写RPC

Netty 是一个基于NIO的客户、服务器端的编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。

socket(套接字):socket是连接运行在网络上两个程序间的双向通信你的端点,通信的两端都有socket,数据在两个socket之间通过IO进行传输。
JAVA基于TCP的Socket多客户端连接同一服务器使用多线程完成(实现多人聊天功能),关于socket编程,这是我之前写的一个小博客,
小凉博客https://blog.csdn.net/weixin_42437164/article/details/89283337


四、为什么要 RPC,直接 WebClient HTTP 调用不行么?

1. 信息孤岛问题

我们使用RPC目的就是解决信息孤岛问题,WebClient HTTP对于在接口不多、系统与系统交互较少的情况下,解决信息孤岛初期常使用的一种通信手段;优点就是简单、直接、开发方便。

其实 RPC 调用是因为服务的拆分,或者本身公司内部的多个服务之间的通信。服务的拆分独立部署,那服务间的调用就必然需要网络通信,用 WebClient 调用当然可行,但是比较麻烦。
我们想即使服务被拆分了但是使用起来还是和之前本地调用一样方便。所以就出现了 RPC 框架,来屏蔽这些底层调用细节,使得我们编码上还是和之前本地调用相差不多。

并且 HTTP 协议比较的冗余,RPC 都是内部调用所以不需要太考虑通用性,只要公司内部保持格式统一即可。所以可以做各种定制化的协议来使得通信更高效。
就像特殊行动的暗号,高效简洁!所以公司内部服务的调用一般都用 RPC;
而 HTTP 的优势在于通用,大家都认可这个协议。所以第三方平台提供的接口都是通过 HTTP 协议调用的。所以我们调用第三方都是 HTTP,公司内部用RPC。

2. HTTP 的本质

超文本传输协议,协议?就是一个公认的规范。
客户端和服务端约定好的一种通信格式。
像你我之间的谈话就用中文,你要突然换成俄语我听不懂那不就 GG 了。
所以说 HTTP 它规定了一种格式,一种通信格式,大家都用这个格式来交谈。
这样不论你是什么服务器、什么浏览器都能顺利的交流。

3. HTTP / RPC ?

HTTP 和 RPC 其实是两个维度的东西。
HTTP 指的是通信协议。
RPC 的通信可以用 HTTP 协议,也可以TCP协议,或者自定义协议,是不做约束的。

RPC是一个完整的远程调用方案,它包括了:接口规范+序列化反序列化规范+通信协议等。
而HTTP只是一个通信协议,工作在OSI的第七层。
在这里插入图片描述

首先是有用信息占比少,毕竟HTTP工作在第七层,包含了大量的HTTP头等信息。
其次是效率低,还是因为第七层的缘故,必须按照HTTP协议进行层层封装。
还有,其可读性似乎没有必要,因为我们可以引入网关增加可读性。
此外,使用HTTP协议调用远程方法比较复杂,要封装各种参数名和参数值。


五、基于HTTP还是TCP协议的RPC调用

1. 基于 HTTP 协议的 RPC 调用

该方法更像是访问网页一样,只是它的返回结果更加单一简单。

其大致流程为:由服务的调用者向服务的提供者发送请求,这种请求的方式可能是 GET、POST、PUT、DELETE 等中的一种,服务的提供者可能会根据不同的请求方式做出不同的处理,或者某个方法只允许某种请求方式。

而调用的具体方法则是根据 URL 进行方法调用,而方法所需要的参数可能是对服务调用方传输过去的 XML 数据或者 JSON 数据解析后的结果,最后返回 JOSN 或者 XML 的数据结果。
由于目前有很多开源的 Web 服务器,如 Tomcat,所以其实现起来更加容易,就像做 Web 项目一样。

优势:基于 HTTP 协议实现的 RPC 则可以使用 JSON 和 XML 格式的请求或响应数据。
而 JSON 和 XML 作为通用的格式标准(使用 HTTP 协议也需要序列化和反序列化,不过这不是该协议下关心的内容,成熟的 Web 程序已经做好了序列化内容),开源的解析工具已经相当成熟,在其上进行二次开发会非常便捷和简单。
劣势:但是由于 HTTP 协议是上层协议,发送包含同等内容的信息,使用 HTTP 协议传输所占用的字节数会比使用 TCP 协议传输所占用的字节数更高。
因此在同等网络下,通过 HTTP 协议传输相同内容,效率会比基于 TCP 协议的数据效率要低,信息传输所占用的时间也会更长,当然压缩数据,能够缩小这一差距。

2. 基于 TCP 协议的 RPC 调用

由服务的调用方与服务的提供方建立 Socket 连接,并由服务的调用方通过 Socket 将需要调用的接口名称、方法名称和参数序列化后传递给服务的提供方,服务的提供方反序列化后再利用反射调用相关的方法。

最后将结果返回给服务的调用方,整个基于 TCP 协议的 RPC 调用大致如此。

优势:基于 TCP 的协议实现的 RPC 调用,由于 TCP 协议处于协议栈的下层,能够更加灵活地对协议字段进行定制,减少网络开销,提高性能,实现更大的吞吐量和并发数。


六、补充一点

RPC 主要用于公司内部的服务调用,性能消耗低,传输效率高,实现复杂。RPC 使用场景(大型的网站,内部子系统较多、接口非常多的情况下适合使用 RPC)。
HTTP 主要用于对外的异构环境,浏览器接口调用,App 接口调用,第三方接口调用等。

但是RPC需要更多关注底层复杂的细节,实现的代价更高。同时对不同平台,如安卓,iOS 等,需要重新开发出不同的工具包来进行请求发送和相应解析,工作量大,难以快速响应和满足用户需求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值