精华内容
参与话题
问答
  • 分布式通信框架

    千次阅读 2018-04-12 16:55:36
    1. 分布式架构的定义以及分布式架构的演进。 2. 分布式架构和集群的区别 3. TCP/UDP、全双工、半双工、3次握手协议、4次挥手协议 1、 FIN标识的报文给到server端 2、 server端接收到FIN报文以后,表示Client端没有...

    回顾

    1.  分布式架构的定义以及分布式架构的演进。
    2.  分布式架构和集群的区别
    3.  TCP/UDP、全双工、半双工、3次握手协议、4次挥手协议
        1、  FIN标识的报文给到server2server端接收到FIN报文以后,表示Client端没有数据要发给Server端了
        3server端发送ACK给到Client端,表示Server端的数据已经发完了。准备关闭链接
        4、  client端收到ACK报文以后,知道可以关闭连接了,发送ACK请求到Server端,自己进入TIME-WAIT
        5Server端接收到ACK以后,表示可以断开连接了
        6、  Client端等待一定时间后,没有收到回复,表示Client可以关闭连接
    4.  TCP的非阻塞IO
    5.  序列化
        1.  SerialVersionUID
        2.  静态变量序列化问题、Transient关键字、父子类的序列化问题
        3.  kryo、FST、JSON、XML、protobuf、Hessian、Avro、Thrift
    6.  http和https协议、RESTful规范
        1.  客户端发起一个https请求
            a)  客户端支持的加密方式
            b)  客户端生成的随机数(第一个随机数)
        2.  服务端收到请求后,拿到随机数,返回
            a)  证书(颁发机构(CA)、证书内容本身的数字签名(使用第三方机构的私钥加密)、证书持有者的公钥、证书签名用到的hash算法)
            b)  生成一个随机数,返回给客户端(第二个随机数)
        3.  客户端拿到证书以后做验证
            a)  根据颁发机构找到本地的跟证书
            b)  根据CA得到根证书的公钥,通过公钥对数字签名解密,得到证书的内容摘要 A
            c)  用证书提供的算法对证书内容进行摘要,得到摘要 B
            d)  通过A和B的对比,也就是验证数字签名
        4.  验证通过以后,生成一个随机数(第三个随机数),通过证书内的公钥对这个随机数加密,发送给服务器端
        5.  (随机数1+2+3)通过对称加密得到一个密钥。(会话密钥)
        6.  通过会话密钥对内容进行对称加密传输
    

    分布式通信框架—RMI讲解

    什么是RPC
        Remote procedure call protocal 
        RPC协议其实是一个规范。DubboThrifRMIWebserviceHessain
    
    网络协议和网络IO对于调用端和服务端来说是透明; 

    一个RPC框架包含的要素

    这里写图片描述

    一个RPC框架需要包含的要素:底层的协议层要包装好、消息处理层(包括序列化和反序列化)、代理层(对象转换,屏蔽掉我们的服务调用的关系逻辑)、业务层(调用接口)

    RMI的概述

    RMI(remote method invocation)  , 可以认为是RPCjava版本。
    
    RMI使用的是JRMPJava Remote Messageing Protocol), JRMP是专门为java定制的通信协议,所以它是纯java的分布式解决方案

    如何实现一个RMI程序

    1.  创建远程接口, 并且继承java.rmi.Remote接口
    2.  实现远程接口,并且继承:UnicastRemoteObject
    3.  创建服务器程序: createRegistry方法注册远程对象
    4.  创建客户端程序

    如果自己要去实现一个RMI

    1.  编写服务器程序,暴露一个监听, 可以使用socket。
    2.  编写客户端程序,通过ip和端口连接到指定的服务器,并且将数据做封装(序列化)。
    3.  服务器端收到请求,先反序列化。再进行业务逻辑处理。把返回结果序列化返回。
    

    Stub和Skeleton是两个代理对象。

    这里写图片描述

    这里写图片描述

    展开全文
  • 从今天开始就来介绍多个进程之间通信的相关内容,那么首先先介绍分布式通信中的远程调用。 什么是远程调用? 以电商购物平台为例,每一笔交易都涉及订单系统、支付系统及库存系统,假设三个系统分别部署在三台机器 A...

    前言

    分布式的本质就是多进程协作,共同完成任务。要协作,自然免不了通信。从今天开始就来介绍多个进程之间通信的相关内容,那么首先先介绍分布式通信中的远程调用

    什么是远程调用?

    以电商购物平台为例,每一笔交易都涉及订单系统支付系统库存系统,假设三个系统分别部署在三台机器 A、B、C 中独立运行,订单交易流程如下所示:

    1. 用户下单时,调用本地(机器 A)的订单系统进行下单;
    2. 下单完成后,会远程调用机器 B 上的支付系统进行支付,待支付完成后返回结果,之后在本地更新订单状态;
    3. 在本地远程调用机器 C 上的仓库系统出货,出货完成后返回出货结果。

    在整个过程中,“下单”和“订单状态更新”两个操作属于本地调用,而“支付”和“出货”这两个操作是通过本地的订单系统调用其他两个机器上的函数(方法)实现的,属于远程调用。

    整个订单交易流程如下图所示。
    在这里插入图片描述

    • 本地调用通常指的是:进程内函数之间的相互调用;
    • 远程调用,是进程间函数的相互调用,是进程间通信 IPC(Inter-Process Communication)的一种方式。通过远程调用,一个进程可以看到其他进程的函数、方法等。

    在分布式领域中,一个系统由很多服务组成,不同的服务由各自的进程单独负责,因此,远程调用在分布式通信中尤为重要。
    根据进程是否部署在同一台机器上,远程调用可以分为如下两类:

    • 本地过程调用(Local Procedure Call,LPC),是指运行在同一台机器上的进程之间的互相通信,即在多进程操作系统中,运行的不同进程之间可以通过 LPC进行函数调用
    • 远程过程调用(Remote Procedure Call,RPC),是指不同机器中运行的进程之间的相互通信,某一机器上运行的进程在不知道底层通信细节的情况下,就像访问本地服务一样,去调用远程机器上的服务。

    在这两种远程调用中,RPC 中的不同进程是跨机器的,适用于分布式场景,也是本文介绍的重点。

    远程调用的原理及应用

    我们熟知的 B/S ( Browser/Server,浏览器 / 服务器) 架构。在这种架构中,被调用方(服务器)有一个开放的接口,然后调用方(用户)通过 Browser 使用这个接口,来间接调用被调用方相应的服务,从而实现远程调用。

    但是,B/S 架构是基于 HTTP 协议实现的,每次调用接口时,都需要先进行 HTTP 请求。既繁琐又费时,不适用于有低时延要求的大规模分布式系统,所以远程调用的实现大多采用更底层的网络通信协议。

    接下来,介绍两种常用的远程调用机制:

    • 远程过程调用 RPC(Remote Procedure Call)
    • 远程方法调用 RMI(Remote Method Invocation)

    RPC 的原理及应用

    RPC 就是调用方采用参数传递的方式,通过调用本机器上的一个函数或方法,去执行远程机器上的函数或方法(可以统称为服务),并返回结果。在整个过程中,RPC 会隐藏具体的通信细节。

    如下图所示,以电商购物平台的“支付”操作为例,来了解 RPC 调用的完整流程:
    在这里插入图片描述

    1. 本地服务器也就是机器 A 中的订单系统,调用本地服务器上的支付系统中的支付操作 Pay(Order),该方法会直接调用 ClientStub(其中,Stub 是用于转换 RPC 过程中在订单系统和支付系统所在机器之间传递的参数),这是一次正常的本地调用。
    2. Client Stub 将方法 Pay、参数 Order 等打包成一个适合网络传输的消息,通过执行一次系统调用(也就是调用操作系统中的函数)来发送消息。
    3. 订单系统所在机器 A 的本地操作系统通过底层网络通信,将打包好的消息根据支付系统所在机器 B 的地址发送出去。
    4. 机器 B 上的操作系统接收到消息后,将消息传递给 Server Stub。
    5. 机器 B 上的 Server Stub 将接收到的消息进行解包,获得里面的参数,然后调用本地的支付订单的操作 Pay(Order)。
    6. 机器 B 上的支付操作 Pay(Order) 完成后,将结果发送给 Server Stub,其中结果可使用 XDR(External Data Representation,一种可以在不同计算机系统间传输的数据格式)语言表示。
    7. 机器 B 上的 Server Stub 将结果数据打包成适合网络传输的消息,然后进行一次系统调用发送消息。
    8. 机器 B 的本地操作系统通过底层网络将打包好的消息发送回机器 A。
    9. 机器 A 的操作系统接收到来自机器 B 的消息,并将消息发送给本地的 Client Stub。
      10.本地的 Client Stub 将消息解包,然后将解包得到的结果返回给本地的订单系统。

    至此整个 RPC 过程结束。

    从整个流程可以看出,机器 A 上的 Pay(Order)、 Client Stub 和网络调用之间的交互属于本地调用,机器 B 上的 Pay(Order)、Server Stub 和网络调用之间的交互也属于本地调用。

    而机器 A 和机器 B 之间的远程调用的核心是,发生在机器 A 上的网络调用和机器 B 上的网络调用。RPC 的目的,其实就是要将第 2 到第 8 步的几个过程封装起来,让用户看不到这些细节。使得从用户的角度看,订单系统的进程只是做了一次普通的本地调用,然后就得到了结果。
    订单系统进程并不需要知道底层是如何传输的,在用户眼里,远程过程调用和调用一次本地服务没什么不同。这,就是 RPC 的核心

    RPC 与本地调用(进程内函数调用)的区别

    在 RPC 中,由于不同进程内存空间无法共享,且涉及网络传输,所以不像本地调用那么简单。RPC 与本地调用主要有三点不同:
    第一个区别是,调用 ID 和函数的映射。
    在本地调用中,进程内可共享内存地址空间,因此程序可直接通过函数名来调用函数。而函数名的本质就是一个函数指针,可以看成函数在内存中的地址。比如,调用函数 f(),编译器会帮我们找到函数 f() 相应的内存地址。

    但在 RPC 中,只通过函数名是不行的,因为不同进程的地址空间是不一样的

    所以在 RPC 中,所有的函数必须要有一个调用 ID 来唯一标识。一个机器上运行的进程在做远程过程调用时,必须附上这个调用 ID

    另外,我们还需要在通信的两台机器间,分别维护一个函数与调用 ID 的映射表。两台机器维护的表中,相同的函数对应的调用 ID 必须保持一致。

    当一台机器 A 上运行的进程 P 需要远程调用时,它就先查一下机器 A 维护的映射表,找出对应的调用 ID,然后把它传到另一台机器 B 上,机器 B 通过查看它维护的映射表,从而确定进程 P 需要调用的函数,然后执行对应的代码,最后将执行结果返回到进程 P。

    第二个区别是,序列化和反序列化。
    我们知道了调用方调用远程服务时,需要向被调用方传输调用 ID 和对应的函数参数,那调用方究竟是怎么把这些数据传给被调用方的呢?

    在本地调用中,进程之间共享内存等,因此我们只需要把参数压到栈里,然后进程自己去栈里读取就行。但是在 RPC 中,两个进程分布在不同的机器上,使用的是不同机器的内存,因此不可能通过内存来传递参数。

    网络协议传输的内容是二进制流,无法直接传输参数的类型,因此这就需要调用方把参数先转成一个二进制流,传到被调用方后,被调用方再把二进制流转换成自己能读取的格式。这个过程,就叫作序列化和反序列化

    同理,被调用方返回的结果也需要有序列化和反序列化的过程,不然调用方无法获取到结果。也就是说,RPC 与本地调用相比,参数的传递需要进行序列化和反序列化操作

    第三个区别是,网络传输协议。
    序列化和反序列化解决了调用方和被调用方之间的数据传输格式问题,但要想序列化后的数据能在网络中顺利传输,还需要有相应的网络协议,比如 TCP、UDP 等,因此就需要有一个底层通信层。

    调用方通过该通信层把调用 ID 和序列化后的参数传给被调用方,被调用方同样需要该通信层将序列化后的调用结果返回到调用方。

    也就是说,只要调用方和被调用方可以互传数据,就可以作为这个底层通信层。因此,它所使用的网络协议可以有很多,只要能完成网络传输即可。目前来看,大部分 RPC 框架采用的是 TCP 协议。

    RPC 框架 Apache Dubbo

    Dubbo 引入了服务注册中心的基础上,又加入了监控中心组件(用来监控服务的调用情况,以方便进行服务治理),从而实现了一个 RPC 框架。

    如下图所示,Dubbo 的架构主要包括 4 部分:

    • 服务提供方:服务提供方会向服务注册中心注册自己提供的服务。
    • 服务注册中心:服务注册与发现中心,负责存储和管理服务提供方注册的服务信息和服务调用方订阅的服务类型等。
    • 服务调用方:根据服务注册中心返回的服务所在的地址列表,通过远程调用访问远程服务。
    • 监控中心:统计服务的调用次数和调用时间等信息的监控中心,以方便进行服务管理或服务失败分析等。

    在这里插入图片描述
    可以看到,Dubbo 的大致工作流程如下:

    1. 服务提供方需要向服务注册中心注册自己提供的服务;
    2. 服务调用方需要向注册中心预订调用服务的提供方地址列表;
    3. 服务注册中心将服务对应的提供方地址列表返回给调用方;
    4. 服务调用方根据服务地址信息进行远程服务调用;
    5. 服务调用方和服务提供方定时向监控中心发送服务调用次数及调用时间等信息。

    RMI 的原理及应用

    RMI 是一个基于 Java 环境的应用编程接口,能够让本地 Java 虚拟机上运行的对象,像调用本地对象一样调用远程 Java 虚拟机上的对象。

    RMI 的具体原理如下图所示:

    RMI 可以说是 RPC 的一种具体形式,其原理与 RPC 基本一致,唯一不同的是 RMI 是基于对象的,充分利用了面向对象的思想去实现整个过程,其本质就是一种基于对象的 RPC 实现。
    RMI 的具体原理如下图所示:
    在这里插入图片描述
    RMI 的实现中,客户端的订单系统中的 Stub 是客户端的一个辅助对象,用于与服务端实现远程调用;服务端的支付系统中 Skeleton 是服务端的一个辅助对象,用于与客户端实现远程调用。

    RPC 与 RMI 对比分析

    在这里插入图片描述

    总结

    在这里插入图片描述

    展开全文
  • 分布式消息通信框架RMI原理分析

    千次阅读 2018-11-11 18:24:12
    什么是RPC  RPC(Remote Procedure Call,远程过程调用),一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远端系统资源;对于客户端来说, 传输层...

    什么是RPC

           RPC(Remote Procedure Call,远程过程调用),一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远端系统资源;对于客户端来说, 传输层使用什么协议,序列化、反序列化都是透明的

    了解 Java RMI 

           RMI 全称是 remote method invocation – 远程方法调用,一种用于远程过程调用的应用程序编程接口,是纯 java 的网络分布式应用系统的核心解决方案之一。

           RMI 目前使用 Java 远程消息交换协议 JRMP(Java Remote Messageing Protocol)进行通信,由于 JRMP 是专为 Java对象制定的,是分布式应用系统的百分之百纯 java 解决方案,用 Java RMI 开发的应用系统可以部署在任何支持 JRE的平台上,缺点是,由于 JRMP 是专门为 java 对象指定的,因此 RMI 对于非 JAVA 语言开发的应用系统的支持不足,不能与非 JAVA 语言书写的对象进行通信

    Java RMI 代码实践

    详见代码

           远程对象必须实现 UnicastRemoteObject,这样才能保证客户端访问获得远程对象时,该远程对象会把自身的一个拷贝以 Socket 形式传输给客户端,客户端获得的拷贝称为“stub” , 而 服 务 器 端 本 身 已 经 存 在 的 远 程 对 象 成 为“skeleton”,此时客户端的 stub 是客户端的一个代理,用于与服务器端进行通信,而 skeleton 是服务端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求

    Java RMI 源码分析

    远程对象发布

    远程引用层

    一步步解读源码

    发布远程对象

           发布远程对象,看到上面的类图可以知道,这个地方会发布两个远程对象,一个是 RegistryImpl、另外一个是我们自己写的 RMI 实现类对象;

            从 HelloServiceImpl 的 构 造 函 数 看 起 。 调 用 了 父 类UnicastRemoteObject 的 构 造 方 法 , 追 溯 到
    UnicastRemoteObject 的私有方法 exportObject()。这里做 了 一 个 判 断 , 判 断 服 务 的 实 现 是 不 是UnicastRemoteObject 的子类,如果是,则直接赋值其 ref(RemoteRef)对象为传入的 UnicastServerRef 对象。反之则调用 UnicastServerRef 的 exportObject()方法。IHelloService helloService=new HelloServiceImpl();因为 HelloServiceImpl 继承了 UnicastRemoteObject,所以在服务启动的时候,会通过 UnicastRemoteObject 的构造方法把该对象进行发布

    服务端启动 Registry 服务

            从上面这段代码入手,开始往下看。可以发现服务端创建了一个 RegistryImpl 对象,这里做了一个判断,如果服务端指定的端口是 1099 并且系统开启了安全管理器,那么就可以在限定的权限集内绕过系统的安全校验。这里纯粹是为 了 提 高 效 率 ,真 正 的 逻 辑 在 this.setup(new UnicastServerRef())这个方法里面

           setup 方法将指向正在初始化的 RegistryImpl 对象的远程引用 ref(RemoteRef)赋值为传入的 UnicastServerRef 对象,这里涉及到向上转型,然后继续执行 UnicastServerRef 的exportObject 方法

      进入 UnicastServerRef 的 exportObject()方法。可以看到,这里首先为传入的 RegistryImpl 创建一个代理,这个代理我们可以推断出就是后面服务于客户端的 RegistryImpl 的Stub(RegistryImpl_Stub)对象。然后将 UnicastServerRef的 skel(skeleton)对象设置为当前RegistryImpl 对象。最后用 skeleton、stub、UnicastServerRef 对象、id 和一个boolean 值构造了一个 Target 对象,也就是这个 Target 对象基本上包含了全部的信息,等待 TCP 调用。调用UnicastServerRef 的 ref(LiveRef)变量的 exportObject()方法。

    【var1=RegistryImpl ; var 2 = null ; var3=true】LiveRef 与 TCP 通信的类

           到上面为止,我们看到的都是一些变量的赋值和创建工作,还没有到连接层,这些引用对象将会被 Stub 和 Skeleton
    对象使用。接下来就是连接层上的了。追溯 LiveRef 的exportObject()方法,很容易找到了 TCPTransport 的exportObject()方法。这个方法做的事情就是将上面构造的Target 对象暴露出去。调用 TCPTransport 的 listen()方法,listen()方法创建了一个 ServerSocket,并且启动了一条线程 等 待客 户端的 请 求。 接着调 用 父类 Transport 的exportObject()将 Target 对象存放进 ObjectTable 中。

    到这里,我们已经将 RegistryImpl 对象创建并且起了服务等待客户端的请求。

    客户端获取服务端 Registry 代理

           从 上面的 代码看 起,容 易追溯 到 LocateRegistry 的getRegistry()方法。这个方法做的事情是通过传入的 host和 port 构造 RemoteRef 对象,并创建了一个本地代理。这个代理对象其实是 RegistryImpl_Stub 对象。这样客户端便 有 了 服 务 端 的 RegistryImpl 的 代 理 ( 取 决 于ignoreStubClasses 变量)。但注意此时这个代理其实还没有和服务端的 RegistryImpl 对象关联,毕竟是两个 VM 上面的对象,这里我们也可以猜测,代理和远程的 Registry对象之间是通过 socket 消息来完成的。

           调用 RegistryImpl_Stub 的 ref(RemoteRef)对象的newCall()方法,将 RegistryImpl_Stub 对象传了进去,不要忘了构造它的时候我们将服务器的主机端口等信息传了进去,也就是我们把服务器相关的信息也传进了 newCall()方法。newCall()方法做的事情简单来看就是建立了跟远程RegistryImpl 的 Skeleton 对象的连接。(不要忘了上面我们说到过服务端通过 TCPTransport 的 exportObject()方法等待着客户端的请求)

          连接建立之后自然就是发送请求了。我们知道客户端终究只是拥有 Registry 对象的代理,而不是真正地位于服务端的 Registry 对象本身,他们位于不同的虚拟机实例之中,无法直接调用。必然是通过消息进行交互的。看看super.ref.invoke() 这 里 做 了 什 么 ? 容 易 追 溯 到StreamRemoteCall 的 executeCall()方法。看似本地调用,但其实很容易从代码中看出来是通过 tcp 连接发送消息到服务端。由服务端解析并且处理调用。

    至此,我们已经将客户端的服务查询请求发出了。服务端接收客户端的服务查询请求并返回给客户端结果这里我们继续跟踪 server 端代码的服务发布代码,一步步往上面翻。按照下图顺序

    LiveRef.class

    TCPEndpoint.class

     

    TCPTransport.class

     

    在 TCP 协议层发起 socket 监听,并采用多线程循环接收请求:TCPTransport.AcceptLoop(this.server)

    继续通过线程池来处理 socket 接收到的请求

           下面这个 run0 方法里面做了一些判断,具体的功能是干嘛不太清楚,我猜想是对不同的协议来做处理。我们的这个案例中,会走到如下的代码中来。最终调用TCPTransport.this.handleMessages(var14, true);

       这个地方也做了判断,你们如果不知道怎么走的话,直接在这里加断点就知道。这里会走到 case 80 的段落,执行serviceCall()这个方法

            一步一步我们找到了 Transport 的 serviceCall()方法,这个方 法 是 关 键 。 瞻 仰 一 下 主 要 的 代 码 , 到
    ObjectTable.getTarget()为止做的事情是从 socket 流中获取 ObjId,并通过 ObjId 和 Transport 对象获取 Target 对象,这里的 Target 对象已经是服务端的对象。再借由 Target的派发器 Dispatcher,传入参数服务实现和请求对象RemoteCall,将请求派发给服务端那个真正提供服务的RegistryImpl 的 lookUp()方法,这就是 Skeleton 移交给具体实现的过程了,Skeleton 负责底层的操作。

    所以客户端通过

    先会创建一个 RegistryImpl_Stub 的代理类,通过这个代理类进行 socket 网络请求,将 lookup 发送到服务端,服务端通过接收到请求以后,通过服务端的 RegistryImpl_Stub(Skeleton),执行 RegistryImpl 的 lookUp。而服务端的RegistryImpl 返回的就是服务端的 HeloServiceImpl 的实现类

    客 户 端 获 取 通 过 lookUp() 查 询 获 得 的 客 户 端HelloServiceImpl 的 Stub 对象

    客 户 端 通 过 Lookup 查 询 获 得 的 是 客 户 端HelloServiceImpl 的 Stub 对象(这一块我们看不到,因为这块由 Skeleton 为我们屏蔽了),然后后续的处理仍然是通过 HelloServiceImpl_Stub 代理对象通过 socket 网络请求到服务端,通过服务端的
    HelloServiceImpl_Stub(Skeleton) 进行代理,将请求通过Dispatcher 转发到对应的服务端方法获得结果以后再次通
    过 socket 把结果返回到客户端;

    RMI 做了什么

    根据上面的源码阅读,实际上我们看到的应该是有两个代理类,一个是 RegistryImpl 的 代 理 类 和 我 们HelloServiceImpl 的代理类。

    通信原理

    我们大概知道了 RMI 框架是如何使用的。下面我们来讲解一下 RMI 的基本原理

           一定要说明,在 RMI Client 实施正式的 RMI 调用前,它必须通过 LocateRegistry 或者 Naming 方式到 RMI 注册表寻找要调用的 RMI 注册信息。找到 RMI 事务注册信息后,Client 会从 RMI 注册表获取这个 RMI Remote Service 的Stub 信息。这个过程成功后,RMI Client 才能开始正式的调用过程。

           另外要说明的是 RMI Client 正式调用过程,也不是由 RMI Client 直接访问 Remote Service,而是由客户端获取的Stub 作为 RMI Client 的代理访问 Remote Service 的代理Skeleton,如上图所示的顺序。也就是说真实的请求调用是在 Stub-Skeleton 之间进行的。

           Registry 并不参与具体的 Stub-Skeleton 的调用过程,只负责记录“哪个服务名”使用哪一个 Stub,并在 Remote Client 询问它时将这个 Stub 拿给 Client(如果没有就会报错)。

    展开全文
  • 通信分布式架构的一个基本问题, 通信是基于通信协议, 通过网络IO来实现的, 基本的通信协议有TCP,HTTP,UDP等, Java的IO分为BIO,NIO,AIO等, java领域有很多支持通信的技术, 如RMI,MINA,JMS等. 网络协议 TCP/IP: 五...

    通信是分布式架构的一个基本问题, 通信是基于通信协议, 通过网络IO来实现的, 基本的通信协议有TCP,HTTP,UDP等, Java的IO分为BIO,NIO,AIO等, java领域有很多支持通信的技术, 如RMI,MINA,JMS等.

    网络协议

    • TCP/IP:

      五层模型: 基于OSI七层模型. 包含: 应用层,传输层(TCP/IP协议),网络层(ICMP,IGMP),链路层,物理层. OSI还包含表现层,会话层.

      三次握手:

      img_ec8e7d6acc152f672024923aab6242bf.png

      Dos攻击就是在第三步发生, 发送大量连接请求, 使网络处在半连接状态. server端的连接未完成, 导致阻塞.

      四次挥手:

      TCP协议是全双工的, 全双工是双方可以相互发起通信, 数据可以往两个方向传输; 半双工是某个阶段只能一方传输; 单工是只能一方往另一方传输数据.

      img_fe448b9d37926a800cb35316aab03b34.png

    • UDP/IP:

    阻塞的概念

    了解阻塞, 就首先需要了解TCP传输协议的缓存区概念.

    应用层发送数据的时候, 首先数据会暂存到传输层的缓存区.

    数据传输的时候有个滑动窗口的概念, 窗口的大小可以控制, 这样可以保证接收方缓存区不够大导致缓存溢出. 窗口的数据全部发送且接收方确认收到后才可以向前继续滑动.

    发送方和接收方均有缓存区, 当缓存区满(或空, 分别对应写和读)的时候就会发生阻塞, 必须等缓存区有足够空间容纳更多数据的时候才能继续发送或接收.

    阻塞分为BIO(同步阻塞),NIO(同步非阻塞, 同路复用技术,netty等使用这种方式),AIO(异步非阻塞, java7开始)

    阻塞和非阻塞, 同步和异步分开理解比较好.阻塞和非阻塞是针对调用者, 阻塞是缓冲区读写没有数据的时候线程等待, 非阻塞是缓冲区读写没有数据时立即返回, 线程去做其他的事情; 同步和异步是针对被调用者, 被调用者处理时不返回时, 调用者需要等待结果是同步, 被调用者立即返回,同时做处理时异步.

    Java 网络通信

    TCP Socket通信

    // 服务端
    public class SocketServer {
        public static void main(String[] args) throws IOException {
            ServerSocket serverSocket = null;
    
            try{
                serverSocket = new ServerSocket(8888);
                Socket socket= serverSocket.accept();
                // 缓冲区读取
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                System.out.println(reader.readLine());
                reader.close();
                socket.close();
            }catch (Exception e){
    
            }finally {
                if(serverSocket!=null){
                    serverSocket.close();
                }
            }
        }
    }
    
    //客户端
    public class SocketClient {
        public static void main(String[] args) throws IOException {
    
            try{
                Socket socket = new Socket("localhost",8888);
                PrintWriter writer = new PrintWriter(socket.getOutputStream(),true);
                writer.println("this is a message from client");
                writer.close();
                socket.close();
            }catch (Exception e){
    
            }finally {
    
            }
        }
    }

    Multicast 多播, 使用UDP协议

    // 服务端
    public class MulticastServer {
        public static void main(String[] args) throws IOException, InterruptedException {
            // 多播必须是224网段
            InetAddress group = InetAddress.getByName("224.7.8.9");
            MulticastSocket socket = new MulticastSocket();
            for (int i = 0; i < 10; i++) {
                String data = "multcast"+i;
                byte[] bytes = data.getBytes();
                socket.send(new DatagramPacket(bytes,bytes.length,group,8888));
                TimeUnit.SECONDS.sleep(2);
            }
        }
    }
    
    // 客户端
    public class MulticastClient {
        public static void main(String[] args) throws IOException, InterruptedException {
            // 多播必须是224网段
            InetAddress group = InetAddress.getByName("224.7.8.9");
            MulticastSocket socket = new MulticastSocket(8888);
            socket.joinGroup(group);
            byte[] buf = new byte[32];
            while (true){
                DatagramPacket packet = new DatagramPacket(buf,buf.length);
                socket.receive(packet);
                String reveived = new String(packet.getData());
                System.out.println("received:"+reveived);
            }
        }
    }
    展开全文
  • 分布式通信

    2020-04-10 09:45:18
    Java 序列化机制 Serialize接口 java本身的序列化机制存在的问题: 序列化数据结果比较大、传输效率比较低 不能跨语言对接 序列化的发展 以至于在后来的很长一段时间,基于XML格式编码的对象序列化机制成为了主流...
  • 分布式系统详解--基础知识(通信

    千次阅读 2018-09-10 17:51:12
    分布式系统详解--基础知识(通信)  上一篇文章我们写到了 分布式系统详解--基础知识(线程) ,简单了解了一下线程的基本概念和线程和分布式的那斩不断理还乱的关系。今天再讲解一下它的另外一个必备知识--通信...
  • 分布式通信的几种方式

    万次阅读 2016-09-20 09:19:01
    分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,特别是在Java领域中有很多可实现远程通讯的技术,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,这些名词之间到底是些什么关系呢,...
  • RPC是远程过程调用协议,它是基于C/S模型调用的机制,客户机向服务器端发送调用请求等待服务器应答,是一种典型的请求应答机制,大致过程可以理解为本地分布式对象向本机发请求,不用自己编写底层通信本机会通过网络...
  • python实现socket分布式通信系统 服务器 #!/usr/bin/python # -*- coding: UTF-8 -*- from socket import * import threading import time import pymysql PiID = 1 adjID = [2,3,4] HOST = '' PORT = 6661 BUFSIZ ...
  • 分布式通信框架-webservice什么是webservice为什么要使用webservice什么时候要去使用webservicewebservice中的一些概念WSDL(web service definition language webservice 定义语言)SOAP(simple object access ...
  • HTTP协议的概述 1、客户端和服务器端 2、资源 html/文本、word、avi电影、其他资源 3. 媒体类型 MIME类型。 text/html、 image/jpeg 4. URI和URL URI: web服务器资源的名字。...query-string] #l...
  • 分布式通信协议

    千次阅读 2017-08-30 16:59:05
    分布式基础通信协议:paxos,totem和gossip 背景: 在分布式中,最难解决的一个问题就是多个节点间数据同步...这里开始介绍几种分布式通信协议。 简单即有效——totem协议: totem协议也许你还比较陌生,但是corosyn
  • 深入浅出Java分布式系统通信 对java分布式系统通信的理解: 1.集群模式,将相同应用模块部署多份 2.业务拆分模式,将业务拆分成多个模块,并分别部署 3.存储分布式 由于分布式概念太大,我们可以缩小下讨论的...
  • ROS 分布式通信

    2019-10-31 18:11:42
  • 近几个月一直从事一个分布式异步通信系统,今天就整理并blog一下. 这是一个全国性的通信平台,对性能,海量数据,容错性以及扩展性有非常高的要求,所以在系统的架构上就不能简单的采用集中式.简单的总结一下就是: ...
  • 分布式系统中的通信机制

    千次阅读 2016-11-02 15:41:23
    1 分布式系统及其透明性 分布式系统是由多个相互连接的处理资源组成的计算系统,它们在整个系统的控制下可合作执行一个共同任务,最少依赖于集中的程序、数据或硬件。进一步说明如下: 1) 系统由多个处理器组成 。 2...
  • 深入理解ROS核心:分布式通信机制

    千次阅读 2019-02-20 09:45:39
    ROS是一个分布式框架,为用户提供多进程之间的通信服务。ROS主要有三种通信机制,下面总结一下: 1. 话题通信机制 通信过程: 1)Talker注册 2)Listener注册 3)ROS Master 进行信息匹配 4)Listener 发送...
  • ros分布式多机通信完整教程

    万次阅读 多人点赞 2018-09-29 17:32:43
    ros多机通信完整试坑教程 文章目录ros多机通信完整试坑教程前言:系统介绍:1、设置IP和~/.bashrc文件: 前言: 老规矩,先讲讲为啥要做这个项目。因为机器人上的工控机没有办法加显卡,所以无法跑TensorFlow-...
  • ROS入门笔记(十三):分布式通信 文章目录01 如何实现分布式多机通信1.1 设置IP地址,确保底层链路的连通1.2 在从机端设置ROS_MASTER_URI,让从机找到ROS Master02 实战操作 ROS是一种分布式软件框架,节点之间通过...
  • ROS分布式多机通信

    千次阅读 2018-10-08 22:29:17
    ROS分布式多机通信 ROS是一种分布式软件框架,节点之间通过松耦合的方式进行组合,在很多应用场景下,节点可以运行在不同的计算平台上,通过Topic、Service进行通信。但是“一山不容二虎”,ROS只允许存在一个...
  • Hessian分布式系统间通信的常见方式有两种,一种是消息通信,比如JMS,RocketMQ等,一种是RPC远程调用。我们先来看一下通信的基础知识,然后主要来看一下RPC远程调用,消息通信大家可以参考我的下一篇文章——分布式...
  • 分布式架构之间的通信

    千次阅读 2018-08-21 10:05:51
    红日悬天 博客园 首页 新随笔 联系 订阅 管理 随笔 - 10&nbsp; 文章 - 0&nbsp; 评论 - 1 &lt;/div&gt;&lt;!--end: blogStats --&gt;...--end: n...
  • 在构建机器人的过程中,为了方便调试和后期扩展,采用“PC+英伟达Jetson Nano”分布式的方式来处理数据。 PC作为主机,跑网络,进行处理数据等主要工作;安装在机器人上的英伟达Jetson Nano作为从机,主要用来采集...
  • 分布式通信框架-RMI回顾分布式通信框架-RMIRPC什么是RPC一个RPC框架包含的要素RMI的概述如何实现一个RMI程序如果自己要去实现一个RMI 回顾 分布式架构的定义以及分布式架构的演进。 分布式架构和集群的区别 TCP/UDP...
  • 07 分布式通信之Kafka

    2020-02-22 20:11:07
    07 分布式通信之Kafka07 分布式通信之Kafka07 分布式通信之Kafka
  • 1.单机服务器能承受的用户并发量不高,它能建立的socket通信通道不够多,所以会大大限制应用的并发量,也就限制了很多其他的业务 2.单机服务器受到单个方法的限制,如果一个方法出错,那么就需要将该服务器上的所有...
  • ytk-learn 分布式机器学习库 项目背景 LR(Logistic Regression), GBDT(Gradient Boosting Decision Tree), FM(Factorization M
  • Java分布式应用:Java分布式通讯方式

    千次阅读 2018-12-26 21:59:14
    第一部分 Java分布式通讯的方式 1.基于消息方式实现系统间通讯 a.数据传输部分 : TCP/IP 、UDP/IP TCP(端口号为23)与UDP(端口号为53)的区别 1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即...
  • 分布式通信方式-----分布式消息传递

    千次阅读 2015-10-19 13:55:25
    背景: 随着社会的发展,经济的飞跃,传统的单系统模式(webApp+DB)已经很难满足业务场景的需要。企业系统开始不断演化成多个子系统并存协作的局面。大大降低了系统间的耦合性,更重要的便于子系统的扩展、升级...
  • 建立多个服务器之间进行数据通信服务,服务自动连接在线服务器,支持热拔,启动服务后自动连接,无需人为干预 注意事项: 需要在conf/application.conf里配置端口和监听、日志等 需要有一个redis服务器,并且...

空空如也

1 2 3 4 5 ... 20
收藏数 310,310
精华内容 124,124
关键字:

分布式通信