> ç´°ããç¹ã§ééããªã©ãããã¨æãã¾ããfork ãã¦ç´ãã¦ããã ããã¨å©ããã¾ãã
Finagle is built using [sbt](http://code.google.com/p/simple-build-tool/wiki/RunningSbt). We've included a bootstrap script to ensure the correct version of sbt is used. To build:
>Finagle 㯠sbt ã使ã£ã¦ãã«ããã¦ãã¾ããç§ãã¡ã¯ç¢ºå®ã«é©åãªãã¼ã¸ã§ã³ã® sbt ã使ãããã«ãã¼ãã¹ãã©ããç¨ã®ã¹ã¯ãªãããå«ãã¦ãã¾ãããã®ããã«å®è¡ãã¾ãã
$ ./sbt test
- - -
# Finagle Developer Guide (December 15, 2011 Draft)
## Quick Start
Finagle is an asynchronous network stack for the JVM that you can use to build *asynchronous* Remote Procedure Call (RPC) clients and servers in Java, Scala, or any JVM-hosted language. Finagle provides a rich set of tools that are protocol independent.
>Finagle 㯠éåæãª RPC ã¯ã©ã¤ã¢ã³ãã¨ãã®ãµã¼ãã Java ã Scalaããã®ä»ã® JVM ä¸ã®è¨èªã§æ¸ãããã«ã¤ãããã JVM åãéåæãããã¯ã¼ã¯ã¹ã¿ãã¯ã§ããFinagle ã¯ç¹å®ã®ãããã³ã«ã«ä¾åããªãè±å¯ãªãã¼ã«ç¾¤ãæä¾ãã¾ãã
The following Quick Start sections show how to implement simple RPC servers and clients in Scala and Java. The first example shows the creation a simple HTTP server and corresponding client. The second example shows the creation of a Thrift server and client. You can use these examples to get started quickly and have something that works in just a few lines of code. For a more detailed description of Finagle and its features, start with Finagle Overview and come back to Quick Start later.
>以ä¸ã®ã¯ã¤ãã¯ã¹ã¿ã¼ãã®ç¯ã§ã¯ã·ã³ãã«ãª RPC ãµã¼ãã¨ã¯ã©ã¤ã¢ã³ãã Scala 㨠Java ã§å®è£
ããæ¹æ³ã説æãã¾ããæåã®ä¾ã¯ãã·ã³ãã«ãª HTTP ãµã¼ãã¨ããã«å¯¾å¿ããã¯ã©ã¤ã¢ã³ãã§ããäºã¤ç®ã®ä¾ã¯ Thrift ãµã¼ãã¨ãã®ã¯ã©ã¤ã¢ã³ãã§ãããããã®ä¾ã¯å°ãªãè¡æ°ã®ã³ã¼ãã§ããã£ã¨ä½ãåããã®ãã¤ããã®ã«æµç¨ã§ããã§ããããFinagle ã«é¢ãããã詳細ãªèª¬æããã®æ©è½ãç¥ãããå ´å㯠Finagle Overview ããèªã¿å§ãã¦ãã¾ããã®ã¯ã¤ãã¯ã¹ã¿ã¼ãã«å¾ã§æ»ã£ã¦ãã¦ãã ããã
**Note:** The examples in this section include both Scala and Java implementations. Other sections show only Scala examples. For more information about Java, see Java Design Patterns for Finagle.
>ãã®ç¯ã§ã®ä¾ã¯ Scala 㨠Java ã®ä¸¡æ¹ã®å®è£
ãå«ãã§ãã¾ããä»ã®ç¯ã§ã¯ Scala ã ãã®ä¾ã示ãã¦ãã¾ããJava ã«é¢ããæ
å ±ããã£ã¨æ¬²ãããã° Java Design Patterns for Finagle ãã覧ãã ããã
[Top](#Top)
### Simple HTTP Server
Consider a very simple implementation of an HTTP server and client in which clients make HTTP GET requests and the server responds to each one with an HTTP 200 OK response.
>ã¯ã©ã¤ã¢ã³ãã HTTP GET ãªã¯ã¨ã¹ããæãã¦ããµã¼ãã 200 OK ã§å¿çããã ãã®ãã¨ã¦ãåç´ãªHTTP ãµã¼ãã»ã¯ã©ã¤ã¢ã³ãã®å®è£
ãèãã¦ã¿ã¾ãããã
The following server, which is shown in both Scala and Java, responds to a client's HTTP request with an HTTP 200 OK response:
>以ä¸ã«ãã Scala 㨠Java 両æ¹ã§æ¸ããããµã¼ãã®ä¾ã¯ã¯ã©ã¤ã¢ã³ãããã® HTTP ãªã¯ã¨ã¹ãã«å¯¾ã㦠200 OK ã§å¿çãã¾ãã
##### Scala HTTP Server Implementation
val service: Service[HttpRequest, HttpResponse] = new Service[HttpRequest, HttpResponse] { // 1
def apply(request: HttpRequest) = Future(new DefaultHttpResponse(HTTP_1_1, OK)) // 2
}
val address: SocketAddress = new InetSocketAddress(10000) // 3
val server: Server[HttpRequest, HttpResponse] = ServerBuilder() // 4
.codec(Http)
.bindTo(address)
.name("HttpServer")
.build(service)
##### Java HTTP Server Implementation
Service service = new Service() { // 1
public Future apply(HttpRequest request) {
return Future.value( // 2
new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK));
}
};
ServerBuilder.safeBuild(service, ServerBuilder.get() // 4
.codec(Http.get())
.name("HttpServer")
.bindTo(new InetSocketAddress("localhost", 10000))); // 3
##### HTTP Server Code Annotations
1. Create a new Service that handles HTTP requests and responses.
2. For each request, respond asynchronously with an HTTP 200 OK response. A Future instance represents an asynchronous operation that may be performed later.
3. Specify the socket addresses on which your server responds; in this case, on port 10000 of localhost.
4. Build a server that responds to HTTP requests on the socket and associate it with your service. In this case, the Server builder specifies
- an HTTP codec, which ensures that only valid HTTP requests are received by the server
- the host socket that listens for requests
- the association between the server and the service, which is specified by `.build` in Scala and the first argument to `safeBuild` in Java
- the name of the service
> - HTTP ãªã¯ã¨ã¹ãã¨ã¬ã¹ãã³ã¹ããã³ãã«ããæ°ãããµã¼ãã¹ãã¤ããã¾ã
> - åãªã¯ã¨ã¹ãã«å¯¾ãã¦éåæã« 200 OK ã§å¿çãã¾ããFuture ã®ã¤ã³ã¹ã¿ã³ã¹ã¯éåæãªå¦çï¼å°ãé
ãã¦å®è¡ããããããããªãï¼ã§ãããã¨ã表ããã¦ãã¾ãã
> - ãµã¼ããå¿çããã½ã±ããã¢ãã¬ã¹ãæå®ãã¾ããä»åã®ã±ã¼ã¹ã§ã¯ localhost ã® 1000 çªãã¼ãã§ãã
> - ãã®ã½ã±ããï¼ã¢ãã¬ã¹ã»ãã¼ãï¼ã«ãã㦠HTTP ãªã¯ã¨ã¹ãã«å¿çãããµã¼ããçæããããããµã¼ãã¹ã«é¢é£ã¥ãã¾ããä»åã®ã±ã¼ã¹ã§ã¯ãServer builder ã以ä¸ãè¦å®ãã¾ãã
>> - HTTP ã³ã¼ããã¯ï¼æå¹ãª HTTP ãªã¯ã¨ã¹ãã®ã¿ããµã¼ãã«ãã£ã¦åãä»ãããããã¨ãä¿è¨¼ããï¼
>> - æå®ãããã½ã±ããã§ãªã¯ã¨ã¹ããå¾
ã¡åãã
>> - ãµã¼ãã¨ãµã¼ãã¹ã®é¢é£ã¥ãï¼Scala ã§ã¯ #buildã® Java ã§ã¯ #safeBuild ã®ç¬¬ä¸å¼æ°ã¨ãã¦ãµã¼ãã¹ã渡ãï¼
>> - ãµã¼ãã¹ã®åå
**Note:** For more information about the Java implementation, see Java Design Patterns for Finagle.
>Java ã§ã®å®è£
ã«é¢ããããè©³ç´°ãªæ
å ±ã¯ Java Design Patterns for Finagle ãã覧ãã ããã
[Top](#Top)
### Simple HTTP Client
The client, which is shown in both Scala and Java, connects to the server, and issues a simple HTTP GET request:
>Scala 㨠Java 両æ¹ã§æ¸ãããã¯ã©ã¤ã¢ã³ãã§ãããµã¼ãã«æ¥ç¶ããåç´ãª HTTP GET ãªã¯ã¨ã¹ããçºè¡ãã¾ãã
##### Scala HTTP Client Implementation
val client: Service[HttpRequest, HttpResponse] = ClientBuilder() // 1
.codec(Http)
.hosts(address)
.hostConnectionLimit(1)
.build()
// Issue a request, get a response:
val request: HttpRequest = new DefaultHttpRequest(HTTP_1_1, GET, "/") // 2
val responseFuture: Future[HttpResponse] = client(request) // 3
onSuccess { response => println("Received response: " + response) // 4
}
##### Java HTTP Client Implementation
Service client = ClientBuilder.safeBuild(ClientBuilder.get() // 1
.codec(Http.get())
.hosts("localhost:10000")
.hostConnectionLimit(1));
// Issue a request, get a response:
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/"); // 2
client.apply(request).addEventListener(new FutureEventListener() { // 3
public void onSuccess(HttpResponse response) { // 4
System.out.println("received response: " + response);
}
public void onFailure(Throwable cause) {
System.out.println("failed with cause: " + cause);
}
});
##### HTTP Client Code Annotations
1. Build a client that sends an HTTP request to the host identified by its socket address. In this case, the Client builder specifies
- an HTTP request filter, which ensures that only valid HTTP requests are sent to the server
- a list of the server's hosts that can process requests
- maximum number of connections from the client to the host
- to build this client service
2. Create an HTTP GET request.
3. Make the request to the host identified in your client.
4. Specify a callback, `onSuccess`, that Finagle executes when the response arrives.
> - ã¯ã©ã¤ã¢ã³ããçæã ã½ã±ããã¢ãã¬ã¹ã§æå®ããããã¹ãã« HTTP ãªã¯ã¨ã¹ããéä¿¡ãã¾ããä»åã®ã±ã¼ã¹ã§ã¯ãClientBuilder ã¯ä»¥ä¸ãè¦å®ãã¾ãã
>> - HTTP ãªã¯ã¨ã¹ããã£ã«ã¿ã¼ï¼æå¹ãª HTTP ãªã¯ã¨ã¹ãã ãããµã¼ãã«éä¿¡ãããã¨ãä¿è¨¼ããï¼
>> - ãªã¯ã¨ã¹ããéããã¨ãã§ãããµã¼ããã¹ãã®ä¸è¦§
>> - ãã®ã¯ã©ã¤ã¢ã³ããããµã¼ããã¹ãã¸ã®æå¤§ï¼åæï¼æ¥ç¶æ°
>> - ã¯ã©ã¤ã¢ã³ããµã¼ãã¹ãçæ
> - HTTP GET ãªã¯ã¨ã¹ããçæãã¾ãã
> - ã¯ã©ã¤ã¢ã³ãã«ãã£ã¦æå®ããããã¹ãã«ãªã¯ã¨ã¹ããéä¿¡ãã¾ãã
> - å¿çãå±ããã¨ãã« Finagle ã«ãã£ã¦å®è¡ããã onSuccess ã³ã¼ã«ããã¯å¦çãæå®ãã¾ãã
**Note:** Although the example shows building the client and execution of the built client on the same thread, you should build your clients only once and execute them separately. There is no requirement to maintain a 1:1 relationship between building a client and executing a client.
>ãã®ä¾ã§ã¯ã¯ã©ã¤ã¢ã³ãã®çæã¨ã¯ã©ã¤ã¢ã³ãã«ããå¦çã®å®è¡ãåãã¹ã¬ããã§ãã£ã¦ãã¾ãããã¯ã©ã¤ã¢ã³ãã¯ä¸åº¦ã ãçæããåãªã¯ã¨ã¹ãã®å®è¡ã¯å¥ã§è¡ãããã¹ãã§ããã¯ã©ã¤ã¢ã³ãã®çæã¨ã¯ã©ã¤ã¢ã³ãã®å®è¡ã¯ 1対1 ã®é¢ä¿ãå®ããªããã°ãªããªãã¨ããæ¡ä»¶ã¯ç¹ã«ããã¾ããã
[Top](#Top)
### Simple Client and Server for Thrift
Apache Thrift is a binary communication protocol that defines available methods using an interface definition language (IDL). Consider the following Thrift IDL definition for a `Hello` service that defines only one method, `hi`:
>Apache Thrift 㯠IDLï¼Interface Definition Languageï¼ãç¨ãã¦å©ç¨å¯è½ãªã¡ã½ãããå®ç¾©ãããã¤ããªè»¢éãããã³ã«ã§ããhi ã¨ããä¸ã¤ã ãã®ã¡ã½ãããæã¤ Hello ãµã¼ãã¹ã«ã¤ãã¦ã以ä¸ã®ãã㪠IDL å®ç¾©ãèãã¦ã¿ã¾ãããã
service Hello {
string hi();
}
#### Simple Thrift Server
In this Finagle example, the `ThriftServer` object implements the `Hello` service defined using the Thrift IDL.
>ãã® Finagle ã®ãµã³ãã«ã§ã¯ã ThriftServer ãªãã¸ã§ã¯ã㯠Thrift IDL ã使ã£ã¦å®ç¾©ããã Hello ãµã¼ãã¹ãå®è¡ãã¾ãã
##### Scala Thrift Server Implementation
object ThriftServer {
def main(args: Array[String]) {
// Implement the Thrift Interface
val processor = new Hello.ServiceIface { // 1
def hi() = Future.value("hi") // 2
}
val service = new Hello.Service(processor, new TBinaryProtocol.Factory()) // 3
val server: Server = ServerBuilder() // 4
.name("HelloService")
.bindTo(new InetSocketAddress(8080))
.codec(ThriftServerFramedCodec())
.build(service)
}
}
##### Java Thrift Server Implementation
Hello.ServiceIface processor = new Hello.ServiceIface() { // 1
public Future hi() { // 2
return Future.value("hi");
}
}
ServerBuilder.safeBuild( // 4
new Hello.Service(processor, new TBinaryProtocol.Factory()), // 3
ServerBuilder.get()
.name("HelloService")
.codec(ThriftServerFramedCodec.get())
// .codec(ThriftServerFramedCodecFactory$.MODULE$) previously
.bindTo(new InetSocketAddress(8080)));
##### Thrift Server Code Annotations
1. Create a Thrift processor that implements the Thrift service interface, which is `Hello` in this example.
2. Implement the service interface. In this case, the only method in the interface is `hi`, which only returns the string `"hi"`. The returned value must be a `Future` to conform the signature of a Finagle `Service`. (In a more robust example, the Thrift service might perform asynchronous communication.)
3. Create an adapter from the Thrift processor to a Finagle service. In this case, the `Hello` Thrift service uses `TBinaryProtocol` as the Thrift protocol.
4. Build a server that responds to Thrift requests on the socket and associate it with your service. In this case, the Server builder specifies
- the name of the service
- the host addresses that can receive requests
- the Finagle-provided `ThriftServerFramedCodec` codec, which ensures that only valid Thrift requests are received by the server
- the association between the server and the service
> - Thrift ãµã¼ãã¹ã¤ã³ã¿ãã§ã¼ã¹ãå®è£
ãã Thrift ããã»ããµãã¤ããã¾ããä»åã®ä¾ã§ã¯ Hello ã®ãã¨ã§ãã
> - ãµã¼ãã¹ã¤ã³ã¿ãã§ã¼ã¹ãå®è¡ãã¾ããä»åã®ã±ã¼ã¹ã§ã¯ãã¤ã³ã¿ãã§ã¼ã¹ã«å®ç¾©ãããã¡ã½ãã㯠"hi" ã¨ããæååãè¿ãã ãã® hi ã¨ããã¡ã½ããã®ã¿ã§ããæ»ãå¤ã¯ Finagle ã® Service ã®ã·ã°ããã£ã«å¾ãããã« Future åã®å¤ã§ãªããã°ãªãã¾ãããï¼ãã£ã¨ã¡ããã¨ãããã®ã§ã¯ Thrift ãµã¼ãã¹ã¯éåæéä¿¡ãå®è¡ããããããã¾ããï¼
> - Thrift ããã»ããµãã Finagle ãµã¼ãã¹ã¸ã®ã¢ããã¿ãã¤ããã¾ããä»åã®å ´å㯠Hello Thrift ãµã¼ãã¹ã¯ TBinaryProtocol ã Thrift ãããã³ã«ã¨ãã¦ä½¿ç¨ãã¾ãã
> - æå®ãããã½ã±ããã§ Thrift ãªã¯ã¨ã¹ãã«å¿çãããµã¼ããçæãããµã¼ãã¹ã«é¢é£ã¥ãã¾ããä»åã®å ´å㯠ServerBuilder ã¯ä»¥ä¸ãè¦å®ãã¾ãã
>> - ãµã¼ãã¹ã®åå
>> - ãªã¯ã¨ã¹ããåãä»ããã½ã±ããã¢ãã¬ã¹
>> - Finagle ãæä¾ãã ThriftServerFramedCodecï¼ãµã¼ããæå¹ãª Thrift ãªã¯ã¨ã¹ãã ããåãä»ãããã¨ãä¿è¨¼ããï¼
>> - ãµã¼ãã¨ãµã¼ãã¹ã®é¢é£ä»ã
#### Simple Thrift Client
In this Finagle example, the `ThriftClient` object creates a Finagle client that executes the methods defined in the `Hello` Thrift service.
>ãã® Finagle ãµã³ãã«ã§ã¯ãThriftClient ãªãã¸ã§ã¯ã㯠Finagle ã¯ã©ã¤ã¢ã³ããçæãã Hello Thrift ãµã¼ãã¹ã«å®ç¾©ãããã¡ã½ãããå®è¡ãã¾ãã
##### Scala Thrift Client Implementation
object ThriftClient {
def main(args: Array[String]) {
// Create a raw Thrift client service. This implements the
// ThriftClientRequest => Future[Array[Byte]] interface.
val service: Service[ThriftClientRequest, Array[Byte]] = ClientBuilder() // 1
.hosts(new InetSocketAddress(8080))
.codec(ThriftClientFramedCodec())
.hostConnectionLimit(1)
.build()
// Wrap the raw Thrift service in a Client decorator. The client provides
// a convenient procedural interface for accessing the Thrift server.
val client = new Hello.ServiceToClient(service, new TBinaryProtocol.Factory()) // 2
client.hi() onSuccess { response => // 3
println("Received response: " + response)
} ensure {
service.release() // 4
}
}
}
##### Java Thrift Client Implementation
Service client = ClientBuilder.safeBuild(ClientBuilder.get() // 1
.hosts(new InetSocketAddress(8080))
.codec(new ThriftClientFramedCodecFactory())
.hostConnectionLimit(1));
Hello.ServiceIface client =
new Hello.ServiceToClient(client, new TBinaryProtocol.Factory()); // 2
client.hi().addEventListener(new FutureEventListener() {
public void onSuccess(String s) { // 3
System.out.println(s);
}
public void onFailure(Throwable t) {
System.out.println("Exception! ", t.toString());
}
});
##### Thrift Client Code Annotation
1. Build a client that sends a Thrift protocol-based request to the host identified by its socket address. In this case, the Client builder specifies
- the host addresses that can receive requests
- the Finagle-provided `ThriftServerFramedCodec` codec, which ensures that only valid Thrift requests are received by the server
- to build this client service
2. Make a remote procedure call to the `Hello` Thrift service's `Hi` method. This returns a `Future` that represents the eventual arrival of a response.
3. When the response arrives, the `onSuccess` callback executes to print the result.
4. Release resources acquired by the client.
> - ã½ã±ããã¢ãã¬ã¹ã«ãã£ã¦æå®ãããThrift ãããã³ã«ãã¼ã¹ã®ãªã¯ã¨ã¹ããéä¿¡ããã¯ã©ã¤ã¢ã³ããçæãã¾ããä»åã®ã±ã¼ã¹ã§ã¯ ClientBuilder ã¯ä»¥ä¸ãè¦å®ãã¾ãã
>> - ãªã¯ã¨ã¹ããåãä»ãããã¹ãã¢ãã¬ã¹
>> - Finagle ãæä¾ãã ThriftServerFramedCodecï¼æå¹ãª Thrift ãªã¯ã¨ã¹ãã ãããµã¼ãã«ãã£ã¦åãä»ãããããã¨ãä¿è¨¼ããï¼
>> - ã¯ã©ã¤ã¢ã³ããµã¼ãã¹ã®çæ
> - Hello Thrift ãµã¼ãã¹ã® hi ã¡ã½ãããå¼ã³åºã RPC ãçæãã¾ãããã®å¼ã³åºãã¯æçµçã«ã¯ã¬ã¹ãã³ã¹ãå±ãã¨ãããã¨ãæå³ãã Future ãè¿ãã¾ãã
> - ã¬ã¹ãã³ã¹ãå±ããã onSuccess ã³ã¼ã«ããã¯ãå®è¡ãããçµæãåºåããã¾ãã
> - ã¯ã©ã¤ã¢ã³ãã«ãã£ã¦ç¢ºä¿ããããªã½ã¼ã¹ãè§£æ¾ããã¾ãã
[Top](#Top)
## Finagle Overview
Use the Finagle library to implement asynchronous Remote Procedure Call (RPC) clients and servers. Finagle is flexible enough to support a variety of RPC styles, including request-response, streaming, and pipelining; for example, HTTP pipelining and Redis pipelining. It also makes it easy to work with stateful RPC styles; for example, RPCs that require authentication and those that support transactions.
>Finagle ã©ã¤ãã©ãªã¯ãéåæãª RPCï¼Remote Procedure Callï¼ã®ã¯ã©ã¤ã¢ã³ãã¨ãµã¼ããå®è£
ããããã«å©ç¨ã§ãã¾ããFinagle ã¯ãªã¯ã¨ã¹ãã»ã¬ã¹ãã³ã¹æ¹å¼ãã¹ããªã¼ãã³ã°æ¹å¼ããã¤ãã©ã¤ã³æ¹å¼ã¨ãã£ãæ§ã
㪠RPC æ¹å¼ã«æè»ã«å¯¾å¿ãããã¨ãã§ãã¾ããä¾ãã° HTTP ã§ã®ãã¤ãã©ã¤ã³æ¹å¼ã Redis ã使ã£ããã¤ãã©ã¤ã³æ¹å¼ãªã©ã§ããã¾ãã¹ãã¼ããã«ãª RPC æ¹å¼ã«ãç°¡åã«å¯¾å¿ãããã¨ãã§ãã¾ããä¾ãã°ãèªè¨¼ããã©ã³ã¶ã¯ã·ã§ã³ã®ãµãã¼ããªã©ã§ãã
[Top](#Top)
### Client Features
* Connection Pooling
* Load Balancing
* Failure Detection
* Failover/Retry
* Distributed Tracing (a la [Dapper](http://research.google.com/pubs/pub36356.html))
* Service Discovery (e.g., via Zookeeper)
* Rich Statistics
* Native OpenSSL Bindings
> - ã³ãã¯ã·ã§ã³ãã¼ã«
> - ãã¼ããã©ã³ã·ã³ã°
> - é害æ¤ç¥
> - ãã§ã¤ã«ãªã¼ãã¼ï¼ãªãã©ã¤æ©æ§
> - Dapper ã«ãã忣ãã¬ã¼ã¹
> - ZooKeeper ã«ãããµã¼ãã¹ãã£ã¹ã«ããª
> - è±å¯ãªçµ±è¨
> - OpenSSL 飿º
[Top](#Top)
### Server Features
* Backpressure (to defend against abusive clients)
* Service Registration (e.g., via Zookeeper)
* Distributed Tracing
* Native OpenSSL bindings
> - 䏿£ãªã¯ã©ã¤ã¢ã³ããé²å¾¡ããèå§å¶å¾¡
> - ZooKeeper ã«ãããµã¼ãã¹ã¬ã¸ã¹ãã¬ã¼ã·ã§ã³
> - 忣ãã¬ã¼ã¹
> - OpenSSL 飿º
[Top](#Top)
### Supported Protocols
* HTTP
* HTTP streaming (Comet)
* Thrift
* Memcached/Kestrel
* More to come!
[Top](#Top)
## Architecture
Finagle extends the stream-oriented [Netty](http://www.jboss.org/netty) model to provide asynchronous requests and responses for remote procedure calls (RPC). Internally, Finagle manages a service stack to track outstanding requests, responses, and the events related to them. Finagle uses a Netty pipeline to manage connections between the streams underlying request and response messages. The following diagram shows the relationship between your RPC client or server, Finagle, Netty, and Java libraries:
>Finagle ã¯ãRPC ã§ã®éåæãªã¯ã¨ã¹ãã»ã¬ã¹ãã³ã¹ãæä¾ããããã«ãã¹ããªã¼ã æå㪠Netty ã®ã¢ãã«ãæ¡å¼µãã¦ãã¾ããFinagle ã¯å
é¨çã« Finagle ã¯æªå¦çã®ãªã¯ã¨ã¹ããã¬ã¹ãã³ã¹ã¨é¢é£ããã¤ãã³ããç£è¦ããããã®ãµã¼ãã¹ã¹ã¿ãã¯ã管çãã¦ãã¾ããFinagle ã¯ãªã¯ã¨ã¹ããã¬ã¹ãã³ã¹ã®ã¡ãã»ã¼ã¸ãå
å¨ããã¹ããªã¼ã ã®ã¤ãªããã管çããããã« Netty ã®ãã¤ãã©ã¤ã³ã使ç¨ãã¾ãã以ä¸ã®å³ã¯ããªããã¤ãã£ã RPC ã¯ã©ã¤ã¢ã³ãããµã¼ã㨠FinagleãNetty 㨠Java ã©ã¤ãã©ãªã®é¢ä¿æ§ã示ãã¦ãã¾ãã

Finagle manages a [Netty pipeline](http://docs.jboss.org/netty/3.2/api/org/jboss/netty/channel/ChannelPipeline.html) for servers built on Finagle RPC services. Netty itself is built on the Java [NIO](http://download.oracle.com/javase/1.5.0/docs/api/java/nio/channels/package-summary.html#package_description) library, which supports asynchronous IO. While an understanding of Netty or NIO might be useful, you can use Finagle without this background information.
>Finagle 㯠Finagle RPC ãµã¼ãã®ããã« Netty ãã¤ãã©ã¤ã³ã管çãã¾ããNetty èªä½ã¯ Java ã® NIO ã©ã¤ãã©ãªï¼éåæ IO ããµãã¼ãããï¼ãå©ç¨ãã¦ãã¾ããNetty ã NIO ãçè§£ãããã¨ã¯æç¨ããããã¾ããããFinagle ã¯ãããã®äºåç¥èããªãã¦ã使ããã¨ãã§ãã¾ãã
Finagle objects are the building blocks of RPC clients and servers:
- Future objects enable asynchronous operations required by a service
- Service objects perform the work associated with a remote procedure call
- Filter objects enable you to transform data or act on messages before or after the data or messages are processed by a service
- Codec objects decode messages in a specific protocol before they are handled by a service and encode messages before they are transported to a client or server.
> - Future ãªãã¸ã§ã¯ã㯠Service ã«ãã£ã¦å¿
è¦ã¨ãããéåæãªå¦çãå¯è½ã«ãã¾ã
> - Service ãªãã¸ã§ã¯ã㯠RPC ã«é¢é£ããä»äºããã¾ã
> - Filter ãªãã¸ã§ã¯ãã¯ãã¼ã¿ã夿ããããService ã«ãã£ã¦ã¡ãã»ã¼ã¸ãå¦çãããåå¾ã«ã¡ãã»ã¼ã¸ã«å¯¾ãã¦ä½ãä½ç¨ããããããã¨ãå¯è½ã«ãã¾ã
> - Codec ãªãã¸ã§ã¯ã㯠Service ã«ãã£ã¦å¦çãããåã«ã¡ãã»ã¼ã¸ãæå®ããããããã³ã«ã§è¤åãã¦ããµã¼ãããã¯ã©ã¤ã¢ã³ãã«éä¿¡ãããåã«ç¬¦å·åãã¾ã
You combine these objects to create:
- Servers
- Clients
Finagle provides a `ServerBuilder` and a `ClientBuilder` object, which enable you to configure servers and clients, respectively.
> Finagle 㯠ãµã¼ããã¯ã©ã¤ã¢ã³ããæ§æããããã«ãããã ServerBuilder ã ClientBuilder ãªãã¸ã§ã¯ããæä¾ãã¦ãã¾ãã
[Top](#Top)
### Future Objects
In Finagle, `Future` objects are the unifying abstraction for all asynchronous computation. A `Future` represents a computation that has not yet completed, which can either succeed or fail. The two most basic ways to use a `Future` are to
> Finagle ã§ã¯ Future ãªãã¸ã§ã¯ãã¯çµ±ä¸çã«ãã¹ã¦ã®éåæãªè¨ç®å¦çãæ½è±¡åãããã®ã§ããFuture ã¯ï¼ãããæçµçã«æåããã«ãã失æããã«ããï¼ã¾ã çµãã£ã¦ããªãè¨ç®å¦çã§ãããã¨ãæå³ãã¾ããFuture ã使ãã«ã¯äºã¤ã®æãåºæ¬çãªæ¹æ³ãããã¾ãã
* block and wait for the computation to return
* register a callback to be invoked when the computation eventually succeeds or fails
> - ãããã¯ãã¦è¨ç®ãçµãã£ã¦çµæãè¿ãããã®ãå¾
ã¤
> - æçµçã«æåã¾ãã¯å¤±æãããå®è¡ãããã³ã¼ã«ããã¯å¦çãç»é²ãã¦ãã
For more information about `Future` objects, see Using Future Objects.
> Future ã«é¢ããããè©³ç´°ãªæ
å ±ã¯ Using Future Objects ãã覧ãã ããã
[Top](#Top)
### Service Objects
A `Service` is simply a function that receives a request and returns a `Future` object as a response. You extend the abstract `Service` class to implement your service; specifically, you must define an `apply` method that transforms the request into the future response.
> Service ã¯ãªã¯ã¨ã¹ããåãåã£ã¦ Future ãã¬ã¹ãã³ã¹ã¨ãã¦è¿ãã ãã®ã·ã³ãã«ãªé¢æ°ã§ããabstract 㪠Service ã¯ã©ã¹ãç¶æ¿ã㦠Service ãå®è£
ãã¾ããå
·ä½çã«ã¯ãªã¯ã¨ã¹ãã Future ãªã¬ã¹ãã³ã¹ã«å¤æãã apply ã¡ã½ãããå®ç¾©ããå¿
è¦ãããã¾ãã
[Top](#Top)
### Filter Objects
It is useful to isolate distinct phases of your application into a pipeline. For example, you may need to handle exceptions, authorization, and other phases before your service responds to a request. A `Filter` provides an easy way to decouple the protocol handling code from the implementation of the business rules. A `Filter` wraps a `Service` and, potentially, converts the input and output types of the service to other types. For an example of a filter, see Creating Filters to Transform Requests and Responses.
> Filter ã¯ã¢ããªã±ã¼ã·ã§ã³ã®æç¢ºãªãã§ã¼ãºããã¤ãã©ã¤ã³ã«åé¢ããã®ã«å½¹ç«ã¡ã¾ãããã¨ãã°ãä¾å¤ããã³ããªã³ã°ããããèªè¨¼ãããããããµã¼ãã¹ããªã¯ã¨ã¹ãã«å¯¾ãã¦å¿çããåã®ãããããã§ã¼ãºãå¿
è¦ã¨ãªãããããã¾ãããFilter ã¯ãããã³ã«ããã³ããªã³ã°ããã³ã¼ããæ¥åçãªã«ã¼ã«ããåæããç°¡åãªæ¹æ³ãæä¾ãã¾ããFilter 㯠Service ãã©ãããã¦æ½å¨çã«ãµã¼ãã¹ã®å
¥åãåºåã®åã夿ããããã®ã§ããFilter ã®ä¾ã¯ Creating Filters to Transform Requests and Responses ãã覧ãã ããã
A `SimpleFilter` is a kind of `Filter` that does not convert the request and response types. For an example of a simple filter, see Creating Filters.
> SimpleFilter ã¯ãªã¯ã¨ã¹ããã¬ã¹ãã³ã¹ã®åã夿ããªã Filter ã®ä¸ç¨®ã§ããSimpleFilter ã®ä¾ã¯ Creating Filters ãã覧ãã ããã
[Top](#Top)
### Codec Objects
A `Codec` object encodes and decodes _wire_ protocols, such as HTTP. You can use Finagle-provided `Codec` objects for encoding and decoding the Thrift, HTTP, memcache, Kestrel, HTTP chunked streaming (ala Twitter Streaming) protocols. You can also extend the `CodecFactory` class to implement encoding and decoding of other protocols.
> Codec ãªãã¸ã§ã¯ãã¯ãã¨ãã° HTTP ã®ãããªãããã³ã«ã符å·åãè¤ååãããã®ã§ããFinagle ãæä¾ãã¦ãã ThirftãHTTPãMemcacheãKestrelãHTTP chunked streamingï¼Twitter ã¹ããªã¼ãã³ã°ã®ãããªï¼ ã¨ãã£ããããã³ã«ã符å·åï¼è¤ååããããã® Codec ãªãã¸ã§ã¯ãã使ããã¨ãã§ãã¾ããCodecFactory ã¯ã©ã¹ãæ¡å¼µãã¦ãã®ä»ã®ãããã³ã«ã符å·åï¼è¤ååãããã¨ãã§ãã¾ãã
[Top](#Top)
### Servers
In Finagle, RPC servers are built out of a `Service` and zero or more `Filter` objects. You apply filters to the service request after which you execute the service itself:
> Finagle ã§ã¯ RPC ãµã¼ãã¯ä¸ã¤ã® Service 㨠0 å以ä¸ã® Filter ãªãã¸ã§ã¯ãããæ§æããã¾ãããªã¯ã¨ã¹ãã«å¯¾ã㦠Service ããèªä½ãå®è¡ãã Filter 群ãé©ç¨ãã¾ãã

Typically, you use a `ServerBuilder` to create your server. A `ServerBuilder` enables you to specify the following general attributes:
> é常㯠ServerBuilder ã使ã£ã¦ãµã¼ããçæãã¾ããServerBuilder ã¯ä»¥ä¸ã®ãããªä¸è¬çãªå±æ§ãæå®ãããã¨ãã§ãã¾ãï¼
Attribute |
Description |
Default Value |
codec |
Object to handle encoding and decoding of the service's request/response protocol |
None |
statsReceiver |
Statistics receiver object, which enables logging of important events and statistics |
None |
name |
Name of the service |
None |
bindTo |
The IP host:port pairs on which to listen for requests; localhost is assumed if the host is not specified |
None |
logger |
Logger object |
None |
You can specify the following attributes to handle fault tolerance and manage clients:
Attribute |
Description |
Default Value |
maxConcurrentRequests |
Maximum number of requests that can be handled concurrently by the server |
None |
hostConnectionMaxIdleTime |
Maximum time that this server can be idle before the connection is closed |
None |
hostConnectionMaxLifeTime |
Maximum time that this server can be connected before the connection is closed |
None |
requestTimeout |
Maximum time to complete a request |
None |
readTimeout |
Maximum time to wait for the first byte to be read |
None |
writeCompletionTimeout |
Maximum time to wait for notification of write completion from a client |
None |
You can specify the following attributes to manage TCP connections:
Attribute |
Description |
Default Value |
sendBufferSize |
Requested TCP buffer size for responses |
None |
recvBufferSize |
Actual TCP buffer size for requests |
None |
You can also specify these attributes:
Attribute |
Description |
Default Value |
tls |
The kind of transport layer security |
None |
channelFactory |
Channel service factory object |
None |
traceReceiver |
Trace receiver object |
new NullTraceReceiver object |
Once you have defined your `Service`, it can be bound to an IP socket address, thus becoming an RPC server.
[Top](#Top)
### Clients
Finagle makes it easy to build RPC clients with connection pooling, load balancing, logging, and statistics reporting. The balancing strategy is to pick the endpoint with the least number of outstanding requests, which is similar to _least connections_ in other load balancers. The load-balancer deliberately introduces jitter to avoid synchronicity (and thundering herds) in a distributed system.
> Finagle ã§ã¯ãã³ãã¯ã·ã§ã³ãã¼ãªã³ã°ããã¼ããã©ã³ã·ã³ã°ããã°åºåãçµ±è¨çµæã®ã¬ãã¼ãã¨ãã£ãæ©è½ãæã¤ RPC ã¯ã©ã¤ã¢ã³ãã®ä½æãç°¡åã«ã§ãã¾ãããã©ã³ã·ã³ã°ã¹ãã©ãã¸ã¼ã¯ããã¼ããã©ã³ãµãæãã³ãã¯ã·ã§ã³ãå°ãªãã¨ãããé¸ã¶ã®ã¨ä¼¼ãæãã§ãæªå¦çã®ãªã¯ã¨ã¹ãã®æ°ãæãå°ãªãã¨ã³ããã¤ã³ããé¸ã¶ããã«ãªã£ã¦ãã¾ãã忣ã·ã¹ãã ã«ããã¦ããã¼ããã©ã³ãµã¯åæçºçããããããã«æå³çã«ã¸ãã¿ã¼ãåãå
¥ãã¾ãã
Your code should separate building the client from invocation of the client. A client, once built, can be used with _lazy binding_, saving the resources required to build a client. Note: The examples, which show the creation of the client and its first execution together, represent the first-execution scenario. Typically, subsequent execution of the client does not require rebuilding.
> ããªãã®æ¸ãã³ã¼ãã¯ã¯ã©ã¤ã¢ã³ãã®çæã¨èµ·åãåé¢ããã¹ãã§ããã¯ã©ã¤ã¢ã³ãã¯ä¸åº¦çæãããã®ãåå©ç¨ãã¦ã¯ã©ã¤ã¢ã³ããçæããããã®ãªã½ã¼ã¹ãç¯ç´ãããã¨ãã§ãã¾ããï¼æ³¨ï¼ã¯ã©ã¤ã¢ã³ãã®çæã¨ãã®ååèµ·åãä¸ç·ã«èª¬æããä¾ã¯ååå®è¡ã®ã·ããªãªã表ãã¦ãã¾ããé常ãå¾ç¶ã®å¦çã§ã¯ã¯ã©ã¤ã¢ã³ããåçæããå¿
è¦ã¯ããã¾ããã
Finagle will retry the request in the event of an error, up to the number of times specified; however, Finagle **does not assume your RPC service is Idempotent**. Retries occur only when the request is known to be idempotent, such as in the event of TCP-related `WriteException` errors, for which the RPC has not been transmitted to the remote server.
> Finagle ã¯æå®ãããåæ°ã¾ã§ã¨ã©ã¼ã¤ãã³ãæã«ãªã¯ã¨ã¹ãããªãã©ã¤ãã¾ããFinagle ã¯ããªãã® RPC ãµã¼ãã¹ãåªçï¼ããæä½ã1åè¡ã£ã¦ãè¤æ°åè¡ã£ã¦ãçµæãåãã§ãããã¨ï¼ã§ããã¨ã¯ä»®å®ãã¾ããããªãã©ã¤ã¯ãªã¯ã¨ã¹ããåªçã§ããã¨ããã£ã¦ããå ´åã®ã¿çºçãã¾ãããã¨ãã° TCP ã«é¢ä¿ãããWriteExceptionãã®ãã㪠RPC ããªã¢ã¼ããµã¼ãã«å±ãã¦ããªããããªã¨ã©ã¼ã¤ãã³ãã§ãã
A robust way to use RPC clients is to have an upper-bound on how long to wait for a response to arrive. With `Future` objects, you can
> RPC ã¯ã©ã¤ã¢ã³ããã¬ã¹ãã³ã¹å°éãã©ããããå¾
ã¤ãã®ä¸éãè¨å®ããã¨ããå¼·åã§ããFuture ãªãã¸ã§ã¯ãã使ã£ã¦ãã®ããã«ï¼
* block, waiting for a response to arrive and throw an exception if it does not arrive in time.
* register a callback to handle the result if it arrives in time, and register another callback to invoke if the result does not arrive in time
> - ãããã¯ãã¦ã¬ã¹ãã³ã¹ãå±ãã®ãå¾
ã¡ãããæéå
ã«å±ããªãã£ããä¾å¤ã throw ãã
> - æéå
ã«ã¬ã¹ãã³ã¹ãå±ããããã®çµæãå¦çããã³ã¼ã«ããã¯ãç»é²ãããã¤æéå
ã«å±ããªãã£ãå ´åã«å®è¡ãããå¥ã®ã³ã¼ã«ããã¯ãç»é²ãã
A client is a `Service` and can be wrapped by `Filter` objects. Typically, you call `ClientBuilder` to create your client service. `ClientBuilder` enables you to specify the following general attributes:
> ã¯ã©ã¤ã¢ã³ã㯠Service ãªã®ã§ Filter ãªãã¨ã¸ã§ã¯ã群ã«ãã£ã¦ã©ãããããã¨ãã§ãã¾ããé常㯠ClientBuilder ã使ã£ã¦ã¯ã©ã¤ã¢ã³ãã® Service ãçæãã¾ããClientBuilder ã¯ä»¥ä¸ã®ãããªä¸è¬çãªå±æ§ãæå®ãããã¨ãã§ãã¾ãï¼
Attribute |
Description |
Default Value |
name |
Name of the service |
None |
codec |
Object to handle encoding and decoding of the service's request/response protocol |
None |
statsReceiver |
Statistics receiver object, which enables logging of important events and statistics |
None |
loadStatistics |
How often to load statistics from the server |
(60, 10.seconds) |
logger |
A Logger object with which to log Finagle messages |
None |
retries |
Number of retries per request (only applies to recoverable errors) |
None |
You can specify the following attributes to manage the host connection:
Attribute |
Description |
Default Value |
connectionTimeout |
Time allowed to establish a connection |
10.milliseconds |
requestTimeout |
Request timeout |
None, meaning it waits forever |
hostConnectionLimit |
Number of connections allowed from this client to the host |
None |
hostConnectionCoresize |
Host connection's cache allocation |
None |
hostConnectionIdleTime |
|
None |
hostConnectionMaxWaiters |
The maximum number of queued requests awaiting a connection |
None |
hostConnectionMaxIdleTime |
Maximum time that the client can be idle until the connection is closed |
None |
hostConnectionMaxLifeTime |
Maximum time that client can be connected before the connection is closed |
None |
You can specify the following attributes to manage TCP connections:
Attribute |
Description |
Default Value |
sendBufferSize |
Requested TCP buffer size for responses |
None |
recvBufferSize |
Actual TCP buffer size for requests |
None |
You can also specify these attributes:
Attribute |
Description |
Default Value |
cluster |
The cluster connections associated with the client |
None |
channelFactory |
Channel factory associated with this client |
None |
tls |
The kind of transport layer security |
None |
If you are using _stateful protocols_, such as those used for transaction processing or authentication, you should call `buildFactory`, which creates a `ServiceFactory` to support stateful connections.
> ãããã©ã³ã¶ã¯ã·ã§ã³å¦çãèªè¨¼ã®ãããªã¹ãã¼ããã«ãªãããã³ã«ãç¨ããå ´åã ã¹ãã¼ããã«ãªã³ãã¯ã·ã§ã³ããµãã¼ããã ServiceFactory ãçæãã BuildFactory ãå¼ã³åºãã¾ãã
[Top](#Top)
### Threading Model
The Finagle threading model requires that you avoid blocking operations in the Finagle event loop. Finagle-provided methods do not block; however, you could inadvertently implement a client, service or a `Future` callback that blocks.
> Finagle ã®ã¹ã¬ããã¢ãã«ã§ã¯ Finagle ã®ã¤ãã³ãã«ã¼ãã®ä¸ã§ãããã¯ããå¦çãããªãããã«ããå¿
è¦ãããã¾ããFinagle ãæä¾ããã¡ã½ããã¯ãããã¯ãã¾ããããããªãããã£ãããããã¯ãããããªã¯ã©ã¤ã¢ã³ããService ã Future ã®ã³ã¼ã«ããã¯ãå®è£
ãããã¨ã¯èãããã¾ãã
Blocking events include but are not limited to
* network calls
* system calls
* database calls
Note: You do not need to be concerned with long-running or CPU intensive operations if they do not block. Examples of these operations include image processing operations, public key cryptography, or anything that might take a non-trivial amount of clock time to perform. Only operations that block in Finagle are of concern. Because Finagle and its event loop use a relatively low number of threads, blocked threads can cause performance issues.
> ï¼æ³¨ï¼ãããã¯ãã¦ããªããã°ãé·æéå®è¡ãããå¦çãCPU ããã¼ãªå¦çã«ã¤ãã¦æ°ã«ãããå¿
è¦ã¯ããã¾ããããããã£ãå¦çã«ã¯ãç»åå¦çãå
¬ééµã®æå·åããããã¯å°ãªããªã CPU ã¯ããã¯æéãè¦ããããããå¦çãå«ã¿ã¾ããFinagle ã§ã¯ãããã¯ãããããªå¦çã ããæ°ã«ããå¿
è¦ãããã¾ããFinagle ã¨ãã®ã¤ãã³ãã«ã¼ãã¯æ¯è¼çå°ãªãã¹ã¬ãããç¨ãã¦ããããããããã¯ãããã¹ã¬ããã¯ããã©ã¼ãã³ã¹ã®åé¡ãå¼ãèµ·ããå ´åãããã¾ãã
Consider the following diagram, which shows how a client uses the Finagle event loop:
> ã¯ã©ã¤ã¢ã³ããã©ã®ããã« Finagle ã使ã£ã¦ãããã説æãã以ä¸ã®å³ãã¿ã¦ã¿ã¾ãããã

Your threads, which are shown on the left, are allowed to block. When you call a Finagle method or Finagle calls a method for you, it dispatches execution of these methods to its internal threads. Thus, the Finagle event loop and its threads cannot block without degrading the performance of other clients and servers that use the same Finagle instance.
> å³ã®å·¦å´ã«ããã¹ã¬ããã§ã¯ãããã¯ãããã¨ã許ããã¾ããFinagle ã®ã¡ã½ãããå¼ã³åºãã¨ãã Finagle ãããªãã®ããã«ããã¡ã½ãããå¼ã³åºãã¨ãã«ããããã®ã¡ã½ããã®å®è¡ãå
é¨ã¹ã¬ããã«éãã¾ãããã®ãããFinagle ã¤ãã³ãã«ã¼ãã¨ãã®ã¹ã¬ãã群ããããã¯ãã¦ãã¾ãã¨ãåã Finagle ã¤ã³ã¹ã¿ã³ã¹ã使ãã¯ã©ã¤ã¢ã³ãã¨ãµã¼ãã«ã²ã©ãããã©ã¼ãã³ã¹å£åããããã¾ãã
In complex RPC operations, it may be necessary to perform blocking operations. In these cases, you must set up your own thread pool and use `Future` or `FuturePool` objects to execute the blocking operation on your own thread. Consider the following diagram:
> è¤é㪠RPC å¦çã§ã¯ããããã¯ããå¦çãè¡ããã¨ãå¿
è¦ã«ãªãããããã¾ããããããã£ãã±ã¼ã¹ã§ã¯ãèªåã§ã¹ã¬ãããã¼ã«ãã»ããã¢ããã㦠Future ã FuturePool ãªãã¸ã§ã¯ãã使ã£ã¦ãèªåã®ã¹ã¬ããã§ããããã³ã°å¦çãå®è¡ããªããã°ãªãã¾ããã以ä¸ã®å³ãã¿ã¦ã¿ã¾ãããï¼

In this example, you can use a `FuturePool` object to provide threads for blocking operations outside of Finagle. Finagle can then dispatch the blocking operation to your thread. For more information about `FuturePool` objects, see Using Future Pools.
> ãã®ä¾ã§ã¯ Finagle ã®å¤å´ã§ããããã³ã°å¦çãå®è¡ããã¹ã¬ãã群ãæä¾ãã FuturePool ãªãã¸ã§ã¯ãã使ããã¨ãã§ãã¾ããFinagle ã¯ããããã³ã°å¦çãããªãã管çããã¹ã¬ããã«ãµãããããã¨ãã§ãã¾ããFuturePool ã«é¢ããããè©³ç´°ãªæ
å ±ã«ã¤ãã¦ã¯ Using Future Pools ãã覧ãã ããã
[Top](#Top)
### Starting and Stopping Servers
A server automatically starts when you call `build` on the server after assigning the IP address on which it runs. To stop a server, call its `close` method. The server will immediately stop accepting requests; however, the server will continue to process outstanding requests until all have been handled or until a specific duration has elapsed. You specify the duration when you call `close`. In this way, the server is allowed to drain out outstanding requests but will not run indefinitely. You are responsible for releasing all resources when the server is no longer needed.
> IP ã¢ãã¬ã¹ãå²ãå½ã¦ãå¾ build ã¡ã½ãããå¼ã³åºãã¨ããµã¼ãã¯èªåçã«ã¹ã¿ã¼ããã¾ãããµã¼ãã忢ããããã«ã¯ close ã¡ã½ãããå¼ã³åºãã¾ãããµã¼ãã¯ããã«ãªã¯ã¨ã¹ããåãä»ããã®ãããã¾ãããæªå¦çã®ãªã¯ã¨ã¹ããããã°ãããããã¹ã¦çµããããæå®ãããæéãçµéããã¾ã§å¦çã¯ç¶ç¶ãã¾ããclose ãå¼ã³åºãã¨ãã«ãã®æéãæå®ãããã¨ãã§ãã¾ãããã®ããæ¹ï¼ï¼ä¸å®æéãçµéããã忢ãããã¨ï¼ã ã¨ãµã¼ãã¯æªå¦çã®ãªã¯ã¨ã¹ãã失ããã¨ããããã¾ããããããã®ãªã¯ã¨ã¹ããå®è¡ããããã¨ã¯ããã¾ãããå©ç¨è
ã¯ãµã¼ãããã¯ãå¿
è¦ã§ãªãã¨ããå ´åã¯ãã¹ã¦ã®ãªã½ã¼ã¹ãè§£æ¾ããå¿
è¦ãããã¾ãã
[Top](#Top)
## Finagle Projects and Packages
The `Core` project contains the execution framework, Finagle classes, and supporting classes, whose objects are only of use within Finagle. The `Core` project includes the following packages:
> Core ããã¸ã§ã¯ãã¯å®è¡ãã¬ã¼ã ã¯ã¼ã¯ãFinagle ã¯ã©ã¹ç¾¤ããµãã¼ãç¨ã®ã¯ã©ã¹ç¾¤ï¼Finagle ã®ä¸ã ãã§å©ç¨ããããã®ï¼ãå«ãã§ãã¾ããCore ããã¸ã§ã¯ãã¯ä»¥ä¸ã®ããã±ã¼ã¸ãå«ã¿ã¾ãï¼
* `builder` - contains `ClientBuilder`, `ServerBuilder`
* `channel`
* `http`
* `loadbalancer`
* `pool`
* `service`
* `stats`
* `tracing`
* `util`
It also contains packages to support remote procedure calls over Kestrel, Thrift, streams, clusters, and provides statistics collection (Ostrich).
> KestrelãThriftãã¹ããªã¼ãã³ã°ãã¯ã©ã¹ã¿ã¼æ§æãçµ±è¨ãã¼ã¿ã®éè¨ï¼OStrichï¼ãç¨ãã RPC ããµãã¼ãããããã±ã¼ã¸ãããã¾ãã
The `Util` project contains classes, such as `Future`, which are both generally useful and specifically useful to Finagle.
> Uitl ããã¸ã§ã¯ã㯠Future ã®ãããªæ±ç¨çã«ãæç¨ã§ãããFingale ã«ã¨ã£ã¦ãæç¨ãªã¯ã©ã¹ãå«ã¿ã¾ãã
[Top](#Top)
## Using Future Objects
In the simplest case, you can use `Future` to block for a request to complete. Consider an example that blocks for an HTTP GET request:
> ãã£ã¨ãåç´ãªã±ã¼ã¹ã 㨠Future ããªã¯ã¨ã¹ãããªã¯ã¨ã¹ããçµããã¾ã§ãããã¯ããããã«ä½¿ããã¨ãã§ãã¾ããHTTP GET ãªã¯ã¨ã¹ããï¼çµäºã¾ã§ï¼ãããã¯ããä¾ã§ãã
// Issue a request, get a response:
val request: HttpRequest = new DefaultHttpRequest(HTTP_1_1, GET, "/")
val responseFuture: Future[HttpResponse] = client(request)
In this example, a client issuing the request will wait forever for a response unless you specified a value for the `requestTimeout` attribute when you built the client.
> ãã®ä¾ã§ã¯ã¯ã©ã¤ã¢ã³ãã¯ãªã¯ã¨ã¹ããçºè¡ãã¦ã¯ã©ã¤ã¢ã³ãçææã« requestTimeout 屿§ã§æå®ãããæéãçµéããªãéããã¬ã¹ãã³ã¹ãå±ãã¾ã§æ°¸é ã«å¾
ã¡ç¶ãã¾ãã
Consider another example:
> å¥ã®ä¾ãèãã¦ã¿ãã¨
val responseFuture: Future[String] = executor.schedule(job)
In this example, the value of `responseFuture` is not available until after the scheduled job has finished executing and the caller will block until `responseFuture` has a value.
> ãã®ä¾ã§ã¯ responseFuture ã¯ã¹ã±ã¸ã¥ã¼ãªã³ã°ãããã¸ã§ãã®å®è¡ãçµäºããã¾ã§å©ç¨ã§ããªãã®ã§ãå¼ã³åºãå´ã¯ responseFuture ãå¤ãè¿ãã¾ã§ãããã¯ãããã¨ã«ãªãã§ãããã
**Note:** For examples of using Finagle `Future` objects in Java, see Using Future Objects With Java.
> Finagle ãªãã¸ã§ã¯ãã Java ã§ä½¿ã£ãä¾ã«ã¤ãã¦ã¯ Using Future Objects With Java ãã覧ãã ããã
[Top](#Top)
### Future Callbacks
In cases where you want to continue execution immediately, you can specify a callback. The callback is identified by the `onSuccess` keyword:
> ããã«å®è¡ãç¶ãããã¨ããå ´åãã³ã¼ã«ããã¯ãæå®ã§ãã¾ãã ã³ã¼ã«ããã¯ã¯ onSucess ãã¼ã¯ã¼ãã§èå¥ããã¾ãã
val request: HttpRequest = new DefaultHttpRequest(HTTP_1_1, GET, "/")
val responseFuture: Future[HttpResponse] = client(request)
responseFuture onSuccess { responseFuture =>
println(responseFuture)
}
[Top](#Top)
### Future Timeouts
In cases where you want to continue execution after some amount of elapsed time, you can specify the length of time to wait in the `Future` object. The following example waits 1 second before displaying the value of the response:
> ä¸å®ã®æéãçµéãããå¦çãç¶ç¶ãããã¨ããå ´åãFuture ãªãã¸ã§ã¯ãã« wait æéã®é·ããæå®ãããã¨ãã§ãã¾ãã以ä¸ã®ä¾ã§ã¯ã¬ã¹ãã³ã¹ã®å¤ã表示ããã¾ã§ 1 ç§å¾
ã¡ã¾ãã
val request: HttpRequest = new DefaultHttpRequest(HTTP_1_1, GET, "/")
val responseFuture: Future[HttpResponse] = client(request)
println(responseFuture(1.second))
In the above example, you do not know whether the response timed out before the request was satisfied. To determine what kind of response you actually received, you can provide two callbacks, one to handle `onSuccess` conditions and one for `onFailure` conditions. You use the `within` method of `Future` to specify how long to wait for the response. Finagle also creates a `Timer` thread on which to wait until one of the conditions are satisfied. Consider the following example:
> ä¸ã®ä¾ã ã¨ãªã¯ã¨ã¹ããå¦çãããåã«ã¬ã¹ãã³ã¹ãã¿ã¤ã ã¢ã¦ããããã©ããç¥ããã¨ãã§ãã¾ãããå®éã«ã©ã®ãããªç¨®é¡ã®ã¬ã¹ãã³ã¹ãåãåã£ãããç¹å®ããããã«ãäºã¤ã®ã³ã¼ã«ããã¯ãæå®ã§ãã¾ããä¸ã¤ã¯ onSuccess ã§ããä¸ã¤ã¯ onFailure ã®æ¡ä»¶æã§ããFuture ã® within ã¡ã½ããã§ã©ããããã®æéã¬ã¹ãã³ã¹ãå¾
ã¤ãæå®ãããã¨ãã§ãã¾ããFinagle ã¯æ¡ä»¶ã®ãã¡ä¸ã¤ãæºããããã¾ã§å¾
㤠Timer ã¹ã¬ãããã¤ãããã¨ãã§ãã¾ãã以ä¸ã®ä¾ãã¿ã¦ã¿ã¾ãããã
import com.twitter.finagle.util.Timer._
...
val request: HttpRequest = new DefaultHttpRequest(HTTP_1_1, GET, "/")
val responseFuture: Future[HttpResponse] = client(request)
responseFuture.within(1.second) onSuccess { response =>
println("responseFuture)
} onFailure {
case e: TimeoutException => ...
}
If a timeout occurs, Finagle takes the `onFailure` path. You can use a `TimeoutException` object to display a message or take other actions.
> ã¿ã¤ã ã¢ã¦ããçºçããããFinagle 㯠onFailure ã®çµè·¯ãéãã¾ããã¨ã©ã¼ã¡ãã»ã¼ã¸ã表示ããããä½ãå¥ã®ãã¨ãããããã« TimeoutException ãªãã¸ã§ã¯ãã触ããã¨ãã§ãã¾ãã
[Top](#Top)
### Future Exceptions
To set up an exception, specify the action in a `try` block and handle failures in a `catch` block. Consider an example that handles `Future` timeouts as an exception:
> ä¾å¤ãã»ããã¢ããããããã«ã¯ try ãããã¯ã®ä¸ã«å¦çãç½®ãã¦å¤±æã catch ç¯ã§å¦çãã¾ãã以ä¸ã®ãã㪠Future ã®ã¿ã¤ã ã¢ã¦ããä¾å¤ã¨ãã¦å¦çããä¾ãã¿ã¦ã¿ã¾ãããã
val request: HttpRequest = new DefaultHttpRequest(HTTP_1_1, GET, "/")
val responseFuture: Future[HttpResponse] = client(request)
try {
println(responseFuture(1.second))
} catch {
case e: TimeoutException => ...
}
In this example, after 1 second, either the HTTP response is displayed or the `TimeoutException` is thrown.
> ãã®ä¾ã§ã¯ 1 ç§å¾ã« HTTP ã¬ã¹ãã³ã¹ã表示ãããã TimeoutException ã throw ããã¾ãã
[Top](#Top)
### Promises
`Promise` is a subclass of `Future`. Although a `Future` can only be read, a `Promise` can be both read and written.
Usually a producer makes a `Promise` and casts it to a `Future` before giving it to the consumer. The following example shows how this might be useful in the case where you intend to make a `Future` service but need to anticipate errors:
> Promise 㯠Future ã®ãµãã¯ã©ã¹ã§ããFuture ã¯èªã¿è¾¼ã¿ã ããã§ãã¾ãã Promise ã¯èªã¿è¾¼ã¿ãæ¸ãè¾¼ã¿ã両æ¹ã§ãã¾ããé常ããããã¥ã¼ãµã¼ã¯ Promise ãä½ã£ã¦ã³ã³ã·ã¥ã¼ãã«æ¸¡ãåã«ããã Future ã«ãã£ã¹ããã¾ãã以ä¸ã®ä¾ã¯ Future ãµã¼ãã¹ãã¤ããã¤ããã§ããããã¨ã©ã¼ãè¦è¾¼ãå¿
è¦ãããå ´åã«ãããã©ã®ããã«ä¾¿å©ããæç¨ã§ãããã示ãã¦ãã¾ãã
def make() = {
...
val promise = new Promise[Service[Req, Rep]]
... {
case Ok(myObject) =>
...
promise() = myConfiguredObject
case Error(cause) =>
promise() = Throw(new ...Exception(cause))
case Cancelled =>
promise() = Throw(new WriteException(new ...Exception))
}
promise
}
You are discouraged from creating your own Promises. Instead, where possible, use `Future` combinators to compose actions (discussed next).
> èªåã§ Promise ãçæãããã¨ã¯ãå§ãã§ãã¾ãããå¯è½ã§ããã°ã代ããã«ãµãã¾ããåæãã Future ã³ã³ããã¼ã¿ã使ã£ã¦ãã ããã
[Top](#Top)
### Using Future map and flatMap Operations
In addition to waiting for results to return, `Future` can be transformed in interesting ways. For instance, it is possible to convert a `Future[String]` to a `Future[Int]` by using `map`:
> è¿ãããçµæãå¾
ã¤ã®ã«å ã㦠Future ã¯è峿·±ãããæ¹ã§å¤æããããã¨ãããã¾ãããã¨ãã° map ã使ã£ã¦ Future[String] ã Future[Int] ã«å¤æãããã¨ãã§ãã¾ãã
val stringFuture: Future[String] = Future("1")
val intFuture: Future[Int] = stringFuture map (_.toInt)
Similar to `map`, you can use `flatMap` to easily _pipeline_ a sequence of `Futures`:
> map ã¨ä¼¼ããã®ã§è¤æ°ã® Future ã®ã·ã¼ã±ã³ã¹ã容æã«ã¤ãªãåããã flatMap ã使ããã¨ãã§ãã¾ãã
val authenticateUser: Future[User] = User.authenticate(email, password)
val lookupTweets: Future[Seq[Tweet]] = authenticateUser flatMap { user =>
Tweet.findAllByUser(user)
}
In this example, `Tweet.findAllByUser(user)` is a function of type `User => Future[Seq[Tweet]]`.
> ãã®ä¾ã§ã¯ Tweet.findAllByUser(user) 㯠User => Future[Seq[Tweet]] ã¨ãã颿°ã§ãã
[Top](#Top)
### Using Future in Scatter/Gather Patterns
For scatter/gather patterns, the challenge is to issue a series of requests in parallel and wait for all of them to arrive. To wait for a sequence of `Future` objects to return, you can define a sequence to hold the objects and use the `Future.collect` method to wait for them, as follows:
> scatterï¼ã¾ãæ£ããï¼/gatherï¼åéããï¼ãã¿ã¼ã³ã§ã®èª²é¡ã¯ã並è¡ãã¦ä¸é£ã®ãªã¯ã¨ã¹ããçºè¡ãããã®ãã¹ã¦ãå±ãã¾ã§å¾
ã¤ãã¨ã§ããFuture ãªãã¸ã§ã¯ãã®ã·ã¼ã±ã³ã¹ãå¾
ã¤ããã«ããªãã¸ã§ã¯ããä¿æããã·ã¼ã±ã³ã¹ãå®ç¾©ã㦠以ä¸ã®ããã« Future.collect ã¡ã½ããã§ããããå¾
ã¡ã¾ãã
val myFutures: Seq[Future[Int]] = ...
val waitTillAllComplete: Future[Seq[Int]] = Future.collect(myFutures)
A more complex variation of scatter/gather pattern is to perform a sequence of asynchronous operations and harvest only those that return within a certain time, ignoring those that don't return within the specified time. For example, you might want to issue a set of parallel requests to _N_ partitions of a search index; those that don't return in time are assumed to be empty. The following example allows 1 second for the query to return:
> scatter/gather ãã¿ã¼ã³ã®ããè¤éãªããªã¨ã¼ã·ã§ã³ã¨ãã¦ã¯ãéåæå¦çã®ã·ã¼ã±ã³ã¹ãå®è¡ãã¦ä¸å®æéå
ã«è¿ãããçµæã ããåéãããã¨ãããã®ãããã¾ããæå®ãããæéå
ã«çµæãè¿ããªãã£ãéåæå¦çã¯ç¡è¦ããã¾ããä¾ãã°ãn åã«åå²ãããæ¤ç´¢ã¤ã³ããã¯ã¹ã«å¯¾ãã¦å¹³è¡ãªã¯ã¨ã¹ãã®ã»ãããçºè¡ãããã¨ããå ´åãæéå
ã«çµæãè¿ããªããã®ã¯ï¼ã¯ã¨ãªã«ãããããï¼æ¤ç´¢çµæããªãã¨ã¿ãªãã¾ãã以ä¸ã®ä¾ã§ã¯ 1 ç§éã¯ã¨ãªãè¿ãã®ãå¾
ã¡ã¾ãã
import com.twitter.finagle.util.Timer._
val results: Seq[Future[Result]] = partitions.map { partition =>
partition.get(query).within(1.second) handle {
case _: TimeoutException => EmptyResult
}
}
val allResults: Future[Seq[Result]] = Future.collect(timedResults)
allResults onSuccess { results =>
println(results)
}
[Top](#Top)
### Using Future Pools
A `FuturePool` object enables you to place a blocking operation on its own thread. In the following example, a service's `apply` method, which executes in the Finagle event loop, creates the `FuturePool` object and places the blocking operation on a thread associated with the `FuturePool` object. The `apply` method returns immediately without blocking.
> FuturePool ãªãã¸ã§ã¯ãã¯èªåã®ã¹ã¬ããã«ããããã³ã°å¦çããããããã¨ãã§ãã¾ãã以ä¸ã®ä¾ã§ã¯ Finagle ã®ã¤ãã³ãã«ã¼ãã®ä¸ã§å®è¡ããã Service ã® apply ã¡ã½ããã FuturePool ãªãã¸ã§ã¯ããçæããããããã³ã°å¦çã FuturePool ã«é¢é£ã¥ããããã¹ã¬ããã§å®è¡ããã¾ããapply ã¡ã½ããã¯ãããã¯ãããã¨ãªãããã«çµæãè¿ãã¾ãã
class ThriftFileReader extends Service[String, Array[Byte]] {
val diskIoFuturePool = FuturePool(Executors.newFixedThreadPool(4))
def apply(path: String) = {
val blockingOperation = {
scala.Source.fromFile(path) // potential to block
}
// give this blockingOperation to the future pool to execute
diskIoFuturePool(blockingOperation)
// returns immediately while the future pool executes the operation on a different thread
}
}
**Note:** For an example implementation of a thread pool in Java, see Implementing a Pool for Blocking Operations in Java.
> Java ã§ã®ã¹ã¬ãããã¼ã«ã®ãµã³ãã«å®è£
ã«ã¤ãã¦ã¯ Implementing a Pool for Blocking Operations in Java ãã覧ãã ããã
[Top](#Top)
## Creating a Service
The following example extends the `Service` class to respond to an HTTP request:
> 以ä¸ã®ä¾ã¯ Service ã¯ã©ã¹ãç¶æ¿ã HTTP ãªã¯ã¨ã¹ãã«å¿çãã¾ãã
class Respond extends Service[HttpRequest, HttpResponse] {
def apply(request: HttpRequest) = {
val response = new DefaultHttpResponse(HTTP_1_1, OK)
response.setContent(copiedBuffer(myContent, UTF_8))
Future.value(response)
}
}
[Top](#Top)
## Creating Simple Filters
The following example extends the `SimpleFilter` class to throw an exception if the HTTP authorization header contains a different value than the specified string:
> 以ä¸ã®ä¾ã¯ SimpleFilter ãç¶æ¿ãããã HTTP Authorization ãããã¼ãæå®ãããæååã¨éã£ãå¤ãå«ãã§ãããä¾å¤ã throw ãã¾ãã
class Authorize extends SimpleFilter[HttpRequest, HttpResponse] {
def apply(request: HttpRequest, continue: Service[HttpRequest, HttpResponse]) = {
if ("shared secret" == request.getHeader("Authorization")) {
continue(request)
} else {
Future.exception(new IllegalArgumentException("You don't know the secret"))
}
}
}
The following example extends the `SimpleFilter`class to set the HTTP response code if an error occurs and return the error and stack trace in the response:
> 以ä¸ã®ä¾ã¯ SimpleFilter ã¯ã©ã¹ãç¶æ¿ããããã¨ã©ã¼ãçºçãããHTTP ã¬ã¹ãã³ã¹ã³ã¼ããè¨å®ããã¨ã©ã¼å
容ã¨ã¹ã¿ãã¯ãã¬ã¼ã¹ãã¬ã¹ãã³ã¹ã¡ãã»ã¼ã¸ã«å«ãã¦è¿ãã¾ãã
class HandleExceptions extends SimpleFilter[HttpRequest, HttpResponse] {
def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]) = {
service(request) handle { case error =>
val statusCode = error match {
case _: IllegalArgumentException =>
FORBIDDEN
case _ =>
INTERNAL_SERVER_ERROR
}
val errorResponse = new DefaultHttpResponse(HTTP_1_1, statusCode)
errorResponse.setContent(copiedBuffer(error.getStackTraceString, UTF_8))
errorResponse
}
}
}
For an example implementation using a `Filter` object, see Creating Filters to Transform Requests and Responses.
> Filter ãªãã¸ã§ã¯ãã使ã£ãå®è£
ä¾ã«ã¤ãã¦ã¯ Creating Filters to Transform Requests and Responses ãã覧ãã ããã
[Top](#Top)
## Building a Robust Server
The following example encapsulates the filters and service in the previous examples and defines the execution order of the filters, followed by the service. The `ServerBuilder` object specifies the service that indicates the execution order along with the codec and IP address on which to bind the service:
> 以ä¸ã®ä¾ã¯ããã¾ã§ã®ä¾ã§åºã¦ãã Filter ã Service ãåãè¾¼ãã ãã®ã§ãFilter ã®å®è¡é åºãå®ç¾©ãã¦ãã¾ããFilter ã®å¾ã« Service ãç¶ãã¾ããServerBuilder ãªãã¸ã§ã¯ãã¯ãµã¼ãã¹ã«çµã³ã¤ãã Codec ã IP ã¢ãã¬ã¹ã¨ã¨ãã« Service ã®å®è¡é åºã«ã¤ãã¦ãæç¤ºãã¾ãã
object HttpServer {
class HandleExceptions extends SimpleFilter[HttpRequest, HttpResponse] {...}
class Authorize extends SimpleFilter[HttpRequest, HttpResponse] {...}
class Respond extends Service[HttpRequest, HttpResponse] {... }
def main(args: Array[String]) {
val handleExceptions = new HandleExceptions
val authorize = new Authorize
val respond = new Respond
val myService: Service[HttpRequest, HttpResponse]
= handleExceptions andThen authorize andThen respond
val server: Server = ServerBuilder()
.codec(Http)
.bindTo(new InetSocketAddress(8080))
.build(myService)
}
}
In this example, the `HandleExceptions` filter is executed before the `authorize` filter. All filters are executed before the service. The server is robust not because of its complexity; rather, it is robust because it uses filters to remove issues before the service executes.
> ãã®ä¾ã§ã¯ HandleExceptions ã¨ãã Filter ã authorize ã¨ãã Filter ã®åã«å®è¡ããã¾ãããã¹ã¦ã® Filter 㯠Service ã®åã«å®è¡ããã¾ãããµã¼ãã¯ãã®è¤éãã«ãã£ã¦ã§ã¯ãªã Filter ã«ãã£ã¦ Service å®è¡ã®åã®åé¡ãåãé¤ãã¦ããããå¼·åã«ãªã£ã¦ãã¾ãã
[Top](#Top)
## Building a Robust Client
A robust client has little to do with the lines of code (SLOC) that goes into it; rather, the robustness depends on how you configure the client and the testing you put into it. Consider the following HTTP client:
> ã¯ã©ã¤ã¢ã³ã㯠SLOCï¼ã³ã¼ãè¡æ°ï¼ã«ãã£ã¦ããããã¨ãå¤ããªãã®ã§ã¯ãªãããã®å¼·åãã¯ã©ã®ããã«ã¯ã©ã¤ã¢ã³ãã«è¨å®ãã§ãããããã¹ããã©ãã ãã§ãããã«ãã£ã¦æ±ºã¾ãã¾ãã以ä¸ã®ãã㪠HTTP ã¯ã©ã¤ã¢ã³ããã¿ã¦ã¿ã¦ãã ããã
val client = ClientBuilder()
.codec(Http)
.hosts("localhost:10000,localhost:10001,localhost:10003")
.hostConnectionLimit(1) // max number of connections at a time to a host
.connectionTimeout(1.second) // max time to spend establishing a TCP connection
.retries(2) // (1) per-request retries
.reportTo(new OstrichStatsReceiver) // export host-level load data to ostrich
.logger(Logger.getLogger("http"))
.build()
The `ClientBuilder` object creates and configures a load balanced HTTP client that balances requests among 3 (local) endpoints. The Finagle balancing strategy is to pick the endpoint with the least number of outstanding requests, which is similar to a *least connections* strategy in other load balancers. The Finagle load balancer deliberately introduces jitter to avoid synchronicity (and thundering herds) in a distributed system. It also supports failover.
> ClientBuilder ãªãã¸ã§ã¯ãã¯ãã¼ããã©ã³ã¹ããã HTTP ã¯ã©ã¤ã¢ã³ããè¨å®ãããªã¯ã¨ã¹ãã 3 ã¤ã®ï¼ãã¼ã«ã«ãªï¼ã¨ã³ããã¤ã³ãã«å¯¾ãã¦æ¯ãåãã¾ããFinagle ã®ãã©ã³ã·ã³ã°ã¹ãã©ãã¸ã¼ã¯æãæªå¦çã®ãªã¯ã¨ã¹ããå°ãªãã¨ã³ããã¤ã³ããé¸ã¶ã¨ãããã®ã§ããFinagle ã®ãã¼ããã©ã³ãµã¯åæ£ãããã·ã¹ãã ã§åæçºçãé²ãããã«æå³çã«ã¸ãã¿ã¼ãåãå
¥ãã¾ããã¾ãããã§ã¤ã«ãªã¼ãã¼ããµãã¼ãããã¦ãã¾ãã
The following examples show how to invoke this client from Scala and Java, respectively:
> 以ä¸ã®ä¾ã¯ãã®ã¯ã©ã¤ã¢ã³ãã Scala 㨠Java ããèµ·åããããæ¹ããããã示ããã®ã§ãã
##### Scala Client Invocation
val request: HttpRequest = new DefaultHttpRequest(HTTP_1_1, Get, "/")
val futureResponse: Future[HttpResponse] = client(request)
##### Java Client Invocation
HttpRequest request = new DefaultHttpRequest(HTTP_1_1, Get, "/")
Future futureResponse = client.apply(request)
For information about using `Future` objects with Java, see Using Future Objects With Java.
> Java ã«ããã Future ãªãã¸ã§ã¯ãã«ã¤ãã¦ã®ããè©³ç´°ãªæ
å ±ã¯ Using Future Objects With Java ãã覧ãã ããã
[Top](#Top)
## Creating Filters to Transform Requests and Responses
The following example extends the `Filter` class to authenticate requests. The request is transformed into an HTTP response before being handled by the `AuthResult` service. In this case, the `RequireAuthentication` filter does not transform the resulting HTTP response:
> 以ä¸ã®ä¾ã¯ Filter ã¯ã©ã¹ãç¶æ¿ãã¦ãªã¯ã¨ã¹ãã«èªè¨¼ãè¡ããã®ã§ãããªã¯ã¨ã¹ã㯠AuthResult ãµã¼ãã¹ã«å¦çãããåã« HTTP ã¬ã¹ãã³ã¹ã«å¤æããã¾ãããã®ã±ã¼ã¹ã§ã¯ RequireAuthentication ã¨ãã Filter ã¯çµæã¨ãã¦è¿ããã HTTP ã¬ã¹ãã³ã¹ã®å¤æãè¡ãã¾ããã
class RequireAuthentication(val p: ...)
extends Filter[Request, HttpResponse, AuthenticatedRequest, HttpResponse]
{
def apply(request: Request, service: Service[AuthenticatedRequest, HttpResponse]) = {
p.authenticate(request) flatMap {
case AuthResult(AuthResultCode.OK, Some(passport: OAuthPassport), _, _) =>
service(AuthenticatedRequest(request, passport))
case AuthResult(AuthResultCode.OK, Some(passport: SessionPassport), _, _) =>
service(AuthenticatedRequest(request, passport))
case ar: AuthResult =>
Trace.record("Authentication failed with " + ar)
Future.exception(new RequestUnauthenticated(ar.resultCode))
}
}
}
In this example, the `flatMap` object enables pipelining of the requests.
> ãã®ä¾ã§ã¯ flatMap ããªã¯ã¨ã¹ãããã¤ãã©ã¤ã³åãããã¨ãå¯è½ã«ãã¦ãã¾ãï¼ï¼ï¼ã
[Top](#Top)
## Using ServerSet Objects
`finagle-serversets` is an implementation of the Finagle Cluster interface using `com.twitter.com.zookeeper` [ServerSets](http://twitter.github.com/commons/apidocs/#com.twitter.common.zookeeper.ServerSet).
> finagle-serversets 㯠com.twitter.common.zookeeper.ServerSet ãç¨ãã Finagle Cluster ã¤ã³ã¿ãã§ã¼ã¹ã®å®è£
ã§ãã
You can instantiate a `ServerSet` object as follows:
> ServerSet ã以ä¸ã®ããã«ãã¦ã¤ã³ã¹ã¿ã³ã¹åã§ãã¾ãã
val serverSet = new ServerSetImpl(zookeeperClient, "/twitter/services/...")
val cluster = new ZookeeperServerSetCluster(serverSet)
Servers join a cluster, as in the following example:
> 以ä¸ã®ä¾ã®ããã«ãã¦ããµã¼ãã¯ã¯ã©ã¹ã¿ã«åå ãã¾ãã
val serviceAddress = new InetSocketAddress(...)
val server = ServerBuilder()
.bindTo(serviceAddress)
.build()
cluster.join(serviceAddress)
A client can access a cluster, as follows:
> 以ä¸ã®ããã«ãã¦ã¯ã©ã¤ã¢ã³ãã¯ã¯ã©ã¹ã¿ã¼ã«ã¢ã¯ã»ã¹ãã¾ãã
val client = ClientBuilder()
.cluster(cluster)
.hostConnectionLimit(1)
.codec(new StringCodec)
.build()