rest服务json传递
微服务是一项大生意。 得益于容器编排,多进程应用程序开发和庞大的用户需求方面的进步,公司正在从传统的单片应用程序向分布式,高可用性的微服务迈进。 将应用程序分成较小的块可获得许多形式的回报。 但是,随着这种分发,出现了新的要求:用于服务间通信的消息传递。
微服务消息传递如何绑定到CI / CD和Codeship产品? 对开发人员意味着什么?
鞋拔解决方案
最近看来,“如果你只有一把锤子,那么每个问题都像钉子”的古老格言适合微服务消息传递。 由于基于云的应用程序也是基于Internet的应用程序,因此许多不熟悉云技术的开发人员本质上都在将每种服务设计作为微型Web服务器来进行。 由于API级服务的公共接口将REST与JSON数据包一起使用,因此对每个内部服务都采用这种格式也是合理的。
现在,可能只是为应用程序中的每个服务使用基于JSON的REST接口就是正确的选择。 充其量,这可能不是错误的选择,但是通过记住“使用正确的工具来完成工作”,应用程序可以得到简化,更高效,更安全并且更易于维护。 我们知道,数据库,语言甚至服务器提供者都是如此。 那为什么不发送消息呢?
互联网消息传递的要点
Internet消息传递使用网络层上的Internet协议(IP)。 它的作用是管理寻址,并促进从发送地址到接收地址的数据包(称为数据报)的传递。
在该层的正上方是传输层。 这包括TCP(传输控制协议),UDP(用户数据报协议)和鲜为人知的SCTP(流控制传输协议)和DCCP(数据报拥塞控制协议)。 TCP和UDP在Internet数据包传输中无处不在,并且构成了网络上几乎所有数据的外部框架。 后两个是Internet传输层的最新添加。
由于传输层非常靠近网络,因此网络硬件(NAT)必须了解传输数据包的成帧。 由于此类设备尚未广泛理解SCTP和DCCP,因此它们的使用受到抑制,因为新的NAT设备不太可能支持这种广为人知的协议,因此这形成了恶性循环。
下一层是TLS(传输层安全性),它为TCP和UDP提供可选的安全性功能。
最后一层是应用程序层。 这有助于在传输层之上进行额外的框架化,从而提供HTTP,SMTP,SIP等协议。
应用层协议通常位于TCP或UDP帧内。 UDP非常轻巧,非常适合处理大量有损数据。 它对于自定义协议也很有用,并构成了许多高速消息平台的基础。 另一方面,TCP提供了许多附加的内置功能,例如传输可靠性,重传和确认。 它还支持带宽更改,将带宽有限的分组数据分成较小的块以提高传递机会。
构图
从一个应用程序发送到另一个应用程序的任何数据都将存在一个或多个帧中。 外框几乎总是UDP或TCP。 在该框架内放置一个应用程序层协议框架,例如HTTP。 额外的帧可以进一步嵌套,直到达到最终的有效载荷数据为止,尽管这不是必需的。
帧通常由标题块和可选的有效负载组成。 有效载荷可以是嵌套帧或原始数据。
帧头提供有关数据包的各种详细信息。 这可以包括(但不限于):
- 签名,以标识帧类型;
- 标头长度;
- 有效载荷长度;
- 标头中存储的参数数量;
- 协议特定的报头参数;
- 安全值,例如数据包校验和。
数据包通过时,NAT会修改UDP / TCP层,从而同时转换传输地址,端口和校验和。 众所周知的嵌套应用程序框架(例如SMTP,FTP和SIP)也是如此。
HTTP数据包由一个以太网外部帧,一个IP帧,一个TCP帧,HTTP帧以及最后的内容有效内容组成。 因此,这些框架的大小为:
最小标题大小 | 最大标题大小 | 典型尺寸 | ||
---|---|---|---|---|
乙太网路 | (固定) | (固定) | 24字节 | |
知识产权 | (固定) | (固定) | 20字节 | |
UDP协议 | (固定) | (固定) | 8字节 | |
TCP协议 | 20字节 | 60字节 | 32字节 | |
HTTP | 没有最低要求 | 没有最大 | 100 – 800字节 |
包括了UDP标头大小以进行比较。 如您所见,简单的REST请求可能会导致响应数据包大小接近900字节,而没有计算实际的正文内容。 好大 如果您想象每秒发送一千个这样的请求,则可以轻松地设想内部网络套接字上不必要的拥塞。
选择消息传递选项
在考虑消息传递需求时,需要同时考虑消息传输的选择和消息正文的格式。
讯息格式
为消息正文选择序列化格式相对简单:
- 数据是否需要序列化(例如,使用非二进制数据或复杂数据类型)?
- 数据是否需要人类读取?
- 基础平台是否提供易于使用的序列化程序库?
- 是否有很多数据将从压缩中受益?
- 现有的第三方平台是否需要了解数据?
有多种消息格式可供选择。 如前所述,由于JSON的清晰性,表达性,灵活性以及它在REST中的普遍使用,因此JSON是一个常用的选择。 其他格式包括:
- Apache Avro :一种二进制序列化格式,其大小比JSON更有效。 该格式使用JSON来描述串行器/解串器使用的数据模式。
- ASN.1 :人机可读。 电信公司使用了一段时间,它是一种久经考验的格式。
- BSON :通常比JSON更冗长,并且不易被人阅读。 但是,它是为提高存储和扫描效率而设计的,非常适合文档存储等。
- 协议缓冲区 :像Apache Avro一样,是一种使用可读模式的压缩二进制格式。 它的普遍性和速度使其成为有吸引力的选择。
运输形式
选择序列化格式后,就该决定如何分发数据了。 但是,这不是直截了当的。
直接通讯
如果消息交换的活动成员知道通过它的所有数据,则可以简化活动伙伴与其对等方之间的连接。
数据可以沿着传输进行推送或拉出。 如果服务具有数据,并且需要将其发送到特定的位置,则将数据推送。 如果数据存在于某处并且是服务需要的,则将其拉出。
在REST的情况下,两种传输类型都会遇到。 数据通常与每个请求一起推送和拉取,无论目的是发送数据,检索数据还是同时进行两者。 但是,推和拉数据被认为是有意的。 因此,下载文件的请求就是请求,而将存储数据的POST视为请求。
在这种情况下,传输可以是简单的UDP或TCP套接字。 如果数据是连续流且格式有损(如果数据包被丢弃,例如某些视频或音频流,则可以恢复),那么UDP非常适合。 但是,如果您需要保证数据的传输(或在数据失败时得到通知),那么TCP是一个不错的选择。 然后,当然有各种基于这些格式的应用程序级别格式。
框架和序列化之间的区别
构成数据包头的数据只是字节。 身体也可以这样说。 这样,在应用程序级别,服务之间发送的数据可以是数据包,序列化主体或两者。
帧存在于较低级别以控制吞吐量。 例如,存储在TCP帧中的值提供了一些段,这些段告诉TCP套接字库利用了如何管理传入和传出数据。 这样做仅仅是为了使更高级别的应用程序更容易。 如果TCP处理数据包重传和确认,则应用程序不必这样做。
在处理自己的数据时,您可以选择使用自己的成帧技术来实现自己的控制功能并实现自己的标头。 或者,如果需要命令,则可以选择将它们嵌入序列化主体中。
例如,Redis数据库将TCP套接字用于其客户端实用程序。 然后,该命令不再使用诸如SELECT,SET和INCR之类的命令来构成数据包数据,而是形成串行化格式的一部分。 例如:
*2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n
可以改写为:
*2 // the packet is an array of two elements
$4 // the first is an element (a command) of 4 characters
LLEN
$6 // the second is a value of 6 characters
mylist
然后,数据库会将其视为命令:
LLEN mylist
RESP(REdis序列化协议)格式和成帧之间的区别只是描述该数据包的元数据是内联的。 但是,如果格式定义为:
*2\r\n\$4\r\n$6\r\nLLEN\r\nmylist\r\n
那么人们可以适当地将其视为一帧,因为整个身体数据都遵循元数据。
消息代理
为了受益于服务封装,从应用程序服务发出或可用的消息有时是未知的,不可用的,或者仅仅是故意模棱两可的。 例如,可能集群中的给定服务会生成动画GIF。 您的应用程序中的其他几个服务都利用这些生成的图像中的通知; 一个服务将图像元数据记录到数据存储中,一个服务将电子邮件发送给发起方,另一个服务给图像加水印。
在这种时候,将每个服务直接连接到GIF生成服务可能没有意义; GIF生成器知道其他每个服务的存在是没有意义的,并且日志记录服务可能会记录应用程序中每个服务的数据。 确保日志记录服务知道应用程序中的所有其他服务的工作量远远超过了必要的工作。
此类通知可以视为Events
。 就像在单片应用程序开发中一样,应该可以发布和订阅这些通知,而无需对服务之间的关系进行硬编码,实际上,通过使用brokers
使之成为可能。
由于经纪人独立于您的服务,因此服务技术不需要与您的服务实现相匹配。 有许多消息代理实现。 其中包括:
- Apache Kafka :使用管道处理数据流,例如基于时间的日志记录。
- RabbitMQ :是AMQP(应用程序级框架)消息传递代理。
- Apache ActiveMQ :是一个多框架支持消息代理。
每个经纪人提供不同的功能,并在不同情况下受益。 您选择的代理应取决于您的应用程序要求,但是可以通过选择合适的代理来减轻服务中的许多编码。
经纪人功能可能包括:
- 消息的短期和长期存储
- 容错
- 高可用性,增加了整个应用程序的HA
- 使用控制台或Web界面进行消息检查和可见性
- 额外的安全性,筛选受权限限制的消息,这些服务没有正确的权限
代理消息的另一个重要方面是它们可能支持的其他消息模式。 例如,RabbitMQ支持多种模式,包括:
- 扇出 。 扇出模式是一种将消息分发到所有侦听队列的方法。 本质上,任何监听代理的服务都将收到扇出消息。
- 主题交流 。 在此,消息是根据部分队列密钥模式进行路由的。 例如,如果有三个队列,路径分别为
users.forms.data
,users.access.data
和files.forms.submitted
,则主题*.forms.*
将匹配两个队列,而files.*.*
将匹配其中之一。 - 标头交换 。 标头交换基于数据包标头值的过滤发送数据包。 使用这种交换,数据包实质上是根据类型对自己进行排序,而不是明确地知道将消息发送到何处。
结论
在消息传递方面有很多选择。 仅仅选择what you know
的并不总是最好的方法。 通过仔细考虑您的需求,可以从长远来看节省很多工作,而且可以整体上提高应用程序的速度和效率。
翻译自: https://www.javacodegeeks.com/2018/08/microservices-messaging-rest.html
rest服务json传递