当前位置: 首页 > news >正文

商品秒杀接口压测及优化

目录

  • 一、生成测试用户
  • 二、jmeter压测
  • 三、秒杀接口优化
    • 1、优化第一步:解决超卖
    • 2、优化第二步:Redis重复抢购
    • 3、优化第三步:Redis预减库存
      • ①商品初始化
      • ②预减库存

一、生成测试用户

将UserUtils工具类导入到zmall-user模块中,运行生成测试用户信息,可根据自身电脑情况来生成用户数量。

1)必须保证zmall-user模块处于运行状态下,在进行测试用户数据生成操作;
2)注意修改UserUtils中的用户登录接口地址及端口;同时请修改用户登录接口,将生成的token令牌存入响应封装类中;

//5.通过UUID生成token令牌并保存到cookie中
String token= UUID.randomUUID().toString().replace("-","");
...
return new JsonResponseBody<>(token);

3)设置生成登录令牌存储位置;
4)修改数据库名、登录账号及密码;
5)设置生成测试用户数量;

UserUtils

package com.zking.zmall.utils;import com.alibaba.nacos.common.utils.MD5Utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zking.zmall.model.User;
import com.zking.zmall.util.JsonResponseBody;import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;public class UserUtils {private static void createUser(int count) throws Exception {List<User> lst=new ArrayList<User>();//循环添加用户数据for(int i=0;i<count;i++){User user=new User();user.setLoginName("user"+i);user.setUserName("测试用户"+i);user.setPassword(MD5Utils.md5Hex("123456".getBytes()));user.setType(0);user.setMobile((17700000000L+i)+"");user.setEmail("user"+i+"@139.com");user.setIdentityCode((430104199912120000L+i)+"");lst.add(user);}System.out.println("create users");//获取数据库连接Connection conn=getConn();//定义SQLString sql="insert into zmall_user(loginName,userName,password,identityCode,email,mobile,type) values(?,?,?,?,?,?,?)";//执行SQLPreparedStatement ps=conn.prepareStatement(sql);//赋值for (User user : lst){ps.setString(1,user.getLoginName());ps.setString(2,user.getUserName());ps.setString(3,user.getPassword());ps.setString(4,user.getIdentityCode());ps.setString(5,user.getEmail());ps.setString(6,user.getMobile());ps.setInt(7,user.getType());ps.addBatch();}ps.executeBatch();ps.clearParameters();ps.close();conn.close();System.out.println("insert to db");//登录,生成UserTicketString urlString="http://localhost:8010/userLogin";File file=new File("C:\\Users\\Administrator\\DeskTop\\config.txt");if(file.exists()){file.delete();}RandomAccessFile accessFile=new RandomAccessFile(file,"rw");//设置光标位置accessFile.seek(0);for (User user : lst) {URL url=new URL(urlString);HttpURLConnection co = (HttpURLConnection) url.openConnection();co.setRequestMethod("POST");co.setDoOutput(true);OutputStream out=co.getOutputStream();String params="loginName="+user.getLoginName()+"&password=123456";out.write(params.getBytes());out.flush();InputStream in=co.getInputStream();ByteArrayOutputStream bout=new ByteArrayOutputStream();byte[] buffer=new byte[1024];int len=0;while((len=in.read(buffer))>=0){bout.write(buffer,0,len);}in.close();bout.close();String response=new String(bout.toByteArray());ObjectMapper mapper=new ObjectMapper();JsonResponseBody jsonResponseBody=mapper.readValue(response, JsonResponseBody.class);String token=jsonResponseBody.getData().toString();System.out.println("create token:"+token);accessFile.seek(accessFile.length());accessFile.write(token.getBytes());accessFile.write("\r\n".getBytes());//System.out.println("write to file:"+token);}accessFile.close();System.out.println("over");}private static Connection getConn() throws Exception {String url="jdbc:mysql://localhost:3306/zmall?useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&characterEncoding=UTF8";String driver="com.mysql.jdbc.Driver";String username="root";String password="123456";Class.forName(driver);return DriverManager.getConnection(url,username,password);}public static void main(String[] args) throws Exception {createUser(50);}
}

在这里插入图片描述
在这里插入图片描述

二、jmeter压测

相关配置

1.线程计划>添加>线程(用户)>线程组
在这里插入图片描述
2.线程组>添加>配置元件>http请求默认值
在这里插入图片描述
在这里插入图片描述

3.线程组>添加>取样器>http请求
在这里插入图片描述
在这里插入图片描述

4.线程组>添加>配置元件>http cookie管理器
在这里插入图片描述
在这里插入图片描述

5.线程组>添加>配置元件>CSV数据文件设置
在这里插入图片描述
在这里插入图片描述

6.线程组>添加>监听器>汇总报告
在这里插入图片描述

7.线程组>添加>监听器>查看结果树
在这里插入图片描述

8.线程组>添加>监听器>用表格查看结果
在这里插入图片描述
线程组:200个线程,1秒之内发送,循环1次。测试结果如下:吞吐量为1328/s
在这里插入图片描述
数据库中的秒杀商品表中的商品出现了库存为负数的问题。
在这里插入图片描述
订单表和订单项表中出现了秒杀商品超卖问题。
在这里插入图片描述
在这里插入图片描述

三、秒杀接口优化

1、优化第一步:解决超卖

更新秒杀商品库存的sql语句,只有当库存大于0才能更新库存;修改更新秒杀库存方法updateKillStockById的返回类型为boolean,用于判断是否更新成功。

OrderServiceImpl

@Transactional@Overridepublic JsonResponseBody<?> createKillOrder(User user, Integer pid, Float price) {//1.根据秒杀商品编号获取秒杀商品库存是否为空//........//2.秒杀商品库存减一boolean update = killService.update(new UpdateWrapper<Kill>().eq("item_id", pid).gt("total", 0).setSql("total=total-1"));if(!update)throw new BusinessException(JsonResponseStatus.STOCK_EMPTY);//3.生成秒杀订单及订单项//........return new JsonResponseBody();}

2、优化第二步:Redis重复抢购

在RedisService中新增以下两个方法,用于Redis重复抢购的判断操作。

  • 根据用户ID和秒杀商品ID为Key,将秒杀订单保存到Redis中;
  • 根据用户ID和秒杀商品ID从Redis中获取对应的秒杀商品;

RedisServiceImpl

/*** 将秒杀订单保存到Redis* @param pid    商品ID* @param order  秒杀订单
*/
@Override
public void setKillOrderToRedis(Integer pid, Order order) {redisTemplate.opsForValue().set("order:"+order.getUserId()+":"+pid,order,1800, TimeUnit.SECONDS);
}/*** 根据用户ID和商品ID从Redis中获取秒杀商品,用于重复抢购判断* @param uid  用户ID* @param pid  商品ID* @return 返回Redis中存储的秒杀订单
*/
@Override
public Order getKillOrderByUidAndPid(Integer uid, Integer pid) {return (Order) redisTemplate.opsForValue().get("order:"+uid+":"+pid);
}

这里用户抢购的秒杀订单保存到Redis默认设置是1800秒,即30分钟;可视情况具体调整。

OrderServiceImpl

@Transactional
@Override
public JsonResponseBody<?> createKillOrder(User user, Integer pid) {.../***********在库存判断是否为空之后***********///6.根据秒杀商品ID和用户ID判断是否重复抢购Order order = redisService.getKillOrderByUidAndPid(user.getId(), pid);if(null!=order)throw new BusinessException(JsonResponseStatus.ORDER_REPART);/***********在根据商品ID获取商品之前***********///4.秒杀商品库存减一boolean flag=killService.updateKillStockById(pid);if(!flag)throw new BusinessException(JsonResponseStatus.STOCK_EMPTY);...//生成秒杀订单等操作//重点,重点,重点,在此处将生成的秒杀订单保存到Redis中,用于之后的重复抢购判断redisService.setKillOrderToRedis(pid,order);return new JsonResponseBody<>();
}

此处第二步优化完毕,再次进行JMeter压测,并查看测试情况。

3、优化第三步:Redis预减库存

①商品初始化

将参与秒杀活动且秒杀状态、秒杀活动时间有效的商品推送到Redis中,并对秒杀商品设置超时时间。

超时时间的设定取至于活动结束时间减去活动开始时间的差值,但必须是有效活动时间,也就是当前时间在活动开始时间与结束时间范围之内。

IRedisService

/**
* 设置秒杀商品库存到Redis中
* @param pid     秒杀商品ID
* @param total   秒杀商品数量
* @param expires 秒杀商品存储过期时间
*/
void setKillTotaltoRedis(Integer pid,Integer total,long expires);

RedisServiceImpl

@Override
public void setKillTotaltoRedis(Integer pid, Integer total,long expires) {redisTemplate.opsForValue().set("goods:"+pid,total,expires,TimeUnit.DAYS);
}

OrderController
在zmall-order订单模块中的OrderController类上实现InitializingBean,完成秒杀商品预加载。

package com.zking.zmall.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zking.zmall.model.Kill;
import com.zking.zmall.model.Order;
import com.zking.zmall.model.User;
import com.zking.zmall.service.IOrderService;
import com.zking.zmall.service.impl.KillServiceImpl;
import com.zking.zmall.service.impl.RedisServiceImpl;
import com.zking.zmall.util.JsonResponseBody;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.List;@Controller
public class OrderController implements InitializingBean {@Autowiredprivate IOrderService orderService;@Autowiredprivate KillServiceImpl killService;@Autowiredprivate RedisServiceImpl redisService;/*** 秒杀商品初始化* @throws Exception*/@Overridepublic void afterPropertiesSet() throws Exception {List<Kill> list =killService.list(new QueryWrapper<Kill>()//秒杀活动必须是激活状态.eq("is_active", 1)//秒杀活动结束时间必须>=当前时间,小于证明活动已结束.ge("end_time",new Date().toLocaleString()));list.forEach(kill -> {//计算秒杀商品存入Redis的过期时间,此处以天为单位Instant start = kill.getStartTime().toInstant();Instant end = kill.getEndTime().toInstant();long days = Duration.between(start, end).toDays();redisService.setKillTotaltoRedis(kill.getItemId(),kill.getTotal(),days);});}@RequestMapping("/orderUserList")@ResponseBodypublic List<Order> orderUserList(){return orderService.list(new QueryWrapper<Order>().eq("userId",18));}@RequestMapping("/createOrder/{pid}/{num}")@ResponseBodypublic Order createOrder(@PathVariable("pid") Integer pid,@PathVariable("num") Integer num){return orderService.createOrder(pid,num);}@RequestMapping("/createKillOrder/{pid}/{price}")@ResponseBodypublic JsonResponseBody<?> createKillOrder(User user,@PathVariable("pid") Integer pid,@PathVariable("price") Float price){return orderService.createKillOrder(user,pid,price);}
}

②预减库存

第一步:在RedisService中定义库存预减和递增方法。预减方法是在用户抢购商品成功后对商品进行库存预减;递增方法是在高并发情况下Redis库存预减可能会出现负数情况,通过递增方法进行库存回滚为0

IRedisService

/**
* 根据秒杀商品ID实现Redis商品库存递增
* @param pid
* @return
*/
long increment(Integer pid);/**
* 根据秒杀商品ID实现Redis商品库存递减
* @param pid
* @return
*/
long decrement(Integer pid);

RedisServiceImpl

@Override
public long increment(Integer pid) {return redisTemplate.opsForValue().increment("goods:"+pid);
}@Override
public long decrement(Integer pid) {return redisTemplate.opsForValue().decrement("goods:"+pid);
}

第二步:修改订单生成方法,加入Redis库存预减判断

请在Redis重复抢购判断的下面加入Redis库存预减操作。

OrderServiceImpl

package com.zking.zmall.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zking.zmall.exception.BusinessException;
import com.zking.zmall.mapper.OrderMapper;
import com.zking.zmall.model.Kill;
import com.zking.zmall.model.Order;
import com.zking.zmall.model.OrderDetail;
import com.zking.zmall.model.User;
import com.zking.zmall.service.ApiProductService;
import com.zking.zmall.service.IOrderService;
//import io.seata.spring.annotation.GlobalTransactional;
import com.zking.zmall.util.JsonResponseBody;
import com.zking.zmall.util.JsonResponseStatus;
import com.zking.zmall.util.SnowFlake;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;/*** <p>*  服务实现类* </p>** @author xnx* @since 2023-02-06*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {@Autowiredprivate KillServiceImpl killService;@Autowiredprivate OrderDetailServiceImpl orderDetailService;@Autowiredprivate ApiProductService productService;@Autowiredprivate RedisServiceImpl redisService;//    @Transactional
//    @Override
//    public Order createOrder(Integer pid, Integer num) {
//        //根据商品ID修改商品对应的库存
//        productService.updateStock(pid,num);
//        //新增订单
//        Order order=new Order();
//        //此处只是做模拟操作
//        this.save(order);
//        return order;
//    }//    @GlobalTransactional@Transactional@Overridepublic Order createOrder(Integer pid, Integer num) {//根据商品ID修改商品对应的库存productService.updateStock(pid,num);//异常模拟int i = 1 / 0;//新增订单Order order=new Order();//此处只是做模拟操作this.save(order);return order;}@Transactional@Overridepublic JsonResponseBody<?> createKillOrder(User user, Integer pid, Float price) {//1.根据秒杀商品编号获取秒杀商品库存是否为空
//        Kill kill = killService.getOne(new QueryWrapper<Kill>().eq("item_id",pid));
//        if(kill.getTotal()<1)
//            throw new BusinessException(JsonResponseStatus.STOCK_EMPTY);//2.秒杀商品库存减一
//        killService.update(new UpdateWrapper<Kill>()
//                .eq("item_id",pid)
//                .setSql("total=total-1"));/***********在库存判断是否为空之后***********///6.Redis库存预减long stock = redisService.decrement(pid);if(stock<0){redisService.increment(pid);throw new BusinessException(JsonResponseStatus.STOCK_EMPTY);}//5.根据秒杀商品ID和用户ID判断是否重复抢购Order order = redisService.getKillOrderByUidAndPid(user.getId(), pid);if(null!=order)throw new BusinessException(JsonResponseStatus.ORDER_REPART);//2.秒杀商品库存减一boolean update = killService.update(new UpdateWrapper<Kill>().eq("item_id", pid).gt("total", 0).setSql("total=total-1"));if(!update)throw new BusinessException(JsonResponseStatus.STOCK_EMPTY);
//        boolean flag=killService.updateKillStockById(pid);
//        if(!flag)
//            throw new BusinessException(JsonResponseStatus.STOCK_EMPTY);//3.生成秒杀订单及订单项SnowFlake snowFlake=new SnowFlake(2,3);Long orderId=snowFlake.nextId();int orderIdInt = new Long(orderId).intValue();//创建订单
//        Order order=new Order();order.setUserId(user.getId());order.setLoginName(user.getLoginName());order.setCost(price);order.setSerialNumber(orderIdInt+"");this.save(order);//创建订单项OrderDetail orderDetail=new OrderDetail();orderDetail.setOrderId(orderIdInt);orderDetail.setProductId(pid);orderDetail.setQuantity(1);orderDetail.setCost(price);orderDetailService.save(orderDetail);//生成秒杀订单等操作//重点,重点,重点,在此处将生成的秒杀订单保存到Redis中,用于之后的重复抢购判断redisService.setKillOrderToRedis(pid,order);return new JsonResponseBody();}}

第三步:还原测试数据,重新使用jmeter压测,这时可以发现明显压测效率要提升很多。

但是还是要根据不同电脑配置情况来决定,配置太低,效率也提升不了多少。

尤其是链接远程redis,会导致压测的吞吐量直线下降
在这里插入图片描述

相关文章:

商品秒杀接口压测及优化

目录一、生成测试用户二、jmeter压测三、秒杀接口优化1、优化第一步&#xff1a;解决超卖2、优化第二步&#xff1a;Redis重复抢购3、优化第三步&#xff1a;Redis预减库存①商品初始化②预减库存一、生成测试用户 将UserUtils工具类导入到zmall-user模块中&#xff0c;运行生…...

NFC 项目前期准备工作

同学,别退出呀,我可是全网最牛逼的 WIFI/BT/GPS/NFC分析博主,我写了上百篇文章,请点击下面了解本专栏,进入本博主主页看看再走呗,一定不会让你后悔的,记得一定要去看主页置顶文章哦。 了解项目信息,FAE联系方式,驱动源码等驱动合入内核配置DTS驱动设备节点验证Push nf…...

(C语言)数据的存储

问&#xff1a;1. 数据类型有哪五大类&#xff1f;2. 数据类型的作用是什么与什么&#xff1f;3. 整型又可以具体分为哪五个&#xff1f;为什么字符char也归属于整型&#xff1f;4. 浮点型又可以具体分为哪两类&#xff1f;5. 构造类型就是什么&#xff1f;具体分为哪四类&…...

C语言深度剖析之文件操作

&#x1f497; &#x1f497; 博客:小怡同学 &#x1f497; &#x1f497; 个人简介:编程小萌新 &#x1f497; &#x1f497; 如果博客对大家有用的话&#xff0c;请点赞关注加关注 &#x1f31e; 什么是文件 磁盘上的文件是文件。 但是在程序设计中&#xff0c;我们一般谈的文…...

RNN神经网络初探

目录1. 神经网络与未来智能2. 回顾数据维度和神经网络1. 神经网络与未来智能 2. 回顾数据维度和神经网络 循环神经网络&#xff0c;主要用来处理时序的数据&#xff0c;它对每个词的顺序是有要求的。 循环神经网络如何保存记忆功能&#xff1f; 当前样本只有 3 个特征&#x…...

【flinkx】【hdfs】【ing】Cannot obtain block length for LocatedBlock

一. 任务描述 使用flinkx去跑HDFS到HIVE的任务时&#xff0c;出现如下报错&#xff1a; CannotObtainBlockLengthException com.dtstack.flinkx.throwable.FlinkxRuntimeException: cant get file size from hdfs, file hdfs://xxx/.data/540240453caeb6fe4b3f118410a05315_2…...

【Day6】合并两个排序链表与合并k个已排序的链表,java代码实现

前言&#xff1a; 大家好&#xff0c;我是良辰丫&#x1f680;&#x1f680;&#x1f680;&#xff0c;今天与大家一起做两道牛客网的链表题&#xff0c;好久写关于链表题的博客了&#xff0c;这两道题可以帮大家巩固一下链表知识&#xff0c;我把两道题的链接放到下面&#xf…...

Swagger PHP

PHP使用Swagger生成好看的API文档不是不可能&#xff0c;而是非常简单。首先本人使用Laravel框架&#xff0c;所以在Laravel上安装swagger-php。一、安装swagger - phpcomposer require zircote/swagger-phpswagger-php提供了命令行工具&#xff0c;所以可以全局安装&#xff0…...

谷粒商城-品牌管理-JSR303数据校验

后端在处理前端传过来的数据时&#xff0c;尽管前端表单已经加了校验逻辑&#xff0c;但是作为严谨考虑&#xff0c;在后端对接口传输的数据做校验也必不可少。 开启校验&#xff1a; 实体类上增加校验注解&#xff0c;接口参数前增加Valid 开启校验 package com.xxh.product.…...

Java零基础教程——数组

目录数组静态初始化数组数组的访问数组的动态初始化元素默认值规则&#xff1a;数组的遍历数组遍历-求和冒泡排序数组的逆序交换数组 数组就是用来存储一批同种类型数据的容器。 20, 10, 80, 60, 90 int[] arr {20, 10, 80, 60, 90}; //位置 0 1 2 3 4数组的…...

AirServer在哪下载?如何免费使用教程

苹果手机投屏到电脑mac是怎么弄&#xff1f;你知道多少&#xff1f;相信大家对苹果手机投屏到电脑mac能在电脑上操作不是很了解&#xff0c;下面就让coco玛奇朵带大家一起了解一下教程。AIrServer是一款ios投屏到mac的专用软件&#xff0c;可将iOS上的音频&#xff0c;视频&…...

加载sklearn covtype数据集出错 fetch_covtype() HTTPError: HTTP Error 403: Forbidden解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...

理论六:为什么基于接口而非实现编程?有必要为每个类定义接口么?

在上一节课中、我们讲了接口和抽象类&#xff0c;以及各种编程语言是如何支持、实现这两个语法概念的。今天&#xff0c;我们继续讲一个跟“接口”相知识点:基于接口而非实现编程。这个原则非常重要,是一种非常有效的提高代码质量的手段,在平时的开发中特别经常被用到。为了让你…...

(HP)react日常开发技巧

高级特性 1&#xff0c;protals&#xff08;传送门&#xff09;&#xff1a;将子组件渲染到父组件之外。 实例场景&#xff1a;父组件的儿子是<Modal>组件&#xff0c;使用fixed定位虽然样式看着是在父组件之外了&#xff0c;但是打开控制台查看元素&#xff0c;Modal相…...

【20230211】【剑指1】搜索与回溯算法II

树的子结构递归思维&#xff1a;对称性递归什么是对称性递归&#xff1f;就是对一个对称的数据结构&#xff08;这里指二叉树&#xff09;从整体的对称性思考&#xff0c;把大问题分解成子问题进行递归&#xff0c;即不是单独考虑一部分(比如树的左子树)&#xff0c;而是同时考…...

STM32F103C8T6—库函数应用I2C/SPI驱动OLED显示中文、字符串

文章目录1. I2C与SPI通信协议对比2. 四脚OLED与六脚OLED3. I2C驱动OLED显示oled.h & oled.c&#xff1a;汉字取模 & oledfont.h&#xff1a;main.c 显示示例&#xff1a;连线方法&#xff1a;4. SPI驱动OLED显示1. I2C与SPI通信协议对比 I2C&#xff08;Inter-Integra…...

sql语句要注意的地方及常用查询语句

sql要注意的地方关键字不能被缩写&#xff0c;也不能分行小写大写不敏感&#xff0c;没区别使用缩进提高语句的可读性常用查询语句1.查询所有库SHOW DATABASES;2.选择数据库 use 数据库名USE myemployees;3.查看数据库中所有表show tables4.查看表中的内容 select 字段一&#…...

数组去重、伪数组和真数组的区别以及伪数组如何转换成真数组

1.数组去重 1&#xff09; 利用数组的indexOf下标属性来查询。 如果找到一个 item&#xff0c;则返回 item 的第一次出现的位置。开始位置的索引为 0。 如果在数组中没找到指定元素则返回 -1。 function unique4(arr) {var newArr []for (var i 0; i < arr.length; i) {i…...

JavaScript内置支持类Array

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>内置支持类Array</title> </head> <body bgcolor"antiquewhite"> <script type"text/javasc…...

GitLab CI-CD 学习笔记

概述 1. CI/CD CI&#xff08;持续集成&#xff09;指开发人员一天内进行多次合并和提交代码操作&#xff0c;并通过自动化测试&#xff0c;完成构建 CD&#xff08;持续部署&#xff09;指每次代码更改都会自动部署到对应环境 CI/CD 结合在一起&#xff0c;可以加快开发团…...

K8S安装

1.创建三台centos虚拟机 使用的官方最小镜像安装 CentOS-7-x86_64-Minimal-1804.iso 建议最小硬件配置&#xff1a;2核CPU、2G内存、20G硬盘 master配置详情 node1和node2配置详情 三台虚拟机在安装centos的时候在网络IPV4指定DHCP,配置IPV4固定地址&#xff0c;保证可以访问…...

【C++】模板初阶STL简介

今天&#xff0c;你内卷了吗&#xff1f; 文章目录一、泛型编程二、函数模板&#xff08;显示实例化和隐式实例化&#xff09;1.函数模板格式2.单参数模板3.多参数模板4.模板参数的匹配原则三、类模板&#xff08;没有推演的时机&#xff0c;统一显示实例化&#xff09;1.类模…...

备战蓝桥杯第一天【二分查找无bug版】

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…...

Java集合中的Map

MapMap接口键 值 对存储键不能重复&#xff0c;值可以重复Map三个实现类的存储结构HashMap&#xff1a;Hash表链表红黑树结构 线程不安全TreeMap&#xff1a; 底层红黑树实现HashTable&#xff1a;hash表链表红黑树 线程安全HashMapHashMap常用方法HashMap<String,String>…...

【java】springboot项目启动数据加载内存中的三种方法

文章目录一、前言二、加载方式2.1、 第一种&#xff1a;使用PostConstruct注解&#xff08;properties/yaml文件&#xff09;。2.2、 第二种&#xff1a;使用Order注解和CommandLineRunner接口。2.3、 第三种&#xff1a;使用Order注解和ApplicationRunner接口。三、代码示例3.…...

【GO】29.go-gin支持ssl/tls,即https示例

本文为演示采用自签名证书一.生成证书通过openssl工具生成证书1.1 安装opensslmacos通过brew安装brew install openssl1.2 生成跟证书私钥openssl genrsa -out ca.key 40961.3 准备配置文件vim ca.conf内容如下[ req ] default_bits 4096 distinguished_name req_disti…...

逻辑仿真工具VCS的使用-Makefile

Gvim写RTL code&#xff0c;VCS仿真&#xff0c;Verdi看波形&#xff0c;DC做综合下约束&#xff0c;Primetime做STA&#xff0c;Spyglass做异步时序分析。 VCS全称Verilog Computer Simulation &#xff0c;VCS是逻辑仿真EDA工具的编译源代码的命令。要用VCS做编译仿…...

信息系统安全技术

一、信息安全的有关概念 1. 属性2. 四个安全层次※3. 信息安全保护等级※4. 安全保护能力的等级※ 二、信息加密、解密与常用算法 1. 对称加密2. 非对称加密3. Hash函数4. 数字签名5. 认证 三、信息系统安全 1. 计算机设备安全2. 网络安全3. 操作系统安全4. 数据库安全5. 应用系…...

【数据结构】最小生成树(Prim算法,普里姆算法,普利姆)、最短路径(Dijkstra算法,迪杰斯特拉算法,单源最短路径)

文章目录前置问题问题解答一、基础概念&#xff1a;最小生成树的定义和性质&#xff08;1&#xff09;最小生成树&#xff08;Minimal Spanning Tree&#xff09;的定义&#xff08;2&#xff09;最小生成树&#xff08;MST&#xff09;的性质二、如何利用MST性质寻找最小生成树…...

Session与Cookie的区别(一)

从我刚开始学程序时这一题就常出现在面试考题里&#xff0c;一直到现在都还是能看见这个问题。 这个问题重要吗&#xff1f;我觉得蛮重要的。因为 Session 所代表的是「状态」&#xff0c;如果没有了状态&#xff0c;一大堆功能都会失效。 对于工程师来说必须去理解什么是 Sess…...

wordpress用户注册邮件内容自定义/哪些网站有友情链接

1、测试用例的设计方法有哪些&#xff1f;请阐述判定表设计测试用例的步骤。 答&#xff1a;等价类划分&#xff0c;边界值分析&#xff0c;错误推断法&#xff0c;因果图法&#xff0c;正交表分析法&#xff0c;场景分析法。 判定表设计测试用例的步骤&#xff1a;确定规则的个…...

可以做3d电影网站有哪些/友情链接交换统计表

SDK版本&#xff1a;SIMPLELINK_CC13X2_26X2_SDK v5.20.0.52 适用场景&#xff1a;首次将工程文件配置到本地时&#xff1b;有bim工程、oad工程、协处理器程序多个部分混杂&#xff1b; 异常问题&#xff1a;MENU_ITEM_MULTIPLE_ACTIONS(spMenuSelectConn, MAX_NUM_BLE_CONNS…...

甘肃精神文明建设网站/杭州网站推广公司

最近在研究JAVA开发Webservice&#xff0c;发现网络上比较流行的几种选择AXIS、XFire、CFX(XFire的下一代)&#xff0c;前几天转了几篇关于这三种选择的比较的文章&#xff0c;对它们已经有了些概念。决定自己实践一个例子 在开始前&#xff0c;先介绍一些概念&#xff1a; …...

10000ip网站怎么做/广告推广代运营公司

和新队友的第一次训练 体验良好 debug到头秃 好困啊靠 A.The Baguette Master 给一个四边形相框的宽度和边框内侧四条边对角线AD的程度&#xff0c;求外侧周长 如图&#xff0c;对四个点做垂线&#xff08;因为懒所以只挑了两个角来做&#xff09;&#xff0c;将总长度分为…...

广州网站建设制作价格/西安做网页的公司

ember 动态切换组件本文由Edwin Reynoso和Nilson Jacques进行了同行评审。 感谢所有SitePoint的同行评审员使SitePoint内容达到最佳状态&#xff01; 组件是Ember应用程序的重要组成部分。 它们允许您定义自己的&#xff0c;特定于应用程序HTML标记&#xff0c;并使用JavaScri…...

那个网站做服装批发/深圳广告策划公司

2013年下半年系统集成项目管理工程师上午试卷&#xff08;网友回忆版&#xff09;项目章程的内容不包括。A&#xff0e;项目目的B&#xff0e;概要进度计划C&#xff0e;工作分解方式D&#xff0e;概要预算……云计算是通过_____的资源来实现相关服务。A&#xff0e;分布式B&am…...