Finagleããã«ã½ã³ã¸è¡ã£ã¦ããã£ï¼ #finagle_hack
Scalaãå§ãã¦æ°ã¶æãããæ·±ãScalaãå¦ã¶ããã«Twitter製RPCãã¬ã¼ã ã¯ã¼ã¯ã§ããFinagleã§éã³åããã®ä¼ã¸åå ãã¦ãã¾ããã
ã¾ã£ããã®Finagleåå¿è
ã®ç§ã§ãããã水島ãã(@kmizu)ã®ããããããè³æãä¸æãã(@gakuzzzz)ã®è§£èª¬ã®ãé°ã§Finagleã¯è§¦ã£ã¦éã¶ãã¨ãã§ãã¾ããï¼
ãããã¨ããããã¾ãã(´âï½)
ã¾ããä¼å ´ãæä¾ãã¦ãã ãã£ãTwitter Japanã®å±±æ¬è£ä»ãã(@yusukey)ã«ãè¯ããã¦ããã ãã¦ãè³ããå°½ãããã§ããï¼
沢山ã®ããã«ãã£ã°ããºãé ãã¾ããï¼
以ä¸ãããã«ã½ã³ãéãã¦å¦ãã ãã¨ã®ã¡ã¢ã¿ãããªãã®Ï(ï½Ð´Â´)ï¾ï¾ï¾ï¾...
Finagleï¼ãµããã¼ããï¼ã¨ã¯ãTwitter製ã®éåæRPCãã¬ã¼ã ã¯ã¼ã¯ã§ãRPCã®ã·ã¹ãã ãä½ãããã®ãã¬ã¼ã ã¯ã¼ã¯ã
â» Apache Thriftã®ããã«ãããèªä½ãRPCãæä¾ããããã§ã¯ãªã
- æ§ã ãªãããã³ã«ã®Serverã¨Clientãç°¡åã«ä½ããã
- JSONã®ã¡ãã»ã¼ã¸ã³ã°ã¨ãç°¡åã«ä½ãã¡ããã
- Finagleã¯ã ãããScalaã§æ¸ããã¦ããã
- JVMä¸ã§åä½ããè¨èªãããå©ç¨ã§ãããåºæ¬çã«Scalaããªã¹ã¹ã¡
Twitter社ãåºãã¦ããEffective Scalaã§ã¯ä»¥ä¸ã®ããã«æ¸ããã¦ãã
Twitterã«ããã¦ãæãéè¦ãªæ¨æºã©ã¤ãã©ãªã¯Utilã¨Finagleã ãUtilã¯ãScalaãJavaã®æ¨æºã©ã¤ãã©ãªã®æ¡å¼µã¨ããä½ç½®ä»ãã§ããããã«æ¬ ãã¦ããæ©è½ãããé©åãªå®è£ ãæä¾ãããFinagleã¯ãTwitterã®RPCã·ã¹ãã ã§ãåæ£ã·ã¹ãã ã®æ§æè¦ç´ ã®ä¸æ ¸ã ã
Twitterã§ã®Finagleã®ä½¿ããæ¹
Twitter Engineering: Finagle: A Protocol-Agnostic RPC System
Finagleã¯Twitterå¤ã§ã使ããã¦ãã
Tumblrï¼PHPããScala(Finagle)ã«ç§»è¡
Herokuï¼ãµã³ãã«ãããã«Finagleï¼ï¼
Finagleã®ã¢ã¼ããã¯ãã£
- ä¸ã§ã¯Nettyãåãã¦ãã
- Nettyã¯Java NIOãã©ãããã¦ãã
- ãã³ããããã³ã°ãªI/Oæä½ãã§ãã
- Finagleã¯JBoss Nettyãã©ãããã¦ä½¿ãããããããã®
- Filter, Codec, Serviceã¨ããæ¦å¿µããã
Twitter Finagle server as an alternate HTTP ser... - Scala Resources - Quora
Finagleã®è¦ç´
éè¦ãªè¦ç´ ã¯Future, Service, Filter, Codecã®4ã¤ï¼
Futureã¯ã©ã¹
class Future[+A]{ def apply():A }
Service
Finagleã«ããããã¸ãã¯ãå®è£ ããé¨å
class Service[-Req,+Rep] extends (Req) => Future[Rep]{ def apply(request:Req):Future[Rep] }
- Reqåãåãåã£ã¦Future[Rep]åãéåæã«è¿ãé¢æ°
- Server
- Serverã¯ä»»æã®ãããã³ã«ã«ä»»æã®Serviceãçµã³ã¤ãã
//EchoServerã®ä¾ val server:Server = ServerBuilder() .codec(Http()) .bindTo(new InetSocketAddress(8000)) .name("ServerName") .build(service)
- Client
- Clientã¯ä»»æã®ãããã³ã«ã®Serviceãã®ãã®
//EchoClientã®ä¾ val client: Service[HttpRequest, HttpResponse] = ClientBuilder() .codec(Http()) .hosts(new InetSocketAddress("localhost",8000)) .build()
Filter
Filterã¯Serviceã«å¯¾ãã¦ä½ãå¤æãè¡ã£ãããã
class Filter[-ReqI, +RepO, +ReqO, -RepI] extends(ReqI, Service[ReqO, RepI])=>Future[RepO] { def apply (request: ReqI, service: Service[ReqO, RepI]): Future[RepO] }
Codec
- Codecã¯ãNettyã«Pipelineã¨å¯æ¥ãªé¢ä¿ããã
- Codecã¯ãåãããã³ã«ã®encodeã¨decodeãå¸ãNettyã¨ã®ã¤ãªãå½¹
- encode:ãªãã¸ã§ã¯ããã·ãªã¢ã©ã¤ãºåããå¦ç
- decode:ã·ãªã¢ã©ã¤ãºåããããã¼ã¿ãããªãã¸ã§ã¯ãã復å ããå¦ç
- Finagleã«æ¨æºã§ãµãã¼ãããã¦ããCodec
- HTTP
- Stream(Http chunked transfer encoding)
- Memcached
- protocol buffer
- Redis
- Thrift
- Kestrel
trait Codec[Req,Rep] //Httpã®ä¾ val client: Service[HttpRequest,HttpResponse] = ClientBuilder() .codec(Http()) .hosts(address) .build() //Memcachedã®ä¾ val client: Service[Command, Response] = ClientBuilder() .codec(Memcached()) .hosts(address) .build()
ãã®ä»ã®æ©è½
- Server Support
- Backpressure
- Service Registration
- Native OpenSSL bindings
- Client Support
- Connection Pooling
- Load Balancing
- Failure Detection
- Failover/Retry
- Distributed Tracing(a la Dapper)
- Service Discovery(e.g., via Zookeeper)
- Rich Statistics
- Native OpenSSL bindings
- Sharding
Hello World
- Echoãµã¼ãï¼ã¯ã©ã¤ã¢ã³ãã§Hello Worldãåºå
Serverå´ï¼HelloServer.scala
import com.twitter.util.Future import com.twitter.finagle.Service import com.twitter.finagle.builder.Server import com.twitter.finagle.builder.ServerBuilder import java.net.InetSocketAddress object HelloServer { def main(atgs:Array[String]){ val service = new Service[String,String]{ def apply(request: String) = Future.value(request) } val server:Server = ServerBuilder() .codec(StringCodec) .bindTo(new InetSocketAddress(8080)) .name("TestServer") .build(service) } }
Clientå´ï¼HelloClient.scala
import com.twitter.finagle.Service import com.twitter.finagle.builder.ClientBuilder import java.net.InetSocketAddress object HelloClient { def main(args:Array[String]){ val client:Service[String,String] = ClientBuilder() .codec(StringCodec) .hosts(new InetSocketAddress("localhost",8080)) .hostConnectionLimit(1) .build() client("Hello, Finagle!!\n") onSuccess{ result => println(result) }onFailure { error => error.printStackTrace() }ensure{ println("end") client.release() } } }
å®è¡çµæ
Hello, Finagle!!