SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 30 day free trial to unlock unlimited reading.
8.
Finagle
• OSS RPC Framework by Twitter, Inc.
• Using Future like Akka
• Wrapper of Netty
• "Server as a function"
9.
Finagle
• We use Finagle for Movie Ad Server
• avg. 20ms latency / Max 2000qps
10.
Pros
• easy to build server
• High Performance (backed by Netty)
• Async Handling by Future type
• shared model by thrift IDL
• provides metrics via twitter-server and Tracer
11.
Cons
• slightly slow to update (e.g. upgrade to Scala 2.11)
• (waiting for finagle-redis update)
• Different Behavior between twitter.util.Future and
scala.concurrent.Future (pop-quiz)
• limited documentation
• not a good fit with NewRelic (instead, use Tracer)
13.
Handling Async
• Type as a document
• Future indicates IO call
• Procedures in AdServer
• Request -> JSON parse -> Data load ->
Campaign Filtering -> Response
14.
Server as a function
• Server : Request => Response
!
class Service[-Req, +Rep] extends (Req => Future[Rep])
15.
Ad Service
• Launches ListeningServer(backed by Netty)
on `:port`
!
class AdService extends Service[Request, Response] {
override def apply(request: Request): Future[Response] = {
// hogehoge
}
}
val server = Http.serve(":port", new AdService())
Await.result(server)
* caution: This code needs transformation of Request to HttpRequest
(also Response)
16.
JSON Parse
• Jackson Streaming API
• AdRequest is defined in .thrift file
!
trait JsonParser {
def read(request: Request):Option[AdRequest]
}
17.
Data Load
• Future type indicates the function causes
heavy IO task
!
trait ContextLoader {
def load(): Future[CampaignContext]
}
18.
Data Load
• Campaign Master Info is stored in MySQL,
and be cached on JVM memories.
• Use AtomicReference to ConcurrentHashMap
as cache
!
trait ContextLoader {
def load(): Future[CampaignContext]
}
19.
Campaign Filtering
• Filtering campaigns based on Context and
Request
!
trait CampaignFilter {
def filter(
request: AdRequest,
ctx: CampaignContext
): Option[AdResponse]
}
20.
Future Chain
• add callback to the function with flatMap
• callback will receive the result of former
Future function, then returns new Future
!
def flatMap[B](f: A => Future[B]): Future[B]
24.
Filter
• Set filter for application-agnostic behavior, like
timeout
class HttpTimeoutFilter (
val timeOutMs: Int
) extends TimeoutFilter[Request, Response](
timeOutMs.milliseconds,
new GlobalRequestTimeoutException(timeOutMs.milliseconds),
DefaultTimer.twitter){
}
!
Http.serve(":port", new HttpTimeoutFilter(100) andThen AdService)
!
25.
Routing
val muxer = new HttpMuxer()
.withHandler("/ad", new AdService())
!
val server = Http.server(":port", muxer)
Await.result(server)
26.
Tips for Performance
• Basically the server will not be CPU-bound
• Wrap IO-bound process by Future
27.
Tips for Performance
• The cost for creating instances for Future or
Option can be ignored
• For constructing List, use mutable data structure
(e.g. ArrayBuffer) and finally call toList
• For transforming List, use Iterator and finally call
toList
• Practice for Performance tuning in Scala (Japanese)
28.
Summary
• Finagle will be a good fit for Ad Server
• We used mutable for data construction
• However, no need for sensitive for tuning
• (́-`).。oO(Hope Finagle will become more popular)