使用jython进行dubbo接口及ngrinder性能测试

快速入门(接口测试)

  • 确认mvn和jdk、jython安装ok。

  • 先下载dubbo的demo,编译运行demo。

# git clone https://github.com/alibaba/dubbo.git dubbo
# cd dubbo/
# mvn clean install -Dmaven.test.skip
# cd dubbo-demo/dubbo-demo-provider/target/
# tar xzvf dubbo-demo-provider-2.5.4-SNAPSHOT-assembly.tar.gz
# cd dubbo-demo-provider-2.5.4-SNAPSHOT/bin
# ./start.sh 
# cd /opt/code/dubbo-demo/dubbo-demo-consumer/target/
# tar xzvf dubbo-demo-provider-2.5.4-SNAPSHOT-assembly.tar.gz
# cd dubbo-demo-consumer-2.5.4-SNAPSHOT/bin
# ./start.sh 

注意:阿里的demo启动脚本有bug,如果启动时报进程已经存在,请修改start.sh中的grep部分,增加" | grep -v grep"。

确认在consumer的的日志可以看到"hello"输出,恭喜你,dubbo的demo已经成功。现在关闭上面程序,用eclipse或其他IDE打开工程进行修改。

  • 安装zk, 下载地址:http://www.apache.org/dyn/closer.cgi/zookeeper/

下载完毕后解压,执行:"# ./zkServer.sh start"

  • 修改工程

修改工程dubbo-demo-provider和dubbo-demo-consumer的dubbo.properties:

dubbo.container=log4j,spring
dubbo.application.name=demo-provider
dubbo.application.owner=william
#dubbo.registry.address=multicast://224.5.6.7:1234
dubbo.registry.address=zookeeper://127.0.0.1:2181
#dubbo.registry.address=redis://127.0.0.1:6379
#dubbo.registry.address=dubbo://127.0.0.1:9090
#dubbo.monitor.protocol=registry
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.service.loadbalance=roundrobin
#dubbo.log4j.file=logs/dubbo-demo-consumer.log
#dubbo.log4j.level=WARN

dubbo-demo-consumer的pom.xml加载的内容太多,需要进行精简,如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo-demo</artifactId>
        <version>2.5.4-SNAPSHOT</version>
    </parent>
    <artifactId>dubbo-demo-consumer</artifactId>
    <packaging>jar</packaging>
    <name>${project.artifactId}</name>
    <description>The demo consumer module of dubbo project</description>
    <properties>
        <skip_maven_deploy>false</skip_maven_deploy>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo-demo-api</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>unpack</id>
                        <phase>package</phase>
                        <goals>
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>com.alibaba</groupId>
                                    <artifactId>dubbo</artifactId>
                                    <version>${project.parent.version}</version>
                                    <outputDirectory>${project.build.directory}/dubbo</outputDirectory>
                                    <includes>META-INF/assembly/**</includes>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptor>src/main/assembly/assembly.xml</descriptor>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

dubbo-demo-consumer工程新增demo.xml, 为jython访问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://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="hello-world-app"  />
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" />

</beans>

新增jython脚本:

from org.springframework.context.support import ClassPathXmlApplicationContext

context = ClassPathXmlApplicationContext("demo.xml")
service = context.getBean("demoService")
print service.sayHello("How are you!")

重新执行第2步的编译,并在CLASSPATH添加对应的目录,比如:

export CLASSPATH=$CLASSPATH:/opt/lib/*

在IDE中运行:DemoProvider

执行:

$ jython dubbo_test.py 
"my" variable $jythonHome masks earlier declaration in same scope at /usr/bin/jython line 15.
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Hello How are you!, response form provider: 172.17.153.6:20880

java里面也可以采用这种方法。下面修改DemoConsumer类:

package com.alibaba.dubbo.demo.consumer;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.alibaba.dubbo.demo.DemoService;

public class DemoConsumer {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("demo.xml"); 

        DemoService service = context.getBean(DemoService.class);

        System.out.println(service.sayHello("How are you!"));

    }

}

可见java的操作和jython是极其类似的,只是在实际测试中,java改动需要频繁,带来不少不便。实际应用通常把多个包含dubbo服务定义的文件放在一个jar包中,这样一个jython就可以灵活地测试多个dubbo接口。当然不同接口要加载的jar是不同的,好在jython可以动态修改CLASSPATH, 参见:http://www.jython.org/jythonbook/en/1.0/appendixB.html#working-with-classpath。

Jmeter做dubbo性能测试就可以用上面这种方法,继承AbstractJavaSamplerClient类就可以。参考资料如下:

http://jmeter.apache.org/api/

下面是一个实际使用的jython接口测试脚本:

#!/usr/local/jython/bin/jython
# -*- coding: utf-8 -*-
# Author Rongzhong Xu 2016-09-06 wechat: pythontesting
"""
Name: dubbo.py

Tesed in python3.5
"""

from org.springframework.context.support import ClassPathXmlApplicationContext
from com.oppo.sso.model.request import SecurityRequest

context = ClassPathXmlApplicationContext("onekey-register-consumer.xml")
service = context.getBean("registerService")

request = SecurityRequest()
request.setMobile("13244448888")
request.setApplicationKey("test")
request.setCreateBy("127.0.0.1")
request.setCreateIP("127.0.0.1")

print("{0} {1} {0}".format("="*30, "Result("))

print(service.register(request))

result = service.register(request)

print(result.getResultCode())
print(result.getResultDesc())

性能测试支持

这里对nGrinder不做入门介绍,相关资料请参考:测试工具nGrinder介绍

nGrinder管理库的方式和grinder并不一样。可以通过web操作,但是如果文件较多的话,还是建议使用svn。

在nGrinder的web页面点击"脚本",选中测试目标之后,里面有个"TestRunner.py"之类的脚本,在当前目前新建lib目录,jar包和python库文件都可以扔到这里,这样nGrinder就可以访问了。

上面demo的测试脚本如下:

# -*- coding:utf-8 -*-

# A simple example using the HTTP plugin that shows the retrieval of a
# single page via HTTP. 
#
# This script is automatically generated by ngrinder.
#
# @author admin
from net.grinder.script.Grinder import grinder
from net.grinder.script import Test
from net.grinder.plugin.http import HTTPRequest
from net.grinder.plugin.http import HTTPPluginControl
from java.util import Date
from HTTPClient import NVPair, Cookie, CookieModule
from org.springframework.context.support import ClassPathXmlApplicationContext

control = HTTPPluginControl.getConnectionDefaults()
# if you don't want that HTTPRequest follows the redirection, please modify the following option 0.
# control.followRedirects = 1
# if you want to increase the timeout, please modify the following option.
control.timeout = 6000

test1 = Test(1, "127.0.0.1")
request1 = HTTPRequest()

# Set header datas
headers = [] # Array of NVPair
# Set param datas
params = [] # Array of NVPair
# Set cookie datas
cookies = [] # Array of Cookie

class TestRunner:
    # initlialize a thread 
    def __init__(self):
        test1.record(TestRunner.__call__)
        grinder.statistics.delayReports=True
        context = ClassPathXmlApplicationContext("demo.xml")
        self.service = context.getBean("demoService")

    def before(self):
        request1.headers = headers
        for c in cookies: CookieModule.addCookie(c, HTTPPluginControl.getThreadHTTPClientContext())

    # test method       
    def __call__(self):
        self.before()

        result = self.service.sayHello("How are you!")
        print result

jython英文教程: http://www.jython.org/jythonbook/en/1.0/

参考资料

python通过协议支持dubbo接口

以下方式支持dubbo的部分协议,序列化是个难点。

# git clone https://github.com/alibaba/dubbo.git dubbo
# cd dubbo/
# mvn clean install -Dmaven.test.skip
# cd dubbo-demo/dubbo-demo-provider/target/
# tar xzvf dubbo-demo-provider-2.5.4-SNAPSHOT-assembly.tar.gz
# cd dubbo-demo-provider-2.5.4-SNAPSHOT/bin
# ./start.sh 
# cd /opt/code/dubbo-demo/dubbo-demo-consumer/target/
# tar xzvf dubbo-demo-provider-2.5.4-SNAPSHOT-assembly.tar.gz
# cd dubbo-demo-consumer-2.5.4-SNAPSHOT/bin
# ./start.sh 

python环境安装

# git clone https://github.com/dmall/dudubbo
# cd dudubbo/
# git checkout remotes/origin/feature/block-socket
# python3 setup.py install

python测试

# /opt/python3.5/bin/python3
Python 3.5.1 (default, May 19 2016, 11:47:26)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dubbo import Dubbo
>>> from dubbo._model import Object
>>> config = { 'classpath' : '/data/code/dubbo/dubbo-demo/dubbo-demo-api/target/dubbo-demo-api-2.5.4-SNAPSHOT.jar' }
>>> client = Dubbo((('localhost', 20880),), config, enable_heartbeat=True)
>>> q = client.getProxy('com.alibaba.dubbo.demo.DemoService')
>>> type(q)
<class 'dubbo.dubbo.ServiceProxy'>
>>> q.sayHello("Test")
Connected to localhost:20880 successfully
'Hello Test, response form provider: 10.51.51.152:20880'

参考资料

links