dubbo-demo实例写作

这是我对Dubbo服务开展性能测试所做准备的第二篇学习笔记,编写了一对Dubbo-Demo实例。主要参照的原帖:http://www.cnblogs.com/miaomiaokaixin/p/6129733.html

由于原作者这篇指导文章写作的时间是2016年,使用的依赖包版本较旧;在学习的过程中,改用了较新版本的Maven依赖,同时遇到一些错误。本文的写作目的在于及时的记录下学习过程、应对问题的解决等。

 

本文讲解jmeter测试dubbo接口的实现方式,文章以一个dubbo的接口为例子进行讲解,该dubbo接口实现的功能为:

 

 

如果想搭建Dubbo学习环境,请看另一篇文档《搭建Dubbo开发学习环境》。

 

 

 

一、      服务端的工程

代码架构如下:

 

 

1、        创建一个Maven工程,取名:demo_dubbo_provider

POM文件为:

<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/xsd/maven-4.0.0.xsd">

       <modelVersion>4.0.0</modelVersion>

       <groupId>com.ustc.demo.provider</groupId>

       <artifactId>demo_dubbo_provider</artifactId>

       <version>0.0.1-SNAPSHOT</version>

       <packaging>jar</packaging>

      

       <name>dubbo-provider</name>

       <url>http://maven.apache.org</url>

      

       <properties>

              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

       </properties>

      

       <dependencies>

             

              <!-- https://mvnrepository.com/artifact/junit/junit -->

              <dependency>

                     <groupId>junit</groupId>

                     <artifactId>junit</artifactId>

                     <version>4.12</version>

                     <scope>test</scope>

              </dependency>

             

              <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->

              <dependency>

                     <groupId>com.alibaba</groupId>

                     <artifactId>dubbo</artifactId>

                     <version>2.6.1</version>

              </dependency>

             

              <!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->

              <dependency>

                     <groupId>com.github.sgroschupf</groupId>

                     <artifactId>zkclient</artifactId>

                     <version>0.1</version>

              </dependency>

             

              <dependency>

            <groupId>org.apache.zookeeper</groupId>

            <artifactId>zookeeper</artifactId>

            <version>3.4.12</version>

        </dependency>

             

              <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->

              <dependency>

                     <groupId>org.springframework</groupId>

                     <artifactId>spring-context</artifactId>

                     <version>5.0.5.RELEASE</version>

              </dependency>

               

              <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->

              <dependency>

                  <groupId>org.apache.curator</groupId>

                  <artifactId>curator-framework</artifactId>

                  <version>4.0.1</version>

              </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>2.6.1</version>

                                                               <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>

                                   <encoding>UTF-8</encoding>

                            </configuration>

                            <executions>

                                   <execution>

                                          <id>make-assembly</id>

                                          <phase>package</phase>

                                          <goals>

                                                 <goal>single</goal>

                                          </goals>

                                   </execution>

                            </executions>

                     </plugin>

              </plugins>

       </build>

 

</project>

 

2、        在src/main下新建文件夹assembly,然后在assembly文件夹下新建assembly.xml文件

<?xml version="1.0" encoding="UTF-8"?>

<assembly>

       <id>assembly</id>

       <formats>

              <format>tar.gz</format>

       </formats>

       <includeBaseDirectory>true</includeBaseDirectory>

       <fileSets>

              <fileSet>

                     <directory>${project.build.directory}/dubbo/META-INF/assembly/bin</directory>

                     <outputDirectory>bin</outputDirectory>

                     <fileMode>0755</fileMode>

              </fileSet>

              <fileSet>

                     <directory>src/main/assembly/conf</directory>

                     <outputDirectory>conf</outputDirectory>

                     <fileMode>0644</fileMode>

              </fileSet>

       </fileSets>

       <dependencySets>

              <dependencySet>

                     <outputDirectory>lib</outputDirectory>

              </dependencySet>

       </dependencySets>

</assembly>

 

3、        在src/main/assembly文件夹下新建conf文件夹,然后在conf文件夹下新建dubbo.properties文件。文件中zookeeper的地址根据实际进行修改。

dubbo.container=log4j,spring

dubbo.application.name=demo-dubbo-provider

dubbo.application.owner=jason

#dubbo.registry.address=multicast://127.0.0.1:1234

dubbo.registry.address=zookeeper://192.168.8.241: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-provider.log

#dubbo.log4j.level=WARN

 

4、        在src/test/resources包路径下,新建dubbo.properties文件,内容和上面3的dubbo.properties文件内容相同。

 

5、        在src/test/resources路径下,新建log4j.xml文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

 

       <!-- Appenders -->

       <appender name="console" class="org.apache.log4j.ConsoleAppender">

              <param name="Target" value="System.out" />

              <layout class="org.apache.log4j.PatternLayout">

                     <param name="ConversionPattern" value="%-5p: %c - %m%n" />

              </layout>

       </appender>

      

       <appender name="myFile" class="org.apache.log4j.RollingFileAppender">   

        <param name="File" value="logs/output.log" /><!-- 设置日志输出文件名 --> 

        <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 --> 

        <param name="Append" value="true" /> 

        <param name="MaxBackupIndex" value="10" /> 

        <layout class="org.apache.log4j.PatternLayout"> 

            <param name="ConversionPattern" value="%p (%c:%L)- %m%n" /> 

        </layout> 

    </appender>

      

       <!-- Application Loggers -->

       <logger name="com.ustcinfo.ishare.eip.si">

              <level value="error" />

       </logger>

      

       <!-- 3rdparty Loggers -->

       <logger name="org.springframework.core">

              <level value="warn" />

       </logger>     

      

       <logger name="org.springframework.beans">

              <level value="info" />

       </logger>

      

       <logger name="org.springframework.context">

              <level value="info" />

       </logger>

 

       <logger name="org.springframework.web">

              <level value="info" />

       </logger>

       <logger name="org.mongodb.driver">

              <level value="warn" />

       </logger>

 

       <!-- Root Logger -->

       <root>

              <priority value="error" />

              <appender-ref ref="console" />

       </root>

      

</log4j:configuration>

 

下面开始编写provider的主方法:

 

 

6、        编写provider的接口sayHello,新建DemoService.java类:

package com.ustc.demo.provider;

 

public interface DemoService {

       public String sayHello(String name);

}

 

7、        编写sayHello接口的实现类,新建DemoServiceImpl.java类:

package com.ustc.demo.provider;

 

import java.text.SimpleDateFormat;

import java.util.Date;

 

public class DemoServiceImpl implements DemoService {

 

       @Override

       public String sayHello(String name) {

              // TODO Auto-generated method stub

              String time = new SimpleDateFormat("HH:mm:ss").format(new Date());

        System.out.println("From consumer: " + name);

       

        return "The current time is:" + time;

       }

      

}

 

8、        编写spring的配置文件,在META-INF/spring文件夹下的demo-provider.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" 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">

       <bean id="demoService" class="com.ustc.demo.provider.DemoServiceImpl" />

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

       <dubbo:protocol name="dubbo" host="192.168.9.107" port="20880" /> 

       <dubbo:service interface="com.ustc.demo.provider.DemoService" ref="demoService"/>

</beans>

dubbo:registry address:服务注册于zookeeper所在的服务器;

dubbo:protocol host:服务提供方provider运行的服务器,添加Host字段可以避免其他机器上的消费方无法访问提供方。

 

9、        编写测试main方法,新建DemoServiceMain.java类:

 

package com.ustc.demo.provider;

 

public class DemoServiceMain {

       public static void main(String[] args) {            

              com.alibaba.dubbo.container.Main.main(args);

       }

}

 

这样服务端的代码就写好了,实现的功能是当消费者来询问当前时间是几点的时候,返回当前时间。

 

二、      消费端的工程

代码架构如下:

 

 

1、        创建一个Maven工程,取名:demo_dubbo_consumer

POM文件为:

<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/xsd/maven-4.0.0.xsd">

       <modelVersion>4.0.0</modelVersion>

       <groupId>com.ustc.demo.consumer</groupId>

       <artifactId>demo_dubbo_comsumer</artifactId>

       <version>0.0.1-SNAPSHOT</version>

      

       <packaging>jar</packaging>

       <name>consumer</name>

       <url>http://maven.apache.org</url>

      

       <properties>

              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

       </properties>

      

       <dependencies>

             

              <!-- https://mvnrepository.com/artifact/junit/junit -->

              <dependency>

                     <groupId>junit</groupId>

                     <artifactId>junit</artifactId>

                     <version>4.12</version>

                     <scope>test</scope>

              </dependency>

             

              <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->

              <dependency>

                     <groupId>com.alibaba</groupId>

                     <artifactId>dubbo</artifactId>

                     <version>2.6.1</version>

              </dependency>

             

              <!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->

              <dependency>

                     <groupId>com.github.sgroschupf</groupId>

                     <artifactId>zkclient</artifactId>

                     <version>0.1</version>

                     <exclusions>

                            <exclusion>

                                   <groupId>log4j</groupId>

                                   <artifactId>log4j</artifactId>

                            </exclusion>

                     </exclusions>

              </dependency>

             

              <dependency>

            <groupId>org.apache.zookeeper</groupId>

            <artifactId>zookeeper</artifactId>

            <version>3.4.12</version>

            <exclusions>

                  <exclusion>

                         <groupId>log4j</groupId>

                         <artifactId>log4j</artifactId>

                  </exclusion>

                  <exclusion>

                         <groupId>org.slf4j</groupId>

                         <artifactId>slf4j-log4j12</artifactId>

                  </exclusion>

            </exclusions>

              </dependency>

             

              <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->

              <dependency>

                  <groupId>org.apache.curator</groupId>

                  <artifactId>curator-framework</artifactId>

                  <version>4.0.1</version>

              </dependency>

             

              <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->

              <dependency>

                     <groupId>org.springframework</groupId>

                     <artifactId>spring-core</artifactId>

                     <version>5.0.5.RELEASE</version>

              </dependency>

             

              <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->

              <dependency>

                     <groupId>org.springframework</groupId>

                     <artifactId>spring-context</artifactId>

                     <version>5.0.5.RELEASE</version>

              </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>2.6.1</version>

                                    <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>

PS:上面文件中,有几处对log4j注释的地方,主要的原因是在最后build的时候,会提示工程中存在多个版本的log4j、产生冲突;因此对几处较旧的版本进行了排除。

 

2. 在src/main下新建文件夹assembly,然后在assembly文件夹下新建assembly.xml文件。文件内容和Provider工程中的同名文件相同。

 

3. 在src/main/assembly文件夹下新建conf文件夹,然后在conf文件夹下新建dubbo.properties文件。文件内容和Provider工程中的同名文件相同。

 

4. 在src/test/resources包路径下,新建dubbo.properties文件,内容和上面的3中dubbo.properties文件内容相同。

 

5. 编写provider的接口sayHello,新建DemoService.java类:

 

package com.ustc.demo.provider;

 

public interface DemoService {

       public String sayHello(String name);

}

 

6. 编写消费端请求类调用sayHello方法,新建DemoAction.java类

package com.ustc.demo.consumer;

 

import com.ustc.demo.provider.DemoService;

 

public class DemoAction {

       private DemoService demoService;

 

    public void setDemoService(DemoService demoService) {

        this.demoService = demoService;

    }

   

    public void start() throws Exception {

        for (int i = 0; i < Integer.MAX_VALUE; i ++) {

            try {

                String hello = demoService.sayHello("Hello, how much is the current time?");

                System.out.println("From provider: " + hello);

            } catch (Exception e) {

                e.printStackTrace();

            }

            Thread.sleep(2000);

        }

    }

}

 

7. 编写spring的配置文件,在META-INF/spring文件夹下的dubbo-demo-action.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" 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">

       <bean class="com.ustc.demo.consumer.DemoAction" init-method="start">

              <property name="demoService" ref="demoService" />

       </bean>

</beans>

 

8. 编写spring的配置文件,在META-INF/spring文件夹下的dubbo-demo-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"

    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:reference id="demoService"

        interface="com.ustc.demo.provider.DemoService" />

</beans>

 

9. 编写测试main方法,新建DemoConsumerMain.java类:

 

package com.ustc.demo.consumer;

 

public class DemoConsumerMain {

       public static void main(String[] args) {

              com.alibaba.dubbo.container.Main.main(args);

       }

}

 

10. 编写log4j2的配置文件,在src/main/resources目录下创建log4j2.xml文件:

<?xml version="1.0" encoding="UTF-8"?>

<Configuration status="warn">

       <Appenders>

              <Console name="Console" target="SYSTEM_OUT">

                     <PatternLayout pattern="%m%n" />

              </Console>

       </Appenders>

       <Loggers>

              <Root level="INFO">

              <AppenderRef ref="Console" />

       </Root>

       </Loggers>

</Configuration>

 

这样我们就完成了本地消费者代码,在编写符合jmeter格式的代码前,我们首先在本地开发工具中运行看看效果。

先启动服务提供方的main方法,然后启动服务消费方的main方法:

 

服务提供方控制台:

 

 

服务消费方控制台:

 

 

这样调试发现消费端向服务端发送:“How much is the current time?”

然后服务端返回当前的时间,该dubbo接口的功能正常实现。

 

三、      用JMeter模拟消费方

我们现在想对dubbo接口进行性能测试,可以用jmeter模拟服务消费方并发调用服务提供方。因为jmeter支持java请求,故我们可以将服务提供方打包部署到服务器上运行,将服务消费方打成jar包放到jmeter的/lib/ext文件夹中,这样就能实现jmeter模拟消费方去请求服务端,进行性能测试。

现在我们来讲解如何将上面的服务消费端的代码编写成可以打包放到jmeter中的jar包代码。

只需要对上面的消费者代码进行3处修改即可:

  1. POM.xml文件

pom.xml文件中添加对jmeter的支持,在<dependencies></dependencies>之间添加如下代码:

       <!-- java jmeter依赖jar包 -->

              <dependency>

                     <groupId>org.apache.jmeter</groupId>

                     <artifactId>ApacheJMeter_core</artifactId>

                     <version>3.3</version>

              </dependency>

              <dependency>

                     <groupId>org.apache.jmeter</groupId>

                     <artifactId>ApacheJMeter_java</artifactId>

                     <version>3.3</version>

              </dependency>

 

  1. 在src/main/resources下新建applicationConsumer.xml文件,zookeeper地址根据需要进行修改:

<?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.xsd 

        http://code.alibabatech.com/schema/dubbo 

        http://code.alibabatech.com/schema/dubbo/dubbo.xsd 

        "> 

 

    <!-- consumer application name --> 

    <dubbo:application name="consumer-jmeter" /> 

    <!-- registry address, used for consumer to discover services --> 

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

    <!-- which service to consume? --> 

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

</beans>

 

  1. 在com.ustc.demo.consumer包下新建JmeterDemoAction.java类:

package com.ustc.demo.consumer;

 

import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;

import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;

import org.apache.jmeter.samplers.SampleResult;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.AbstractApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import com.ustc.demo.provider.DemoService;

 

public class JmeterDemoAction extends AbstractJavaSamplerClient {

      

       ApplicationContext context = null;

       public DemoService demoService = null;

      

       public void setupTest(JavaSamplerContext arg0) {

              context = new ClassPathXmlApplicationContext("applicationConsumer.xml");

              ((AbstractApplicationContext) context).start();

              demoService = (DemoService) context.getBean("demoService");

       }

             

       @Override

       public SampleResult runTest(JavaSamplerContext arg0) {

              SampleResult sr = new SampleResult();

             

              try {   

            sr.sampleStart();

            // 将Request内容输出到Jmeter-查看结果树的请求页面

            sr.setSamplerData("From consumer: Hello, how much is the current time?");

            sr.setDataType(SampleResult.TEXT);

            // 调用provider的demoService.sayHello方法

            String response = demoService.sayHello("Hello, how much is the current time?");

            // 填写Jmeter-查看结果树的取样器结果

            sr.setResponseCodeOK();

            sr.setResponseMessage("Java Sampler Response is done. ");

            // 将Response内容输出到Jmeter-查看结果树的响应数据页面

            sr.setResponseData("From provider: " + response, "utf-8");

            sr.setDataType(SampleResult.TEXT);

            // 标记成功,并停止采样

            sr.setSuccessful(true);

            sr.sampleEnd();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return sr;

       }

      

       @SuppressWarnings("deprecation")

       public void teardownTest(JavaSamplerContext arg0) {

              if(null != context){

              ((AbstractApplicationContext) context).destroy();

              }

       }

      

      

       // 供调试使用;打包前记得注释掉 main 方法

       public static void main(String[] args) {

              JmeterDemoAction test = new JmeterDemoAction();

              test.setupTest(null);

              test.runTest(null);

              test.teardownTest(null);

              System.exit(0);           

       }

      

}

 

这样就完成了jmeter的消费端代码编写。

 

四、      Maven Install打包消费端工程

打包完成后可以看到消费端的target下生成了两个文件:
一个demo_dubbo_comsumer-0.0.1-SNAPSHOT.jar;
一个demo_dubbo_comsumer-0.0.1-SNAPSHOT-assembly.tar.gz。

 

-      创建一个新的dependency-demo_dubbo_consumer文件夹;将consumer-0.0.1-SNAPSHOT-assembly.tar.gz中的lib文件夹下所有的jar包解压到dependency-demo_dubbo_consumer文件夹下,然后将此文件夹拷贝到jmeter的lib/目录下。

-      将consumer-0.0.1-SNAPSHOT.jar拷贝到jmeter的lib/ext目录下。

 

由于在这个Demo中,我没有打包服务提供方的工程,因此Jmeter模拟消费方的执行过程中,在Eclipse中Provider工程的main方法要保持运行。

在Dubbo-Admin页面查看的情况如下:

 

 

五、      创建Jmeter模拟的消费方测试脚本

  1. 引用测试依赖的jar文件

测试计划 – Add directory or jar to classpath - 点击浏览、定位到dependency-demo_dubbo_consumer文件夹,之后按Enter键就可以全部引入到classpath中。

 

 

2.创建一个Java请求

添加一个线程组、添加Sampler – Java Sampler;

选中刚刚编写的consumer.JmeterDemoAction:

 

 

3.添加结果查看器

添加监听器:结果查看器、聚合报告。

 

4.简单的执行

修改线程组的设置:

希望以20个线程启动执行,循环10次:

 

 

启动测试执行:

查看聚合报告:

 

 

查看结果树:

  

 

在Dubbo-Admin页面查看到如下:

 

由于脚本中做了优化,不会过多创建消费方,仅为Jmeter执行时启动的线程数量。

 

posted @ 2018-08-28 11:40  来自火星的莹莹  阅读(357)  评论(0编辑  收藏  举报