package cn.java.dubbo.demo.internal;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.remoting.Channel;
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.exchange.ExchangeChannel;
import org.apache.dubbo.remoting.exchange.Request;
import org.apache.dubbo.rpc.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.function.Function;
/**
*/
@Slf4j
public class CompletableFutureTest {
public static void main(String[] args) {
(new Server()).doRun(args);
{
CompletableFutureInternal completableFutureInternal = new CompletableFutureInternal();
completableFutureInternal.doDemo0();
completableFutureInternal.doDemo1();
}
}
static class Server {
private static FooOneServiceImpl fooOneServiceImpl = new FooOneServiceImpl();
public void doRun(String[] args) {
HeaderExchangeHandler handler = new HeaderExchangeHandler();
try {
handler.received(null, null, fooOneServiceImpl.getClass().getMethod("sayHello", String.class));
} catch (java.lang.Exception ex) {
log.error("sayHello", ex);
}
try {
handler.received(null, null, fooOneServiceImpl.getClass().getMethod("doThrowRpcException", String.class));
} catch (java.lang.Exception ex) {
log.error("doThrowRpcException", ex);
}
try {
handler.received(null, null, fooOneServiceImpl.getClass().getMethod("doThrowException", String.class));
} catch (java.lang.Exception ex) {
log.error("doThrowException", ex);
}
}
static class HeaderExchangeHandler {
/**
* @see org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler#received(org.apache.dubbo.remoting.Channel, java.lang.Object)
*/
public void received(Channel channel, Object message, Method method) throws RemotingException {
Request request = (Request) message;
handleRequest(null, request, method);
}
/**
* @see org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler# handleRequest(org.apache.dubbo.remoting.exchange.ExchangeChannel, org.apache.dubbo.remoting.exchange.Request)
*/
void handleRequest(final ExchangeChannel channel, Request req, Method method) throws RemotingException {
// Response res = new Response(req.getId(), req.getVersion());
try {
// invoke dubboProtocol requestHandler
CompletableFuture<Object> future = reply(method);
future.whenComplete((appResult, ex) -> {
try {
if (ex == null) {
// res.setStatus(Response.OK);
// res.setResult(appResult);
log.info("appResult = {}", appResult); // 业务数据、业务方法抛出的异常
} else { // 框出现异常
// res.setStatus(Response.SERVICE_ERROR);
// res.setErrorMessage(StringUtils.toString(t));
log.error("error", ex);
}
// channel.send(res); // 发送数据到客户端
if (false) {
throw new RemotingException(null, "xxx");
}
} catch (RemotingException e) {
log.warn("Send result to consumer failed, channel is channel, msg is " + e);
} finally {
log.info("channel 发送数据 finally");
}
});
} catch (Throwable ex) {
String exStr = StringUtils.toString(ex);
log.error("handleRequest 调用 reply 出现异常, exStr = {}", exStr, ex);
// res.setStatus(Response.SERVICE_ERROR);
// res.setErrorMessage(StringUtils.toString(ex));
// channel.send(res); // 发送数据到客户端
}
}
}
/**
* @see org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol# requestHandler
*/
static CompletableFuture<Object> reply(Method method) {
AbstractProxyInvoker invoke = new AbstractProxyInvoker();
Result result = invoke.invoke(method);
return result.completionFuture().thenApply(Function.identity());
}
/**
* @see org.apache.dubbo.rpc.proxy.jdk.JdkProxyFactory#getInvoker(java.lang.Object, java.lang.Class, org.apache.dubbo.common.URL)
*/
static class AbstractProxyInvoker {
Invocation mockInvocation(Method method) {
RpcInvocation invocation = new RpcInvocation();
invocation.setMethodName(method.getName());
return invocation;
}
/**
* @see org.apache.dubbo.rpc.proxy.AbstractProxyInvoker#invoke(org.apache.dubbo.rpc.Invocation)
*/
public Result invoke(Method method) throws RpcException {
Invocation invocation = mockInvocation(method);
try {
Object value = doInvoke(method);
CompletableFuture<Object> future = wrapWithFuture(value, invocation); // Future 模式
AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
future.whenComplete((obj, ex) -> {
AppResponse result = new AppResponse();
if (ex != null) { // 存在异常
if (ex instanceof CompletionException) {
result.setException(ex.getCause());
} else {
result.setException(ex);
}
} else { // 无异常
result.setValue(obj);
}
asyncRpcResult.complete(result);
});
return asyncRpcResult;
} catch (InvocationTargetException e) { // 反射调用异常
if (RpcContext.getContext().isAsyncStarted() && !RpcContext.getContext().stopAsync()) {
log.error("Provider async started, but got an exception from the original method, cannot write the exception back to consumer because an async result may have returned the new thread.", e);
}
return AsyncRpcResult.newDefaultAsyncResult(null, e.getTargetException(), invocation); // 异常数据
} catch (Throwable e) { // 捕获取服务端的《所有异常》
throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to xxx, cause: " + e.getMessage(), e);
}
}
protected Object doInvoke(Method method) throws Throwable {
return method.invoke(fooOneServiceImpl, "");
}
private CompletableFuture<Object> wrapWithFuture(Object value, Invocation invocation) {
if (RpcContext.getContext().isAsyncStarted()) {
return ((AsyncContextImpl) (RpcContext.getContext().getAsyncContext())).getInternalFuture();
} else if (value instanceof CompletableFuture) {
return (CompletableFuture<Object>) value;
}
return CompletableFuture.completedFuture(value);
}
}
}
static class FooOneServiceImpl {
public String sayHello(String name) {
return "hi, " + name;
}
public String doThrowRpcException(String name) throws RpcException {
throw new RpcException(RpcException.BIZ_EXCEPTION, "user is not login.");
}
public String doThrowException(String name) throws java.lang.Exception {
throw new java.lang.Exception("user is not login.");
}
}
static class CompletableFutureInternal {
private AsyncRpcResult getAsyncRpcResult() {
RpcInvocation invocation = new RpcInvocation();
invocation.setMethodName("method0");
AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
return asyncRpcResult;
}
public void doDemo0() {
// 异步结果
AsyncRpcResult asyncRpcResult = getAsyncRpcResult();
// 调用方法
{
Object value = "this is result.";
CompletableFuture<Object> future = CompletableFuture.completedFuture(value);
future.whenComplete((obj, ex) -> {
AppResponse result = new AppResponse();
if (ex != null) { // 存在异常
if (ex instanceof CompletionException) {
result.setException(ex.getCause());
} else {
result.setException(ex);
}
} else { // 无异常
result.setValue(obj);
}
asyncRpcResult.complete(result);
});
}
// 处理异步执行结果
{
CompletableFuture<Object> future = asyncRpcResult.completionFuture().thenApply(Function.identity());
future.whenComplete((appResult, ex) -> {
if (ex == null) {
log.info("appResult = {}", appResult); // 业务数据、业务方法抛出的异常
} else { // 框出现异常
log.error("error", ex);
}
// channel.send(res); // 发送数据到客户端
});
}
}
public void doDemo1() {
doDemo1Common("complete");
doDemo1Common("completeExceptionally");
}
private void doDemo1Common(Object value) {
CompletableFuture asyncRpcResult = new CompletableFuture();
{
CompletableFuture<Object> future = CompletableFuture.completedFuture(value);
future.whenComplete((obj, ex) -> {
if ("completeExceptionally".equals(value)) {
asyncRpcResult.completeExceptionally(new Exception("throw exception for " + value));
} else {
asyncRpcResult.complete(obj);
}
});
}
{
asyncRpcResult.whenComplete((appResult, ex) -> {
if (ex == null) {
log.info("appResult = {}", appResult); // 业务数据、业务方法抛出的异常
} else { // 框出现异常
log.error("happen exception", ex);
}
// channel.send(res); // 发送数据到客户端
});
}
}
}
}