乐趣区

关于后端:从原理到操作让你在-APISIX-中代理-Dubbo-服务更便捷

背景

Apache Dubbo 是由阿里巴巴开源并捐献给 Apache 的微服务开发框架,它提供了 RPC 通信 微服务治理 两大要害能力。不仅通过了阿里电商场景中海量流量的验证,也在国内的技术公司中被宽泛落地。

在理论利用场景中,Apache Dubbo 个别会作为后端系统间 RPC 调用的实现框架,当须要提供 HTTP 接口给到前端时,会通过一个「胶水层」将 Dubbo Service 包装成 HTTP 接口,再交付到前端零碎。

Apache APISIX 是 Apache 软件基金会的顶级开源我的项目,也是以后最沉闷的开源网关我的项目。作为一个动静、实时、高性能的开源 API 网关,Apache APISIX 提供了负载平衡、动静上游、灰度公布、服务熔断、身份认证、可观测性等丰盛的流量治理性能。

得益于 Apache Dubbo 的利用场景劣势,Apache APISIX 基于开源我的项目 tengine/mod_dubbo 模块为 Apache Dubbo 服务装备了 HTTP 网关能力。通过 dubbo-proxy 插件,能够轻松地将 Dubbo Service 公布为 HTTP 服务。

如何应用

入门篇:装置应用

这里咱们倡议应用 Apache APISIX 2.11 版本镜像进行装置。该版本的 APISIX-Base 中已默认编译了 Dubbo 模块,可间接应用 dubbo-proxy 插件。

在接下来的操作中,咱们将应用dubbo-samples 我的项目进行局部展现。该我的项目是一些应用 Apache Dubbo 实现的 Demo 利用,本文中咱们采纳其中的一个子模块作为 Dubbo Provider。

在进入正式操作前,咱们先简略看下 Dubbo 接口的定义、配置以及相干实现。

接口实现一览

public interface DemoService {



    /**

     * standard samples dubbo infterace demo

     * @param context pass http infos

     * @return Map<String, Object></> pass to response http

     **/

    Map<String, Object> apisixDubbo(Map<String, Object> httpRequestContext);

}

如上所示,Dubbo 接口的定义是固定的。即办法参数中 Map 示意 APISIX 传递给 Dubbo Provider 对于 HTTP request 的一些信息(如:header、body…)。而办法返回值的 Map 示意 Dubbo Provider 传递给 APISIX 要如何返回 HTTP response 的一些信息。

接口信息之后可通过 XML 配置形式公布 DemoService。

 <!-- service implementation, as same as regular local bean -->

<bean id="demoService" class="org.apache.dubbo.samples.provider.DemoServiceImpl"/>



 <!-- declare the service interface to be exported -->

<dubbo:service interface="org.apache.dubbo.samples.apisix.DemoService" ref="demoService"/>

通过上述配置后,Consumer 可通过 org`.apache.dubbo.samples.apisix.DemoService 拜访其中的 apisix`Dubbo 办法。具体接口实现如下:

public class DemoServiceImpl implements DemoService {

    @Override

    public Map<String, Object> apisixDubbo(Map<String, Object> httpRequestContext) {for (Map.Entry<String, Object> entry : httpRequestContext.entrySet()) {System.out.println("Key =" + entry.getKey() + ", Value =" + entry.getValue());

        }



        Map<String, Object> ret = new HashMap<String, Object>();

        ret.put("body", "dubbo success\n"); // http response body

        ret.put("status", "200"); // http response status

        ret.put("test", "123"); // http response header



        return ret;

    }

}

上述代码中,DemoServiceImpl 会打印接管到的 httpRequestContext,并通过返回蕴含有指定 Key 的 Map 对象去形容该 Dubbo 申请的 HTTP 响应。

操作步骤

  1. 启动 dubbo-samples 我的项目。
  2. config.yaml 文件中进行 dubbo-proxy 插件启用。
# Add this in config.yaml

plugins:

  - ... # plugin you need

  - dubbo-proxy
  1. 创立指向 Dubbo Provider 的 Upstream。
curl http://127.0.0.1:9180/apisix/admin/upstreams/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{"nodes": {"127.0.0.1:20880": 1},

    "type": "roundrobin"

}'
  1. 为 DemoService 裸露一个 HTTP 路由。
curl http://127.0.0.1:9180/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '{"host":"example.org""uris": ["/demo"],

    "plugins": {

        "dubbo-proxy": {

            "service_name": "org.apache.dubbo.samples.apisix.DemoService",

            "service_version": "0.0.0",

            "method": "apisixDubbo"

        }

    },

    "upstream_id": 1

}'
  1. 应用 curl 命令申请 Apache APISIX,并查看返回后果。
curl http://127.0.0.1:9080/demo  -H "Host: example.org"  -X POST --data '{"name":"hello"}'



< HTTP/1.1 200 OK

< Date: Sun, 26 Dec 2021 11:33:27 GMT

< Content-Type: text/plain; charset=utf-8

< Content-Length: 14

< Connection: keep-alive

< test: 123

< Server: APISIX/2.11.0

<

dubbo success

上述代码返回中蕴含了test: 123 Header,以及 dubbo success 字符串作为 Body 体。这与咱们在 DemoServiceImpl 编码的预期成果统一。

  1. 查看 Dubbo Provider 的日志。
Key = content-length, Value = 17

Key = host, Value = example.org

Key = content-type, Value = application/x-www-form-urlencoded

Key = body, Value = [B@70754265

Key = accept, Value = */*

Key = user-agent, Value = curl/7.80.0

通过 httpRequestContext 能够拿到 HTTP 申请的 Header 和 Body。其中 Header 会作为 Map 元素,而 Body 中 Key 值是固定的字符串 ”body”,Value 则代表 Byte 数组。

进阶篇:简单场景示例

在上述的简略用例中能够看出,咱们的确通过 Apache APISIX 将 Dubbo Service 公布为一个 HTTP 服务,然而在应用过程中的限度也非常明显。比方:接口的参数和返回值都必须要是 Map<String, Object>

那么,如果我的项目中呈现曾经定义好、但又不合乎上述限度的接口,该如何通过 Apache APISIX 来裸露 HTTP 服务呢?

操作步骤

针对上述场景,咱们能够通过 HTTP Request Body 形容要调用的 Service 和 Method 以及对应参数,再利用 Java 的反射机制实现目标办法的调用。最初将返回值序列化为 JSON,并写入到 HTTP Response Body 中。

这样就能够将 Apache APISIX 的 「HTTP to Dubbo」 能力进一步增强,并利用到所有已存在的 Dubbo Service 中。具体操作可参考下方:

  1. 为已有我的项目减少一个 Dubbo Service 用来对立解决 HTTP to Dubbo 的转化。
public class DubboInvocationParameter {

    private String type;

    private String value;

}



public class DubboInvocation {

    private String service;

    private String method;

    private DubboInvocationParameter[] parameters;}



public interface HTTP2DubboService {Map<String, Object> invoke(Map<String, Object> context)  throws Exception;

}





@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. 通过如下命令申请来发动相干调用。
curl http://127.0.0.1:9080/demo  -H "Host: example.org"  -X POST --data '{"service":"org.apache.dubbo.samples.apisix.DemoService","method":"createUser","parameters": [

        {

            "type": "org.apache.dubbo.samples.apisix.User",

            "value": "{'name':'hello'}"

        }

    ]

}'

总结

本文为大家介绍了如何借助 Apache APISIX 实现 Dubbo Service 的代理,通过引入 dubbo-proxy 插件便可为 Dubbo 框架的后端系统构建更简略更高效的流量链路。

心愿通过上述操作步骤和用例场景分享,能为大家在相干场景的应用提供借鉴思路。更多对于 dubbo-proxy 插件的介绍与应用可参考官网文档。

对于 Apache APISIX

Apache APISIX 是一个动静、实时、高性能的开源 API 网关,提供负载平衡、动静上游、灰度公布、服务熔断、身份认证、可观测性等丰盛的流量治理性能。

Apache APISIX 能够帮忙企业疾速、平安地解决 API 和微服务流量,包含网关、Kubernetes Ingress 和服务网格等。目前已被普华永道数据安全团队、腾讯蓝军、安全河汉实验室、爱奇艺 SRC 和源堡科技平安团队等业余网络安全机构测试,并给予了高度认可。

Apache APISIX 落地用户(仅局部)

  • Apache APISIX GitHub:https://github.com/apache/apisix
  • Apache APISIX 官网:https://apisix.apache.org/
  • Apache APISIX 文档:https://apisix.apache.org/zh/…
退出移动版