use of io.servicecomb.core.AsyncResponse in project java-chassis by ServiceComb.
the class LoadbalanceHandler method sendWithRetry.
private void sendWithRetry(Invocation invocation, AsyncResponse asyncResp, final LoadBalancer choosenLB) throws Exception {
long time = System.currentTimeMillis();
// retry in loadbalance, 2.0 feature
final int currentHandler = invocation.getHandlerIndex();
final SyncResponseExecutor orginExecutor;
final Executor newExecutor;
if (invocation.getResponseExecutor() instanceof SyncResponseExecutor) {
orginExecutor = (SyncResponseExecutor) invocation.getResponseExecutor();
newExecutor = new Executor() {
@Override
public void execute(Runnable command) {
// retry的场景,对于同步调用, 需要在网络线程中进行。同步调用的主线程已经被挂起,无法再主线程中进行重试。
command.run();
}
};
invocation.setResponseExecutor(newExecutor);
} else {
orginExecutor = null;
newExecutor = null;
}
ExecutionListener<Invocation, Response> listener = new ExecutionListener<Invocation, Response>() {
@Override
public void onExecutionStart(ExecutionContext<Invocation> context) throws AbortExecutionException {
}
@Override
public void onStartWithServer(ExecutionContext<Invocation> context, ExecutionInfo info) throws AbortExecutionException {
}
@Override
public void onExceptionWithServer(ExecutionContext<Invocation> context, Throwable exception, ExecutionInfo info) {
LOGGER.error("onExceptionWithServer msg {}; server {}", exception.getMessage(), context.getRequest().getEndpoint());
}
@Override
public void onExecutionSuccess(ExecutionContext<Invocation> context, Response response, ExecutionInfo info) {
if (orginExecutor != null) {
orginExecutor.execute(() -> {
asyncResp.complete(response);
});
} else {
asyncResp.complete(response);
}
}
@Override
public void onExecutionFailed(ExecutionContext<Invocation> context, Throwable finalException, ExecutionInfo info) {
if (orginExecutor != null) {
orginExecutor.execute(() -> {
asyncResp.consumerFail(finalException);
});
} else {
asyncResp.consumerFail(finalException);
}
}
};
List<ExecutionListener<Invocation, Response>> listeners = new ArrayList<>(0);
listeners.add(listener);
ExecutionContext<Invocation> context = new ExecutionContext<>(invocation, null, null, null);
LoadBalancerCommand<Response> command = LoadBalancerCommand.<Response>builder().withLoadBalancer(choosenLB).withServerLocator(invocation).withRetryHandler(new DefaultLoadBalancerRetryHandler(Configuration.INSTANCE.getRetryOnSame(invocation.getMicroserviceName()), Configuration.INSTANCE.getRetryOnNext(invocation.getMicroserviceName()), true)).withListeners(listeners).withExecutionContext(context).build();
Observable<Response> observable = command.submit(new ServerOperation<Response>() {
public Observable<Response> call(Server s) {
return Observable.create(f -> {
try {
((CseServer) s).setLastVisitTime(time);
choosenLB.getLoadBalancerStats().incrementNumRequests(s);
invocation.setHandlerIndex(currentHandler);
invocation.setEndpoint(((CseServer) s).getEndpoint());
invocation.next(resp -> {
if (resp.isFailed()) {
LOGGER.error("service call error, msg is {}, server is {} ", ((Throwable) resp.getResult()).getMessage(), s);
choosenLB.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s);
f.onError(resp.getResult());
} else {
choosenLB.getLoadBalancerStats().incrementActiveRequestsCount(s);
choosenLB.getLoadBalancerStats().noteResponseTime(s, (System.currentTimeMillis() - time));
f.onNext(resp);
f.onCompleted();
}
});
} catch (Exception e) {
LOGGER.error("execution error, msg is " + e.getMessage());
f.onError(e);
}
});
}
});
observable.subscribe(response -> {
}, error -> {
}, () -> {
});
}
use of io.servicecomb.core.AsyncResponse in project java-chassis by ServiceComb.
the class TestLoadbalanceHandler method testLoadbalanceHandlerHandleWithSendWithRetry.
@Test
public void testLoadbalanceHandlerHandleWithSendWithRetry() throws Exception {
boolean status = true;
LoadbalanceHandler lh = new LoadbalanceHandler();
Invocation invocation = Mockito.mock(Invocation.class);
AsyncResponse asyncResp = Mockito.mock(AsyncResponse.class);
Mockito.when(invocation.getConfigTransportName()).thenReturn("baadshah");
Map<String, LoadBalancer> loadBalancerMap = new ConcurrentHashMap<String, LoadBalancer>();
loadBalancerMap.put("baadshah", lb);
try {
Deencapsulation.setField(lh, "loadBalancerMap", loadBalancerMap);
Deencapsulation.invoke(lh, "sendWithRetry", invocation, asyncResp, lb);
lh.handle(invocation, asyncResp);
} catch (Exception e) {
status = false;
}
Assert.assertTrue(status);
}
use of io.servicecomb.core.AsyncResponse in project java-chassis by ServiceComb.
the class TestLoadbalanceHandler method testLoadbalanceHandlerHandleWithLoadBalancerHandler.
@Test
public void testLoadbalanceHandlerHandleWithLoadBalancerHandler() throws Exception {
boolean status = true;
new MockUp<LoadbalanceHandler>() {
@Mock
private LoadBalancer createLoadBalancer(String appId, String microserviceName, String microserviceVersionRule, String transportName) {
return lb;
}
};
LoadbalanceHandler lh = new LoadbalanceHandler();
Invocation invocation = Mockito.mock(Invocation.class);
Mockito.when(invocation.getConfigTransportName()).thenReturn("baadshah");
Mockito.when(invocation.getMicroserviceVersionRule()).thenReturn("VERSION_RULE_LATEST");
AsyncResponse asyncResp = Mockito.mock(AsyncResponse.class);
Mockito.when(invocation.getMicroserviceName()).thenReturn("test");
new MockUp<Configuration>() {
@Mock
public boolean isRetryEnabled(String microservice) {
return true;
}
};
SyncResponseExecutor orginExecutor = new SyncResponseExecutor();
Mockito.when(invocation.getResponseExecutor()).thenReturn(orginExecutor);
List<ExecutionListener<Invocation, Response>> listeners = new ArrayList<>(0);
@SuppressWarnings("unchecked") ExecutionListener<Invocation, Response> listener = Mockito.mock(ExecutionListener.class);
ExecutionListener<Invocation, Response> e = null;
listeners.add(e);
listeners.add(listener);
try {
lh.handle(invocation, asyncResp);
} catch (Exception ex) {
status = false;
}
Assert.assertTrue(status);
}
use of io.servicecomb.core.AsyncResponse in project java-chassis by ServiceComb.
the class GrpcTransport method send.
@Override
public void send(Invocation invocation, AsyncResponse asyncResp) throws Exception {
HttpClientWithContext httpClientWithContext = clientMgr.findThreadBindClientPool();
OperationMeta operationMeta = invocation.getOperationMeta();
OperationProtobuf operationProtobuf = ProtobufManager.getOrCreateOperation(operationMeta);
String cseContext = JsonUtils.writeValueAsString(invocation.getContext());
// 在verticle之外的线程调用
IpPort ipPort = (IpPort) invocation.getEndpoint().getAddress();
Buffer requestBuf = GrpcCodec.encodeRequest(invocation, operationProtobuf);
String url = "/" + invocation.getSchemaId() + "/" + operationMeta.getOperationId();
Handler<HttpClientResponse> responseHandler = httpResponse -> {
httpResponse.bodyHandler(responseBuf -> {
invocation.getResponseExecutor().execute(() -> {
try {
Response response = GrpcCodec.decodeResponse(invocation, operationProtobuf, httpResponse, responseBuf);
ResponseMeta responseMeta = operationMeta.findResponseMeta(response.getStatusCode());
for (String headerName : responseMeta.getHeaders().keySet()) {
for (String value : httpResponse.headers().getAll(headerName)) {
response.getHeaders().addHeader(headerName, value);
}
}
asyncResp.complete(response);
} catch (Exception e) {
asyncResp.fail(invocation.getInvocationType(), e);
}
});
});
};
// 从业务线程转移到网络线程中去发送
httpClientWithContext.runOnContext(httpClient -> {
HttpClientRequest httpClientRequest = httpClient.post(ipPort.getPort(), ipPort.getHostOrIp(), url, responseHandler);
httpClientRequest.exceptionHandler(e -> {
asyncResp.fail(invocation.getInvocationType(), e);
});
httpClientRequest.setTimeout(AbstractTransport.getRequestTimeout());
httpClientRequest.putHeader(HEADER_CONTENT_TYPE, "application/grpc").putHeader(HEADER_TE, "trailers").putHeader(HEADER_USER_AGENT, "cse-client/1.0.0").putHeader(Const.CSE_CONTEXT, cseContext).putHeader(Const.DEST_MICROSERVICE, invocation.getMicroserviceName()).end(requestBuf);
});
}
use of io.servicecomb.core.AsyncResponse in project java-chassis by ServiceComb.
the class HighwayClient method send.
public void send(Invocation invocation, AsyncResponse asyncResp) throws Exception {
TcpClientPool tcpClientPool = clientMgr.findThreadBindClientPool();
OperationMeta operationMeta = invocation.getOperationMeta();
OperationProtobuf operationProtobuf = ProtobufManager.getOrCreateOperation(operationMeta);
TcpOutputStream os = HighwayCodec.encodeRequest(invocation, operationProtobuf);
tcpClientPool.send(invocation.getEndpoint().getEndpoint(), os, ar -> {
invocation.getResponseExecutor().execute(() -> {
if (ar.failed()) {
asyncResp.consumerFail(ar.cause());
return;
}
try {
Response response = HighwayCodec.decodeResponse(invocation, operationProtobuf, ar.result());
asyncResp.complete(response);
} catch (Throwable e) {
asyncResp.consumerFail(e);
}
});
});
}
Aggregations