一、项目介绍(本项目用的编程语言是jdk8,项目源码: https://github.com/zhzhair/mybatis-druid-spring-boot.git)
  1.引入pom依赖:
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid-spring-boot-starter</artifactId>
      <version>1.1.14</version>
    </dependency>
  </dependencies>
  由引入的jar包可知,项目用MySQL + mybatis + redis架构,数据库连接池用阿里的druid

  2.配置文件application.yml配置(配置MySQL数据源、druid连接池及监控、redis):
  spring:
    datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: "jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false"
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      max-active: 100
      min-idle: 10
      max-wait: 60000
      filter:
        stat:
          merge-sql: true
          slow-sql-millis: 200
      test-on-borrow: true
      validation-query: SELECT 1
      use-global-data-source-stat: true
      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
      # http://127.0.0.1:8080/druid2/index.html
      filters: stat,wall,slf4j
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
    redis:
      host: 127.0.0.1
      password:
      database: 0
      timeout: PT1M1S
      jedis:
        pool.max-active: 200
        pool.max-idle: 50
        pool.max-wait: PT-1S
        pool.min-idle: 10

  table-num: 64

  3.引入druid配置类(sql和uri监控访问地址:http://localhost:8080/druid/index.html,用户名和密码分别是admin和123456):

    packagecom.example.demo.config.druid;importcom.alibaba.druid.support.http.StatViewServlet;importcom.alibaba.druid.support.http.WebStatFilter;importorg.springframework.boot.web.servlet.FilterRegistrationBean;importorg.springframework.boot.web.servlet.ServletRegistrationBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@Configurationpublic classDruidConfiguration {@BeanpublicServletRegistrationBean DruidStatViewServle2() {//org.springframework.boot.context.embedded.ServletRegistrationBean提供类的进行注册.ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid2/*");//添加初始化参数:initParamsservletRegistrationBean.addUrlMappings("/druid/*");//白名单://servletRegistrationBean.addInitParameter("allow","192.168.1.106");//IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.//servletRegistrationBean.addInitParameter("deny", "192.168.1.73");//登录查看信息的账号密码.servletRegistrationBean.addInitParameter("loginUsername","admin");servletRegistrationBean.addInitParameter("loginPassword","123456");//是否能够重置数据.servletRegistrationBean.addInitParameter("resetEnable","false");returnservletRegistrationBean;}@BeanpublicFilterRegistrationBean druidStatFilter2(){FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>(newWebStatFilter());filterRegistrationBean.setName("druidFilter2");//添加过滤规则.filterRegistrationBean.addUrlPatterns("/*");//添加不需要忽略的格式信息.filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid2/*");returnfilterRegistrationBean;}}

  4.在测试类创建表user_*和user_mobile_*:

    @RunWith(SpringRunner.class)@SpringBootTestpublic classDemoApplicationTests {@ResourceprivateTestUserService userService;@Testpublic voidcontextLoads() {userService.dropTables();userService.createTables();}}@Servicepublic class TestUserServiceImpl implementsTestUserService {@Resourceprivate UserMapper userMapper;//jdbc操作接口@Value("${table-num}")private int tableNum;//分表的个数
@Overridepublic voiddropTables() {IntStream.range(0,tableNum).parallel().forEach(this::dropTables);}private void dropTables(inti){userMapper.dropTable("user_" +i);userMapper.dropTable("user_mobile_" +i);}@Overridepublic voidcreateTables() {IntStream.range(0,tableNum).parallel().forEach(this::createTables);}private void createTables(inti){String suffix=String.valueOf(i);userMapper.createTableUser(suffix);userMapper.createTableUserMobile(suffix);}}

  5.编写restful风格的接口(包括登录和注册):

@RestController@RequestMapping("test/user")public class TestUserController extendsBaseController {@ResourceprivateTestUserService userService;@Resourceprivate TokenManager tokenManager;//给登录用户生成token,并放到redis@RequestMapping(value = "/loginByMobile", method = {RequestMethod.GET}, produces ={MediaType.APPLICATION_JSON_VALUE})public BaseResponse<LoginResponse>loginByMobile() {BaseResponse<LoginResponse> baseResponse = new BaseResponse<>();Integer userId=userService.getUserIdByMobile();if(userId != null){baseResponse.setCode(0);baseResponse.setMsg("手机号登录成功");String token=tokenManager.generateToken(userId);LoginResponse loginResponse= newLoginResponse();loginResponse.setUserId(userId);loginResponse.setToken(token);loginResponse.setExpire(System.currentTimeMillis()+ 3600 * 1000);baseResponse.setData(loginResponse);}else{baseResponse.setCode(-3);baseResponse.setMsg("手机号未注册");}returnbaseResponse;}@RequestMapping(value= "/register", method = {RequestMethod.POST}, produces ={MediaType.APPLICATION_JSON_VALUE})public BaseResponse<User>register() {BaseResponse<User> baseResponse = new BaseResponse<>();Integer userId=userService.getUserIdByMobile();if(userId == null){User user=userService.register();baseResponse.setCode(0);baseResponse.setData(user);baseResponse.setMsg("注册成功");}else{baseResponse.setCode(1);baseResponse.setMsg("手机号已被注册");}returnbaseResponse;}}@Servicepublic class TestUserServiceImpl implementsTestUserService {@ResourceprivateUserService userService;@Value("${table-num}")private int tableNum;//分表的个数
@OverridepublicInteger getUserIdByMobile() {returnuserService.getUserIdByMobile(getMobileStr());}@OverridepublicUser register() {UserRequest userRequest= newUserRequest();userRequest.setMobile(getMobileStr());userRequest.setIcon("http://127.0.0.1/"+getMobileStr()+".jpg");int rand = new Random().nextInt(4);userRequest.setNickname(new String[]{"xiaoming","xiaohong","xiaoqiang","xiaoli"}[rand]);returnuserService.register(userRequest);}/*** 模拟手机号*/privateString getMobileStr(){String[] strings= {"13","15","16","18"};String beginString= strings[new Random().nextInt(4)];int a = newRandom().nextInt(10_0000_0000);String endString=String.valueOf(a);int length = 9 -endString.length();StringBuilder stringBuilder= newStringBuilder(beginString);for (int i = 0; i < length; i++) {stringBuilder.append("0");}returnstringBuilder.append(endString).toString();}}    @Servicepublic class UserServiceImpl implementsUserService {private final String USER_ID_INC = "USER_ID_INC";@Resourceprivate UserMapper userMapper;//jdbc操作接口@Resource(name = "stringRedisTemplate")private RedisTemplate<String, String>redisTemplate;@Value("${table-num}")private int tableNum;//分表的个数
@Transactional(isolation=Isolation.REPEATABLE_READ)@OverridepublicUser register(UserRequest userRequest) {String usercode=redisTemplate.opsForValue().get(USER_ID_INC);Integer userId;if(usercode == null){//如果redis的数据丢失,就找出最大的userId,并给USER_ID_INC赋值int temp = 0;for (int i = 0; i < tableNum; i++) {Integer maxUserId=userMapper.getMaxUserId(String.valueOf(i));if(maxUserId != null && temp <maxUserId){temp=maxUserId;}}userId= temp + 1;redisTemplate.opsForValue().set(USER_ID_INC,String.valueOf(userId));}else{Long num= redisTemplate.opsForValue().increment(USER_ID_INC,1);userId= Integer.valueOf(num + "");}User user= newUser();user.setUserId(userId);user.setMobile(userRequest.getMobile());user.setIcon(userRequest.getIcon());user.setNickname(userRequest.getNickname());int rem = userId %tableNum;userMapper.insertUser(user,String.valueOf(rem));int rem0 = Math.abs(userRequest.getMobile().hashCode()) %tableNum;String mobile=userRequest.getMobile();userMapper.insertUserMobile(mobile,userId,String.valueOf(rem0));returnuser;}@OverridepublicInteger getUserIdByMobile(String mobile) {int rem = Math.abs(mobile.hashCode()) %tableNum;returnuserMapper.getUserByMobile(mobile,String.valueOf(rem));}}

二、用jmeter做并发测试(jmeter版本4.0):
  1.双击打开bin目录下的jmeter.bat文件,菜单选简体中文:Options->Choose language->Chinese(Simplified)。点文件夹图标可以选择已有的jmeter脚本。

  2.右键测试计划->添加->Threads(Users)->线程组,然后配置执行线程数、持续时间等信息。登录和注册我都建了单独的线程组,其中:登录的线程数36000,持续时间600秒;注册的线程数6000,持续时间600秒。
  3.右键测试计划->添加->监听器->(查看结果数和聚合报告等,用于分析并发测试结果)。
  4.分别右键选中登录和注册的线程组->添加->sampler->HTTP请求,配置如下:
登录和注册的协议都填http,IP都填127.0.0.1,端口号都填8080。登录的方式选GET,注册的方式选POST。登录的路径填/test/user/loginByMobile,注册的路径填/test/user/register。
  5.点击打开聚合报告,启动项目,点击菜单栏绿色的三角形图标运行,观察聚合报告的结果如下图所示:

三、查看druid的sql监控和uri监控:
  jmeter运行时,访问http://localhost:8080/druid/index.html,sql监控和webUI等监控结果如图所示:

转载于:https://www.cnblogs.com/zhzhair-coding/p/10657971.html

spring boot2.0.4集成druid,用jmeter并发测试工具调用接口,druid查看监控的结果相关推荐

  1. JMeter——并发测试工具类安装及使用

    关注微信公众号:CodingTechWork,一起学习进步. 引言   在程序员开发完代码后,我们需要先自测,对于restful风格的代码,我们常常需要调用接口api进行测试,一般我们会在浏览器上直接 ...

  2. Spring Boot2.0+中,自定义配置类扩展springMVC的功能

    在spring boot1.0+,我们可以使用WebMvcConfigurerAdapter来扩展springMVC的功能,其中自定义的拦截器并不会拦截静态资源(js.css等). @Configur ...

  3. Mongodb网页管理工具,基于Spring Boot2.0,前端采用layerUI实现

    源码:https://github.com/a870439570/Mongodb-WeAdmin 项目介绍 Mongodb网页管理工具,基于Spring Boot2.0,前端采用layerUI实现. ...

  4. Spring Boot2.0之性能优化

    1.JVM参数调优   针对运行效果  吞吐量    初始堆内存与最大堆尽量相同   减少垃圾回收次数  2.扫包优化: 启动优化 默认Tomcat容器改为Undertow Tomcat的吞吐量500 ...

  5. jmeter并发测试教程_JMeter压力测试并发测试(入门篇)

    jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全,使用方便,是一个比较轻量级的测试工具,使用起来非常简单.因为jmeter是java开发的,所以运行的时候必须先要安 ...

  6. Jmeter并发测试:重现插入重复数据问题

    Jmeter  压力测试工具 直接上图 查询重复数据如下: select count(order_id),order_id,report_type from t_mapping_order_repor ...

  7. jmeter并发测试报错

    jmeter并发测试报错 请大神给指点一下是因为什么报错,并发循环1-5次的时候不会报错,循环多次就开始报错了.

  8. Spring Boot2.0 整合mybatis、分页插件、druid

    2019独角兽企业重金招聘Python工程师标准>>> 前言 本文主要是针对SpringBoot2.0.2版本,实现整合mybatis.分页插件.druid等组件,实现完整的web服 ...

  9. spring boot2.0整合富文本编辑器summernote

    summernote对上传图片,以及对图片大小细节,删除图片移除服务器资源等处理的比较完美. 整合过程,summernote的官网https://summernote.org/getting-star ...

  10. 【redis】在spring boot2.0中使用redis的StringRedisTemplate 自动注入@Autowired

    1.使用opv.increment 达到增量的效果[判断某个用户 是第几次做这种操作] @RequestMapping("createCode") @RestController ...

最新文章

  1. Linux疑难杂症解决方案100篇(二)-SHELL编程函数的定义及调用
  2. python 常用内置函数
  3. Petya and Exam 模拟
  4. 网优5g前景_网优行业的吐槽,附吐槽记录
  5. Python关键字和标识符
  6. pkgm : 压缩包维护与解压脚本
  7. web 前端签名插件_10款前端开发神器,助你成前端高手?
  8. NSIS安装或卸载时检查程序是否正在运行
  9. C++ fork函数理解
  10. Google浏览器安装插件
  11. 笔记本win10玩红警黑屏_你的红警还黑屏吗?
  12. “阿里云OS”是如何失控的
  13. 一、DC DC电源转换电路设计
  14. 软件外包交易平台排行
  15. 计算机数控编程特点,什么是数控图像编程系统有哪些特点
  16. 计算机怎样将多行文字转换成表格,怎么把表格里的字变成两行
  17. 关于三代基因测序,你所需要知道的都在这儿!
  18. 判断和推论_数据科学的假设和推论
  19. 什么是Ceph?听听Ceph创始人怎么说
  20. 动画云创始人胥克谦课程格子创始人李天放分享创业经历

热门文章

  1. salesforce 零基础学习(三十二)通过Streams和DOM方式读写XML
  2. mac git 拉代码太慢或是拉不下来,可能是这个原因
  3. 如何修改硬盘挂载的名字LABEL
  4. ubuntu虚拟环境
  5. 用Vue.js和Webpack开发Web在线钢琴
  6. python学习笔记之module package
  7. 解读absolute与relative(转载)
  8. Monkeyrunner介绍
  9. 【cocos2d-x 手游研发小技巧(4)与Android混编实现换“头像图片”】
  10. String类基础的那些事!