APISIX dubbo-proxy 实战
APISIX
APISIX 声称支持 Dubbo Proxy
实践
主要是 APISIX 官方网站上的这篇博客写的问题很大。
博客上写的 HTTP2DubboService 实现类
@Component
public class HTTP2DubboServiceImpl implements HTTP2DubboService {
@Autowired
private ApplicationContext appContext;
@Override
public Map<String, Object> invoke(Map<String, Object> context) throws Exception {
DubboInvocation invocation = JSONObject.parseObject((byte[]) context.get("body"), DubboInvocation.class);
Object[] args = new Object[invocation.getParameters().size()];
for (int i = 0; i < args.length; i++) {
DubboInvocationParameter parameter = invocation.getParameters().get(i);
args[i] = JSONObject.parseObject(parameter.getValue(), Class.forName(parameter.getType()));
}
Object svc = appContext.getBean(Class.forName(invocation.getService()));
Object result = svc.getClass().getMethod(invocation.getMethod()).invoke(args);
Map<String, Object> httpResponse = new HashMap<>();
httpResponse.put("status", 200);
httpResponse.put("body", JSONObject.toJSONString(result));
return httpResponse;
}
}
槽点1
首先名字就很让人误解:HTTP2Dubbo,其实这个根本不是HTTP协议。这个是 Tengine 提供的 mod_dubbo 实现的功能,openresty/tengine 接收的是 HTTP数据报文,但是对于应用程序提供者,仍然不是HTTP协议。
本质上,要让 APISIX 的 Dubbo Proxy 能调用成功,还是有很多前提条件的。
槽点2
官方给的 Demo 没问题,但是没有强调这点:入参和出参只支持 Map<String, Object> ,否则500 Bad Gateway。
槽点3
上述程序,作用是将统一的参数转换成反射调用,调用实际方法,但是这能跑的通?
-
如果参数类型为 com.slankka.service.dubbo.ISampleService.getData(java.lang.Long, java.lang.String)。
这样会导致 JSONObject.parseObject("string value", String.class), 这样无论是 fastjson,fastjson2还是 jackson 都是会失败的。 -
反射是这样用的吗?
svc.getClass().getMethod(invocation.getMethod()).invoke(args);
实际上应该是这样用的
Class<?>[] = ...
parameterTypes[i] = Class.forName(parameter.getType())
svc.getClass().getMethod(invocation.getMethod(), parameterTypes).invoke(svc, args);
槽点4
apisix的 nginx 返回值,Content-Type 是 text/plain; 这样岂不是要了 OpenFeign 的命!Spring Cloud OpenFeign,RestTemplate, Spring HttpMessageConverter 全部反对!
HTTP/1.1 200 OK
Date: Sun, 24 Dec 2023 12:16:29 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 178
Connection: keep-alive
Server: APISIX/3.2.1
实际情况可能因apisix自己编译 mod_dubbo 的实现有关
解决办法是 设置HTTP Response Header
Map<String, Object> httpResponse = new HashMap<>();
httpResponse.put("status", 200);
httpResponse.put("Content-Type", "application/json; charset=utf-8");
httpResponse.put("body", JSONObject.toJSONString(result));
槽点5
Dubbo-proxy 插件的 service_version 不支持 1.0
,只支持\d+.\d+.\d+
如果是 1.0
则报错:
failed to check the configuration of plugin dubbo-proxy err: property "service_version" validation failed: failed to match pattern "^\\d+\\.\\d+\\.\\d+" with "1.0"
参考文档
Tengine: Dubbo Example
APISIX dubbo-proxy
实测Tengine开源的Dubbo功能
通过网关将 http 流量接入 Dubbo 后端服务
让你在 Apache APISIX 中代理 Dubbo 服务更便捷
Tengine Header Response Content-Type
github.com/api7/mod_dubbo
github.com/api7/apisix-build-tools