docker-compose安装
这个安装比较简单,执行下面三个步骤就完事了😀
docker-compose官网地址: docs.docker.com/compose/ins…
安装步骤如下:✌
下载docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 复制代码
赋予权限
sudo chmod +x /usr/local/bin/docker-compose 复制代码
查看版本
docker-compose --version 复制代码
配置文件
准备好下面两个配置文件。😄
docker-compose.yml
博主把 easymock 相关文件映射到 /home/ryzeyang/easymock
目录下,小伙伴们可以修改成自己的😄
version: '3' services: mongodb: image: mongo:3.4.1 volumes: # ./data/db 数据库文件存放地址,根据需要修改为本地地址 - '/home/ryzeyang/easymock/data/db:/data/db' networks: - easy-mock restart: always redis: image: redis:4.0.6 command: redis-server --appendonly yes volumes: # ./data/redis redis 数据文件存放地址,根据需要修改为本地地址 - '/home/ryzeyang/easymock/data/redis:/data' networks: - easy-mock restart: always web: image: easymock/easymock:1.6.0 command: /bin/bash -c "npm start" ports: - 7300:7300 volumes: # 日志地址,根据需要修改为本地地址 - '/home/ryzeyang/easymock/logs:/home/easy-mock/easy-mock/logs' # 配置地址,请使用本地配置地址替换 - '/home/ryzeyang/easymock/production.json:/home/easy-mock/easy-mock/config/production.json' networks: - easy-mock restart: always networks: easy-mock: 复制代码
production.json
这是根据官网提示修改好了的版本。😋
{ "port": 7300, "host": "0.0.0.0", "pageSize": 30, "proxy": false, "db": "mongodb://mongodb/easy-mock", "unsplashClientId": "", "redis": { "keyPrefix": "[Easy Mock]", "port": 6379, "host": "redis", "password": "", "db": 0 }, "blackList": { "projects": [], "ips": [] }, "rateLimit": { "max": 1000, "duration": 1000 }, "jwt": { "expire": "14 days", "secret": "shared-secret" }, "upload": { "types": [".jpg", ".jpeg", ".png", ".gif", ".json", ".yml", ".yaml"], "size": 5242880, "dir": "../public/upload", "expire": { "types": [".json", ".yml", ".yaml"], "day": -1 } }, "ldap": { "server": "", "bindDN": "", "password": "", "filter": { "base": "", "attributeName": "" } }, "fe": { "copyright": "", "storageNamespace": "easy-mock_", "timeout": 25000, "publicPath": "/dist/" } } 复制代码
启动
创建配置文件中对应logs文件夹(不然后面跑起来会报权限问题)
如:Error: EACCES: permission denied
可以通过xftp将上面的配置文件上传到easymock
目录下,然后执行下面的命令启动docker-compose up
,这样不会在后台运行,然后你就可以看到项目是否成功跑起来了🐷
注意!connect EHOSTUNREACH 错误
这是因为我们是通过network
去实现容器间的互联,这也是为什么配置里要改成mogodb
和redis
,而不能用localhost
🐷
这两个名字其实就是我们dockerfile文件中,services下的服务名称
简单粗暴的方法如下:
如果启动不了!注意查看下防火墙!!
遇上这种情况,直接关闭防火墙sudo systemctl stop firewalld.service
就可以了😄
关闭防火墙后需要重启docker systemctl restart docker.service
后台运行docker-compose up -d
访问地址:http://192.168.80.128:7300
换成自己的ip即可😁
效果如下
环境搭好后,我们就可以来 mock 数据啦,如下!😄
Springboot2+Quartz+MybatisPlus+easymock
主要功能:
通过easymock模拟数据,使用restTemplate去获取这些mock数据,结合Jackson将json转换成实体类,利用 MybatisPlus 批量存储数据, 通过 Quartz 实现一个定时 job ,重复执行上面的步骤。
帮助小伙伴们快速熟悉这个MP的使用和了解下Easymock😄
这事其实是发生在 S10 那天,那会在研究 Mysql 的 Innodb 索引这些 ~ 一边看着比赛,一边想着造点乱七八糟的数据填下DB 并尝试下这个 MybaitsPlus 和用这个 easymock 去 mock 些数据😝
Mysql
看了下时间,有两百多万条了~
建表Sql以下面这一份为主! 其他文章里忘了改了(直接使用了测试时的,有些不一样)
-- 创建user表 CREATE TABLE `test_user` ( `id` int(0) NOT NULL AUTO_INCREMENT, `user_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户ID', `user_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名称', `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '手机号码', `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '邮箱', `ip` varbinary(4) NOT NULL COMMENT 'IP', `create_time` datetime(0) NOT NULL COMMENT '创建时间', `update_time` datetime(0) NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; 复制代码
Easymock
数据格式如下图:
点击预览可以看到下图:
Json格式文本
这里500-2000 主要是根据自己的机器去配置的,记得easymock中超时时间是1s来着好像,设置太大可能会超时😱
{ "data|500-2000": [{ "userId": '@guid', "userName": '@cname', "phone": /^1[385][1-9]\d{8}/, "email": "@email", "ip": "@ip", "createTime": "@datetime('yyyy-MM-dd HH:mm:ss')" }] } 复制代码
主要代码
Job概要
通过 RestTemplate 去获取 mock 数据,使用 Jackson 解析获取 User 信息并反序列化成对象,注意这里 User 实体的 createTime 属性是 LocalDateTime ,需要加上那两行代码! 否则 Jackson无法帮我们完成这个反序列化。
package com.java4ye.demo.job; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.java4ye.demo.entity.User; import com.java4ye.demo.service.IUserService; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobKey; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.util.StopWatch; import org.springframework.web.client.RestTemplate; import java.util.List; /** * @author Java4ye * @date 2021/1/11 23:16 * @微信公众号: Java4ye * @GitHub https://github.com/RyzeYang * @博客 https://blog.csdn.net/weixin_40251892 */ @Slf4j public class GetMockUserJob extends QuartzJobBean { @Autowired RestTemplate restTemplate; @Autowired IUserService userService; @SneakyThrows @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { JobKey key = jobExecutionContext.getJobDetail().getKey(); log.info("GetMockUserJob start: "); ResponseEntity<String> forEntity = restTemplate.getForEntity("http://192.168.80.128:7300/mock/5f8c1175994a570020e4dfe4/user/arry#!method=get", String.class); HttpStatus statusCode = forEntity.getStatusCode(); if (statusCode.is2xxSuccessful()) { String body = forEntity.getBody(); ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNode = objectMapper.readTree(body); JsonNode data = jsonNode.get("data"); System.out.println(data); // LocalDateTime 的解决方案 objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.registerModule(new JavaTimeModule()); JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, User.class); List<User> users = objectMapper.readValue(data.toString(), javaType); StopWatch stopWatch = new StopWatch("save mock users"); stopWatch.start("save mock users"); // 插入一个用户试试 User user = users.get(0); userService.save(user); // 批量插入用户 // userService.saveBatch(users,5000); stopWatch.stop(); System.out.println(stopWatch.prettyPrint()); } } } 复制代码
UserMapper 文件
重写insert方法,主要是为了 自定义 IP 字段 INET6_NTOA(ip)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.java4ye.demo.mapper.UserMapper"> <resultMap id="BaseResultMap" type="com.java4ye.demo.entity.User"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="user_id" jdbcType="VARCHAR" property="userId" /> <result column="user_name" jdbcType="VARCHAR" property="userName" /> <result column="phone" jdbcType="VARCHAR" property="phone" /> <result column="email" jdbcType="VARCHAR" property="email" /> <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> </resultMap> <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.java4ye.demo.entity.User"> <result column="ip" jdbcType="VARBINARY" property="ip"/> </resultMap> <sql id="Base_Column_List"> id, user_id, user_name, phone, email, create_time, update_time </sql> <sql id="Blob_Column_List"> INET6_NTOA(ip) </sql> <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.java4ye.demo.entity.User" useGeneratedKeys="true"> insert into test_user (user_id, user_name, phone, email, create_time, update_time, ip) values (#{userId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}, INET6_ATON(#{ip,jdbcType=VARBINARY})) </insert> </mapper> 复制代码
运行效果
插入单条数据
批量插入
可以看到这里插入 873 个用户用了 1781ms