Metersphere之Thrift协议插件开发

前言
现在要支持MS的Thrfit 协议,因为MS是集成的jmeter,所以要开发MS插件其实就是开发Jmeter插件,然后再进行封装。


一、JMeter介绍

1. JMeter

JMeter 是 Apache 基金会旗下的一款完全基于 Java 的开源软件,主要用作性能测试,通过模拟并发负载来测试并分析应用的性能状况。JMeter 最初被用于测试部署在服务器端的 Web 应用程序,现在发展到了更广泛的领域。目前 JMeter 已成为主流的性能测试工具。

1.1 功能特性

  1. JMeter 作为优秀的开源项目,拥有开放、强大且活跃的社区支持。
  2. JMeter 支持多种类型的应用、服务及协议,官方支持包括:HTTP Web 应用、HTTPS Web 应用、SOAP、REST、FTP、TCP、LDAP、Java 对象、JDBC 方式连接的数据库等。扩展后可支持更多协议。
  3. JMeter 具备跨平台特性,可运行于 Linux、Windows、Mac OSX 等多种操作系统平台上。测试人员通过 JMeter GUI 界面创建 JMeter 脚本,或通过录制的方式生成脚本,然后通过 GUI 界面或命令行方式来运行测试。
  4. JMeter 具有高可扩展性,测试人员可基于 JMeter 开发自定义的插件,由 JMeter 装载后运行。

由此可见,JMeter可以支持自定义第三方插件的。

2. 本地安装JMeter

参考链接:
https://www.jianshu.com/p/0e4daecc8122

二、开发Thrift协议插件

2.1 Thrift

Thrift 是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++、Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk、and OCaml 等等编程语言间无缝结合的、高效的服务。

Thrift 最初由 facebook 开发,07 年四月开放源码,08 年 5 月进入 Apache 孵化器。Thrift 允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成 RPC 客户端和服务器通信的无缝跨编程语言。

官方链接:https://thrift.apache.org/

2.2 MAC安装Thrift环境

  1. Thrift 是一个rpc的框架,所以,要想编译Thrift 的IDL语言,首先要安装编辑器。
  2. Mac 安装还是比较方便的直接通过 brew 的方式安装
brew install thrift 
  1. 安装成功之后看下版本信息,出现版本即为成功。
thrift -version

image.png

2.3 IDEA中编写Thrift 脚本

  1. 首先需要安装支持Thrift IDL语言的插件。(Thrift Support)
  2. 这个插件对idea的版本有限制,安装的时候需要注意下。
  3. 当然也可以直接在任何文本编辑器中进行编写,保存文件的时候保存为.thrift为结尾的就行。

插件地址:https://plugins.jetbrains.com/plugin/7331-thrift-support

image.png

  1. 下载完之后就可以编写IDL脚本了。

2.3.1 Thrift IDL 语法对应如下:

  • 基本类型:
    bool:布尔值,true 或 false,对应 Java 的 boolean
    byte:8 位有符号整数,对应 Java 的 byte
    i16:16 位有符号整数,对应 Java 的 short
    i32:32 位有符号整数,对应 Java 的 int
    i64:64 位有符号整数,对应 Java 的 long
    double:64 位浮点数,对应 Java 的 double
    string:utf-8 编码的字符串,对应 Java 的 String
  • 结构体类型:
    struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean
  • 容器类型:
    list:对应 Java 的 ArrayList
    set:对应 Java 的 HashSet
    map:对应 Java 的 HashMap
  • 异常类型:
    exception:对应 Java 的 Exception
  • 服务类型:
    service:对应服务的类。

2.3.2 服务端编码基本步骤

  1. 实现服务处理接口 impl
  2. 创建 TProcessor
  3. 创建 TServerTransport
  4. 创建 TProtocol
  5. 创建 TServer
  6. 启动 Server

2.3.3 客户端编码基本步骤

  1. 创建 Transport
  2. 创建 TProtocol
  3. 基于 TTransport 和 TProtocol 创建 Client
  4. 调用 Client 的相应方法

2.3.4 数据传输协议

  1. TBinaryProtocol 二进制格式
  2. TCompactProtocol 压缩格式
  3. TJSONProtocol JSON 格式
  4. TSimpleJSONProtocol 提供 JSON 只写协议,生成的文件很容易通过脚本语言解析

提示: 客户端和服务端的协议要一致

2.3.5 编写Thrift脚本

  1. 创建一个maven或者java 项目都可以

image.png

  1. 编写Thrift脚本
namespace  java com.thrift.demo  // 使用java 语言定义 package 

service ThriftHelloService{  // 定义一个service  相当于java当中的接口
    
    string sayHello(1:string username)  // 输入一个参数,返回string类型参数。
        
}
  1. 注意名字必须要以.thrift 结尾的。
  2. idea 没有.thrift文件,直接创建text修改名字即可。

2.3.6 编译Thrift脚本

image.png

  1. 通过 thrift -gen java 文件名.thrift 进行编译.
  2. 编译成功之后会在当前项目里面看到.

image.png3. 可以看到报错不用管,因为这个项目就是我们用来使用生成java类的项目。可以看到这个类中,有很多代码,
image.png

简单分析一下这个类:生成的类主要有5个部分

  1. 接口类型,默认名称都是Iface。这个接口类型被服务器和客户端共同使用。服务器端使用它来做顶层接口,编写实现类。客户端代码使用它作为生成代理的服务接口。

自动生成的接口有两个,一个是同步调用的Iface,一个是异步调用的AsyncIface。异步调用的接口多了一个回调参数。

  1. 客户端类型,一个同步调用的客户端Client,一个异步调用的客户端AsyncClient
  2. Processor,用来支持方法调用,每个服务的实现类都要使用Processor来注册,这样最后服务器端调用接口实现时能定位到具体的实现类。 一个同步调用Processor,一个异步调用AsyncProcessor
  3. 方法参数的封装类,以"方法名_args"命名
  4. 方法返回值的封装类,以"方法名_result"命名

详细的源码分析参考:https://www.kancloud.cn/digest/thrift/118986

2.3.7 编写服务器端

  1. 在idea中新建一个maven项目,报名要与刚刚在Thrift当中生成的namespace一样,并且把刚刚生成好的java类给复制过来

image.png

  1. 添加pom依赖
<dependencies>
  <!--      thrift 集成-->
  <dependency>
    <groupId>org.apache.thrift</groupId>
    <artifactId>libthrift</artifactId>
    <version>0.16.0</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.12</version>
  </dependency>
  
  <!--        jmeter 集成-->
  <dependency>
    <groupId>org.apache.jmeter</groupId>
    <artifactId>ApacheJMeter_core</artifactId>
    <version>5.5</version>
  </dependency>
  <dependency>
    <groupId>org.apache.jmeter</groupId>
    <artifactId>ApacheJMeter_java</artifactId>
    <version>5.5</version>
  </dependency>
  
</dependencies>
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.3</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <encoding>utf-8</encoding>
      </configuration>
    </plugin>
      <!--       完整依赖打包 集成-->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
      <executions>
        <execution>
          <id>assemble-all</id>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

  1. 写接口的实现类
public class ThriftHelloServiceImpl implements ThriftHelloService.Iface {
    @Override
    public String sayHello(String username) throws TException {
        return "Hello Thrift :" + username;
    }
}
  1. 写服务端main方法
   public static void main(String[] args) throws Exception {
        try {
            // 实现处理接口impl
            ThriftHelloServiceImpl thriftHelloService = new ThriftHelloServiceImpl();
            // 创建TProcessor
            TProcessor processor = new ThriftHelloService.Processor<>(thriftHelloService);
            // 创建TServerTransport,非阻塞式I/O,服务端和客户端需要TFramedTransport 数据传输方式
            TNonblockingServerSocket tNonblockingServerSocket = new TNonblockingServerSocket(9099);
            // 创建TProtocol
            TThreadedSelectorServer.Args args1 = new TThreadedSelectorServer.Args(tNonblockingServerSocket);
            args1.transportFactory(new TFramedTransport.Factory());
            // 二进制格式反序列化
            args1.protocolFactory(new TBinaryProtocol.Factory());
            args1.processor(processor);
            args1.selectorThreads(16);
            args1.workerThreads(32);
            System.out.println("computer service server on port:" + 9099);
            TThreadedSelectorServer tThreadedSelectorServer = new TThreadedSelectorServer(args1);
            System.out.println("启动 Thrift 服务端");
            tThreadedSelectorServer.serve();
        } catch (Exception e) {
            System.out.println("启动 Thrift 服务端失败" + e.getMessage());
        }
    }

2.3.8 编写客户端

public static void main(String[] args) {

        TTransport transport = null;
        try {
            // 要跟服务器端的传输方式一致
            transport = new TFramedTransport(new TSocket("127.0.0.1", 9099, 6000));
            TProtocol protocol = new TBinaryProtocol(transport);
            ThriftHelloService.Client client = new ThriftHelloService.Client(protocol);
            transport.open();
            String result = client.sayHello("thrift-1");
            System.out.println(result);
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }
    }
  1. 启动验证
  • 服务端

image.png

  • 客户端
    image.png

验证成功,说明没有问题。

2.4 编写JMeter 插件

  1. 因为我们目的是要写jmeter插件,所以要集成JMeter对应的依赖包,详细参考上面的pom文件。
  2. 两种方式:
    1. 一种是继承 AbstractJavaSamplerClient ,此方式集成之后,直接打包,在jmeter当中选择,java请求即可验证功能。偏向于验证功能。
    2. 一种是继承 AbstractSampler 和 继承AbstractSamplerGui 此方式可以通过GUI 的方式,实现JMeter的调用。

ThriftClient (封装公用client)

ThriftHelloService.Client client = null;

    private TTransport tTransport = null;


    public ThriftClient(String ip, int port, int timeout) {
        try {
            // 注意传输协议要跟服务器端一致
            tTransport = new TFramedTransport(new TSocket(ip, port, timeout));
            TProtocol tProtocol = new TBinaryProtocol(tTransport);
            client = new ThriftHelloService.Client(tProtocol);
            tTransport.open();
        } catch (TTransportException e) {
            e.printStackTrace();
        }
    }

    public String getResponse(String str) {
        try {
            return client.sayHello(str);
        } catch (TException e) {
            e.printStackTrace();
            return null;
        }
    }

    public void close() {
        if (tTransport != null && tTransport.isOpen()) {
            tTransport.close();
        }
    }

2.4.1 继承AbstractJavaSamplerClient

 private ThriftClient thriftClient;

    /**
     * 方法为性能测试时的线程运行体;
     *
     * @param javaSamplerContext
     * @return
     */
    @Override
    public SampleResult runTest(JavaSamplerContext javaSamplerContext) {

        SampleResult sampleResult = new SampleResult();
        // 开始统计响应时间标记
        sampleResult.sampleStart();
        try {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            String response = thriftClient.getResponse("哈哈我是性能调试");
            stopWatch.stop();
            System.out.println(response + "总计花费:" + stopWatch.getTime());
            if (StringUtils.isNotBlank(response)) {
                sampleResult.setSuccessful(true);
                sampleResult.setResponseMessage(response);
            } else {
                sampleResult.setSuccessful(false);
                sampleResult.setResponseMessage("请求失败....");
            }
        } catch (Exception e) {
            sampleResult.setSuccessful(false);
            sampleResult.setResponseMessage("请求失败....");
        } finally {
            // 结束统计响应时间标记
            sampleResult.sampleEnd();
        }
        return sampleResult;
    }


    /**
     * 方法为初始化方法,用于初始化性能测试时的每个线程;
     *
     * @param context
     */
    @Override
    public void setupTest(JavaSamplerContext context) {
        String ip = context.getParameter("ip");
        String port = context.getParameter("port");
        String timeout = context.getParameter("timeout");
        // 初始化客户端
        thriftClient = new ThriftClient(ip, Integer.valueOf(port), Integer.valueOf(timeout));
        super.setupTest(context);
    }


    /**
     * 方法为测试结束方法,用于结束性能测试中的每个线程。
     *
     * @param context
     */
    @Override
    public void teardownTest(JavaSamplerContext context) {
        if (thriftClient != null) {
            thriftClient.close();
        }
        super.teardownTest(context);
    }

    /**
     * 方法主要用于设置传入界面的参数,初始化默认参数
     *
     * @return
     */
    @Override
    public Arguments getDefaultParameters() {
        Arguments jMeterProperties = new Arguments();
        jMeterProperties.addArgument("ip", "127.0.0.1");
        jMeterProperties.addArgument("port", "9099");
        jMeterProperties.addArgument("timeout", "6000");
        return jMeterProperties;
    }

  1. 写完之后直接打成jar包 。 mvn clean install
  2. 然后会看到生成两个包。 然后把对应的jar包放到 jmeter 的 lib/ext/ 下面.
  3. 注意: 如果打的是源码包要放源码包: 即ThriftDemo-1.0-1-jar-with-dependencies.jar
  4. jmeter 下面 lib 和 lib/ext 的区别: 一般我们自定义协议的包都会放到 lib/ext下面,当我们自定义里面的包有依赖第三方的依赖包,并且此时我们没有打成源码包的情况下,会将所依赖的第三方依赖包放置到 lib当中。
  5. 比如: 我在 lib/ext 下面放置的是 ThriftDemo-1.0-1.jar 包,这个并不是源码包。所以,还需要将项目当中pom文件所依赖的org.apache.libthrift 的jar包放置到 lib目录下面才行。否则在调用的时候,会提示找不到对应类(classNotFountException)的错误信息。

image.png

  • Jmeter 效果
  1. 放置好jar包之后,重启jmeter,java请求,就会看到自己编写的类。
  2. 下面是默认的参数。

image.png

服务端启动,即可验证成功。

2.4.2 继承AbstractSampler 和AbstractSamplerGui

  1. 这种方式的效果如下:

image.png
就是在jmeter当中写一个自己的sampler ,并且有对应ui页面。

2.4.2.1 ThriftSamplerUI

继承AbstractSamplerGui 编写gui的页面,跟java当中swing 一样。

package com.thrift.demo.gui;

import com.thrift.demo.jmeterTest.ThriftSampler;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.gui.JLabeledTextField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.awt.*;


/**
 * @author fit2cloudzhao
 * @date 2022/8/2 18:58
 * @description:
 */
public class ThriftSamplerUI extends AbstractSamplerGui {


    Logger log = LoggerFactory.getLogger(ThriftSamplerUI.class);
    private final JLabeledTextField serverIp = new JLabeledTextField("ServerIp");
    private final JLabeledTextField port = new JLabeledTextField("Port");
    private final JLabeledTextField param = new JLabeledTextField("Param");
    private void init() {
        log.info("Initializing the UI.");
        setLayout(new BorderLayout());
        setBorder(makeBorder());

        add(makeTitlePanel(), BorderLayout.NORTH);
        JPanel mainPanel = new VerticalPanel();
        add(mainPanel, BorderLayout.CENTER);

        JPanel DPanel = new JPanel();
        DPanel.setLayout(new GridLayout(3, 2));
        DPanel.add(serverIp);
        DPanel.add(port);
        DPanel.add(param);

        JPanel ControlPanel = new VerticalPanel();
        ControlPanel.add(DPanel);
        ControlPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray), "Parameters"));
        mainPanel.add(ControlPanel);
    }

    public ThriftSamplerUI() {
        super();
        this.init();
    }

    @Override
    public String getStaticLabel() {
        return "Thrift Sampler";
    }
    @Override
    public String getLabelResource() {
        throw new IllegalStateException("This shouldn't be called");
    }

    /**
     * 该方法创建一个新的Sampler,然后将界面中的数据设置到这个新的Sampler实例中。
     * @return
     */
    @Override
    public TestElement createTestElement() {
        ThriftSampler sampler = new ThriftSampler();
        this.setupSamplerProperties(sampler);
        return sampler;
    }


    private void setupSamplerProperties(ThriftSampler sampler) {
        this.configureTestElement(sampler);
        sampler.setServerIp(serverIp.getText());
        sampler.setPort(Integer.valueOf(port.getText()));
        sampler.setParam(param.getText());
    }


    /**
     * 这个方法用于把界面的数据移到Sampler中。
     * @param testElement
     */
    @Override
    public void modifyTestElement(TestElement testElement) {
        ThriftSampler sampler = (ThriftSampler) testElement;
        this.setupSamplerProperties(sampler);
    }


    /**
     * 界面与Sampler之间的数据交换
     * @param element
     */
    @Override
    public void configure(TestElement element) {
        super.configure(element);
        ThriftSampler sampler = (ThriftSampler) element;
        this.serverIp.setText(sampler.getServerIp());
        this.port.setText(sampler.getPort().toString());
        this.param.setText(sampler.getParam());
    }


    /**
     * 该方法会在reset新界面的时候调用,这里可以填入界面控件中需要显示的一些缺省的值(就是默认显示值)
     */
    @Override
    public void clearGui() {
        super.clearGui();
        this.serverIp.setText("服务端ip");
        this.port.setText("9099");
        this.param.setText("参数");
    }
}

2.4.2.2 ThriftSampler
package com.thrift.demo.jmeterTest;

import com.thrift.demo.client.ThriftClient;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.TestStateListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author fit2cloudzhao
 * @date 2022/8/2 21:45
 * @description:
 */
public class ThriftSampler extends AbstractSampler implements TestStateListener {

    Logger log = LoggerFactory.getLogger(ThriftSampler.class);
    private ThriftClient thriftClient;

    private static final String SERVER_IP = "server_ip";
    private static final String PORT = "port";

    private static final String PARAM = "request_param";


    public ThriftSampler() {
        setName("Thrift sampler");
    }

    @Override
    public SampleResult sample(Entry entry) {

        SampleResult sampleResult = new SampleResult();
        // 开始统计响应时间标记
        sampleResult.sampleStart();
        try {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            String param = getParam();
            String response = "";
            System.out.println("入参:" + param);
            log.info("入参:" + param);
            thriftClient = getThriftClient();
            if (StringUtils.isNotBlank(param)) {
                response = thriftClient.getResponse(param);
            } else {
                response = thriftClient.getResponse("我是空的");
            }
            System.out.println("response==>" + response);
            log.info("response==>" + response);
            stopWatch.stop();
            System.out.println(response + "总计花费:" + stopWatch.getTime());
            log.info(response + "总计花费:" + stopWatch.getTime());
            if (StringUtils.isNotBlank(response)) {
                sampleResult.setSuccessful(true);
                sampleResult.setResponseMessage(response);
                sampleResult.setResponseData(("请求成功:"+response).getBytes());
                sampleResult.setResponseCode("200");
            } else {
                sampleResult.setSuccessful(false);
                sampleResult.setResponseMessage("请求失败....请求参数:" + param);
                sampleResult.setResponseCode("500");
                sampleResult.setResponseData("请求失败".getBytes());
            }
        } catch (Exception e) {
            sampleResult.setSuccessful(false);
            sampleResult.setResponseMessage("请求失败...." + e.getMessage());
            sampleResult.setResponseCode("500");
            sampleResult.setResponseData(("请求失败...." + e.getMessage()).getBytes());
        } finally {
            // 结束统计响应时间标记
            sampleResult.sampleEnd();
        }
        return sampleResult;
    }


    public ThriftClient getThriftClient() {
        if (thriftClient == null) {
            thriftClient = new ThriftClient(getServerIp(), getPort(), 10000);
        }
        return this.thriftClient;
    }

    public String getServerIp() {
        return getPropertyAsString(SERVER_IP);
    }

    public Integer getPort() {
        return getPropertyAsInt(PORT);
    }


    public void setServerIp(String serverIp) {
        setProperty(SERVER_IP, serverIp);
    }

    public void setPort(Integer port) {
        setProperty(PORT, port);
    }

    public void setParam(String param) {
        setProperty(PARAM, param);
    }


    public String getParam() {
        return getPropertyAsString(PARAM);
    }

    @Override
    public void testStarted() {

    }

    @Override
    public void testStarted(String s) {

    }

    @Override
    public void testEnded() {
        this.testEnded("local");
    }

    @Override
    public void testEnded(String s) {

    }
}

  1. 这里的sample 方法跟继承AbstractJavaSamplerClient 里面的runTest方法差不多,都是写执行逻辑的,请求客户端的逻辑可以写在这里。
  2. 写完之后,进行打包,跟之前打包一样,需要把源码包放到jmeter lib/ext下面。
  3. 重启jmeter ,选择自己写的sampler ,就会看到下面的效果。
  4. 注意:如果打包完之后,看不到自己写的sampler,需要看下jmeter日志。会有错误日志的,根据错误信息进行进一步处理。

image.png

2.5 编写MS的插件

  1. 因为MS集成的JMeter,所以首先必须是JMeter支持的插件,其次在封装成MS的插件。
  2. 前面已经写了一个JMeter支持的Thrift插件了,现在只需要把这个插件给集成到MS插件里面就好了。
  3. 看一下我们要实现的效果。

image.png

2.5.1 MeterSphere 接口自动化插件基础开发教程

参考链接:
https://wiki.fit2cloud.com/pages/viewpage.action?pageId=67671925

metersphere-plugin-DummySampler

2.5.2 编写MS 的 Thrift 插件

  1. 新建一个maven项目 ,目录结构如下:

image.png

  1. 然后参考以上文章直接去改自己的逻辑就行。
  2. 这边有一点要注意:要把自己写的Thrfit的jar 给依赖进来。一定要是源码包!!!否则集成到MS当中会报错。跟在JMeter当中错误一样。
  3. 在resource创建 lib文件夹,然后把集成的第三方jar放进来,并且在pom文件中添加依赖。

image.png

  1. 然后进行打包就行。mvn clean install 打完包之后,一个MS的插件就封装好了,然后直接在MS的插件管理上传插件就行。

image.png

  1. 上传完插件之后,检查下后面的小眼睛,看下自己编写的表单内容是否有添加上来。如果没有,检查打包问题。
  2. 注意:MS删除插件必须重启ms-server服务才行,否则依赖的还是上一次的jar包。
  3. 上传完成之后在接口自动化会看到自己添加的插件信息

image.png

  1. 这个时候客户端写好了,如果是本地部署的,本地服务端直接启动就好。因为我这个是放到服务器上的,所以在把刚才的服务端给封装成docker镜像给放上去。
  2. 打开刚刚写的服务端的代码,打成jar包。具体方式如下:
  3. 打开Project Structure

image.png

  1. 选择Artifacts 添加一个jar包。

image.png

image.png

选择resource之后,就会看到下面生成的MANIFEST.MF 文件,打开会看到很多class,说明选择成功。
image.png

然后再build一下
image.png

image.png

build完之后会看到当前项目当中有一个out的文件夹
image.png

找到image.png

这个也就是我们打的jar包。到此,jar已经打包完成了,放置到有jdk的环境当中 java -jar 就可以起来了。

我们这边封装成docker 镜像的方式,方便启动。

2.5.2.1 封装Dockerfile
FROM fabric8/java-alpine-openjdk11-jre:latest  // 注意arm/amd 的区别

MAINTAINER FIT2CLOUD <support@fit2cloud.com>

RUN mkdir -p /opt/apps

ADD out/artifacts/ThriftDemo_jar /opt/apps

WORKDIR /opt/apps

EXPOSE 9099

CMD ["java","-jar","ThriftDemo.jar"]

然后执行打成镜像, 并上传到服务器当中。

docker build -t ms-thrift-server:1.0 .

docker save -o ms-thrift-server.tar ms-thrift-server:1.0

上传服务器,加载镜像并启动

docker load -i ms-thrift-server.tar  

docker run --name ms-thrift-server  -d -p 9099:9099 ms-thrift-server:1.0

docker ps  // 查看状态

docker logs -f ms-thrift-server  // 出现启动Thrift 服务端,即启动成功。

2.5.3 调试

万事俱备了,只欠最后一哆嗦。

  1. 填写对应的服务器的地址和端口,然后随便传一个参数,可以看到返回200 即链接成功。

image.png

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值