小兔网

服务器之间的通信

通常我们交互除了P2P等协议,大多数都是基于C/S架构的通信场景,比如FTP, HTTP, DNS等。但是再射一一些安全协议方案的时候通常包括多方服务器和用户。此时应该如何通信那?比如传递命令和传输密钥。

(1)Socket

一般情况下比如我们设计一个后端服务,包括多个服务器:数据库服务器,web服务器,文件服务器、缓存服务器等的通信,一般是通过socket来设计专门的通信协议,因为比较高效。比如MySQL,MS SQL等也都是有知名的专用端口号。这个场景大多是在一个内网中,所以通信效率一般没问题。

(1)大学毕业设计,我是采用socket编程来实现客户端与服务器之间的通信,所以当需要服务器之间通信的时候,我也采用了socke的方法,只不过请求的服务器变成了“客户端”。所以相当于各方既是C也是S。只不过主动发起的一方是C,被动监听的一方是S。

(2)Socket通讯简单的方法是发送方用1个固定连接发送(比如SMTP/POP3等),或发送方每个请求数据包新建一个连接发送(比如PHP/Ruby连MySQL)。

(2)Http

服务器和服务器直接同样可以用HTTP,特别现在最常用的RESTful风格的通信方式(webserivces )。这时通信的时候就不需要浏览器了,比如服务器A可以使用curl系列命令向服务器B发出HTTP请求,获取数据,格式可以用通用的JSON或XML。也可以用java自带的HttpURLConnection,或者Apache的HttpClient等Http客户端来实现。当然低层还是通过Socket实现。

优点是:

1 易于编程,目前java提供了多种框架,屏蔽了底层通信细节以及数据传输转换细节。

2 容易控制权限。通过传输层协议https,加密传输的数据,使得安全性提高。

3 通用性比较强,无论客户端是.net架构,java,python 都是可以的。尤其是webservice规范,使得服务变得通用。

缺点是:

1 服务器和客户端必须同时工作,当服务器端不可用的时候,整个数据交互是不可进行。

2 当传输数据量比较大的时候,严重占用网络带宽,可能导致连接超时。使得在数据量交互的时候,服务变的很不可靠。

(3)RMI

如果用socket的话,需要自己封装协议来处理不同的通讯请求,但效率要高些。如果用rmi的话,实现要简单,但效率可能要低些。RMI=socket +object 也比较底层。

(4)RPC

RPC 的全称是 Remote Procedure Call,是进程间通信的一种方式,常见的分布式系统通信可以用http,socket或rpc来实现,但rpc相比于http性能更高,相比于纯socket实现会更轻量更容易。目前比较火的微服务架构一般是基于rpc框架的,微服务是指开发一个单个小型的但有业务功能的服务,每个服务都有自己的处理和轻量通讯机制,可以部署在单个或多个服务器上。基于rpc的微服务架构优点如下:每个微服务都很小,这样能聚焦一个指定的业务功能或业务需求。微服务能够被小团队单独开发,这个小团队是2到5人的开发人员组成。

微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的,单个服务方便扩展。一般来讲RPC主要分为四个部分,分别是序列化层、函数调用层、网络传输层和服务器端处理框架,具体实现机制如下:

序列化层:序列化主要作用是将结构化对象转为字节流以便于通过网络进行传输或写入持久存储,在RPC框架中,它主要用于将用户请求中的参数或者应答转化成字节流以便跨机器传输。常用的序列化方式有xml,json,hessian,pb等。

函数调用层:函数调用层主要功能是定位要调用的函数并执行该函数,可以采用Java反射机制与动态代理实现函数调用。

网络传输层:网络传输层描述了Client与Server之间消息传输的方式。

服务器端处理框架:服务器端处理框架可被抽象为网络I/O模型,它描述了客户端与服务器端间信息交互方式,它的设计直接决定着服务器端的并发处理能力,常见的网络I/O模型有阻塞式I/O、非阻塞式I/O、事件驱动I/O等,而Hadoop RPC采用了基于Reactor设计模式的事件驱动I/O模型。

提供一台服务器作为调用的中转,业务调用者和提供者都连接该中心服务器,该中心服务器用于服务的具体调用。rpc主要解决的一个痛点在于服务调用的高度透明化。

透明化是指隐藏socket通信细节,比如http这种是应用层透明,但是rpc站的高度比应用层更高,是代码级的透明。

rpc是站在比http更上层的调用,也就相当于多了一层封装,仅此而已,下层可以依赖http、json、或者你自己定义的元数据协议,任何能清晰描述出“坐标、服务类、服务名、调用参数”的whatever都可以。多了这层封装使我们在调用的时候不必关注这些底层细节。而rpc这层封装其实技术含量很低,反射加强制转换罢了。

rpc试图将远程调用包装成本地调用,但是网络调用的情况比本地调用要复杂的多,并且网络调用本身应该也是无状态,幂等性的,和本地调用背离,随便举个例子,你在本地会自然而然的写诸如i++,i--这种,但是在rpc上面不能这么用,一旦网络情况复杂i++可能会被调用多次导致结果就不正确。

总结:
当前的普遍场景是:对内rpc,对外rest。RPC 更适合集群内部通讯。所以在当前网络环境下,并不值得去推广和使用。

(5)ftp/文件共享服务器方式

文件共享服务器:对于大数据量的交互,采用这种文件的交互方式最适合不过了。

2021082402300012345601

这种方式的优点:

1 在数据量大的情况下,可以通过文件传输,不会超时,不占用网络带宽。

2 方案简单,避免了网络传输,网络协议相关的概念。

这种方式的缺点:

1 不太适合做实时类的业务。

2 必须有共同的文件服务器,文件服务器这里面存在风险。因为文件可能被篡改,删除,或者存在泄密等。

3 必须约定文件数据的格式,当改变文件格式的时候,需要各个系统都同步做修改。

(6)数据库共享数据方式

系统A和系统B通过连接同一个数据库服务器的同一张表进行数据交换。当系统A请求系统B处理数据的时候,系统A Insert一条数据,系统B select 系统A插入的数据进行处理。

2021082402300012345602

这种方式的优点:

1 相比文件方式传输来说,因为使用的同一个数据库,交互更加简单。

2 由于数据库提供相当做的操作,比如更新,回滚等。交互方式比较灵活,而且通过数据库的事务机制,可以做成可靠性的数据交换。

这种方式的缺点:

1 当连接B的系统越来越多的时候,由于数据库的连接池是有限的,导致每个系统分配到的连接不会很多,当系统越来越多的时候,可能导致无可用的数据库连接。

2 一般情况,来自两个不同公司的系统,不太会开放自己的数据库给对方连接,因为这样会有安全性影响。

(7)message方式

Java消息服务(Java Message Service)是message数据传输的典型的实现方式,是一种发布-订阅模式。系统A和系统B通过一个消息服务器进行数据交换。系统A发送消息到消息服务器,如果系统B订阅系统A发送过来的消息,消息服务器会消息推送给B。双方约定消息格式即可。目前市场上有很多开源的jms消息中间件,比如 ActiveMQ, OpenJMS 。

2021082402300012345603

这种方式的优点:

1 由于jms定义了规范,有很多的开源的消息中间件可以选择,而且比较通用。接入起来相对也比较简单。

2 通过消息方式比较灵活,可以采取同步,异步,可靠性的消息处理,消息中间件也可以独立出来部署。

这种方式的缺点:

1 学习jms相关的基础知识,消息中间件的具体配置,以及实现的细节对于开发人员来说还是有一点学习成本的。

2 在大数据量的情况下,消息可能会产生积压,导致消息延迟,消息丢失,甚至消息中间件崩溃。

(8)其他协议:

主要是rcp,scp,rsync,ftp,sftp,lftp,wget,curl等Linux服务或命令。

1 rcp
rcp不是一种安全的的传输文件的方式,rcp通过rsh(rsh见下面)来执行远程命令,要使用rcp必须经过一些配置,现在rcp已经被scp取代了,常用scp来进行文件传输。

2 scp
scp 命令是 SSH中最方便有用的命令了,scp就是secure copy,是用来进行远程文件拷贝的。数据传输使用 ssh,并且和ssh 使用相同的认证方式,提供相同的安全保证 。 与rcp 不同的是,scp 在需要进行验证时会要求你输入密码或口令。

3 rsync
rsync是rcp的替代品之一,rsync 是一款高效的远程数据备份和镜象工具,可快速地同步多台主机间的文件,其具有如下特性:

支持链接、所有者、组信息以及权限信息的拷贝;
通过远程 shell(ssh, rsh)进行传输;
无须特殊权限即可安装使用;
流水线式文件传输模式,文件传输效率高;
支持匿名操作;
需要提及的是 rsync 以其优越的性能优势区别于其它几种 Linux 文件传输方法,其同步文件的速度相当快,这主要归功于 rsync 所使用的传输算法。简而言之 rsync 算法能在相当短的时间内计算出需要备份的数据,只对源文件与目标文件的不同之处进行传输(增量传输),从而降低网络中传输的数据量,以此达到快速备份镜像的目的。

4 ftp
ftp命令使用文件传输协议(File Transfer Protocol ,FTP)在本地主机和远程主机之间或者两个远程主机之间进行文件传输。FTP 协议允许数据在不同文件系统的主机之间传输。尽管这个协议在传输数据上提供了高适应性,但是它并没有尝试去保留一个特定文件系统上的文件属性(例如一个文件的保护模式或者修改次数)。而且 FTP 协议很少对一个文件系统的整体结构作假定,也不提供这样的功能,比如递归的拷贝子目录。在使用 ftp 命令时,需要注意 FTP 协议的这些特性。当需要保留文件属性或者需要递归的拷贝子目录时,可以使用 rcp/scp 等命令。

5 sftp
sftp(安全文件传输协议)与 ftp 有着几乎一样的语法和功能。SFTP 为 SSH的一部份,是一种传输档案至 Blogger 伺服器的安全方式。它并不使用ftp守护进程(ftpd或wu-ftpd)来进行连接,而是有意义地增强系统的安全性。实际上,通过监视一些系统中的log文件,可以注意到很多攻击是针对于ftpd守护进程的。sftp避免了这些攻击从而可以停止在wu-ftpd上潜在的危险。SFTP本身没有单独的守护进程,它必须使用sshd守护进程(端口号默认是22)来完成相应的连接操作。使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低得多,如果您对网络安全性要求更高时,可以使用SFTP代替FTP。

6 lftp
lftp 是一个功能强大的下载工具,它支持访问文件的协议: ftp, ftps, http, https, hftp, fish.(其中ftps和https需要在编译的时候包含openssl库)。llftp非常像一个shell: 有命令补全,历史记录,允许多个后台任务执行等功能,使用起来非常方便。它还有书签、排队、镜像、断点续传、多进程下载等功能。

7 wget
wget 是一个经由 GPL 许可的可从网络上自动获取文件的自由软件包。它是一个非交互式的命令行工具。支持 HTTP,HTTPS 和 FTP 协议,支持代理服务器以及断点续传功能。 wget 可实现递归下载,即可跟踪 HTML 页面上的链接依次下载来创建远程服务器的本地版本,完全重建原始站点的目录结构,实现远程网站的镜像。在递归下载时,wget 将页面中的超级链接转换成指向本地文件,方便离线浏览。由于非交互特性,wget 支持后台运行,用户在退出系统后,仍可继续运行。功能强大,设置方便简单。

8 curl
curl是对 libcurl 库的一个命令行工具包装。 libcurl 库中提供了相应功能的 API,可以在程序中调用。 curl 使用 URL 的语法来传输文件,它支持 FTP, FTPS, HTTP, HTTPS, TFTP, SFTP, TELNET 等多种协议。 curl 功能强大,它提供了包括代理支持,用户认证,FTP 上载,HTTP post,SSL 连接,文件续传等许多特性。

基本语法:curl [options … ]

总结 :
(1) 传输性能:wget 通过支持后台执行及断点续传提高文件传输效率; rsync 则以其高效的传输及压缩算法达到快传输的目的。

(2) 配置难度:rcp 只需进行简单的配置,创建.rhost文件以及设置/etc/hosts文件中主机名与IP地址列表; wget设置方便简单,只需在客户端指定参数执行命令即可; rsync 在使用前需要对服务端/etc/rsyncd.conf 进行参数设定,配置内容相对复杂。

(3) 安全性能:ftp、rcp不保证传输的安全性,scp、rsync则均可基于ssh 认证进行传输,提供了较强的安全保障。wget 也可通过指定安全协议做到安全传输。

通过上述的对比不难发现,每种文件传输方法基于其自身的特点与优势均有其典型的适用场景:

(1) ftp 作为最常用的入门式的文件传输方法,使用简单,易于理解,并且可以实现脚本自动化;但是需要安装ftp server才可以访问远程ftp server

(2) rcp 相对于ftp可以保留文件属性并可递归的拷贝子目录;

(3) scp 利用ssh传输数据,并使用与ssh相同的认证模式,相对于rcp提供更强的安全保障;

(4) wget实现递归下载,可跟踪HTML 页面上的链接依次下载来创建远程服务器的本地版本,完全重建原始站点的目录结构,适合实现远程网站的镜像;

(5) curl 则适合用来进行自动的文件传输或操作序列,是一个很好的模拟用户在网页浏览器上的行为的工具;

(6) rsync 更适用于大数据量的每日同步,拷贝的速度很快,相对wget来说速度快且安全高效;

(7) sftp使用在数据连接上使用ssh2,所以文件的传输是尽可能地安全。但传输速度慢。是ftp的替代品,比ftp安全,不能访问http资源;

(8) lftp可以访问ftp资源,也可以访问http资源。支持断点续传,多进程下载。

 

服务器集群中的服务器之间的通信

多用远程过程调用协议RPC(Remote Procedure Call Protocol)。

只要涉及到分布式服务,就绕不开RPC调用。RPC是什么,我认为大部分同学都能说出个一二三。

那么RPC一次调用,到底经历了哪些过程?

一直在说RPC耗时优化,那到底时间耗在了哪里?

本篇带大家一起来梳理清晰。再遇到面试官问RPC,直接灭丫

Part1 前言 扯一扯RPC

RPC ?(Remote Procedure Call) 远程过程调用,目的是让调用远程服务的体验,就像调用本地方法一样简单。

已经有了HTTP,为啥还要实现个RPC? 首先,两者不在一个水平面,不好比较。http是一种传输协议,RPC由TCP传输协议和其他部分组成,算是一种架构;再者,效率和性能有所差异,Http相比tcp传输更耗性能;再再者,定位不同,Rpc一般用于实现内部网络各服务间的高性能调用,Http一般用于跨环境的数据传输和接口调用。

RPC亘古不变的三个主题? 客户端、服务端、注册中心。后续包括服务注册、服务发现、路由寻址、序列化、IO模型等等事项,都是在围绕三者之间的合作和交互来进行的。

常见RPC有哪些?

出镜最多的要数dubbo,因为总被面试官问到;

性能优良的grpc,google出品,可以在任何环境下运行;

美团的OCTO和pigeon,一个章鱼水里游,一个鸽子天上飞;

京东之前的saf,是对dubbo的定制化开发,后面升级到了自研的jsf框架,其作者之一的章老板之前就已经是蚂蚁的P8大佬了;

蚂蚁自研的sofaRPC也有章老板的参与,由于设计初衷和蚂蚁内部的使用规模,功能丰富度和服务稳定性上,那是相当不错,目前也已经开源。

Thrift

发布-订阅,请求-应答模式

Apahce Thrift是FaceBook实现的一种高效的、支持多种语言的远程服务调用的框架。具体可以利用JMS/CORBA/RMI,XMLRPC/SOAP等

消息队列:简单的可以用zeromq做,稍微复杂一点可以用rabbitmq/activemq/qpid等等各种成熟方案。

在做服务器集群时,集群中的服务器需要通信,比如Client1(简称C1)连接到Server1(简称S1),Client2连接到Server2,Client1需要向Client2发消息,S1并不知道C2已连接到S2。

A方案:采用组播(或广播),S1在接收到C1消息后,发送广播包查询C2位于哪个Server上,这时S2向S1回复,S1再将消息发送到S2,S2转发给C2,但是udp是不可靠的,虽然Server都位于同一局域网内,如果消息丢了,那C2就接收不到C1的消息了。

B方案:增加一个路由服务器,所有Server都连接到路由服务器(tcp长连接),S1将消息转发给路由服务器,路由服务器再广播给所有Server,由各个Server自行判断,但这样程序复杂度就上升了,每个Server都会处理本来不属于自己处理的消息,而且路由服务器会成为瓶颈,消息数量大规模增加的话。

rabbitmq

MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。其中较为成熟的MQ产品有IBM WEBSPHERE MQ等等。

ActiveMQ

1、ActiveMQ是消息队列技术,为解决高并发问题而生!

2、ActiveMQ生产者消费者模型(生产者和消费者可以跨平台、跨系统)有中间平台

3、ActiveMQ支持两种消息传输方式

1)Queue,队列模式,生产者生产了一个消息,只能由一个消费者进行消费

2)Topic,发布/订阅模式,生产者生产了一个消息,可以由多个消费者进行消费

Qpid

AMQP是一种用于业务消息的开放网络协议。他定义了一种允许双方进行可靠业务消息传递的二进制线级协议。该协议的目标是成为所有消息中间件之间进行互操作的标准协议。

消息队列是一种进程间通信线程或同一进程的不同线程间的通信方式。

Qpid则是由Apache开发的一种消息队列,实现了AMQP协议,并且支持多种语言与多种平台。

zeromq

这是个类似于Socket的一系列接口,他跟Socket的区别是:普通的socket是端到端的(1:1的关系),而ZMQ却是可以N:M 的关系,人们对BSD套接字的了解较多的是点对点的连接,点对点连接需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而ZMQ屏蔽了这些细节,让你的网络编程更为简单。ZMQ用于node与node间的通信,node可以是主机或者是进程。

引用官方的说法: “ZMQ(以下ZeroMQ简称ZMQ)是一个简单好用的传输层,像框架一样的一个socket library,他使得Socket编程更加简单、简洁和性能更高。是一个消息处理队列库,可在多个线程、内核和主机盒之间弹性伸缩。ZMQ的明确目标是“成为标准网络协议栈的一部分,之后进入Linux内核”。现在还未看到它们的成功。但是,它无疑是极具前景的、并且是人们更加需要的“传统”BSD套接字之上的一 层封装。ZMQ让编写高性能网络应用程序极为简单和有趣。”