中间件层
请求-应答协议
一对进程间进行消息传递需要两个消息通信操作的支持(send和receive),用于定义目的地和消息的定义。
为了能够使一个进程能够和另一个进程通信,一个进程发送一个消息到目的地,而另一个进程在目的地接收消息。
通信活动涉及数据从发送进程到接收进程的通信,可能包含进程间同步。
每个消息目的地与一个队列相关。发送进程将消息加到远程队列中,接收进程从本地队列中移走消息。
进程间通信可以是同步也可以是异步:
1.同步通信,发送进程和接收进程在每个消息上同步,send/receive都是阻塞操作。每次发送一个send后,发送进程将一直阻塞直到发送了响应的receive,每次发送receive进程将一直阻塞直到消息达到。
2.异步通信中,send操作不阻塞,只要消息被复制到一个本地缓冲区,发送进程就被允许继续进行其他处理。消息的传递处理与发送进程是并行工作。
receive操作可有阻塞和不阻塞,
不阻塞方式,接收进程在发出receive操作后可继续执行它的程序,这时receive操作在后台提供一个缓冲区,但必须通过轮询或中断独立接收缓冲区满的通知。
因特网协议中消息被发送到本地端口是计算机内部的消息目的地。
如果客户使用一个固定的因特网地址访问服务,那么这个服务就必须总在这个地址的计算机上运行,保持服务的有效性。
提供位置透明性:
- 客户程序通过名字使用服务,将名字绑定为具体服务器位置。允许重定位但不能迁移。
- 操作系统Mach给消息目的地提供了一个位置独立的标识符,并将映射到一个底层地址以便于将消息传递到端口,这种方法允许服务迁移和重构定位
Mach机制是一种微内核操作系统架构,它将操作系统的核心功能划分为若干个独立的服务,每个服务运行在自己的地址空间中,通过消息传递机制进行通信。
Mach机制的核心是Mach内核,它负责管理系统资源、进程调度、内存管理等核心功能。
Mach机制的优点是可以实现更加灵活的系统扩展和定制,同时也有利于系统的可靠性和安全性。
Mach机制的缺点是消息传递机制可能引入较大的开销,同时由于服务间的相互依赖关系复杂,系统的可维护性也可能受到影响。
有效性而言,如果一个点对点消息服务无论丢失了多少合理数量的数据包,总能保证发送消息,那么它就是可靠的。
从完整性角度,到达的消息必须完好无损,且没有重复。
有些应用要求消息按发送方顺序发送。
如果和发送方发送的顺序不一致这些应用被认为是一个失败的发送。
两种通信方式(UDP和TCP)都使用套接字抽象,套接字提供进程间通信的一个端点。
进程间通信是一个进程的一个套接字与另一个进程的套接字之间传送一个消息。
对接收消息的进程,它的套接字必须绑定到本地计算机的一个因特网地址和一个本地端口。
发送到特定因特网地址和端口号的消息只能被套接字与这个因特网地址和端口号相连的进程接收。
进程可以使用同一个套接字发送和接收消息。
进程之间不同共享端口。IP组播是一个例外
套接字(Socket)是计算机网络编程中的一个概念,是一种用于网络通信的编程接口(API),它是一个抽象层,用于在应用程序中实现网络通信。套接字的概念最初是由UNIX操作系统引入的,后来被广泛应用于各种操作系统和网络环境中。
早期的计算机网络通信都是基于低层次的网络协议实现的,而这些协议通常需要编写底层的网络代码来完成网络通信。这样的编程方式非常繁琐和复杂,因此需要一种更高级别的网络编程接口来简化网络编程。
套接字就是这样一种高级别的网络编程接口,它提供了一组简单易用的函数,可以方便地实现网络通信。套接字提供了一种标准的方式,使不同的应用程序能够在不同的计算机之间进行通信,这使得网络编程更加容易和可靠。
随着计算机网络的发展,套接字也在不断发展和改进,出现了各种不同的套接字类型和协议,如TCP套接字、UDP套接字、IPv4套接字、IPv6套接字等等。套接字已经成为了计算机网络编程中不可或缺的一部分,为我们的日常生活和工作提供了便利
由UDP发送的数据报从发送进程传输到接收进程,不需要确认和重发。
发生故障消息可能到达不了。
数据报在进程间传送,一个进程发送一个进程接收。
需要发送和接收的进程首先创建一个与一个因特网和本地端口绑定的套接字。
服务器将它的套接字绑定到一个服务器端口,该端口能让客户知道以便客户向该端口发送消息。
接收进程需要指定大小固定的用于接收消息的字节数组。
如果消息超出字节数组大小,则将会发送消息截断。
底层的IP协议允许数据包的长度最大是2^16字节(包括消息头和消息本身)
普通环境大小为8KB,如果应用程序超出则会发生分段处理。
UDP数据通信使用非阻塞send和receive。
当send操作将消息传递给底层的UDP和IP协议就返回。
由UDP和IP协议负责将消息传递给目的地。
消息到达时被放在与目的端口绑定的套接字队列中。
通过该套接字的下一个receive调用可以从队列中获取该消息。
如果没有一个进程具有绑定到目的端口的套接字,消息会在目的地丢弃。
阻塞超时情况:在套接字上设置超时,否则receive方法将一个阻塞直到接收到一个数据报
一直阻塞的receive适用于正在等待接收客户端请求的服务器。
设置超时的原因是:
进程可能发生崩溃或期待的消息已经丢失,此时receive阻塞下去就无意义,此时可以使用超时失败处理。
超时时间的设计应该大于正常传输消息的时间
receive方法不指定消息的源。
调用receive可获得从任何地方发送到该套接字上的消息。
receive消息返回发送方的因特网地址和本地端口,允许接收方检查消息的来源。
可以将数据报套接字连接到一个特定的远程端口和因特网地址,指定源。
完整性和有效性定义了可靠通信。
完整性要求消息不能被损坏和重复。
利用校验和可保证接收到的消息是否损坏
信道中的遗漏故障
消息有时候没有按照发送方顺序发送
抽象的可读写的字节流
1.消息大小:应用程序可以读写或大或小的数据集。
TCP流的底层实现决定了作为一个或多个IP数据包传送前要收集的数据量。
数据到达后,实现根据应用的请求传递给应用。应用程序可以强制数据马上发送。
2.丢失的消息:TCP协议使用确认机制。发送端记录数据包,如果超时则重传。
更复杂的滑动窗口减少了确认的消息。
3.流控制:TCP协议试图匹配读写流的进程的速度。对读方,如果写的太快,就会被阻塞,直到消耗掉足够的数据。
4.消息重复和排序:每个IP数据包与消息标识相关联,使得接收方能检测和丢弃重复的消息。或重排没有以发送方顺序到达的消息。
5.消息目的地:一对通信进程在能通信之前建立好链接。一旦建立好,进程就可以不需要使用因特网地址和端口读写流。
在通信之前建立链接涉及客户和服务器发送一个connect请求,然后服务器给客户发送一个accept请求,对于单个客户请求和应答是巨大的开销——HTTP
TCP的滑动窗口是用于流量控制和拥塞控制的机制,其设计思路如下:
- 发送方和接收方都有一个缓冲区,用于存储待传输的数据。
- 发送方发送数据时,将数据分成多个大小相等的数据段,每个数据段都有一个序号。
- 接收方接收到数据时,会向发送方发送确认消息(ACK),确认已经成功接收到哪些数据段。
- 发送方会根据接收方发送的确认消息,动态调整自己的发送窗口大小,即允许发送多少个数据段。
- 发送方发送的数据段必须在接收方确认之前保持在发送窗口中,一旦确认之后就可以从发送窗口中删除。
- 发送方可以根据接收方发送的确认消息,向发送窗口中添加新的数据段。
- 如果发送方发送的数据段没有及时得到接收方的确认消息,就会认为数据丢失,重新发送这些数据段。
- 发送方和接收方可以根据滑动窗口大小来控制传输速度,从而避免拥塞和网络阻塞的问题。
通过这种方式,TCP可以在网络中可靠地传输数据,同时保证了流量控制和拥塞控制的效果。
运行程序中存储的信息都表示为数据结构——消息中的信息是由字节序列组成。
不论何种通信方式,数据结构在传输前必须进行平整化(转换成字节序列),到达目的地后再进行重构。
传输的单个基本数据项可以是多个不同类型的数据值,不同的机器对于不同的类型处理方式不同
关于字符编码是ASCII一个字符占用一个字节,Unicdoe标准允许不同语言的文字,每个字符占两个字节。
两个方法表示整数编码的顺序:
- 大端排序:高位有效字节排在前面
- 小端排序:高位有效字节排在后面
计算机交换数值:
- 值在传送前先转换成一致的外部格式,然后在接收端转换成本地格式;如果两台机器是同一类型,可以不必转换。
- 值以发送端的格式传送,同时传送所使用格式的标志,接收方根据需要转换该值。
字节本省在传送过程中并不改变。为了支持RPC/RMI,任何能够作为参数返回值的数据类型必须能够平整化,单个基本数据值能以一致的格式表示。对数据结构和基本值的一致的表示标准称为外部数据表示。
编码:将多个数据项组装成适合消息传送的格式。
解码:消息到达后拆装消息,在目的地生成等价的数据集合。
编码是将结构化数据项和基本值转换成一个外部数据表示,解码是从外部数据表示生成基本值,并重构数据结构。
CORBA 是 Common Object Request Broker Architecture 的缩写,是一种面向对象的分布式计算标准。它提供了一种通用的机制,使得来自不同计算机平台、使用不同编程语言和运行在不同操作系统上的对象可以相互通信、交互和调用。CORBA 是一种开放标准,由 OMG(Object Management Group)组织开发和维护。
- 基本类型:CDR定义了大序法排序和小序法排序的表示。
- 构造类型:组成每个构造类型的基本类型值按特定的顺序加到字节序列中。
java中是将一个对象或一组相关联的对象平整化成适合于磁盘存储或消息传送的串行格式。
解序列化是指从串行格式中恢复对象或一组对象。
反序列化需要预先知道序列化格式对象的类型。
每个对象的类的一些信息包含在序列化格式中。满足反序列化的要求。
java对象能包含对其他对象的引用。当对象序列化时,引用对象一起随着序列化。
确保对象在目的地重构是能够恢复对应用对象的引用。
序列化过程必须确保在对象引用和句柄之间一一对应的。
必须确保对象只能被写一次,在对象第二次或后面出现时,能够写句柄而不是写对象。
反射能够通过类名创建类,以及为一个给定的类创建具有给定参数类型的构造函数。
反射使以完全通用方式进行序列化和反序列化称为可能。
客户调用远程对象中的一个方法,就会向存放远程对象的服务器进程发送一个调用消息。
这个消息需要指定哪一个特定的对象具有调用的方法。远程对象引用是远程对象的标识,在整个分布式系统中有效。
远程对象引用用于在调用消息中指定调用哪一个对象。
在远程对象上有许多进程,所以进程对象应用必须在分布式系统的所有进程为唯一(确保引用必须确保空间和时间唯一性方法生成),即使在与给定远程对象引用相关线程删除后,该远程对象引用也不能重复,可能有潜在的调用者还保留着过期的对应引用。
对于任何调用已删除对象的企图都应该产生一个出错信息而不应该允许访问一个对象。
在理论上,UUID是由128位二进制数字组成的,因此在理论上,UUID的数量是非常巨大的,有2^128种可能性,这意味着几乎可以保证在分布式系统中不会出现重复的UUID。但是,在实践中,由于生成UUID的算法和实现不同,可能会出现重复的情况。为了确保在分布式系统中不会出现重复的UUID,可以使用专门的UUID生成器或实现自定义的UUID生成算法。
雪花算法在分布式系统中不会重复,因为它是基于时间戳和机器节点ID生成唯一的64位ID。时间戳确保了每个ID在同一台机器上的生成是递增的,而机器节点ID确保了不同机器上生成的ID不会重复。因此,只要机器节点ID是唯一的,雪花算法生成的ID就是唯一的。但是,如果机器节点ID重复,就有可能导致ID重复的问题。
doOperation,getRequest,sendReply通信原语
- 存在遗漏故障
- 不能保证消息按发送方顺序发送
协议还要承受进程故障,丢失请求消息或丢失应答消息的情况,doOperation在等待服务器应答消息的时候使用超时。超时发生时采取的行为取决于要提供的传递保证。
超时:超时后的doOperation方法有不同的选项,简单的就是马上返回一个请求失败。
丢失重复的请求消息:万一请求消息被重传,服务器可能多次收到该消息。
如果服务器收到第一个请求的消息,但执行命令并将结果返回所花费的时间超过了客户的超时时限。
这就导致服务器对相同请求执行了多次操作。
协议设计者要识别具有相同请求标识的后续消息,过滤掉。
如果服务器还没有发送应答,也不需要采取特殊的动作——服务器在完成操作的执行后会传递应答。
丢失应答消息:如果服务器在收到一个重复的请求时它已经发送了应答,那么它将需要再次执行操作以获得结果,除非它将原来执行的结果保存了起来。
如果服务器支持幂等操作就可以忽略多次重复请求,但也浪费了资源一种保证手段。
历史:对那些要求不重新执行操作而重传应答的服务器,可以使用历史。
历史是对于已经传送的消息记录的结构。
任何历史结果都会越来越大。
- 请求协议(R):用于没有数据从过程中返回而客户端不要求对过程的执行进行确认的情况。客户端在发送请求消息之后可以继续执行其他的动作。
- 请求-应答(RR)协议:用于大多数客户-服务器交互,基于请求应答协议。这一协议不需要特殊的确认消息,因为服务器的应答消息被认为是对客户端请求消息的确认;
- 请求-应答-确认应答(RRA)协议:确认应答消息包含确认应答消息的请求id,使得服务器能丢弃历史中的数据项。确认消息中的请求id的到达将解释成对所有小于该请求id的应答消息的确认。
数据报的有效长度(通常是8KB)并不被认为是使用透明RMI系统的合适长度,因为过程的参数或结果可以是任何大小的。
在TCP流上实现请求-应答协议的理由之一是:流允许传任意大小的参数和结果。
流控制机制允许大的参数和结果不必为避免接收方的崩溃采用特殊的手段进行传输。TCP自带处理机制。
TCP简化协议的实现:如果同一客户-服务器之间的后继请求和应答是同一个流上发送.
那么不需要在每个远程调用上都有链接的开销。除非是多线程的场景下。看看JDBC的设计模式。
TCP流的设计机制包括以下几个方面:
- 可靠传输:TCP使用可靠的传输机制,确保数据的完整性和正确性,能够检测和纠正传输中的错误,保证数据传输的可靠性。
- 滑动窗口:TCP使用滑动窗口机制来控制发送方和接收方之间的数据流量,以避免网络拥塞和数据丢失。发送方根据接收方的反馈信息调整窗口大小,以保证传输效率和可靠性。
- 流量控制:TCP使用流量控制机制来限制发送方发送数据的速率,以避免网络拥塞和数据丢失。接收方可以通过发送窗口大小来控制发送方的发送速率。
- 拥塞控制:TCP使用拥塞控制机制来避免网络拥塞和数据丢失。TCP发送方根据网络拥塞程度动态调整发送速率和窗口大小,以保证网络的可靠性和稳定性。
- 三次握手:TCP使用三次握手机制来建立连接,发送方发送一个SYN报文段,接收方返回一个SYN+ACK报文段,最后发送方发送一个ACK报文段,建立连接。这个过程确保了双方都能够通信,并且避免了重复连接和错误连接的情况。
- 四次挥手:TCP使用四次挥手机制来关闭连接,发送方发送一个FIN报文段,接收方返回一个ACK报文段,然后接收方发送一个FIN报文段,发送方返回一个ACK报文段,完成关闭连接的过程。这个过程确保了双方都完成了数据传输并且释放了资源。
Web浏览器使用这个协议向Web服务器发送请求并从服务器接收应答
WEB服务器管理资源的几种方式:
- 数据实现的资源(HTML页面的正文,图像或程序)
- 以程序实现的资源(web服务器运行的servlet提供服务)
客户请求指定了一个URL,包含web服务器的DNS主机名和web服务器上的一个可选的端口和服务器上资源一个标识符。
HTTP协议指定了请求-应答交互所需的消息,方法,参数和结果以及它们在消息中的表示(编码)规则。
提供支持一套固定的用于所有资源的方法集(GET,PUT,POST,DELETE)
除了在WEB上调用方法,HTTP协议允许内容协商和口令形式的认证方式。
- 内容协商:客户请求中包含了可以接收何种数据表示之类的信息(如语言和介质类型),让服务器能够选择适合用户的数据标识(content-type)
- 认证:证书和询问用于支持口令形式的认证。在第一次试图访问受口令保护的区域时,服务器的应答包含了该资源所需的质询。当客户接受到一个质询,用户输入口令,并在后续请求中提交相关的证书。
HTTP是基于TCP上实现,该协议的原始版本中,每个客户-服务器交互步骤如下:
- 客户请求一个链接,服务器在默认的端口或URL指定端口上进行链接。
- 客户发送请求消息到服务器。
- 关闭链接
HTTP1.1的长链接解决每次请求建立链接的开销。
如果一个服务或是为了提供容错能力或是为了提高可用性而实现成多个不同计算机上的多个进程,那么一定程度上会有一个进程到一组进程的通信。消息成对交换不是一个进程到一组进程通信的最佳模式。
组播:一个将单个消息从一个进程发送到一组进程的每个成员的操作,通常,组的成员对发送方式透明的。
组播的消息提供了构造具有的分布式系统的有用的基础结构:
- 基于复制服务的容错能力:一个复制的服务有一组服务器组成。客户请求被组播到组的所有成员。每一个都完成相同的操作。一些成员故障之后依然能够提供服务(HDFS)
- 在自发网络中找到发现服务器:客户和服务器能使用组播消息定位可用的发现服务以便在分布式系统中注册服务接口或查找其他服务的接口。
- 通过复制的数据获得更好的性能:数据复制能增加服务的性能
- 事件通知的传播:组播到一个组可用于在发生某些事情时通知有关的进程。
建立在因特网协议(IP)的上层。IP数据包是面向计算机的——端口属于TCP和UDP层。
IP的组播允许发送方将单个IP数据包传送给组成一个组播的计算机集合。发送方并不知道集合的大小。集合大小是动态的。
组播仅通过UDP协议可用。
组播组由D类因特网地址指定——IPV4,都4位是1110的地址。