通过js fetch() 模拟后台接口的并发测试

java哥 阅读:679 2021-03-31 16:57:49 评论:0

业务需求:今天开发人员向我反馈,说之前的旧系统存在,在高并发的情况下,会产生流水发号重新的现象。

说是迟,写是快。快速写完高并发情况下的流水号生成服务。核心代码如下:

@Controller 
@RequestMapping("/api/sys/pip/record") 
@Api(value = "流水号记录Controlle", tags = "流水号记录操作服务") 
public class SysPipNumberRecordController extends AbstractController { 
	 
	@Autowired 
	private SysPipNumberRecordService service; 
	 
	@ApiOperation(httpMethod = "POST", value = "流水号记录信息保存") 
	@RequestMapping(value = "/insert", method = { RequestMethod.POST }, produces = "application/json;charset=UTF-8") 
	@ResponseBody 
	public Result insert( 
			@RequestBody @ApiParam(name = "流水号规则对象", value = "json格式对象", required = true) SysPipNumberRecord entity) { 
		 
		// 判断流水规则是否为空 
		if(!StringUtils.isEmpty(entity.getRuleSid())){ 
			service.insertSelective(entity); 
			return Result.ok(); 
		} else { 
			return Result.error("流水规则不存在"); 
		} 
 
	} 
@Override 
	public int insertSelective(SysPipNumberRecord record) { 
		// TODO Auto-generated method stub 
		// 解决并发请求,发号重复问题:锁定当前代码块 
		synchronized(this){ 
			// 分布式sid 生成 
			SnowflakeIdGenerator snowflake = new SnowflakeIdGenerator(0,2); 
			record.setSid(Long.toBinaryString(snowflake.nextId())); 
			 
			// 判断流水规则 是否在流水记录中生成 
			Map<String, Object> parame = new HashMap<String, Object>(); 
			parame.put("ruleSid", record.getRuleSid()); 
			 
			// 公共属性 
			SysPipNumberRule rule = ruleMapper.selectByPrimaryKey(record.getRuleSid()); 
			record.setCategory(rule.getCategory()); 
			record.setZoneOrgCode(rule.getZoneOrgCode()); 
			 
			List<SysPipNumberRecord> list = mapper.selectAll(parame); 
			if (list != null && list.size() > 0) { 
				// 获取流水记录最大值 
				List<Integer> num = list.stream().map(SysPipNumberRecord::getInitValue).collect(Collectors.toList()); 
				Integer number = Collections.max(num) + 1; 
				 
				record.setInitValue(number); 
				// 序列号 
				String serialNumber = StringFormatUtil.addZeroForNum(String.valueOf(number), 
						rule.getLength()); 
				 
				StringBuilder builder = new StringBuilder(); 
				// 判断是否启动分类 
				if(rule.getIsCategory().equalsIgnoreCase("1")){ 
					// 判断是否截取分类 
					if(rule.getCutLength() != null && rule.getCutLength() > 0){ 
						// 判断截取长度与分类key 长度问题 
						if(rule.getCategory().length() >= rule.getCutLength()){ 
							builder.append(rule.getCategory().substring(0, rule.getCutLength()));							 
						} else { 
							builder.append(rule.getCategory()); 
						} 
					} else { 
						builder.append(rule.getCategory()); 
					} 
					// 判断连接符是否配置 
					if(!StringUtils.isEmpty(rule.getConnector())){ 
						builder.append(rule.getConnector()); 
					} 
				}  
				// 判断是否启动日期 
				if (rule.getIsDate().equalsIgnoreCase("1")) { 
					SimpleDateFormat format = new SimpleDateFormat(rule.getDateFormat()); 
					builder.append(format.format(new Date())); 
					if(!StringUtils.isEmpty(rule.getConnector())){ 
						builder.append(rule.getConnector()); 
					} 
				} 
				// 添加流水号 
				builder.append(serialNumber); 
				record.setPipNumberValue(builder.toString()); 
				 
			} else { 
				record.setInitValue(rule.getStartValue()); 
				// 序列号 
				String serialNumber = StringFormatUtil.addZeroForNum(String.valueOf(rule.getStartValue()), 
						rule.getLength()); 
				StringBuilder builder = new StringBuilder(); 
				// 判断是否启动分类 
				if(rule.getIsCategory().equalsIgnoreCase("1")){ 
					// 判读是否截取分类 
					if(rule.getCutLength() != null && rule.getCutLength() > 0){ 
						// 判断截取长度与分类key 长度问题 
						if(rule.getCategory().length() >= rule.getCutLength()){ 
							builder.append(rule.getCategory().substring(0, rule.getCutLength()));							 
						} else { 
							builder.append(rule.getCategory()); 
						} 
					} else { 
						builder.append(rule.getCategory()); 
					} 
					 
					 
					if(!StringUtils.isEmpty(rule.getConnector())){ 
						builder.append(rule.getConnector()); 
					} 
				}  
				// 判断是否启动日期 
				if (rule.getIsDate().equalsIgnoreCase("1")) { 
					SimpleDateFormat format = new SimpleDateFormat(rule.getDateFormat()); 
					builder.append(format.format(new Date())); 
					if(!StringUtils.isEmpty(rule.getConnector())){ 
						builder.append(rule.getConnector()); 
					} 
				} 
				// 添加流水号 
				builder.append(serialNumber); 
				record.setPipNumberValue(builder.toString()); 
			} 
			 
			// 数据入库 
			return mapper.insertSelective(record); 
		} 
	}

核心代码已经写完,如何验证我写的代码,让我很纠结,测试人员提示我,可以使用ab 测试工具 模拟高并发的情况,但是我从我们公司的前端学到一手,通过HTML5 新特性fetch 函数模拟高并发.

前端js 代码如下:

var sends = (num) => { 
	for(var i =0;i<num;i++) { 
		fetch("http://localhost:9090/api/sys/pip/record/insert", {"credentials":"include","headers":{"accept":"application/json;charset=UTF-8","accept-language":"zh,en;q=0.9,zh-CN;q=0.8","content-type":"application/json"},"referrer":"http://localhost:9090/swagger-ui.html","referrerPolicy":"no-referrer-when-downgrade","body":"{\"ruleSid\":\"100011000100111000100000010101101000100001000000000000001010\"}","method":"POST","mode":"cors"}) 
	} 
}

通过模拟2次,每次都是100 个请求,查看数据库结果,没有重复。

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号