Netty, which is used within Finagle, uses a pipeline of \"handlers\" to sequentially process in and out bound data. Netty examples, and included libraries, show various handler
Finagle and Netty are structured quite differently.
Services, Filters, and codecs are actually quite orthogonal concepts. Let me try & explain. As a user -- ie. not an implementor of a codec -- you should only need to know about services and filters.
First, a codec is responsible for turning a stream of bytes into a discrete requests or responses. For example, the HTTP codec reads the bytestream, and produces HttpRequest
or HttpResponse
objects.
A Service
is an object that, given a request, produces a Future
of a reply -- it’s a simple function (and indeed it extends Function
). The interesting thing about services is that they are symmetric. A client uses a service, a server provides one. The important thing about services is that (1) they operate over discrete requests and responses, and (2) they match requests to responses - all of which is implied by its type. This is why we call finagle an “RPC” system - request/response pairs are the defining characteristic of RPCs.
So, we have Services, but it's useful and important to have modify Service behavior independently of the service itself. For example, we might want to provide timeout functionality, or retries. This is what Filter
s do. They provide a service independent method of modifying Service behavior. This enhanced modularity and reuse. For example, timeouts in finagle are implemented as a filter, and can be applied to any service.
You can find more details about services & filters in the Scala School.
*
So, let’s contrast this to Netty’s handlers. These are generic event handlers, that are also stackable. You can do many similar things with them, but the underlying model is a stream of events that are attached to a connection. This makes it more difficult to write generic modules (eg. to implement retries, timeouts, failure accrual, tracing, exception reporting, etc..) because you cannot make many assumptions about the pipeline you’re operating with.
Netty pipelines also conflate the protocol implementation with application handlers. Finagle cleanly separates the two, and modularity is enhanced because of it.
Netty is a wonderful set of abstractions, but for RPC servers, finagle offers greater modularity and composability.
*
Summarizing crudely you could say that Netty is “stream oriented” while finagle is “service oriented”. This is an important distinction, and it's what allows us to implement robust RPC services in a modular manner. For example, connection pooling and load balancing - crucially important to RPC clients - fall out naturally from the service model, but doesn’t fit in the stream model.