class MethodBuilder extends BaseMethodBuilder[MethodBuilder]
MethodBuilder is a collection of APIs for client configuration at
a higher level than the Finagle 6 APIs while improving upon the deprecated
ClientBuilder. MethodBuilder provides:
- Logical success rate metrics.
- Retries based on application-level requests and responses (e.g. an HTTP 503 response code).
- Configuration of per-attempt and total timeouts.
All of these can be customized per method (or endpoint) while sharing a single
underlying Finagle client. Concretely, a single service might offer both
GET statuses/show/:id as well as POST statuses/update, whilst each having
wildly different characteristics. The GET is idempotent and has a tight latency
distribution while the POST is not idempotent and has a wide latency
distribution. If users want different configurations, without MethodBuilder
they must create separate Finagle clients for each grouping. While long-lived
clients in Finagle are not expensive, they are not free. They create
duplicate metrics and waste heap, file descriptors, and CPU.
Example
A client that has timeouts and retries on a 418 status code.
import com.twitter.conversions.DurationOps._ import com.twitter.finagle.Http import com.twitter.finagle.service.{ReqRep, ResponseClass} import com.twitter.util.Return val client: Http.Client = ??? client.methodBuilder("inet!example.com:80") .withTimeoutPerRequest(50.milliseconds) .withTimeoutTotal(100.milliseconds) .withRetryForClassifier { case ReqRep(_, Return(rep)) if rep.statusCode == 418 => ResponseClass.RetryableFailure } .newService("an_endpoint_name")
Timeouts
Defaults to using the StackClient's configuration.
An example of setting a per-request timeout of 50 milliseconds and a total timeout of 100 milliseconds:
import com.twitter.conversions.DurationOps._ import com.twitter.finagle.Http import com.twitter.finagle.http.MethodBuilder val builder: MethodBuilder = ??? builder .withTimeoutPerRequest(50.milliseconds) .withTimeoutTotal(100.milliseconds)
Retries
Retries are intended to help clients improve success rate by trying failed requests additional times. Care must be taken by developers to only retry when it is known to be safe to issue the request multiple times. This is because the client cannot always be sure what the backend service has done. An example of a request that is safe to retry would be a read-only request.
Defaults to using the client's ResponseClassifier to retry failures marked as retryable. See withRetryForClassifier for details.
A com.twitter.finagle.service.RetryBudget is used to prevent retries from overwhelming
the backend service. The budget is shared across clients created from
an initial MethodBuilder. As such, even if the retry rules
deem the request retryable, it may not be retried if there is insufficient
budget.
Finagle will automatically retry failures that are known to be safe to retry via com.twitter.finagle.service.RequeueFilter. This includes WriteExceptions and retryable nacks. As these should have already been retried, we avoid retrying them again by ignoring them at this layer.
Additional information regarding retries can be found in the user guide.
The classifier is also used to determine the logical success metrics of the method. Logical here means after any retries are run. For example should a request result in retryable failure on the first attempt, but succeed upon retry, this is exposed through metrics as a success. Logical success rate metrics are scoped to "clnt/your_client_label/method_name/logical" and get "success" and "requests" counters along with a "request_latency_ms" stat.
Unsuccessful requests are logged at com.twitter.logging.Level.DEBUG level.
Further details, including the request and response, are available at
TRACE level.
- See also
com.twitter.finagle.Http.Client.methodBuilder to construct instances.
The user guide.
- Alphabetic
- By Inheritance
- MethodBuilder
- BaseMethodBuilder
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Value Members
-
final
def
!=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
##(): Int
- Definition Classes
- AnyRef → Any
-
final
def
==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
asInstanceOf[T0]: T0
- Definition Classes
- Any
-
def
clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( ... ) @native()
-
final
def
eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
equals(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( classOf[java.lang.Throwable] )
-
final
def
getClass(): Class[_]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
def
hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
def
idempotent(maxExtraLoad: Tunable[Double], minSendBackupAfterMs: Int): MethodBuilder
<invalid inheritdoc annotation>
<invalid inheritdoc annotation>
This additionally causes any server error HTTP status codes (500s) to be retried.
-
def
idempotent(maxExtraLoad: Tunable[Double]): MethodBuilder
<invalid inheritdoc annotation>
<invalid inheritdoc annotation>
This additionally causes any server error HTTP status codes (500s) to be retried.
- Definition Classes
- MethodBuilder → BaseMethodBuilder
-
def
idempotent(maxExtraLoad: Double, minSendBackupAfterMs: Int): MethodBuilder
<invalid inheritdoc annotation>
<invalid inheritdoc annotation>
This additionally causes any server error HTTP status codes (500s) to be retried.
-
def
idempotent(maxExtraLoad: Double): MethodBuilder
<invalid inheritdoc annotation>
<invalid inheritdoc annotation>
This additionally causes any server error HTTP status codes (500s) to be retried.
- Definition Classes
- MethodBuilder → BaseMethodBuilder
-
final
def
isInstanceOf[T0]: Boolean
- Definition Classes
- Any
-
final
def
ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
newService: Service[Request, Response]
Construct a Service to be used for the client.
-
def
newService(methodName: String): Service[Request, Response]
Construct a Service to be used for the
methodNamemethod.Construct a Service to be used for the
methodNamemethod.- methodName
used for scoping metrics (e.g. "clnt/your_client_label/method_name").
-
def
nonIdempotent: MethodBuilder
- Definition Classes
- MethodBuilder → BaseMethodBuilder
-
final
def
notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
synchronized[T0](arg0: ⇒ T0): T0
- Definition Classes
- AnyRef
-
def
toString(): String
- Definition Classes
- MethodBuilder → AnyRef → Any
-
final
def
wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... ) @native()
-
def
withMaxRetries(value: Int): MethodBuilder
- Definition Classes
- MethodBuilder → BaseMethodBuilder
-
def
withRetryDisabled: MethodBuilder
- Definition Classes
- MethodBuilder → BaseMethodBuilder
-
def
withRetryForClassifier(classifier: ResponseClassifier): MethodBuilder
- Definition Classes
- MethodBuilder → BaseMethodBuilder
-
def
withTimeoutPerRequest(howLong: Tunable[Duration]): MethodBuilder
- Definition Classes
- MethodBuilder → BaseMethodBuilder
-
def
withTimeoutPerRequest(howLong: Duration): MethodBuilder
- Definition Classes
- MethodBuilder → BaseMethodBuilder
-
def
withTimeoutTotal(howLong: Tunable[Duration]): MethodBuilder
- Definition Classes
- MethodBuilder → BaseMethodBuilder
-
def
withTimeoutTotal(howLong: Duration): MethodBuilder
- Definition Classes
- MethodBuilder → BaseMethodBuilder
- def withTraceInitializer(initializer: TypeAgnostic): MethodBuilder