Finagle中服务、过滤器和编解码器之间的边界

11

Netty在Finagle内部使用,使用一系列“处理程序”管道顺序处理传入和传出的数据。Netty示例和包含的库展示了各种处理程序用于身份验证、协议编解码器和服务实际业务逻辑。

Finagle似乎采用了处理程序的概念,而是直接为API用户提供编解码器、过滤器和服务。虽然这些具有不同的签名,但是Finagle的新用户需要决定使用哪个来实现其整个服务器的每个部分。他们现在需要决定哪一部分应该成为编解码器,哪些是过滤器,哪些是管道末端的单个服务,而不仅仅是决定在哪里将链分解成各种Netty处理程序。总之,尽管Finagle比Netty更高级,应该使构建服务的任务更容易,但API用户可能有更多的选择。

将处理流的特定部分放入编解码器、过滤器还是单个服务的关键决策点以及其优缺点是什么?如果有可能进一步扩展管道,是否应该将服务逻辑放入过滤器中,最后使用“noop”服务?考虑到可以调整过滤器(作为管道中的处理程序)的灵活性,与单个编解码器和服务的区别,为什么不将“所有内容”都设置为过滤器?

2个回答

18

Finagle和Netty的结构非常不同。

服务、过滤器和编解码器实际上是相当独立的概念。让我来试着解释一下。作为一个用户——即不是编解码器的实现者——您只需要知道服务和过滤器。

首先,编解码器负责将字节流转换为离散的请求或响应。例如,HTTP编解码器读取字节流,并生成HttpRequestHttpResponse对象。

Service是一个对象,在给定请求时,生成一个回复的Future——它是一个简单的函数(实际上它扩展了Function)。服务的有趣之处在于它们是对称的。客户端使用服务,服务器提供服务。服务的重要之处在于它们(1)操作离散的请求和响应,以及(2)将请求与响应匹配——这都隐含在它的类型中。这就是为什么我们将finagle称为“RPC”系统——请求/响应对是RPC的定义特征。

因此,我们有了服务,但是在服务本身之外修改服务行为是非常有用和重要的。例如,我们可能想提供超时功能或重试。这就是Filter的作用。它们提供了一种独立于服务本身的修改服务行为的方法。这增强了模块化和重用。例如,在finagle中,超时是作为过滤器实现的,并且可以应用于任何服务。

您可以在Scala学校中找到有关服务和过滤器的更多详细信息。

*

那么,让我们对比一下Netty的处理程序。它们是通用的事件处理程序,也可以堆叠使用。您可以通过它们做很多类似的事情,但底层模型是连接附加的事件流。这使得编写通用模块(例如实现重试、超时、故障累积、跟踪、异常报告等)更加困难,因为您无法对正在操作的管道进行许多假设。

Netty管道还将协议实现与应用程序处理程序混合在一起。Finagle则将两者清晰地分离,因此增强了模块化。

Netty是一个非常出色的抽象集合,但对于RPC服务器,Finagle提供了更大的模块化和可组合性。

*

粗略地概括,您可以说Netty是“面向流”的,而Finagle是“面向服务”的。这是一个重要的区别,它允许我们以模块化的方式实现强大的RPC服务。例如,连接池和负载平衡-对RPC客户端至关重要-自然地从服务模型中推导出来,但不适用于流模型。


哦,我想更简洁地回答你最后一段问题:服务公开应用程序行为,过滤器以通用和模块化的方式修改它们的行为。因此,例如,您可能有一个服务,用于提供HTTP端点,但是一个过滤器可以将异常转换为漂亮的HTTP 500消息。 - marius a. eriksen
感谢Marius清晰地阐述了使用Finagle而不是一堆Netty处理程序所能获得的好处。 - scaling_out

0

我认为这不应该是编解码器或过滤器之间的决定。编解码器更适合包含在过滤器中。

至于决策逻辑,放置在哪里取决于必须做出的决策。业务决策应该与您的业务逻辑一起进行,而某些决策(例如路由、负载平衡、某些类型的访问控制等)可以很好地作为过滤器。

服务通常位于最后一条线上,而使用其过滤器的Finagle将帮助您到达那里。

不知道这是否有意义?

暂时远离技术细节,看看逻辑。什么应该负责什么,然后使技术适合您的设计。不要过度弯曲设计以适应技术。

顺便说一句,我已经在Finagle之上实现了一个网关服务器,并且我必须说:这是一个很好的库。

我不知道您正在尝试构建什么,但也可以查看可能的替代方案:Spray、Blueeyes、Unfiltered、Play-Mini等。这可能会帮助您更好地理解何处适用。


如果您查看Finagle的ServerBuilder类的源代码,您会发现离散的步骤确实是通过向管道添加更多处理程序来实现的。顺序围绕各种选项(例如统计接收器选项)进行固定。我的问题的要点是,仅坚持使用单个过滤器概念(即Netty处理程序),并提供更多的如何排序它们以获得所需结果的示例,可能既更简单易懂,也更灵活,这对于Finagle用户来说都是有益的。编解码器、统计选项、SSL和其他功能都是处理程序。 - scaling_out
标准的处理程序设置/顺序可以轻松地在库中提供,并且用户可以使用“andThen”链构建自己的处理程序。这种方法可以通过减少特殊概念的数量来减少学习Finagle所涉及的认知负荷。此外,谁能说有人不想对某些内容进行编码,然后将结果发送到另一个编解码器以进行进一步封装呢?同样适用于线路另一端的Finagle服务。当您希望另一个服务直接跟在后面时会发生什么? - scaling_out
很酷,如果我误解了什么请原谅。我本来想建议你在Finaglers论坛上发布这个问题,但是已经有人发了。https://groups.google.com/forum/?fromgroups#!topic/finaglers/upDrkR4GX7o - Jack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接