我是靠谱客的博主 甜美项链,这篇文章主要介绍从原理到操作,让你在 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 接口的定义、配置以及相关实现。

接口实现一览

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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。

复制代码
1
2
3
4
5
6
7
8
9
10
<!-- 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方法。具体接口实现如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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 successn"); // 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 插件启用。
复制代码
1
2
3
4
5
6
7
8
# Add this in config.yaml plugins: - ... # plugin you need - dubbo-proxy
  1. 创建指向 Dubbo Provider 的 Upstream。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 路由。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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,并查看返回结果。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 的日志。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
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 的转化。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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. 通过如下命令请求来发起相关调用。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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/docs/apisix/getting-started

最后

以上就是甜美项链最近收集整理的关于从原理到操作,让你在 APISIX 中代理 Dubbo 服务更便捷的全部内容,更多相关从原理到操作,让你在内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(103)

评论列表共有 0 条评论

立即
投稿
返回
顶部