更新時間:2022-03-18 12:04:45 來源:動力節點 瀏覽1681次
通用接口調用方式主要用于沒有API接口和模型類元素的客戶端,所有...中的參數和返回值POJO都使用Map Express。使用泛化調用時,服務提供者應用沒有特殊操作,服務消費者應用不再需要引入服務提供者 SDK 兩方包。
適用于 API Gateway 服務、框架集成等場景,提供一個 Dubbo 統一的服務管理平臺,讓所有消費者調用統一管理平臺中注冊的服務,無需引入 SDK 雙方庫。
public interface GreetingService {
String sayHello(String name);
}
/**
* adopt API The method uses generalization to call
*/
@Test
public void test() {
// Application configuration
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("dubbo-consumer");?
// Registry configuration
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("zookeeper://127.0.0.1:2181");?
// Reference remote service
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
reference.setApplication(applicationConfig);
reference.setRegistry(registryConfig);
reference.setInterface("com.xxx.GreetingService");
reference.setGeneric(true);?
// obtain GenericService, Instead of
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
GenericService genericService = cache.get(reference);?
// Call the service
String[] parameterTypes = new String[] { "java.lang.String" };
Object[] args = Stream.of("xiaoming").toArray();
Object result = genericService.$invoke("sayHello", parameterTypes, args);
System.out.println("result = " + result);
}
服務消費者
在 dubbo 的責任鏈中,GenericImplFilter 會攔截泛化調用,檢查參數,并發起 RPC 調用。
org.apache.dubbo.rpc.filter.GenericImplFilter#invoke
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
String generic = invoker.getUrl().getParameter(Constants.GENERIC_KEY);
// Determine whether it is a generalization call
if (invocation.getMethodName().equals(Constants.$INVOKE)
&& invocation.getArguments() != null
&& invocation.getArguments().length == 3
&& ProtocolUtils.isGeneric(generic)) {
// Call parameters
Object[] args = (Object[]) invocation.getArguments()[2];
if (ProtocolUtils.isJavaGenericSerialization(generic)) {
for (Object arg : args) {
if (!(byte[].class == arg.getClass())) {
error(generic, byte[].class.getName(), arg.getClass().getName());
}
}
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
for (Object arg : args) {
if (!(arg instanceof JavaBeanDescriptor)) {
error(generic, JavaBeanDescriptor.class.getName(), arg.getClass().getName());
}
}
}
// Pass generic call mode parameters , So that the service provider can analyze the request parameters and other data
((RpcInvocation) invocation).setAttachment(
Constants.GENERIC_KEY, invoker.getUrl().getParameter(Constants.GENERIC_KEY));
}
// launch RPC call
return invoker.invoke(invocation);
}
服務提供者
服務提供者使用GenericFilter攔截請求,反序列化并解析泛化參數,將請求轉發給具體的服務提供者實現類對象進行業務執行。
org.apache.dubbo.rpc.filter.GenericFilter#invoke
@Override
public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
// Generalization call
if (inv.getMethodName().equals(Constants.$INVOKE)
&& inv.getArguments() != null
&& inv.getArguments().length == 3
&& !GenericService.class.isAssignableFrom(invoker.getInterface())) {
// parameter information
String name = ((String) inv.getArguments()[0]).trim();
String[] types = (String[]) inv.getArguments()[1];
Object[] args = (Object[]) inv.getArguments()[2];
try {
// Get call method
Method method = ReflectUtils.findMethodByMethodSignature(invoker.getInterface(), name, types);
Class<?>[] params = method.getParameterTypes();
if (args == null) {
args = new Object[params.length];
}
String generic = inv.getAttachment(Constants.GENERIC_KEY);
?
if (StringUtils.isBlank(generic)) {
generic = RpcContext.getContext().getAttachment(Constants.GENERIC_KEY);
}?
// The generalized type is null , Use the default deserialization method
if (StringUtils.isEmpty(generic)
|| ProtocolUtils.isDefaultGenericSerialization(generic)) {
args = PojoUtils.realize(args, params, method.getGenericParameterTypes());
// nativejava Deserialization method
} else if (ProtocolUtils.isJavaGenericSerialization(generic)) {
for (int i = 0; i < args.length; i++) {
if (byte[].class == args[i].getClass()) {
try(UnsafeByteArrayInputStream is = new UnsafeByteArrayInputStream((byte[]) args[i])) {
args[i] = ExtensionLoader.getExtensionLoader(Serialization.class)
.getExtension(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA)
.deserialize(null, is).readObject();
} catch (Exception e) {
throw new RpcException("Deserialize argument [" + (i + 1) + "] failed.", e);
}
} else {
throw new RpcException(...);
}
}
// bean Deserialization method
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof JavaBeanDescriptor) {
args[i] = JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) args[i]);
} else {
throw new RpcException(...));
}
}
}
// Perform specific services
Result result = invoker.invoke(new RpcInvocation(method, args, inv.getAttachments()));
if (result.hasException()
&& !(result.getException() instanceof GenericException)) {
return new RpcResult(new GenericException(result.getException()));
}
// Serialize the result and return
if (ProtocolUtils.isJavaGenericSerialization(generic)) {
try {
UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream(512);
ExtensionLoader.getExtensionLoader(Serialization.class)
.getExtension(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA)
.serialize(null, os).writeObject(result.getValue());
return new RpcResult(os.toByteArray());
} catch (IOException e) {
throw new RpcException("Serialize result failed.", e);
}
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
return new RpcResult(JavaBeanSerializeUtil.serialize(result.getValue(), JavaBeanAccessor.METHOD));
} else {
return new RpcResult(PojoUtils.generalize(result.getValue()));
}
} catch (NoSuchMethodException e) {
throw new RpcException(e.getMessage(), e);
} catch (ClassNotFoundException e) {
throw new RpcException(e.getMessage(), e);
}
}
// Non generalized call , Pass the request to the next filter
return invoker.invoke(inv);
}
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習