Dubbo接口测试原理及多种方法,dubbo接口测试框架

4747 324 2022-07-12


1、什么是Dubbo

最开始是应用于淘宝网,由阿里巴巴开源的一款优秀的高性能服务框架,由Java开发,后来贡献给了Apache组织

下面以官网的一个说明来了解一下架构的演变过程,从而了解dubbo的诞生原因:

image.png

单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。

垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。

分布式服务架构

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。

流动计算架构

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

2、Dubbo架构简介

image.png

image.png

Dubbo比较有特点的地方就是这个注册中心,平常我们测试较多的HTTP接口,直接请求接口,调用后端服务即可;而Dubbo是要先走注册中心获取服务的位置,下面来举个现实生活中的例子来说明

现实举例

好比大家平常约个同事朋友一起出去吃饭,吃什么呢?今天我们就吃个川菜吧,听说赠李白(没收广告费~)不错,于是就决定去赠李白吃饭。

然后我们需要去找这家饭店在哪,这个时候我们打开了我们的小蓝或小黄APP去查这家店的信息,找到了之后知道了具体的地址,在哪家商场,哪层的几号;

接着我们就根据地址出发,至于是走路,打车还是骑车,就随意了

最后,找到了店铺,开始消费,开始长胖~

而这里APP就相当于注册中心(Registry),我们这群吃货就是消费者(Consumer),商家,也就是赠李白属于生产者(Provider)。商家把自己的信息注册在APP上,消费者根据APP查询到商家的信息,再根据信息找到商家进行消费。

2.1、zookeeper简介

之前经常有小伙伴问我zk是啥?干啥的?怎么干的?下面我们来简单了解一哈

ZK,全称就是zookeeper,wikipedia上的解释是这样的:Apache软件基金会的一个软件项目,它为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册

下面的图示也可以清晰的说明zk的部署和工作的一些方式(具体的技术细节需要的话可以针对zk专门搜索学习):

image.png

Leader:集群工作的核心,事务请求的唯一调度和处理者,保证事务处理的顺序性。对于有写操作的请求,需统一转发给Leader处理。Leader需决定编号执行操作。

Follower:处理客户端非事务请求,转发事务请求转发给Leader,参与Leader选举。

Observer观察者:进行非事务请求的独立处理,对于事务请求,则转发给Leader服务器进行处理.不参与投票。

3、什么是Dubbo接口?

所谓的Dubbo接口,其实就是一个个Dubbo服务中的方法,而测试Dubbo接口就相当于我们测试人员充当消费者或者创造消费者去"消费"这个方法

具体的方式有很多,代码、工具、命令皆可,下面来一一演示

4、Dubbo接口测试(创造消费者)

以下我将以本地的一个简单的dubbo服务demo为例,演示dubbo测试的各种方法。

interface只有两个,分别是OrderService和UserService

OrderService:

package com.qinzhen.testmall.service;

import com.qinzhen.testmall.bean.UserAddress;

import java.util.List;

public interface OrderService {

    /**

     * 初始化订单

     * @param userID

     */

    public List<UserAddress> initOrder(String userID);

}

UserService:

package com.qinzhen.testmall.service;

import com.qinzhen.testmall.bean.UserAddress;

import java.util.List;

/**

 * 用户服务

 */

public interface UserService {

    /**

     * 按照userId返回所有的收获地址

     * @param userId

     * @return

     */

    public List<UserAddress> getUserAddressList(String userId);

    /**

     * 返回所有的收获地址

     * @param 

     * @return

     */

    public List<UserAddress> getUserAddressList();

}

JavaBean对象UserAddress如下:

package com.qinzhen.testmall.bean;

import lombok.AllArgsConstructor;

import lombok.Data;

import java.io.Serializable;

@AllArgsConstructor

@Data

public class UserAddress implements Serializable {

    private Integer id;

    private String userAddress; //用户地址

    private String userId; //用户ID

    private String consignee; //收货人

    private String phoneNum; //电话号码

    private String isDefault; //是否为默认地址 Y-是  N-否

    public UserAddress(){

    }

}

创建一个provider来实现UserService的Interface:

实现方法中,根据id返回对应的用户地址信息即可:

package com.qinzhen.testmall.bootuserserviceprovider.service.impl;

import com.alibaba.dubbo.config.annotation.Service;

import com.qinzhen.testmall.bean.UserAddress;

import com.qinzhen.testmall.service.UserService;

import org.springframework.stereotype.Component;

import java.util.Arrays;

import java.util.Collections;

import java.util.List;

@Component

@Service  //暴露服务

public class UserServiceImpl implements UserService {

    private UserAddress userAddress1 = new UserAddress(1, "杭州市西湖区XX公司", "1", "qz", "12345678", "Y");

    private UserAddress userAddress2 = new UserAddress(2, "杭州市西湖区花园", "2", "qz", "12345678", "N");

    @Override

    public List<UserAddress> getUserAddressList(String userId) {

        if (userId.equals("1")){

            return Collections.singletonList(userAddress1);

        }

        else if (userId.equals("2")){

            return Collections.singletonList(userAddress2);

        }

        else {

            return Arrays.asList(userAddress1, userAddress2);

        }

    }

    @Override

    public List<UserAddress> getUserAddressList(){

        return Arrays.asList(userAddress1, userAddress2);

    }

}

4.1 Java consumer代码

下面我们编写consumer代码,让服务消费者去注册中心订阅服务提供者的服务地址,以RPC方式,获取远程服务代理,从而执行远程方法,代码也很简单,如下:

代码结构:

实现场景就是实现OrderService中的initOrder()方法,初始化订单,初始化中直接调用userService的getUserAddressLis(java.lang.String)方法,具体代码如下:

package com.qinzhen.testmall.service.impl;

import com.qinzhen.testmall.bean.UserAddress;

import com.qinzhen.testmall.service.OrderService;

import com.qinzhen.testmall.service.UserService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.util.List;

/**

 * 1、讲服务提供者注册到注册中心(暴露服务)

 *          1)导入dubbo依赖:操作zookeeper的客户端(curator)

 * 2、让服务消费者去注册中心订阅服务提供者的服务地址

 */

@Service

public class OrderServiceImpl implements OrderService {

    @Autowired

    UserService userService;

    public List<UserAddress> initOrder(String userId) {

        //1.查询用户的收货地址

        System.out.println("用户ID为:" + userId);

        List<UserAddress> userAddressList = userService.getUserAddressList(userId);

        return userAddressList;

    }

}

consumer MainApplication

package com.qinzhen.testmall;

import com.qinzhen.testmall.bean.UserAddress;

import com.qinzhen.testmall.service.OrderService;

import com.qinzhen.testmall.service.UserService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.springframework.stereotype.Service;

import java.io.IOException;

import java.util.List;

/**

 * 1、将服务提供者注册到注册中心(暴露服务)

 *          1)导入dubbo依赖:操作zookeeper的客户端(curator)

 * 2、让服务消费者去注册中心订阅服务提供者的服务地址

 */

@Service

public class MainApplication {

    public static void main(String[] args) throws IOException {

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"consumer.xml"});

        context.start();

        OrderService orderService = context.getBean(OrderService.class); // 获取远程服务代理

        List<UserAddress> userAddresses = orderService.initOrder("3");// 执行远程方法

        System.out.println(userAddresses);

        System.out.println("调用完成。。。");

        System.in.read();

    }

}

consumer.xml:

<?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://code.alibabatech.com/schema/dubbo"

       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.qinzhen.testmall.service.impl"></context:component-scan>

    <dubbo:application name="order-service-comsumer"></dubbo:application>

    <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>

    <!--声明需要远程调用远程服务的接口,生成远程服务代理-->

    <dubbo:reference interface="com.qinzhen.testmall.service.UserService" id="userService"></dubbo:reference>

</beans>

实例演示:

首先确保provider已启动

运行consumer,可以看到成功调用到dubbo方法,获取地址列表信息:

4.2 telnet+invoke

我们使用telnet命令可以直接访问对应的服务,但是前提是你需要知道服务对应的ip+端口

如下配置文件,我们可以知道服务暴露在本地的20880端口

dubbo.application.name=boot-user-service-provider

dubbo.registry.address=127.0.0.1:2181

dubbo.registry.protocol=zookeeper

dubbo.protocol.name=dubbo

dubbo.protocol.port=20880

使用telnet命令进行访问,如下出现dubbo字样时说明连接成功:

% telnet localhost 20880

Trying ::1...

Connected to localhost.

Escape character is '^]'.

dubbo>

dubbo 内建的 telnet 命令的说明和用法如下

ls

ls: 显示服务列表

ls -l: 显示服务详细信息列表

ls XxxService: 显示服务的方法列表

ls -l XxxService: 显示服务的方法详细信息列表

dubbo>ls

com.qinzhen.testmall.service.UserService

dubbo>ls -l

com.qinzhen.testmall.service.UserService -> dubbo://192.168.2.xxx:20880/com.qinzhen.testmall.service.UserService?anyhost=true&application=boot-user-service-provider&bind.ip=192.168.2.xxx&bind.port=20880&dubbo=2.6.2&generic=false&interface=com.qinzhen.testmall.service.UserService&methods=getUserAddressList&pid=55472&qos.enable=false&side=provider&timestamp=1615088321885

dubbo>dubbo>ls com.qinzhen.testmall.service.UserService

getUserAddressList

getUserAddressList

dubbo>dubbo>ls -l com.qinzhen.testmall.service.UserService

java.util.List getUserAddressList(java.lang.String)

java.util.List getUserAddressList()

invoke

invoke XxxService.xxxMethod(1234, "abcd", {"prop" : "value"}): 调用服务的方法

invoke com.xxx.XxxService.XxxService.xxxMethod(1234, "abcd", {"prop" : "value"}): 调用全路径服务的方法

invoke xxxMethod(1234, "abcd", {"prop" : "value"}): 调用服务的方法(自动查找包含此方法的服务)

invoke xxxMethod({"name":"zhangsan","age":12,"class":"org.apache.dubbo.qos.legacy.service.Person"}) :当有参数重载,或者类型转换失败的时候,可以通过增加class属性指定需要转换类

当参数为Map<Integer,T>,key的类型为Integer时,建议指定类型。例如invoke com.xxx.xxxApiService({"3":0.123, "class":"java.util.HashMap"})

然后我们使用invoke 命令对dubbo方法getUserAddressList()进行调用,如下:

dubbo>invoke getUserAddressList()

[{"consignee":"qz","id":1,"isDefault":"Y","phoneNum":"12345678","userAddress":"杭州市西湖区xx公司","userId":"1"},{"consignee":"qz","id":2,"isDefault":"N","phoneNum":"12345678","userAddress":"杭州市西湖区xx花园","userId":"2"}]

dubbo>invoke getUserAddressList("1")

[{"consignee":"qz","id":1,"isDefault":"Y","phoneNum":"12345678","userAddress":"杭州市西湖区xx公司","userId":"1"}]

elapsed: 14 ms.

学习链接:

其他Telnet命令相关操作,需要可参考dubbo官网:

https://dubbo.apache.org/zh/docs/v2.7/user/references/telnet/

4.3 Jmeter

对于Jmeter测试dubbo接口的方法,可参考文档:

基于Jmeter完成Dubbo接口的测试

4.4 dubbo-admin

对于dubbo-admin的安装调试,可参考文档:

dubbo-admin+zookeeper的环境搭建实操与Could not extract archive报错踩坑

4.5 泛化调用

测试dubbo服务的时候,我们需要服务端的同学给我们提供API,没有这个API我们是测不了的,而为了解决这个问题,dubbo官方又给我们提供了另外一个方法,就是泛化调用,来看看官方的解释:

4.5.1 泛化调用的使用

dubbo给我们提供了一个接口GenericService,这个接口只有一个方法,就是$invoke,它接受三个参数,分别为方法名、方法参数类型数组和参数值数组;

下面我们直接上代码演示:

import com.alibaba.dubbo.config.ApplicationConfig;

import com.alibaba.dubbo.config.ReferenceConfig;

import com.alibaba.dubbo.config.RegistryConfig;

import com.alibaba.dubbo.rpc.service.GenericService;

import org.junit.jupiter.api.Test;

public class TestDemo {

    @Test

    void testDubboGenericService(){

        // 引用远程服务

        // 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存

        ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();

        // 弱类型接口名

        reference.setApplication(new ApplicationConfig("order-service-consumer"));

        reference.setInterface("com.qinzhen.testmall.service.UserService");

        reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));

        // 声明为泛化接口

        reference.setGeneric(true);

        // 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用

        GenericService genericService = reference.get();

        Object result = genericService.$invoke("getUserAddressList", new String[] {"java.lang.String"}, new Object[] {"2"});

        System.out.println(result);

    }

}

运行后我们来看看结果,咦~也成功访问了:

4.5.1 泛化调用的原理

我们通过debug跟入dubbo的源码中,可以得到如下的调用链:

服务消费端:image.png

服务提供端:image.png

从上面的调用链可以知道完成一次泛化调用,dubbo框架经历了很多过滤器,我们分别选取两端链路中的最后一步的Filter来简单(难了我也不会~)了解一下泛化调用做了哪些事

简化后的调用关系就如下:image.png

先来看consumer端的GenericImplFilter,大概看下核心的处理步骤:

// 判断是否为泛化调用

if (invocation.getMethodName().equals(Constants.$INVOKE)

                && invocation.getArguments() != null

                && invocation.getArguments().length == 3

                && ProtocolUtils.isGeneric(generic)) {

// 获取泛化调用参数

            Object[] args = (Object[]) invocation.getArguments()[2];

            // 判断是否为nativejava方式

            if (ProtocolUtils.isJavaGenericSerialization(generic)) {

                for (Object arg : args) {

                    if (!(byte[].class == arg.getClass())) {

                        error(byte[].class.getName(), arg.getClass().getName());

                    }

                }

            // 判断是否为bean方式

            } else if (ProtocolUtils.isBeanGenericSerialization(generic)) {

                for (Object arg : args) {

                    if (!(arg instanceof JavaBeanDescriptor)) {

                        error(JavaBeanDescriptor.class.getName(), arg.getClass().getName());

                    }

                }

            }

// 设置为泛化调用方式

            ((RpcInvocation) invocation).setAttachment(

                    Constants.GENERIC_KEY, invoker.getUrl().getParameter(Constants.GENERIC_KEY));

        }

        // 发起远程调用

        return invoker.invoke(invocation);

再来看provider端的GenericFilter,大概的核心处理步骤如下:

package com.alibaba.dubbo.rpc.filter;

import ...

/**

 * GenericInvokerFilter.

 */

@Activate(group = Constants.PROVIDER, order = -20000)

public class GenericFilter implements Filter {

    @Override

    public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {

    // 判断是否为泛化请求

        if (inv.getMethodName().equals(Constants.$INVOKE)

                && inv.getArguments() != null

                && inv.getArguments().length == 3

                && !ProtocolUtils.isGeneric(invoker.getUrl().getParameter(Constants.GENERIC_KEY))) {

            // 获取参数名称、参数类型、参数值

            String name = ((String) inv.getArguments()[0]).trim();

            String[] types = (String[]) inv.getArguments()[1];

            Object[] args = (Object[]) inv.getArguments()[2];

            try {

            // 使用反射获取调用方法

                Method method = ReflectUtils.findMethodByMethodSignature(invoker.getInterface(), name, types);

                Class<?>[] params = method.getParameterTypes();

                if (args == null) {

                    args = new Object[params.length];

                }

                // 获取泛化引用方式使用的泛化类型

                String generic = inv.getAttachment(Constants.GENERIC_KEY);

                // 泛化类型为空的话就使用generic=true的方式

                if (StringUtils.isEmpty(generic)

                        || ProtocolUtils.isDefaultGenericSerialization(generic)) {

                    args = PojoUtils.realize(args, params, method.getGenericParameterTypes());

                // 判断是否为generic=nativejava方式

                } else if (ProtocolUtils.isJavaGenericSerialization(generic)) {

                    for (int i = 0; i < args.length; i++) {

                        if (byte[].class == args[i].getClass()) {

                            try {

                                UnsafeByteArrayInputStream is = new UnsafeByteArrayInputStream((byte[]) args[i]);

                                args[i] = ExtensionLoader.getExtensionLoader(Serialization.class)

                                        .getExtension(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA)

                                        .deserialize(null, is).readObject();

                            } catch (Exception e) {

                                。。。

                            }

                        } else {

                            。。。

                        }

                    }

                  // 判断是否为generic=bean方式

                } else if (ProtocolUtils.isBeanGenericSerialization(generic)) {

                    for (int i = 0; i < args.length; i++) {

                        if (args[i] instanceof JavaBeanDescriptor) {

                            args[i] = JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) args[i]);

                        } else {

                            。。。

                        }

                    }

                }

                // 传递请求,执行服务

                Result result = invoker.invoke(new RpcInvocation(method, args, inv.getAttachments()));

                。。。

}

上面的代码很多,着重来提取一小段看一下:

// 使用反射获取调用方法

Method method = ReflectUtils.findMethodByMethodSignature(invoker.getInterface(), name, types);

Class<?>[] params = method.getParameterTypes();

从上面的代码中我们便可以得知原来泛化调用中使用了Java的反射技术来获取对应的方法信息完成调用的

4.6 用Python来测试Dubbo

我们现在知道了Dubbo是个Java项目,测试Dubbo就是模拟消费者去调用Dubbo的Java方法,那显而易见,用Python是肯定没法去直接调用Java的,但是在日常的工作中,很多小伙伴可能是pyhton技术栈的,或者因为一些测试条件限制亦或历史原因,必须要将Dubbo测试用Python实现以满足各种接口测试的一个组合

4.6.1 python-hessian库

Dubbo是支持hessian+http协议调用的,hessian是一种二进制序列化的方式。

了解到可以通过这种方式实现,具体没有尝试过,还需要开发在项目中将序列化的方式改为hessian,并且需要知道URL,有兴趣的小伙伴可以去了解一下

4.6.2 telnetlib库

telnetlib是Python3自带的一个库,可以调用telnet命令,其实也就相当于上面说到的使用telnet方式访问dubbo的方法

4.6.3 开发dubbo测试服务

我们可以使用Java来开发一个dubbo测试的web服务,实现上就可以使用dubbo的泛化调用,然后我们再用HTTP访问的形式去访问这个服务,将我们的测试参数信息传过去,剩下的就交给Java去处理就好了。

这样经过封装设计后,可以实现Python端的使用者在访问dubbo时就像在测试HTTP接口一样(例如Python的request库);另外服务的IP、端口、注册中心等信息都不用出现在测试的工程中,只需要用环境标签做区分,在服务端进行请求转发即可,也保证了一定安全性。

大体上的思路流程如下:

image.png

最近公司开发新的一套系统,开发出来的方案会基于dubbo分布式服务框架开发的,那么什么是dubbo,身为测试的我,第一眼看到这个,我得去了解了解dubbo是啥玩意,为开展的测试工作做准备,提前先学 dubbo的相关知识。

  1.什么是dubbo

    Dubbo来源于阿里巴巴集团某个团队研发出来的一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东。

     其核心部分包含:
1. 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
2. 集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
3. 自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。

  Dubbo本身支持多种远程调用方式,例如Dubbo RPC(二进制序列化 + tcp协议)、http invoker(二进制序列化 + http协议)、hessian(二进制序列化 + http协议)、WebServices (文本序列化 + http协议)等。

  2. Dubbo能做什么?
1.透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。      
2.软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
3. 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。

3. dubbo的架构

Provider

暴露服务方称之为“服务提供者”。

Consumer

调用远程服务方称之为“服务消费者”。

Registry

服务注册与发现的中心目录服务称之为“服务注册中心”。

Monitor

统计服务的调用次数和调用时间的日志服务称之为“服务监控中心”。

调用关系说明:

   0 服务容器负责启动,加载,运行服务提供者。

  1. 服务提供者在启动时,向注册中心注册自己提供的服务。

  2. 服务消费者在启动时,向注册中心订阅自己所需的服务。

  3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

  4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

  5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

以上均是dubbo框架的一些理论知识、那么了解了基础的知识,我们怎么来测试dubbo提供的接口呢。

遇到这个问题我也会咨询一些前辈,有人说java编写代码可以测试,但是需要的依赖多,有些人说基于python也是可以调用的,那么也是需要第三库来支持的,

我们可以去下载对应的python库,有的版本不支持python3 你可以下载下来源码,对源码中的一些代码格式调整到python3支持的格式就好。

我这里才用的是dubbo_telnet,下载安装后我们先测试下,看代码是否能够正常运行。

我们拿来了官方的例子。

import dubbo_telnet
Host = '192.168.1.203' # Doubble服务器IP
Port = 28008 # Doubble服务端口
# 初始化dubbo对象
conn = dubbo_telnet.connect(Host, Port)
# 设置telnet连接超时时间
conn.set_connect_timeout(10)
# 设置dubbo服务返回响应的编码
conn.set_encoding('gbk')
interface = 'com.zrj.pay.trade.api.QueryTradeService'#接口
method = 'tradeDetailQuery'#方法
param = '{"message": "HelloWorld"}'#参数
print (conn.invoke(interface, method, param))
command = 'invoke com.zrj.pay.trade.api.QueryTradeService.tradeDetailQuery({"message":"HelloWorld"})'
print (conn.do(command)) #打印接口返回结果
运行后,

这样我们的代码是没有问题的,由于我本地没有dubbo的服务,所以这里是返回None。

对于上述代码,我做了进一步的优化。

import dubbo_telnet
def coondoubble_data(Host,Port,interface,method,param):
    try:
        # 初始化dubbo对象
        conn = dubbo_telnet.connect(Host, Port)
        # 设置telnet连接超时时间
        conn.set_connect_timeout(10)
        # 设置dubbo服务返回响应的编码
        conn.set_encoding('gbk')
        conn.invoke(interface, method, param)
        command = 'invoke %s.%s(%s)'%(interface,method,param)
        return  conn.do(command)
    except:
        return  Exception
if __name__=="__main__":
    Host = '192.168.1.203'  # Doubble服务器IP
    Port = 28008  # Doubble服务端口
    interface = 'com.zrj.pay.trade.api.QueryTradeService'  # 接口
    method = 'tradeDetailQuery'  # 方法
    param = '{"message": "HelloWorld"}'  # 参数
    data=coondoubble_data(Host,Port,interface,method,param)
    print(data)
可见,我们用python是能够调用出来我们的dubbo服务的,那么接下来就是根据现有的dubbo接口进行测试了,由于现在研发还没有进行一系列的开发,所以我打算先自己去尝试的按照网上例子写一个dubbo的例子,用作自己的测试。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:接口测试之webservice,webservice接口测试方法
下一篇:全媒派:从10万到50万,美国报业如何报道新冠死亡人数?
相关文章

 发表评论

暂时没有评论,来抢沙发吧~