【前五篇】系列文章传送门:网络协议15-P2P协议:小种子大学网络协议16-DNS协议:网络中的地址世界图书网络协议17-HTTPDNS:私人定制的DNS服务网络协议18-CDN:你家门口的小店网络协议19-RPC协议概述:远在天边,近在咫尺上一节我们学习了经典RPC的模型和设计要点,并以最早的ONCRPC为例,详细描述其具体实现。但是时代在进步,ONCRPC由于各种问题正在逐渐被替代,而SOAP协议就是其中之一。ONCRPC存在的问题ONCRPC将客户端要发送的参数和服务器要发送的回复压缩成一个二进制字符串,当然可以解决双方的约定问题,但不方便。首先,双方的压缩格式需要完全一致,不能差。一旦出现一点点错误,多一点,少一点或错误,都可能导致无法压缩。当然,我们可以利用传输层的可靠性,加上校验和来减少传输过程中的错误。其次,协议修改不灵活。如果不是传输过程中导致的错误,而是客户端因业务逻辑变化增删字段,或者服务端增删字段,但双方没有及时通知,或者线上系统没有升级久而久之,就会导致解压不成功。因此,当业务发生变化,需要传输的参数多了或者传输的参数少了,都需要及时通知对方,按照约定的协议文件重新生成双方的存根程序。自然,这种灵活性是比较差的。如果这只是一个沟通问题,那很容易解决。其实版本问题更难解决。比如服务端提供一个服务,参数格式为version1,已经有50个客户端在线调用。现在有个客户端需要添加字段,怎么办?这是一个大项目,所有客户都要适应这个,需要重写程序,添加这个字段,但是传输值为0,不需要这个字段的客户是“不公正的”,与我无关,为什么让我忙?最后,ONCRPC的设计显然是面向函数的,而不是面向对象的。当前面向对象的业务逻辑设计和实现已经成为主流。这一切的根源是压缩。就好像我们平时爱用缩略词一样。如果你是一个篮球爱好者,你直接说NBA,他马上就知道是什么意思,但是如果你对阿姨说NBA,她可能就不知道是什么意思。所以这个RPC框架只能用在客户端和服务端都是一群人开发的场景,或者至少客户端和服务端的开发者必须紧密沟通,相互配合,有很大的共同点。一些共同的语言才能按照既定的协议顺利运作。XML和SOAP?????????????????????????????????????????????????一般情况下,我们做服务的时候,是提供给陌生人的。你和你的客户不会经常交流,也没有共同语言。就像你给别人介绍NBA,就得说说美国的职业篮球比赛,这样不管他做什么,他都能看得懂。放在我们的场景中,对应的是以文字的形式传输。无论哪个客户端得到这个文本,都可以知道它的意思。一种常见的类文本格式是XML。让我们在这里举个例子。2019-01-08栗子焖鸡58在这里我不打算详细描述XML的语法规则,但是相信我,看完下面的内容,即使你没有学过XML,也能一目了然。这个XML描述的不像是综合二进制,你看到的是010101,看不懂。有了这个,我们刚才说的几个问题就不是问题了。首先,格式不必完全相同。比如我们改变price和author的位置,不会影响client和server解析文本,完全不会误认为作者的名字是68。如果有的客户端要添加字段,比如添加推荐人字段,只需要在上面的文件中添加一行:Gary对于不需要该字段的客户端,不解析该行即可向上。只要使用简单的处理,就不会出现错误。另外,这个表述很明显描述的是一个订单对象,是一种更贴近用户场景的面向对象的表示。既然XML这么好,那我们就看看如何在RPC中使用吧。传输协议问题我们来解决第一个问题,传输协议问题。最著名的基于XML的通信协议是SOAP,全称是SimpleObjectAccessProtocol(简单对象访问协议)。它使用XML编写简单的请求和回复消息,并使用HTTP协议传输它们。SOAP将请求和回复放在一个信封中,就像发送邮件一样。信封内的信头和正文POST/purchaseOrderHTTP/1.1Host:www.cnblog.comContent-Type:application/soap+xml;charset=utf-8Content-Length:nnn12342019-01-08栗子焖鸡88我们学习过的HTTP协议,这个请求使用POST方式,发送一个格式为application/soap+xml的XML文本到www.geektime.com下单,封装在一个SOAP信封中里面说明这是一个交易(transaction),订单的细节已经写明了协议协议问题接下来我们解决第二个问题,双方的协议协议是什么?因为服务是为了给陌生人使用而开发的,就像上面放的XML文件一样,对于客户端来说,它怎么知道应该组装成上面的格式呢?这就需要对服务的描述,因为调用者不认识你,所以没办法找到你问你的服务应该怎么调用。当然你可以写文档放在官网,但是你的文档可能更新的不及时,你写的文档可能没有那么严谨,所以经常会出现调试失败的情况。因此,我们需要一种比较严谨的Web服务描述语言,WSDL(WebServiceDescriptionLanguages)。它也是一个XML文件。在这个文件中,应该定义一个类型顺序,对应于上面的XML。接下来需要定义消息结构。接下来,应该公开一个端口。最后,我们需要编写服务。WSDL还是有点复杂,幸好有工具可以生成。对于某个服务,即使是陌生人也可以在服务地址后面加上“?wsdl”得到这个文件,但是这个文件还是比较复杂,不易理解。幸运的是,还有一些工具可以基于WSDL生成客户端存根,允许客户端通过存根进行远程调用,就像调用本地方法一样。服务发现问题‖‖‖最后,解决第三个问题,服务发现问题。有一个UDDI(UniversalDescription,Discovery,andIntegration),它是一个统一的描述、发现和集成协议。它实际上是一个注册中心。服务提供商可以将上述WSDL描述文件发布到该注册中心。注册完成后,服务使用者可以找到服务的描述,封装为本地客户端调用。总结原来的二进制RPC有很多缺点,格式要求严格,修改过于复杂,不面向对象,于是产生了一种基于文本的调用方式——XML-basedSOAP;SOAP具有三个主要元素:用于协议约定的WSDL、用于传输协议的HTTP、使用UDDL的服务发现。