Flex Gateway新着情報
Governance新着情報
Monitoring API ManagerHTTP 要求を発行するか、または HTTP エンドポイントを公開することによってリモートシステムにアクセスするコネクタでは、特別に考慮すべき点がいくつかあります。
HTTP 要求の実行には Mule HTTP クライアントを使用する必要があります。他の HTTP クライアント (Jersey クライアント、Apache HTTP クライアント、Jetty、Netty など) を Mule HTTP クライアントの代わりに使用すべきではありません。
このルールの唯一の例外は、Mule HTTP クライアントで再現するのが非常に困難な付加価値を持つクライアントライブラリが、すでにリモートシステムベンダーから提供されている場合です。
たとえば、Amazon AWS Connector は、カスタムメッセージ署名を必要とする HTTP API を消費することで機能します。Amazon では、この署名を行うためのロジックをカプセル化したクライアントライブラリを提供しています。
一方、利便性を高めるために HTTP クライアントをラップする以外は何もしないクライアントライブラリ (Google クライアントなど) は、このルールの例外とはなりません。
HTTP クライアントライフサイクルの処理
HTTP クライアントのライフサイクルは、HttpClient クラスを作成する ConnectionProvider クラスの責任です。
キャッシュされた接続プロバイダーの使用
HttpClient クラスを作成するすべての ConnectionProvider クラスは、CachedConnectionProvider インターフェースを実装する必要があります。
このルールは、接続プロバイダーが生成する接続オブジェクトにも影響します。以前に説明した「接続オブジェクトは内部クライアントを公開しては (内部クライアントであっては) ならない」というルールにより、提供される接続オブジェクトは、その状態の一部として HTTP クライアントを含む必要があり、スレッドセーフである必要があります。
Startable および Stoppable 接続プロバイダーの使用
接続プロバイダーは、Startable インターフェースと Stoppable インターフェースも提供する必要があります。HttpClient は、start() フェーズで作成および開始される必要があり、stop() フェーズで終了される必要があります。
ライフサイクルの例:
public class HttpConnectionProvider implements CachedConnectionProvider<HttpConnection>, Startable, Stoppable {
@Inject
private HttpService httpService;
@Parameter
private TlsContextFactory tlsContext;
@Override
public void start() throws MuleException {
initialiseIfNeeded(tlsContext);
httpClient = httpService.getClientFactory().create(getHttpClientConfiguration());
httpClient.start();
}
@Override
public void stop() throws MuleException {
if (httpClient != null) {
httpClient.stop();
}
}
// rest of the implementation removed for example simplicity
}
HTTP クライアント名の設定
各 ConnectionProvider で作成された HttpClient には、その ConnectionProvider を所有する設定の名前に基づいた (あるいは単純に一致する) 名前を付ける必要があります。
これは、パフォーマンスのトラブルシューティングにおいて非常に重要です。各 HttpClient は、I/O に使用するセレクタースレッドを作成します。これらのスレッドには、クライアント名にちなんだ名前が付けられます。これらのスレッドに意味のある名前を付けることで、パフォーマンスの問題を診断しやすくなります。
所有する設定の名前は @RefName アノテーションを使用して取得できます。
そのやり方の例を次に示します。
public class HttpConnectionProvider implements
CachedConnectionProvider<HttpConnection>, Startable, Stoppable {
@Inject
private HttpService httpService;
@RefName
private String configName
@Override
public void start() throws MuleException {
httpClient = httpService.getClientFactory().
create(new HttpClientConfiguration.Builder()
.setName(configName)
.build());
httpClient.start();
}
// rest of implementation removed for example simplicity
}
操作での非ブロック I/O の活用
HttpClient は、非ブロック I/O を使用して要求を実行できます。操作は、この機能を活用し、さらに非ブロックとして定義される必要があります。
<http:requester-config> 要素を参照しない
HttpService では、個別の <http:requester-config> 要素に関連付けられている HttpClient を取得できます。この機能は、コネクタで使用するために用意されているわけではありません。コネクタでは、この機能を使用してはなりません。
HttpClient インスタンスを必要とするすべてのコネクタは、自分で作成して管理する必要があります。
HTTP プロキシ設定の提供
HTTP クライアントインスタンスを使用するコネクタは、HTTP Connector と同様にプロキシを設定する機能を提供する必要があります。プロキシ設定を使用する一般的な理由には、セキュリティ、メンテナンス、プロキシキャッシュなどがあります。多くの組織では、ファイアウォールの背後で作業する場合にもプロキシ設定が必要です。
次のコードスニペットは、HTTP 要求コネクタの OAuth エンドポイントなどでプロキシを設定する方法を示しています。
このグローバルプロキシ設定を参照として使用します。
<http:proxy name="proxyConfig" host="localhost" port="3128" username="yourProxyUsername" password="yourProxyPassword" />
クライアントログイン情報許可種別を設定する場合は、次のスニペットを使用します。
<http:request-config name="HTTP_Request_Configuration" host="api.github.com" port="443" doc:name="HTTP Request Configuration"> <oauth2:client-credentials-grant-type clientId="111" clientSecret="222" > <oauth2:token-request tokenUrl="https://github.com/login/oauth/authorize"" /> <spring:property name="proxyConfig" ref="proxyConfig"/> </oauth2:client-credentials-grant-type> </http:request-config>
認証コード許可種別を設定する場合は、次のスニペットを使用します。
<http:request-config name="HTTP_Request_Configuration" host="api.github.com" protocol="HTTPS" port="443" usePersistentConnections="false" doc:name="HTTP Request Configuration"> <oauth2:authorization-code-grant-type clientId="00a3d08a823faf378568" clientSecret="19c09306adbb84c2d4bc99c585df51d49fe858cf" redirectionUrl="http://localhost:8082/callback">; <oauth2:authorization-request authorizationUrl="https://github.com/login/oauth/authorize"" localAuthorizationUrl="http://localhost:8082/login"/>; <oauth2:token-request tokenUrl="https://github.com/login/oauth/access_token">; <oauth2:token-response accessToken="#[payload.'access_token']" refreshToken="#[payload['access_token']]"/> </oauth2:token-request> <spring:property name="proxyConfig" ref="proxyConfig"/> </oauth2:authorization-code-grant-type> </http:request-config>
proxyConfig
種別を使用する場合、次のように、接続プロバイダーで接続がプロキシを参照するように @Parameter
アノテーションを含める必要があります。
@Parameter
@Optional
@Placement(tab = "Proxy", order = 1)
private MyConnectorProxyConfiguration proxyConfig;
HTTP クライアントでプロキシ設定も定義する必要があります。
.setProxyConfig(connectionParams.getProxyConfig())
詳細は、HTTP Connector がプロキシを処理する方法に関する Java コードを参照してください。
一部のコネクタでは、自身の HTTP インバウンドエンドポイントを公開する必要があります。
そのためには、コネクタで外部 <http:listener-config> 要素を参照して HttpServer インスタンスを取得する必要があります。コネクタ自身でサービスを作成してはなりません。
これは次のようにして実現する必要があります。
リスナー設定を正しく参照する
接続プロバイダーは、listenerConfig という文字列パラメーターを公開する必要があります。このパラメーターは、文字列型で、式を受け入れず、@ConfigReference アノテーションを使用して自身が <http:listener-config> 要素を参照することを示す必要があります。
次に例を示します。
@Parameter
@Expression(NOT_SUPPORTED)
@ConfigReference(name = "LISTENER_CONFIG", namespace = "HTTP")
private String listenerConfig;
RequestHandler の追加
上の listenerConfig パラメーターを使用して、一致する HttpServer インスタンスを次のように取得できます。
HttpServer httpServer;
try {
httpServer = httpService.getServerFactory().lookup(listenerConfig);
} catch (ServerNotFoundException e) {
throw new IllegalArgumentException(
format("Connector configuration '%s' refers to an <http:listener-config> with name '%s', "
+ "but such element doesn't exist", configName, listenerConfigName),
e);
}
取得した HttpServer で org.mule.runtime.http.api.server.HttpServer#addRequestHandler(java.lang.String, org.mule.runtime.http.api.server.RequestHandler) メソッドを使用して、新しい RequestHandler を追加できます。
コネクタは、このメソッドの Javadocs で定義されているコントラクトに慎重に準拠する必要があります。最も重要な点として、このメソッドを呼び出すと RequestHandlerManager インスタンスが返されます。これらのインスタンスは、start() と stop() という 2 つの重要なメソッドを公開するため、コネクタ側で保持する必要があります。
インバウンドエンドポイントは、RequestHandlerManager で start() メソッドを呼び出すまでは実際には機能しません。また、RequestHandlerManager で stop() メソッドを呼び出すまで、このエンドポイントは機能し続けます。
そのため、カスタムエンドポイントを所有するコンポーネントが停止した場合は、RequestHandlerManager も停止する必要があります。そうしないと、コネクタでメモリリークが発生します。