Jmeter压测Hprose for dotnet or java

    科技2022-08-04  107

    使用Jmeter压测Hprose for dotnet or java

    前言

    1.目标

    项目组想对.Net平台的webapi和基于RPC协议的hprose做一个性能的对比。

    2.问题:

    Postman没有压测功能;LoadRunner太笨重,费钱且学习成本大,且不支持win10家庭版;其他的测试工具网上文档太少,担心出了问题没办法自己解决,因此选用了Jmeter。Jmeter是纯java脚本,查看了一下其插件库,没有类似于将C#脚本转化为java的插件在vs2019中有Jmeter的Nuget包,但没有使用示例,只有一个github网址,其readme文档没什么内容,wiki百科里也没有说明;vs2019扩展工具里有Jmeter Test Explorer但还是不知道怎么用,不好意思真的是废物。

    解决方案

    1.用idea写一个hprose-server的java脚本,作为hprose的服务端。

    2.用idea写一个hprose-client的java脚本,作为hprose的客户端。

    3.hprose是一个多语言跨平台基于RPC协议的高性能远程调用服务框架,因此理论上可以使用vs2019来写hprose-server的C#脚本,即hprose for dotnet。在上两步尝试如果可行的情况下,书写C#脚本的服务端,然后使用步骤2的java脚本的客户端去调用,当然可能语法上有一点点需要修改。

    4.将hprose-client的java脚本稍作修改,引入jar包,实现jmeter里jar包的类。

    5.将hprose-client的java脚本在idea里打成jar包封装,然后装进jmeter目录文件夹lib\ext内。

    6.重启Jmeter,使用java请求和查看结果树就可以成功实现。

    具体实现步骤

    1. 写java脚本的hprose-server。

    1.1建立简单的maven项目,next

    1.2初始化项目
    在pom.xml里引入hprose-java的依赖,如图 <dependencies> <dependency> <groupId>org.hprose</groupId> <artifactId>hprose-java</artifactId> <version>2.0.38</version> </dependency> </dependencies> 新建java类,命名随便,这里命名为TCPHelloServer,写他。 import hprose.server.HproseTcpServer; public class TCPHelloServer { public static String hello(String name) { return "Hello " + name + "!"; } public static void main(String[] args) throws Exception { HproseTcpServer server = new HproseTcpServer("tcp://localhost:4322"); server.add("hello", TCPHelloServer.class); server.start(); System.out.println("START"); System.in.read(); server.stop(); System.out.println("STOP"); } }
    1.3点击小绿箭头运行起来看看。

    2.写java脚本的hprose-client。

    2.1建立简单的maven项目,next

    2.2初始化项目
    在pom.xml里引入hprose-java的依赖,如图 <dependencies> <dependency> <groupId>org.hprose</groupId> <artifactId>hprose-java</artifactId> <version>2.0.38</version> </dependency> </dependencies> 新建java类,随便命名,这里命名为TCPHelloClient,写他。 import hprose.client.HproseTcpClient; interface IHello { String hello(String name); } public class TCPHelloClient { public static void main(String[] args) throws Throwable { System.out.println("START"); HproseTcpClient client = new HproseTcpClient("tcp://localhost:4322"); IHello helloClient = client.useService(IHello.class); System.out.println(helloClient.hello("World")); System.out.println("END"); } }
    2.3点击小绿箭头运行起来看看。nice~

    3.写C#脚本的hprose-server,用java脚本的hprose-client调用,尝试是否可行。

    3.1打开vs2019建立简单的控制台程序。

    3.2hprose for dot net环境配置
    工具-Nuget包-浏览(全装上嘻嘻) 不知道在哪里找“Hprose"的dll文件,我这里还添加了一个引用,师姐直接给我的,就是这个dll文件。
    3.3编写类并测试类
    写一个Hello类,封装有一个测试方法。在入口函数里调用该类,完成server的搭建。测试运行 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Hprose.Server; namespace Hprose_Server_csdn { class Program { static void Main(string[] args) { HproseHttpListenerServer server = new HproseHttpListenerServer("http://localhost:2020/"); server.GlobalMethods.AddInstanceMethods(new Hello()); server.Start(); Console.WriteLine("server-start"); Console.ReadKey(); server.Stop(); } } public class Hello { public string sayHello(string input) { return "hello" + input + "!"; } } } 成功
    3.4对java-hproseclient略作修改,调用C#-hproseserver。
    3.4.1修改java-hproseclient的代码,其中被注释掉的是之前写的,未被注释的是修改的时候添加的。

    import hprose.client.HproseHttpClient; import hprose.client.HproseTcpClient; interface IHello { String hello(String name); } interface Hello { String sayHello(String input) ; } public class TCPHelloClient { public static void main(String[] args) throws Throwable { // System.out.println("START"); // HproseTcpClient client = new HproseTcpClient("tcp://localhost:4322"); // IHello helloClient = client.useService(IHello.class); // System.out.println(helloClient.hello("World")); // System.out.println("END"); System.out.println("START"); HproseHttpClient client = new HproseHttpClient("http://localhost:2020/"); Hello hello = client.useService(Hello.class); String s = hello.sayHello("linjianshu"); System.out.println(s); System.out.println("END"); } }
    3.4.2运行C#-hproseServer,运行java-hproseClient看看是否成功调用,ps:可以在服务器端方法体内打个断点看看是否跳进断点里来。

    成功噜

    4.将hprose-client的java脚本稍作修改,引入jar包,实现jmeter里jar包的类。

    既已实现第三步,剩下的就很快了。要实现jmeter识别并编译jar包,需要引入jmeter里的两个jar包并实现。
    4.1向java-hproseClient引入jmeter的jar包
    从Jmeter的安装目录lib/ext中拷贝两个文件ApacheJMeter_core.jar和ApacheJMeter_java.jar到TestNumber项目中,然后引入这两个JAR包。点击Project Structure --Modules --Dependencies --+ – JARs or directories 打开jmeter存放地址,寻找两个jar包引入。OK-- Apply – OK 让原来的TCPHelloClient类继承引入jar包中的AbstractJavaSamplerClient抽象类,并实现missing methods(alt+enter万能键)(PS:return 的值这里先定义为null , 后面需要修改) 将main方法里的有效代码移到runTest方法体里,注释掉整个main方法 import hprose.client.HproseHttpClient; import hprose.client.HproseTcpClient; import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient; import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext; import org.apache.jmeter.samplers.SampleResult; interface IHello { String hello(String name); } interface Hello { String sayHello(String input) ; } public class TCPHelloClient extends AbstractJavaSamplerClient { // public static void main(String[] args) throws Throwable { // System.out.println("START"); // HproseTcpClient client = new HproseTcpClient("tcp://localhost:4322"); // IHello helloClient = client.useService(IHello.class); // System.out.println(helloClient.hello("World")); // System.out.println("END"); // // } public SampleResult runTest(JavaSamplerContext javaSamplerContext) { System.out.println("START"); HproseHttpClient client = new HproseHttpClient("http://localhost:2020/"); Hello hello = client.useService(Hello.class); String s = hello.sayHello("linjianshu"); System.out.println(s); System.out.println("END"); return null; } } 理论上只会实现一个方法,但这个方法在测试的时候只能在jmeter控制台输出,与测试目的相去甚远,因此还需要再写其他3个方法。 setupTest方法初始化、getDefaultParameters允许jmeter编译后传入参数、teardownTest方法测试结束方法形似释放进程滴。这里贴出的代码我还没全部理解透,先放着不影响程序执行。(ps:现在是两天后编辑此篇文章的我,我已经理解一点啦,请有需要的小伙伴移步我的下一篇压测实例,在那将以一个学生crud压测实例做示范,传入随机参数sno来做压测嘻) import hprose.client.HproseHttpClient; import hprose.client.HproseTcpClient; import org.apache.jmeter.config.Arguments; import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient; import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext; import org.apache.jmeter.samplers.SampleResult; interface IHello { String hello(String name); } interface Hello { String sayHello(String input) ; } public class TCPHelloClient extends AbstractJavaSamplerClient { // public static void main(String[] args) throws Throwable { // System.out.println("START"); // HproseTcpClient client = new HproseTcpClient("tcp://localhost:4322"); // IHello helloClient = client.useService(IHello.class); // System.out.println(helloClient.hello("World")); // System.out.println("END"); // // } private SampleResult results; private String inNum; private String resultNum; public TCPHelloClient() { } /** * 初始化方法,初始化性能测试时的每个线程 * 实际运行时每个线程仅执行一次,在测试方法运行前执行,类似于LoadRunner中的init方法 */ public void setupTest(JavaSamplerContext jsc) { this.results = new SampleResult(); this.inNum = jsc.getParameter("inNum", ""); this.resultNum = jsc.getParameter("resultNum11", ""); if (this.inNum != null && this.inNum.length() > 0) { this.results.setSamplerData(this.inNum); } if (this.resultNum != null && this.resultNum.length() > 0) { this.results.setSamplerData(this.resultNum); } } /** * 设置传入参数 * 可以设置多个,已设置的参数会显示到Jmeter参数列表中 */ public Arguments getDefaultParameters() { Arguments params = new Arguments(); params.addArgument("inNum", ""); params.addArgument("input", "ljs"); return params; } /** * 性能测试时的线程运行体 * 测试执行的循环体,根据线程数和循环次数的不同可执行多次,类似于Loadrunner中的Action方法 */ public SampleResult runTest(JavaSamplerContext javaSamplerContext) { System.out.println("START"); //计时器启动 results.sampleStart(); HproseHttpClient client = new HproseHttpClient("http://localhost:2020/"); Hello hello = client.useService(Hello.class); String s = hello.sayHello("linjianshu"); //计时器终止 results.sampleEnd(); //请求表示true则成功 //results.setSuccessful(true); System.out.println(s); System.out.println("END"); this.results.setResponseData(s,null); return this.results; } /** * 测试结束方法,结束测试中的每个线程 * 实际运行时,每个线程仅执行一次,在测试方法运行结束后执行,类似于Loadrunner中的End方法 */ public void teardownTest(JavaSamplerContext arg0) { } }

    5.在idea里打成jar包封装,装进jmeter目录文件夹lib\ext内。

    Project Structure --Artifacts --+ – JAR – From modules with dependencies OK–apply–OK后 Build–Build Artifacts 给老子biu~ biu~成功后,将会在项目根目录—out–artifacts中看到jar包 复制一份,装进jmeter目录文件夹lib\ext内。

    6.重启Jmeter进行测试

    打开bin\jmeter.bat构建线程组,在其下添加java请求和查看结果树,jar包导入成功的话,java请求里能够自动识别内部的类,且告知可以传入的参数及参数的默认值。(这里demo未使用传入参数,但是后续测试肯定会用到滴,例如利用jmeter里的随机函数作为传入参数来做文章) 点击绿色儿的小箭头,跑一跑试试看 成功~ 控制台

    总结

    到此,一个hprose for dot net 的服务端测试demo搭建完毕,实在是头痛,想了一周了裂了裂了。希望对大家有所帮助,最后,希望hprose for dot net用的人多多滴,人少真滴资料也少,找的我痛不欲生。

    参考文档

    极力推荐先做这个demo,给了我巨大的灵感,一半代码都是这个老哥写的呜呜呜我是废物hprose for java-githubhprose for dot net-github尝试了一下发现不行 可能我不太会使用,毕竟学的是.Net平台打jar包的正确步骤,可以参考给测试小姐姐讲RPC如何在ieda项目中引入jar包这个也可以参考
    Processed: 0.020, SQL: 9