use of rpc.turbo.param.MethodParam in project turbo-rpc by hank-whu.
the class RemoteServiceFactory method generateRemoteObject.
private Object generateRemoteObject(App app, Class<?> clazz, Collection<MethodConfig> configs) throws Exception {
if (app == null) {
throw new RuntimeException("app must not be null");
}
if (clazz == null) {
throw new RuntimeException("clazz must not be null");
}
if (configs == null || configs.isEmpty()) {
throw new RuntimeException("configs must not be empty");
}
for (MethodConfig config : configs) {
if (config == null) {
throw new RuntimeException("config must not be null");
}
if (config.method == null) {
throw new RuntimeException("config.method must not be null");
}
if (config.timeout < 1) {
throw new RuntimeException("config.timeout must > 0");
}
if (config.timeout > 5 * 60 * 1000) {
throw new RuntimeException("config.timeout must < 5 * 60 * 1000 (5 mintues)");
}
}
Method[] allMethods = clazz.getMethods();
List<Method> allPublicMethods = //
Stream.of(//
allMethods).filter(//
m -> Modifier.isPublic(m.getModifiers())).filter(//
m -> !Modifier.isStatic(m.getModifiers())).peek(m -> {
if (!CompletableFuture.class.equals(m.getReturnType())) {
throw new RuntimeException("method return-type must be CompletableFuture, " + InvokerUtils.getServiceMethodName("", "", m));
}
}).collect(Collectors.toList());
if (configs.size() != allPublicMethods.size()) {
throw new RuntimeException("configs must contains all the interface's methods");
}
for (Method method : allMethods) {
if (!CompletableFuture.class.equals(method.getReturnType())) {
throw new RuntimeException("method return-type must be CompletableFuture, " + method);
}
if (!configs.stream().anyMatch(config -> config.method.equals(method))) {
throw new RuntimeException("configs must contains the method: " + method);
}
}
final String remoteClassName = //
clazz.getName() + "_RemoteService_" + UUID.randomUUID().toString().replace("-", "");
// 创建类
ClassPool pool = ClassPool.getDefault();
CtClass remoteCtClass = pool.makeClass(remoteClassName);
CtClass[] interfaces = { pool.getCtClass(clazz.getName()), pool.getCtClass(RemoteInterface.class.getName()) };
remoteCtClass.setInterfaces(interfaces);
// 添加私有成员app
CtField appField = new CtField(pool.get(App.class.getName()), "app", remoteCtClass);
appField.setModifiers(Modifier.PRIVATE | Modifier.FINAL);
remoteCtClass.addField(appField);
// 添加get方法
remoteCtClass.addMethod(CtNewMethod.getter("getApp", appField));
// 添加有参的构造函数
CtConstructor constructor1 = new CtConstructor(new CtClass[] { pool.get(App.class.getName()) }, remoteCtClass);
constructor1.setBody("{$0.app = $1;}");
remoteCtClass.addConstructor(constructor1);
for (MethodConfig config : configs) {
Method method = config.method;
Class<? extends MethodParam> methodParamClass = MethodParamClassFactory.createClass(method);
long timeout = config.timeout;
// 添加私有成员failoverInvoker
String failoverFieldName = getFailoverInvokerFieldName(app, method);
CtField failoverField = new CtField(pool.get(Invoker.class.getName()), failoverFieldName, remoteCtClass);
appField.setModifiers(Modifier.PRIVATE);
remoteCtClass.addField(failoverField);
StringBuilder methodBuilder = new StringBuilder();
methodBuilder.append("public ");
methodBuilder.append(method.getReturnType().getName());
methodBuilder.append(" ");
methodBuilder.append(method.getName());
methodBuilder.append("(");
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
Class<?> parameterType = parameterTypes[i];
methodBuilder.append(parameterType.getName());
methodBuilder.append(" param");
methodBuilder.append(i);
if (i != parameterTypes.length - 1) {
methodBuilder.append(", ");
}
}
methodBuilder.append("){\r\n");
methodBuilder.append(" return ");
if (config.ignore) {
if (logger.isInfoEnabled()) {
logger.info(InvokerUtils.getServiceMethodName(app.group, app.app, config.method) + " ignore");
}
methodBuilder.append("$remote_ignore()");
} else {
if (logger.isInfoEnabled()) {
logger.info(//
InvokerUtils.getServiceMethodName(app.group, app.app, config.method) + " register, config:" + config);
}
methodBuilder.append("$remote_execute(");
methodBuilder.append(app.getMethodId(method));
methodBuilder.append(", ");
methodBuilder.append(timeout);
methodBuilder.append("L, ");
methodBuilder.append("new ");
methodBuilder.append(methodParamClass.getName());
methodBuilder.append("(");
for (int i = 0; i < parameterTypes.length; i++) {
methodBuilder.append("param");
methodBuilder.append(i);
if (i != parameterTypes.length - 1) {
methodBuilder.append(",");
}
}
methodBuilder.append("), ");
methodBuilder.append(failoverFieldName);
methodBuilder.append(")");
}
methodBuilder.append(";\r\n}");
CtMethod m = CtNewMethod.make(methodBuilder.toString(), remoteCtClass);
remoteCtClass.addMethod(m);
}
Class<?> invokerClass = remoteCtClass.toClass();
return invokerClass.getConstructor(App.class).newInstance(app);
}
use of rpc.turbo.param.MethodParam in project turbo-rpc by hank-whu.
the class JavassistInvoker method generateRealInvoker.
private Invoker<T> generateRealInvoker() throws Exception {
final String invokerClassName = //
"rpc.turbo.invoke.generate.Invoker_" + serviceId + //
"_" + UUID.randomUUID().toString().replace("-", "");
// 创建类
ClassPool pool = ClassPool.getDefault();
CtClass invokerCtClass = pool.makeClass(invokerClassName);
invokerCtClass.setInterfaces(new CtClass[] { pool.getCtClass(Invoker.class.getName()) });
// 添加私有成员service
CtField serviceField = new CtField(pool.get(service.getClass().getName()), "service", invokerCtClass);
serviceField.setModifiers(Modifier.PRIVATE | Modifier.FINAL);
invokerCtClass.addField(serviceField);
// 添加有参的构造函数
CtConstructor constructor = new CtConstructor(new CtClass[] { pool.get(service.getClass().getName()) }, invokerCtClass);
constructor.setBody("{$0.service = $1;}");
invokerCtClass.addConstructor(constructor);
{
// 添加MethodParam方法
StringBuilder methodBuilder = new StringBuilder();
StringBuilder resultBuilder = new StringBuilder();
methodBuilder.append("public Object invoke(rpc.turbo.param.MethodParam methodParam) {\r\n");
if (parameterTypes.length > 0) {
// 强制类型转换
methodBuilder.append(methodParamClass.getName());
methodBuilder.append(" params = (");
methodBuilder.append(methodParamClass.getName());
methodBuilder.append(")methodParam;");
}
methodBuilder.append(" return ");
resultBuilder.append("service.");
resultBuilder.append(method.getName());
resultBuilder.append("(");
for (int i = 0; i < parameterTypes.length; i++) {
resultBuilder.append("params.$param");
resultBuilder.append(i);
resultBuilder.append("()");
if (i != parameterTypes.length - 1) {
methodBuilder.append(", ");
}
}
resultBuilder.append(")");
String resultStr = box(method.getReturnType(), resultBuilder.toString());
methodBuilder.append(resultStr);
methodBuilder.append(";\r\n}");
CtMethod m = CtNewMethod.make(methodBuilder.toString(), invokerCtClass);
invokerCtClass.addMethod(m);
}
{
// 添加通用方法
StringBuilder methodBuilder = new StringBuilder();
StringBuilder resultBuilder = new StringBuilder();
methodBuilder.append("public Object invoke(Object[] params) {\r\n");
methodBuilder.append(" return ");
resultBuilder.append("service.");
resultBuilder.append(method.getName());
resultBuilder.append("(");
for (int i = 0; i < parameterTypes.length; i++) {
Class<?> paramType = parameterTypes[i];
resultBuilder.append("((");
resultBuilder.append(forceCast(paramType));
resultBuilder.append(")params[");
resultBuilder.append(i);
resultBuilder.append("])");
resultBuilder.append(unbox(paramType));
}
resultBuilder.append(")");
String resultStr = box(method.getReturnType(), resultBuilder.toString());
methodBuilder.append(resultStr);
methodBuilder.append(";\r\n}");
CtMethod m = CtNewMethod.make(methodBuilder.toString(), invokerCtClass);
invokerCtClass.addMethod(m);
}
if (parameterCount <= 6) {
// just for benchmark
StringBuilder methodBuilder = new StringBuilder();
StringBuilder resultBuilder = new StringBuilder();
methodBuilder.append("public Object invoke(");
String params = //
IntStream.range(0, //
parameterCount).mapToObj(//
i -> "Object param" + i).collect(Collectors.joining(","));
methodBuilder.append(params);
methodBuilder.append(") {\r\n");
methodBuilder.append(" return ");
resultBuilder.append("service.");
resultBuilder.append(method.getName());
resultBuilder.append("(");
for (int i = 0; i < parameterCount; i++) {
Class<?> paramType = parameterTypes[i];
resultBuilder.append("((");
resultBuilder.append(forceCast(paramType));
resultBuilder.append(")param");
resultBuilder.append(i);
resultBuilder.append(")");
resultBuilder.append(unbox(paramType));
if (i != parameterCount - 1) {
resultBuilder.append(",");
}
}
resultBuilder.append(")");
String resultStr = box(method.getReturnType(), resultBuilder.toString());
methodBuilder.append(resultStr);
methodBuilder.append(";\r\n}");
CtMethod m = CtNewMethod.make(methodBuilder.toString(), invokerCtClass);
invokerCtClass.addMethod(m);
}
Class<?> invokerClass = invokerCtClass.toClass();
// 通过反射创建有参的实例
@SuppressWarnings("unchecked") Invoker<T> invoker = (Invoker<T>) invokerClass.getConstructor(service.getClass()).newInstance(service);
return invoker;
}
use of rpc.turbo.param.MethodParam in project turbo-rpc by hank-whu.
the class KryoSerializer method readRequest.
public Request readRequest(ByteBuf byteBuf) throws IOException {
int requestId = byteBuf.readInt();
int serviceId = ByteBufUtils.readVarInt(byteBuf);
Tracer tracer = tracerSerializer.read(byteBuf);
MethodParam methodParam = null;
if (byteBuf.readBoolean()) {
Class<?> clazz = getClass(serviceId);
methodParam = (MethodParam) kryoContext().readObject(byteBuf, clazz);
}
Request request = RecycleRequest.newInstance(requestId, serviceId, tracer, methodParam);
return request;
}
use of rpc.turbo.param.MethodParam in project turbo-rpc by hank-whu.
the class NettyRestHandler method channelRead0.
@Override
protected void channelRead0(ChannelHandlerContext ctx, final FullHttpRequest httpRequest) throws Exception {
boolean keepAlive = HttpUtil.isKeepAlive(httpRequest);
String uri = httpRequest.uri();
HttpMethod httpMethod = httpRequest.method();
int index = uri.indexOf('&', invokerFactory.restPrefix.length());
if (index < 0) {
index = uri.length();
}
if (invokerFactory.restPrefix.length() >= index) {
if (logger.isInfoEnabled()) {
logger.info("not support this method " + toString(httpRequest));
}
doRequestFilter(httpRequest, null);
ctx.write(new RestHttpResponse(null, httpRequest, NOT_FOUND, NOT_SUPPORT_THIS_METHOD, keepAlive), ctx.voidPromise());
return;
}
String restPath = uri.substring(invokerFactory.restPrefix.length(), index);
final Invoker<CompletableFuture<?>> invoker = invokerFactory.get(restPath);
CompletableFuture<?> future = null;
try {
if (invoker == null) {
if (logger.isInfoEnabled()) {
logger.info("not support this method " + toString(httpRequest));
}
doRequestFilter(httpRequest, null);
ctx.write(new RestHttpResponse(null, httpRequest, NOT_FOUND, NOT_SUPPORT_THIS_METHOD, keepAlive), ctx.voidPromise());
return;
}
boolean allowHandle = doRequestFilter(httpRequest, invoker);
if (!allowHandle) {
ctx.write(new RestHttpResponse(invoker, httpRequest, SERVICE_UNAVAILABLE, RestServerFilter.SERVER_FILTER_DENY, keepAlive), ctx.voidPromise());
return;
}
Object params = null;
if (httpMethod == HttpMethod.GET) {
params = HttpParamExtractor.extractFromQueryPath(invoker, uri, index);
} else if (httpMethod == HttpMethod.POST) {
params = HttpParamExtractor.extractFromBody(invoker, jsonMapper, httpRequest.content());
} else {
if (logger.isInfoEnabled()) {
logger.info("only support get and post " + toString(httpRequest));
}
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, ONLY_SUPPORT_GET_POST, keepAlive), ctx.voidPromise());
return;
}
if (params == null) {
future = invoker.invoke();
} else if (params instanceof MethodParam) {
future = invoker.invoke((MethodParam) params);
} else if (params instanceof Object[]) {
future = invoker.invoke((Object[]) params);
} else {
future = invoker.invoke((Object) params);
}
} catch (Throwable e) {
if (logger.isWarnEnabled()) {
logger.warn(uri + " error ", e);
}
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, e, keepAlive), ctx.voidPromise());
return;
}
if (future == null) {
if (logger.isWarnEnabled()) {
logger.warn("unknown error " + toString(httpRequest));
}
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, UNKNOWN, keepAlive), ctx.voidPromise());
return;
}
future.whenComplete((result, throwable) -> {
if (result != null) {
ctx.write(new RestHttpResponse(invoker, httpRequest, OK, result, keepAlive), ctx.voidPromise());
} else if (throwable != null) {
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, throwable, keepAlive), ctx.voidPromise());
} else {
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, UNKNOWN, keepAlive), ctx.voidPromise());
}
});
}
use of rpc.turbo.param.MethodParam in project turbo-rpc by hank-whu.
the class ProtostuffSerializer method readRequest.
public Request readRequest(ByteBuf byteBuf) throws IOException {
int requestId = byteBuf.readInt();
int serviceId = ByteBufUtils.readVarInt(byteBuf);
Tracer tracer = tracerSerializer.read(byteBuf);
Schema<MethodParam> schema = schema(serviceId);
MethodParam methodParam = null;
if (EmptyMethodParam.class.equals(schema.typeClass())) {
methodParam = EmptyMethodParam.empty();
} else {
ByteBufInput input = getOrUpdate(INPUT_ATTACHMENT_INDEX, INPUT_SUPPLIER);
input.setByteBuf(byteBuf, true);
methodParam = schema.newMessage();
schema.mergeFrom(input, methodParam);
}
Request request = RecycleRequest.newInstance(requestId, serviceId, tracer, methodParam);
return request;
}
Aggregations