プロジェクトではSpringクラウドを使用しています。いくつかのマイクロ サービスがあり、それぞれに独自の .yml ファイルがあります。
以下のプロパティは zuul サーバーにのみあります
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000
テスト 1:
アカウント サービス:
このサービスは、タイムアウトをテストするために呼び出しているものであり、ポート 8006 を使用して、zuul 経由で要求を呼び出しています。
@RequestMapping(value = "/accountholders/{cardHolderId}/accounts", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
@ResponseBody
public AllAccountsVO getAccounts(@PathVariable("cardHolderId") final String cardHolderId,
@RequestHeader("userContextId") final String userContextId,
@RequestParam final MultiValueMap<String, String> allRequestParams, final HttpServletRequest request) {
return iAccountService.getCardHolderAccountsInfo(cardHolderId, userContextId, request, allRequestParams,
ApplicationConstants.ACCOUNTHOLDER);
}
上記のサービスは、Spring RestTemplate を使用して内部的に以下のサービスを呼び出します。Association Serviceに以下のように 5000ms のスリープ時間を追加してテストを開始し、Accounts Serviceにリクエスト(getAccounts 呼び出し) を行いました。
アソシエーション サービス:
@RequestMapping(value = "/internal/userassociationstatus", produces = "application/json; charset=utf-8", consumes = "application/json", method = RequestMethod.GET)
@ResponseBody
public UserAssociationStatusVO getUserAssociationStatus(@RequestParam final Map<String, String> allRequestParams) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return iUserAssociationsService.getUserAssociationStatus(allRequestParams);
}
以下は、 Association Serviceで得たエラーです。
org.apache.catalina.connector.ClientAbortException: java.io.IOException: An established connection was aborted by the software in your host machine
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:393) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:426) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:342) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
以下は、アカウント サービスで発生したエラーです。
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://USERASSOCIATIONS-V1/user/v1/internal/userassociationstatus?cardholderid=123&usercontextid=222&role=ACCOUNT": com.sun.jersey.api.client.ClientHandlerException: java.net.SocketTimeoutException: Read timed out; nested exception is java.io.IOException: com.sun.jersey.api.client.ClientHandlerException: java.net.SocketTimeoutException: Read timed out
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:607) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:475) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
スリープ時間を 4500 にしておくと応答が返されますが、4800 以上の場合は上記の例外がスローされます。これはリボンのタイムアウトではなく、別の何かに関係していると思います。特定の時点以降の上記の例外の特定の理由。
テスト 2
次に、 Accounts Serviceで直接75000 ミリ秒のスリープ時間を維持しようとし、スリープ時間Association Serviceを削除しました。
@RequestMapping(value = "/accountholders/{cardHolderId}/accounts", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
@ResponseBody
public AllAccountsVO getAccounts(@PathVariable("cardHolderId") final String cardHolderId,
@RequestHeader("userContextId") final String userContextId,
@RequestParam final MultiValueMap<String, String> allRequestParams, final HttpServletRequest request) {
try {
Thread.sleep(75000);
} catch (InterruptedException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
return iAccountService.getCardHolderAccountsInfo(cardHolderId, userContextId, request, allRequestParams,
ApplicationConstants.ACCOUNTHOLDER);
}
この場合、「com.netflix.zuul.exception.ZuulException」という「例外」が発生しました。
そして、APIGateway(Zuul アプリケーション) ログに以下のエラーが表示されます。
com.netflix.zuul.exception.ZuulException: Forwarding error
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:134) ~[spring-cloud-netflix-core-1.1.0.M5.jar:1.1.0.M5]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:76) ~[spring-cloud-netflix-core-1.1.0.M5.jar:1.1.0.M5]
at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112) ~[zuul-core-1.1.0.jar:1.1.0]
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:197) ~[zuul-core-1.1.0.jar:1.1.0]
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: useraccounts-v1RibbonCommand timed-out and no fallback available.
at com.netflix.hystrix.AbstractCommand$16.call(AbstractCommand.java:806) ~[hystrix-core-1.4.23.jar:1.4.23]
at com.netflix.hystrix.AbstractCommand$16.call(AbstractCommand.java:790) ~[hystrix-core-1.4.23.jar:1.4.23]
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:99) ~[rxjava-1.0.14.jar:1.0.14]
at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-1.0.14.jar:1.0.14]
これは、Ribbon ConnectTimeout や ReadTimeout とは関係がないと思います。このエラーは、プロパティ"execution.isolation.thread.timeoutInMilliseconds: 60000"が原因です。また、動作をテストするためにこのプロパティを 10000 ミリ秒に減らしましたが、スリープ時間がそれ以上の場合 (例: 12000)、同じ例外が発生しました。
リボンの ConnectTimeout と Read-timeout と Hystrix のタイムアウト、およびアプリケーションでリボンのタイムアウトをテストする方法を理解したいです。また、マイクロサービスごとに異なるタイムアウトが必要な場合は、これらのプロパティをそれぞれの .yml ファイルに保持しますか? 何かご意見は?
開発者が Spring クラウドでこれらのタイムアウト オプションがどのように機能するかを簡単に理解できるように、チームで使用するドキュメントを作成しようとしています。
(説明が長くなりましたが、わかりやすくするために詳しく書きました)