Under The Hood
The key problem with #Finagle adoption that it solves tons of problems that you know nothing about until it's too late #FinagleCon
— Alexey Kachayev (@kachayev) August 13, 2015
This is third major clone of @finagle I am aware of, other ones are in Rust and Java 8https://t.co/eewNYEaQPE
— Mansur Ashraf (@mansur_ashraf) April 20, 2016
trait Service[-Req, +Rep] extends (Req => Future[Rep])
<Protocol>.client.with*
and <Protocol>.server.with*
.configured
, .transformed
, .filtered
import com.twitter.finagle.Http
val server = Http.server
.withAdmissionControl.concurrencyLimit(
maxConcurrentRequests = 10,
maxWaiters = 0
)
Maintains the concurrency level of this server (default: disabled
).
import com.twitter.conversions.time._
import com.twitter.finagle.Http
val server = Http.server
.withRequestTimeout(42.seconds)
Time out requests that weren't handled in a given time
(default: disabled
).
Quick poll by @kevino: Does Finagle treat HTTP 500 response as a failure or success?
— Finagle (@finagle) February 9, 2016
finagle-core
knows nothing about the protocol/application its used byimport com.twitter.finagle.{Http, http}
import com.twitter.finagle.service._
import com.twitter.util._
val classifier: ResponseClassifier = {
case ReqRep(_, Return(r: http.Response)) if r.statusCode == 503 =>
ResponseClass.NonRetryableFailure
}
val client = Http.client
.withResponseClassifier(classifier)
Treat 503 (Service Unavailable)
as a non-retriable failure.
RetryBuget
(leaky token bucket) allows it
import com.twitter.finagle.Http
import com.twitter.conversions.time._
import com.twitter.finagle.service.RetryBudget
val budget = RetryBudget(
ttl = 10.seconds,
minRetriesPerSec = 5,
percentCanRetry = 0.1
)
val client = Http.client.withRetryBudget(budget)
Allow retrying 10%
of total requests on top of 5
retries per second.
Stream[Duration]
Backoff.linear
and Backoff.exponential
Backoff.exponentialJittered
Backoff.equalJittered
Backoff.decorrelatedJittered
import com.twitter.finagle.Http
import com.twitter.conversions.time._
import com.twitter.finagle.service.Backoff
val client = Http.client
.withRetryBackoff(Backoff.exponentialJittered(2.seconds, 32.seconds))
Backoff for rnd(2s), rnd(4s), rnd(8), ..., rnd(32s), ... rnd(32s)
import com.twitter.conversions.time._
import com.twitter.finagle.Http
val client = Http.client
.withTransport.connectTimeout(1.second) // TCP connect
.withSession.acquisitionTimeout(42.seconds)
.withSession.maxLifeTime(20.seconds) // connection max life time
.withSession.maxIdleTime(10.seconds) // connection max idle time
import com.twitter.conversions.time._
import com.twitter.finagle.Http
import com.twitter.finagle.loadbalancer.Balancers
val balancer = Balancers.aperture(
lowLoad = 1.0, highLoad = 2.0, // the load band adjusting an aperture
minAperture = 10 // min aperture size
)
val client = Http.client.withLoadBalancer(balancer)
FailFast
- a session-driven circuit breakerFailureAccrual
- a request-driven circuit breakerThresholdFailureDetector
- ping based failure detector (Mux only)import com.twitter.conversions.time._
import com.twitter.finagle.Http
import com.twitter.finagle.service.{Backoff, FailureAccrualFactory.Param}
import com.twitter.finagle.service.exp.FailureAccrualPolicy
val twitter = Http.client
.configured(Param(() => FailureAccrualPolicy.successRate(
requiredSuccessRate = 0.95,
window = 100,
markDeadFor = Backoff.const(10.seconds)
)))
Mark a replica dead if SR is below 95%
over the most recent 100
requests
and then backoff for 10 s
.