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

posted @ 2023-12-24 20:41  一杯半盏  阅读(56)  评论(1编辑  收藏  举报