Permalink
Browse files

reformatting

  • Loading branch information...
1 parent c6f4a02 commit 068ec550baecf39c9e0fb073b928a03484ca35a0 Nick Kallen committed Feb 18, 2011
Showing with 12 additions and 14 deletions.
  1. +12 −14 README.md
View
26 README.md
@@ -1,8 +1,8 @@
# Finagle
-## What is it?
+Finagle is an library for building *asynchronous* RPC servers and clients in Java, Scala, or any JVM language. Built atop [Netty](http://www.jboss.org/netty), Finagle provides a rich set of tools that are protocol independent.
-Finagle is an library for building *asynchronous* RPC servers and clients in Java, Scala, or any JVM language. Built atop [Netty](http://www.jboss.org/netty), Finagle provides a rich set of tools that are protocol independent:
+Finagle is flexible enough to support a variety of RPC styles, including request-response, streaming, and pipelining (e.g., HTTP pipelining and Redis pipelining). It also makes it easy to work with stateful RPC styles (e.g., those requiring authentication and those that support transactions).
### Client Features
@@ -28,11 +28,9 @@ Finagle is an library for building *asynchronous* RPC servers and clients in Jav
* Memcached/Kestrel
* More to come!
-Finagle is flexible enough to support a variety of RPC styles, including request-response, streaming, and pipelining (e.g., HTTP pipelining and Redis pipelining). It also makes it easy to work with stateful RPC styles (e.g., those requiring authentication and those that support transactions).
-
## How do I start?
-Here is a simple HTTP server and client:
+Here is a simple HTTP server and client. The server returns a simple HTTP 200 response:
### Scala
@@ -47,6 +45,8 @@ Here is a simple HTTP server and client:
.bindTo(address)
.build(service)
+The client connects to the server, and issues a simple HTTP GET request:
+
val client: Service[HttpRequest, HttpResponse] = ClientBuilder()
.codec(Http)
.hosts(address)
@@ -56,7 +56,9 @@ Here is a simple HTTP server and client:
val request: HttpRequest = new DefaultHttpRequest(HTTP_1_1, GET, "/")
val responseFuture: Future[HttpResponse] = client(request)
-### Java
+ // all done!
+ client.close()
+ server.close()
Note that the variable `responseFuture` in this example is of type `Future[HttpResponse]`, which represents an asynchronous HTTP response (i.e., a response that will arrive sometime later). With a `Future` object, you can express your program in either a synchronous or asynchronous style: the program can either 1) block, awaiting the response, or 2) provide a callback to be invoked when a response is available. For example,
@@ -70,11 +72,9 @@ Note that the variable `responseFuture` in this example is of type `Future[HttpR
println(response)
}
-### Java
-
`Futures` allow the programmer to easily express a number of powerful idioms such as pipelining, scatter-gather, timeouts, and error handling. See the section "Using Futures" for more information.
-## Services and Filters
+## Services
In Finagle, RPC Servers are built out of `Services` and `Filters`. A `Service` is a simply a function that receives a request and returns a `Future` of a response. For example, here is a service that increments a number by one.
@@ -84,18 +84,18 @@ In Finagle, RPC Servers are built out of `Services` and `Filters`. A `Service` i
def apply(request: Int) = Future { request + 1 } // (1)
}
-### Java
-
Note that `plusOneService` acts as if it were asynchronous despite that it is not doing any asynchronous work. It adheres to the `Service[Req, Rep]` contract by wrapping the synchronously computed response in a "constant" `Future` of type `Future[Int]`.
-More sophisticated `Services` than `plusOneService` might make truly asynchronous calls (e.g., by making further RPC calls or by scheduling work in a queue), and so the return type of `Future[Rep]` is the more general.
+More sophisticated `Services` than `plusOneService` might make truly asynchronous calls (e.g., by making further RPC calls or by scheduling work in a queue), and `apply` having a return type of `Future[Rep]` is general enough to handle most cases.
Once you have defined your `Service`, it can be bound to a SocketAddress, thus becoming an RPC Server:
ServerBuilder()
.bindTo(address)
.build(plusOneService)
+### Filters
+
However, an RPC Server must speak a specific protocol. One nice way to design an RPC Server is to decouple the protocol handling code from the implimentation of the business service. A `Filter` provides a easy way to do this.
Here is a `Filter` that adapts the `HttpRequest => HttpResponse` protocol to the `Int => Int` `plusOneService`:
@@ -116,8 +116,6 @@ Here is a `Filter` that adapts the `HttpRequest => HttpResponse` protocol to the
val httpPlusOneService: Service[HttpRequest, HttpResponse] =
httpToIntFilter.andThen(plusOneService) // (3)
-### Java
-
This example illustrates three important concepts:
1. A `Filter` wraps a `Service` and (potentially) converts the input and output types of the service to other types. Here `Int => Int` is mapped to `HttpRequest => HttpResponse`.

0 comments on commit 068ec55

Please sign in to comment.