原文地址:Accessing Other Services using HTTP or HTTPS
概貌
squbs-httpclient
項目在保持Akka Http API的同時谱俭,向Akka HTTP Host-Level Client-Side API添加了可操作化方面昆著,以下是它添加的功能的列表
Service Discovery: 允許插入任何服務(wù)發(fā)現(xiàn)機制术陶,并且允許通過字符標識符解析斷點(endpoint),例如:
paymentserv
.Per Client configuration: 允許每個客戶端單獨覆蓋
application.conf
中的默認值Metrics: 為每個客戶端提供開箱即用的Codahale Metrics
JMX Beans: 通過JMX beans的方式暴露每個客戶端的配置
Circuit Breaker: // TODO In progress
依賴
在你的build.sbt或scala構(gòu)建文件中加入如下依賴:
"org.squbs" %% "squbs-httpclient" % squbsVersion
用法
squbs-httpclient項目堅持 Akka HTTP API接谨。唯一的例外時在創(chuàng)建主機連接池期間塘匣。代替 Http().cachedHostConnectionPool
,它使用一組參數(shù)定義 ClientFlow
(和一些可選參數(shù))跑揉。
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
// construct a pool client flow with context type `Int`
val poolClientFlow = ClientFlow[Int]("sample") // Only this line is specific to squbs
val responseFuture: Future[(Try[HttpResponse], Int)] =
Source.single(HttpRequest(uri = "/") -> 42)
.via(poolClientFlow)
.runWith(Sink.head)
同時,類似在Akka HTTP Host-Level Client-Side API中的例子现拒,ClientFlow
在JAVA中的使用如下:
final ActorSystem system = ActorSystem.create();
final ActorMaterializer mat = ActorMaterializer.create(system);
final Flow<Pair<HttpRequest, Integer>, Pair<Try<HttpResponse>, Integer>, HostConnectionPool>
clientFlow = ClientFlow.create("sample", system, mat);
CompletionStage<Pair<Try<HttpResponse>, Integer>> =
Source
.single(Pair.create(request, 42))
.via(clientFlow)
.runWith(Sink.head(), mat);
HTTP 模型
Scala
以下是一個HttpRequest
Scala的創(chuàng)建例子望侈,更多請查閱 HTTP Model Scala documentation
import HttpProtocols._
import MediaTypes._
import HttpCharsets._
val userData = ByteString("abc")
val authorization = headers.Authorization(BasicHttpCredentials("user", "pass"))
HttpRequest(
PUT,
uri = "/user",
entity = HttpEntity(`text/plain` withCharset `UTF-8`, userData),
headers = List(authorization),
protocol = `HTTP/1.0`)
Java
以下是一個HttpRequest
Java的創(chuàng)建例子脱衙,更多請查看Http Model Java documentation :
import HttpProtocols.*;
import MediaTypes.*;
Authorization authorization = Authorization.basic("user", "pass");
HttpRequest complexRequest =
HttpRequest.PUT("/user")
.withEntity(HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8, "abc"))
.addHeader(authorization)
.withProtocol(HttpProtocols.HTTP_1_0);
服務(wù)發(fā)現(xiàn)鏈
在創(chuàng)建池的時候,squbs-httpclient
不需要提供主機名/端口的組合退唠。取而代之的是,它允許注冊服務(wù)發(fā)現(xiàn)鏈瞧预,通過注冊服務(wù)發(fā)現(xiàn)機制仅政,允許通過string識別符來解析端點(endpoint)。舉個例子滩愁,在上面的例子中, "sample"
是客戶端想要訪問的服務(wù)的邏輯名稱硝枉,配置的服務(wù)發(fā)現(xiàn)鏈會將它解析成一個包含主機名和端口的端點(endpoint)倦微,例如: http://akka.io:80
.。
這里有兩個不同的注冊端點解釋器如下弧可。閉包的風(fēng)格允許更加緊湊和可讀的代碼。然而棕诵,這個子類擁有保持狀態(tài)和基于這個狀態(tài)做解決決定的能力凿将。
Scala
注冊函數(shù)類型 (String, Env) => Option[Endpoint]
:
EndpointResolverRegistry(system).register("SampleEndpointResolver", { (svcName, env) =>
svcName match {
case "sample" => Some(Endpoint("http://akka.io:80"))
case "google" => Some(Endpoint("http://www.google.com:80"))
case _ => None
})
注冊類繼承于 EndpointResolver
:
class SampleEndpointResolver extends EndpointResolver {
override def name: String = "SampleEndpointResolver"
override def resolve(svcName: String, env: Environment): Option[Endpoint] = svcName match {
case "sample" => Some(Endpoint("http://akka.io:80"))
case "google" => Some(Endpoint("http://www.google.com:80"))
case _ => None
}
}
// Register EndpointResolver
EndpointResolverRegistry(system).register(new SampleEndpointResolver)
Java
注冊BiFunction<String, Env, Optional<Endpoint>>
:
EndpointResolverRegistry.get(system).register("SampleEndpointResolver", (svcName, env) -> {
if ("sample".equals(svcName)) {
return Optional.of(Endpoint.create("http://akka.io:80"));
} else if ("google".equals(svcName))
return Optional.of(Endpoint.create("http://www.google.com:80"));
} else {
return Optional.empty();
}
});
注冊類繼承AbstractEndpointResolver
:
class SampleEndpointResolver extends AbstractEndpointResolver {
String name() {
return "SampleEndpointResolver";
}
Optional<Endpoint> resolve(svcName: String, env: Environment) {
if ("sample".equals(svcName)) {
return Optional.of(Endpoint.create("http://akka.io:80"));
} else if ("google".equals(svcName))
return Optional.of(Endpoint.create("http://www.google.com:80"));
} else {
return Optional.empty();
}
}
// Register EndpointResolver
EndpointResolverRegistry.get(system).register(new SampleEndpointResolver());
你可以注冊多個EndpointResolver
牧抵。這個鏈是根據(jù)注冊的逆序執(zhí)行侨把。如果一個解析器返回None
,這就意味著它無法解釋秋柄,下一個解釋器嘗試解釋。
如果解釋的端點(endpoint)是安全的骇笔,例如(https)嚣崭,可以將SSLContext
傳遞給Endpoint
。
每個客戶端的配置(Per Client Configuration)
Akka HTTP Configuration 定義了配置的默認值芦劣。你可以在application.conf
中重寫這些默認值;然而這樣會影響所有的客戶端持寄。做一個特定客戶端的重寫娱俺,在HostConnectionPool
流創(chuàng)建時荠卷,Akka HTTP允許在HostConnectionPool
流創(chuàng)建期間傳遞ConnectionPoolSettings
。這也是由squbs支持油宜。
除了以上之外怜姿,squbs還允許客戶端特定重寫 application.conf
。你僅需要通過客戶端名稱提出一個有 type = squbs.httpclient
的配置部分沧卢。然后,你可以在這個部分提出任何的客戶端配置披诗。例如立磁,如果我們只想要重寫上面"sample"
客戶端中的 max-connections
設(shè)置,我們可以如下做:
sample {
type = squbs.httpclient
akka.http.host-connection-pool {
max-connections = 10
}
}
管道(Pipeline)
我們通常需要公用的基礎(chǔ)功能或不同客戶端的組織標準唱歧。這些基礎(chǔ)設(shè)施包括而不限于粒竖,日志蕊苗、指標手機、請求跟蹤岁歉、認證\授權(quán)膝蜈,跟蹤,cookie管理饱搏,A/B測試等等。正因squbs促成關(guān)注分離备绽,這樣的邏輯將屬于基礎(chǔ)設(shè)置鬓催,而非客戶端實現(xiàn)。 squbs pipeline 允許基礎(chǔ)設(shè)施提供組件宇驾,安裝在客戶端,客戶端所有者不需要擔心這些方面塌西。更多詳細可查看 squbs pipeline筝尾。
一般來說,一個pipeline是一個雙向流筹淫,構(gòu)建了squbs客戶端和Akka HTTP 層的橋梁。squbs-httpclient
允許為所有或個別的客戶端注冊全局雙向流(默認 pipeline)庵寞。注冊一個特定客戶端pipeline,設(shè)置 pipeline
配置捐川。你可以通過defaultPipeline
設(shè)置開啟/關(guān)閉默認pipeline(如果未指定逸尖,則設(shè)置為on
)瘸右。
sample {
type = squbs.httpclient
pipeline = metricsFlow
defaultPipeline = on
}
請參照 squbs pipeline來查看如何創(chuàng)建pipeline和配置默認pipeline
指標(Metrics)
squbs帶有預(yù)編譯pipeline指標集岩齿,squbs激活模板將這些設(shè)為默認。因此盹沈,不需要任何代碼變更或配置,每個squbs http客戶端可以收集Codahale Metrics即開即用做裙。默認情況下肃晚,JMX提供以下指標:
- 請求計時器(Request Timer)
- 請求計數(shù)儀表(Request Count Meter)
- 為每個http相應(yīng)狀態(tài)歸類的儀表:2xx, 3xx, 4xx, 5xx
-
ClientFlow
.返回的每個異常類型的儀表
JMX Beans
故障排除問題時,可視化系統(tǒng)配置是非常重要的关串。squbs-httpclient
為每個客戶端注冊了JMX bean。JMX bean發(fā)布所有的配置吧碾,例如端點(endpoint)墓卦,主機連接池設(shè)置等。bean的名稱設(shè)置如 org.squbs.configuration.${system.name}:type=squbs.httpclient,name=$name
趴拧。所以著榴,如果actor系統(tǒng)名稱是 squbs
屁倔,客戶端名稱為 sample
,那么JMX bean的名稱為org.squbs.configuration.squbs:type=squbs.httpclient,name=sample
锐借。
Circuit Breaker
// TODO In progress