首页 > 其他分享 >Dubbo使用APISIX作为网关

Dubbo使用APISIX作为网关

时间:2023-08-08 23:22:06浏览次数:97  
标签:Dubbo 网关 服务 String dubbo 接口 APISIX

为什么使用网关

Dubbo服务本身没有暴露HTTP接口,客户端(如:Web,APP)无法直接调用其提供的方法。
APISIX可以通过dubbo-proxy插件为Dubbo服务提供外部访问的HTTP接口,因此特别适合与Dubbo框架一起使用。

在Dubbo服务架构中如何使用APISIX

关于在Dubbo服务架构中使用APISIX作为接入网关,Dubbo官方的文档已经给出了说明。
在此,结合具体的示例进行实践。

假设已经存在了基于Dubbo架构的服务提供者和消费者,如下所示:

// Dubbo服务提供者接口
public interface HelloService {
    String sayHello(String name);
}

//  Dubbo服务提供者接口实现类
@DubboService
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

// Dubbo服务消费者接口
public interface HelloServiceConsumer {
    Object hello(String name);
}

// Dubbo服务消费者接口实现类
@Service
public class HelloServiceConsumerImpl implements HelloServiceConsumer {
    // 引用Dubbo服务提供者
    @DubboReference
    private HelloService helloService;

    @Override
    public Object hello(String name) {
        return this.helloService.sayHello(name);
    }
}

此时如果希望Dubbo服务消费者(也可以是任何Dubbo服务)希望被来自APISIX的HTTP请求调用,那么如何实现呢?

按照dubbo-proxy插件文档示例描述,APISIX路由中指定的插件参数包含3个部分:

"service_name": "org.apache.dubbo.sample.tengine.DemoService", # 要调用的Dubbo服务接口完整限定名
"service_version": "0.0.0",                                    # Dubbo服务版本名称,默认为0.0.0
"method": "tengineDubbo"                                       # Dubbo服务方法名

也就是说,必须存在一个Dubbo服务接口org.apache.dubbo.sample.tengine.DemoService,该接口有一个名为tengineDubbo的方法。

// java package: org.apache.dubbo.sample.tengine
public interface DemoService {
    // 通过APISIX传递的参数保存在Map对象中
    // 返回给APISIX的结果也必须是一个Map对象,且在该Map对象中的数据结构为:
    // {
    //    "status": "200",     // 状态码,200表示成功,500表示错误
    //    "header1": "value1", // 消息头
    //    "header2": "valu2",
    //    "body": "blahblah"   // 消息体
    // }
    Map<String, Object> tengineDubbo(Map<String, Object> context);
}

如果此时向APISIX的路由接口发起一个请求:

curl http://127.0.0.1:9080/demo  -H "Host: example.org"  -X POST --data '
{
    "service": "org.chench.extra.dubbo.consumer.service.HelloServiceConsumer",
    "method": "hello",
    "parameters": [
        {
            "type": "java.lang.String",
            "value": "chench"
        }
    ]
}'

那么,消息体中的内容就是传递给Dubbo服务方法的Map对象数据。

所以,为了调用任意的Dubbo服务,应该编写一个专门对接APISIX请求的胶水层Dubbo服务,在该服务方法中通过反射的方式实现对任意其他Dubbo服务的调用。
如下接口或实现类都定义在Java包org.chench.extra.dubbo.apisix中。

// 对Dubbo服务调用做一个抽象,包含三个属性:要调用的Dubbo服务完整接口限定名,Dubbo服务方法名,Dubbo服务方法参数列表
public class DubboInvocation {
    /** 服务的完整限定名,如:org.chench.extra.dubbo.HelloService */
    private String service;

    /** 服务的方法名 */
    private String method;

    /** 服务的方法参数列表 */
    private DubboInvocationParameter[] parameters;
}

// 定义Dubbo服务方法参数,包含类型和值
public class DubboInvocationParameter {
    private String type;
    private String value;
}


// 对接APISIX请求的胶水层Dubbo服务接口
public interface APISIX2DubboService {
    Map<String, Object> invoke(Map<String, Object> context) throws Exception;
}

// 对接APISIX请求的胶水层Dubbo服务接口实现
public class APISIX2DubboServiceImpl implements APISIX2DubboService {
    private static final Logger LOGGER = LoggerFactory.getLogger(APISIX2DubboServiceImpl.class);

    @Autowired
    private ApplicationContext appContext;

    @Override
    public Map<String, Object> invoke(Map<String, Object> context) throws Exception {
        // 返回给APISIX的数据为一个Map对象
        Map<String, Object> httpResp = new HashMap<>();
        String body = null;
        try {
            body = new String((byte[]) context.get("body"));
            // 利用反射机制调用Dubbo服务的方法
            DubboInvocation invocation = JSONObject.parseObject(body, DubboInvocation.class);
            int paramSize = invocation.getParameters().length;
            Object[] args = new Object[paramSize];
            Class[] types = new Class[paramSize];
            for (int i = 0; i < args.length; i++) {
                DubboInvocationParameter parameter = invocation.getParameters()[i];
                args[i] = parameter.getValue();
                types[i] = Class.forName(parameter.getType());
            }
            Object svc = appContext.getBean(Class.forName(invocation.getService()));
            Object result = svc.getClass().getMethod(invocation.getMethod(), types).invoke(svc, args);
            httpResp.put("status", 200);
            httpResp.put("body", JSONObject.toJSONString(result));
        } catch (Exception e) {
            LOGGER.error("invoke dubbo error, body: {}, error: {}", body, e.getMessage(), e);
            httpResp.put("status", 500);
            httpResp.put("body", e.getStackTrace());
            e.printStackTrace();
        }
        return httpResp;
    }
}

然后将这个对接APISIX的Dubbo服务进行注册:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://dubbo.apache.org/schema/dubbo
        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    <!-- service implementation, as same as regular local bean -->
    <bean id="APISIX2DubboService" class="org.chench.extra.dubbo.apisix.APISIX2DubboServiceImpl"/>

    <!-- declare the service interface to be exported -->
    <dubbo:service interface="org.chench.extra.dubbo.apisix.APISIX2DubboService" ref="APISIX2DubboService"/>
</beans>

至此,在Dubbo服务侧需要准备的工作就完毕了。

在APISIX这一侧,需要做2件事情:
第一,启用dubbo-proxy插件。
如果是以Docker方式启动的APISIX,在配置文件${APISIX_HOME}/example/apisix_conf/config.yaml中添加插件配置。

# 在APISIX 3.4.1中需要手动添加如下配置参数启用dubbo-proxy插件
plugins:
  - dubbo-proxy

第二,创建一个路由指定需要调用的Dubbo服务。

curl http://127.0.0.1:9180/apisix/admin/routes/2  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
    "uris": [
        "/demo"
    ],
    "plugins": {
        "dubbo-proxy": {
            "service_name": "org.chench.extra.dubbo.apisix.APISIX2DubboService", # 这是对接APISIX的Dubbo服务接口
            "service_version": "0.0.0",
            "method": "invoke"
        }
    },
    "upstream": {
		"type": "roundrobin",
		"nodes": {
		  "192.168.2.8:20881": 1
	    }
	}
}'

最后,调用APISIX接口进行验证:

curl http://127.0.0.1:9080/demo  -X POST --data '
{
    "service": "org.chench.extra.dubbo.consumer.service.HelloServiceConsumer", # 指定需要调用的Dubbo服务接口完整限定名
    "method": "hello",                                                         # 指定需要调用的Dubbo服务接口方法
    "parameters": [                                                            # 指定需要调用的Dubbo服务接口方法参数列表,每一个参数都要指定类型和值
        {
            "type": "java.lang.String",
            "value": "chench"
        }
    ]
}' -D-
# 调用成功返回
HTTP/1.1 200 OK
Date: Mon, 07 Aug 2023 15:17:24 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 15
Connection: keep-alive
Server: APISIX/3.4.1

"Hello, chench"

# 调用失败返回
HTTP/1.1 502 Bad Gateway
Date: Mon, 07 Aug 2023 15:18:09 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 229
Connection: keep-alive
Server: APISIX/3.4.1
X-APISIX-Upstream-Status: 502

<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>openresty</center>
<p><em>Powered by <a href="https://apisix.apache.org/">APISIX</a>.</em></p></body>
</html>

至此,一个以APISIX作为网关调用Dubbo服务的方法就实现了。

但是如果在每一个Dubbo架构的应用中都需要定义一个对接APISIX的胶水层Dubbo服务,显得重复而且不利用维护,所以可以将这个胶水层Dubbo服务单独做成一个Spring Boot Starter组件,然后在每一个需要使用的地方直接引入即可,具体实现参考:dubbo-apisix-springboot-starter

【参考】
APISIX+Dubbo+Nacos 最佳实践
Dubbo注解方式与spring的整合原理即@DubboService的机制(2)
【Dubbo】三种Dubbo配置与实现原理(XML、注解、API)

标签:Dubbo,网关,服务,String,dubbo,接口,APISIX
From: https://www.cnblogs.com/nuccch/p/17615690.html

相关文章

  • Dubbo是干嘛的,Dubbo原理和机制,Dubbo的核心组件
    大家好,我是哪吒。Dubbo是一个高性能的JavaRPC框架。RPC是远程过程调用的缩写,其基本思想是:客户端像调用本地方法一样,通过网络请求调用远程服务器上的服务。Dubbo可以帮助我们更方便地构建分布式应用程序,它具有高效的远程调用、服务自动注册和发现、负载均衡、容错机制等众多特性,是......
  • Profibus DP主站转Modbus TCP网关profibus主站和从站的数据交互方式
    捷米JM-DPM-TCP网关。这款产品在Profibus总线侧实现了主站功能,在以太网侧实现了ModbusTcp服务器功能,为我们的工业自动化网络带来了全新的可能。捷米JM-DPM-TCP网关是如何实现这些功能的呢?首先,让我们来看看它的Profibus总线侧的主站功能。通过高效的通信协议和稳定的硬件设计,这款......
  • Modbus TCP转Profibus DP网关modbusTCP就是以太网吗
    捷米JM-DPM-TCP网关。在Profibus总线侧作为主站,在以太网侧作为ModbusTcp服务器功能,下面是介绍捷米JM-DPM-TCP主站网关组态工具的配置方法2,Profibus主站组态工具安装执行资料光盘中的安装文件setup64.exe或setup.exe安装组态工具。安装过程中一直选择Next即可,安装完成后程序......
  • ETHERCAT转CANOPEN协议网关canopen和can区别
    1.产品功能JM-ECT-COP是自主研发的一款ETHERCAT从站功能的通讯网关。该产品主要功能是将ETHERCAT网络和CANOPEN网络连接起来。本网关连接到ETHERCAT总线中做为从站使用,连接到CANOPEN总线中做为主站使用。3.技术参数ETHERCAT技术参数网关做为ETHERCAT网络的从站......
  • DEVICENET转ETHERCAT网关连接汇川ethercat通讯协议
    你有没有遇到过生产管理系统中,设备之间的通讯问题?两个不同协议的设备进行通讯,是不是很麻烦?今天,我们为大家介绍一款神奇的产品,能够将不同协议的设备进行连接,让现场的数据交换不再困扰!捷米JM-ECT-DNT是一款DEVICENET从站功能的通讯网关,可以将DEVICENET转ETHERCAT网络连接起来。它......
  • ETHERCAT转ETHERCAT网关西门子为什么不支持ethercat两个ETHERCAT设备互联
     1.1产品功能捷米JM-ECT-ECT是自主研发的一款ETHERCAT从站功能的通讯网关。该产品主要功能是将2个ETHERCAT网络连接起来。本网关连接到ETHERCAT总线中做为从站使用。1.2技术参数1.2.1捷米JM-ECT-ECT技术参数●网关做为ETHERCAT网络的从站,可以连接倍福、欧姆龙、基恩士......
  • OPC数据采集网关:实现多种通信协议与上网方式的物联网系统
    在现代工业自动化领域,数据采集与传输的重要性日益凸显。为了让用户更加便捷地实现数据采集与远程监控,物通博联推出了一款高性能的OPC数据采集网关。这款网关具备多种通信协议和上网方式,能够满足各种工业环境下的数据采集需求。 一、多种通信协议OPC数据采集网关支持大量的通信协议......
  • 【新品发布】鸿蒙边缘计算网关震撼来袭!
    IDO-IPC3528鸿蒙边缘计算网关基于RK3568研发设计,采用22nm先进工艺制程,四核A55CPU,主频高达2.0GHz,支持高达8GB高速LPDDR4,1T算力NPU,4KH.265/H264硬解码;视频输出接口HDMI2.0,双千兆以太网,工业互联接口CAN/RS232/RS485。适用于各种智慧显示终端产品、视频类终端产品、工业自动化终端......
  • 计讯物联3.0智慧灯杆网关TG473,创造智慧城市“数智”美好
    基于5G、物联网、智能传感、大数据、人工智能等新兴技术趋向于成熟,我国智慧城市规模发展迅速,并得到广泛的实施应用。除了技术层面,政策扶持对于智慧城市的建设也具有重大意义。今年的政府工作报告明确指出,要建设数字信息基础设施,推进5G规模化应用,促进产业数字化转型,发展智慧城市。......
  • ETHERCAT主站网关转DEVICENET连接devicenet工业
    大家好,今天要和大家分享一款自主研发的通讯网关——捷米JM-ECTM-DNT。这款产品可是解决了不同协议设备数据交换的麻烦问题,让我们一起来看看它的神奇之处吧!这款通讯网关有什么特别的呢?首先,它可以连接DEVICENET总线和ETHERCAT网络,也就是说,它可以作为主站连接到ETHERCAT总线,同时又作......