use of com.netflix.loadbalancer.reactive.ServerOperation 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 com.netflix.loadbalancer.reactive.ServerOperation in project incubator-servicecomb-java-chassis by apache.
the class LoadbalanceHandler method sendWithRetry.
private void sendWithRetry(Invocation invocation, AsyncResponse asyncResp, final LoadBalancer chosenLB) 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的场景,对于同步调用, 同步调用的主线程已经被挂起,无法再主线程中进行重试;
// 重试也不能在网络线程(event-loop)中进行,未被保护的阻塞操作会导致网络线程挂起
RETRY_POOL.submit(command);
}
};
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(chosenLB).withServerLocator(invocation).withRetryHandler(ExtensionsManager.createRetryHandler(invocation.getMicroserviceName())).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);
chosenLB.getLoadBalancerStats().incrementNumRequests(s);
// for retry
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);
chosenLB.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s);
((CseServer) s).incrementContinuousFailureCount();
f.onError(resp.getResult());
} else {
chosenLB.getLoadBalancerStats().incrementActiveRequestsCount(s);
((CseServer) s).clearContinuousFailure();
chosenLB.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 com.netflix.loadbalancer.reactive.ServerOperation in project ribbon by Netflix.
the class LoadBalancerCommandTest method testRetrySameServer.
@Test
public void testRetrySameServer() {
BaseLoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(list);
RetryHandler handler = new RetryHandler() {
@Override
public boolean isRetriableException(Throwable e, boolean sameServer) {
return (e instanceof IllegalArgumentException);
}
@Override
public boolean isCircuitTrippingException(Throwable e) {
return false;
}
@Override
public int getMaxRetriesOnSameServer() {
return 3;
}
@Override
public int getMaxRetriesOnNextServer() {
return 0;
}
};
LoadBalancerCommand<String> command = LoadBalancerCommand.<String>builder().withLoadBalancer(loadBalancer).withRetryHandler(handler).withServer(server1).build();
ServerOperation<String> operation = new ServerOperation<String>() {
AtomicInteger count = new AtomicInteger();
@Override
public Observable<String> call(final Server server) {
return Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> t1) {
if (count.incrementAndGet() < 3) {
t1.onError(new IllegalArgumentException());
} else {
t1.onNext(server.getHost());
t1.onCompleted();
}
}
});
}
};
String result = command.submit(operation).toBlocking().single();
assertEquals(3, loadBalancer.getLoadBalancerStats().getSingleServerStat(server1).getTotalRequestsCount());
assertEquals("1", result);
}
use of com.netflix.loadbalancer.reactive.ServerOperation in project ribbon by Netflix.
the class LoadBalancerCommandTest method testRetryNextServer.
@Test
public void testRetryNextServer() {
BaseLoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(list);
RetryHandler handler = new RetryHandler() {
@Override
public boolean isRetriableException(Throwable e, boolean sameServer) {
return (e instanceof IllegalArgumentException);
}
@Override
public boolean isCircuitTrippingException(Throwable e) {
return false;
}
@Override
public int getMaxRetriesOnSameServer() {
return 1;
}
@Override
public int getMaxRetriesOnNextServer() {
return 5;
}
};
ServerOperation<String> operation = new ServerOperation<String>() {
AtomicInteger count = new AtomicInteger();
@Override
public Observable<String> call(final Server server) {
return Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> t1) {
if (count.incrementAndGet() < 3) {
t1.onError(new IllegalArgumentException());
} else {
t1.onNext(server.getHost());
t1.onCompleted();
}
}
});
}
};
LoadBalancerCommand<String> command = LoadBalancerCommand.<String>builder().withLoadBalancer(loadBalancer).withRetryHandler(handler).build();
String result = command.submit(operation).toBlocking().single();
// server2 is picked first
assertEquals("3", result);
assertEquals(1, loadBalancer.getLoadBalancerStats().getSingleServerStat(server3).getTotalRequestsCount());
}
use of com.netflix.loadbalancer.reactive.ServerOperation in project ribbon by Netflix.
the class LoadBalancingHttpClient method requestToOperation.
/**
* Convert an HttpClientRequest to a ServerOperation
*
* @param request
* @param rxClientConfig
* @return
*/
protected ServerOperation<HttpClientResponse<O>> requestToOperation(final HttpClientRequest<I> request, final ClientConfig rxClientConfig) {
Preconditions.checkNotNull(request);
return new ServerOperation<HttpClientResponse<O>>() {
final AtomicInteger count = new AtomicInteger(0);
@Override
public Observable<HttpClientResponse<O>> call(Server server) {
HttpClient<I, O> rxClient = getOrCreateRxClient(server);
setHostHeader(request, server.getHost());
Observable<HttpClientResponse<O>> o;
if (rxClientConfig != null) {
o = rxClient.submit(request, rxClientConfig);
} else {
o = rxClient.submit(request);
}
return o.concatMap(new Func1<HttpClientResponse<O>, Observable<HttpClientResponse<O>>>() {
@Override
public Observable<HttpClientResponse<O>> call(HttpClientResponse<O> t1) {
if (t1.getStatus().code() / 100 == 4 || t1.getStatus().code() / 100 == 5)
return responseToErrorPolicy.call(t1, backoffStrategy.call(count.getAndIncrement()));
else
return Observable.just(t1);
}
});
}
};
}
Aggregations