# gulimall **Repository Path**: dolinp/gulimall ## Basic Information - **Project Name**: gulimall - **Description**: 谷粒商城-leifengyang-尚硅谷系列课程-自学 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-10-03 - **Last Updated**: 2022-04-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # gulimall #### 介绍 #### 软件架构 软件架构说明 #### 安装教程 Vagrant 启动 vagrant 常见命令 vagrant up 启动 vagrant halt 关机 vagrant reload 重启 vagrant destroy 移除机器 vagrant ssh 登陆 su root 进入root权限 box管理命令 vagrant box list 查看本地box列表 vagrant box add 添加box到列表 vagrant box remove 从box列表移除 找到vagrant目录结构的下的如下文件 1.1: L:\Vagrant\embedded\gems\2.2.6\gems\vagrant-2.2.6\plugins\providers\virtualbox\plugin.rb 在这个文件里增加6.1版本 autoload :Version_6_1, File.expand_path("../driver/version_6_1", __FILE__) 1.2: L:\Vagrant\embedded\gems\2.2.6\gems\ vagrant2.2.6\plugins\providers\virtualbox\driver\meta.rb 在这个文件增加6.1版本 "6.1"=>Version_6_1, 在此目录上新建version_6_1.rb require File.expand_path("../version_6_0", __FILE__) module VagrantPlugins module ProviderVirtualBox module Driver # Driver for VirtualBox 6.1.x class Version_6_1 < Version_6_0 def initialize(uuid) super @logger = Log4r::Logger.new("vagrant::provider::virtualbox_6_1") end end end end end error: VT-x is not available (VERR_VMX_NO_VMX)报错 管理员打开cmd小黑窗 输入bcdedit /set hypervisorlaunchtype off https://www.jianshu.com/p/7c8c275aed91 下载镜像box(以centos/7为例,实际以官网为准,官网下载较慢,可复制下载链接使用迅雷下载)https://cloud.centos.org/centos/7/vagrant/x86_64/images/CentOS-7-x86_64-Vagrant-2004_01.VirtualBox.box ​ 在vagrant 根目录下 cmd 输入 vagrant up ​ 等待连接 vagrant shh ​ 退出 exit ​ 重启 vagrant reload 进入 centos/7 查看使用者 whoami 环境-虚拟机网路设置 在 Vagrantfile 修改 在 cmd中 ipconfig 查看VirtualBox 虚拟ip 以太网适配器 VirtualBox Host-Only Network: 连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::de7:b70f:60df:bf29%9 IPv4 地址 . . . . . . . . . . . . : 192.168.56.1 子网掩码 . . . . . . . . . . . . : 255.255.255.0 默认网关. . . . . . . . . . . . . : 打开私有地址栏 : config.vm.network "private_network", ip: "192.168.33.10" 修改IP 同一网段config.vm.network "private_network", ip: "192.168.56.10" 然后重启vagrant ​ 使用: vagrant reload 再次:vagrant ssh ​ IP addr 显示第三个IP 192.168.56.10 在 windows cmd中 ping 192.168.56.10 在 vagrant ping 主机的IP地址 能够相互ping同即可 安装 cocker 虚拟化容器技术 基于镜像, 秒启动各种容器, 每一种容器都是一个完美运行环境, 容器之间相互隔离 1.设置存储库 $ sudo yum install -y yum-utils $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo 2.安装码头工人引擎、客户端、容器 $ sudo yum install docker-ce docker-ce-cli containerd.io 3.启动Docker $ sudo systemctl start docker 4.运行hello-world映像,验证Docker引擎是否正确安装。 $ sudo docker run hello-world 5.开机自动启动 $ sudo systemctl enable docker 6.查看是否有镜像 $ sudo docker images 7.配置国内镜像 阿里云 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://5qjyyx2p.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker docker下载MySQL sudo docker pull mysql:5.7 /*安装MySQL 版本为5.7*/ docker run -p 3306:3306 --name mysql \ /*-p 3306:3306 将容器的3306端口映射到主机的3306 */ -v /mydata/mysql/log:/var/log/mysql \ /*配置文件夹挂载到主机*/ -v /mydata/mysql/data:/var/lib/mysql \ /*将日志文件夹挂载到主机*/ -v /mydata/mysql/conf:/etc/mysql \ /*将配置文件夹挂载到主机*/ -e MYSQL_ROOT_PASSWORD=root \ /*初始化root用户密码*/ -d mysql:5.7 /*后台运行 表明镜像*/ /*出现如下字符串,则启动成功 be7139f81eab3bb51270b0639ab4ba6aac86a11a7e37ebdcc6476cb0dd4a8dc7*/ /*docker ps 查看*/ 启动本地slq 查看是否连接成功 sql主机地址 为设定的IP地址 192.168.56.10 用户名:root 密码: root 端口: 3306 [client] default-character-set=utf8 [mysql] default-character-set=utf8 [mysqld] init_connect='SET collation_connection = utf8_unicode_ci' init_connect='SET NAMES utf8' character-set-server=utf8 collation-server=utf8_unicode_ci skip-character-set-client-handshake skip-name-resolve docker restart mysql /*写入后重新启动如下操作即可*/ mysql [root@10 conf]# docker exec -it mysql /bin/bash root@be7139f81eab:/# cd /etc/mysql/ root@be7139f81eab:/etc/mysql# ls my.cnf root@be7139f81eab:/etc/mysql# cat my.cnf [client] default-character-set=utf8 [mysql] default-character-set=utf8 [mysqld] init_connect='SET collation_connection = utf8_unicode_ci' init_connect='SET NAMES utf8' character-set-server=utf8 collation-server=utf8_unicode_ci skip-character-set-client-handshake skip-name-resolve root@be7139f81eab:/etc/mysql# exit exit [root@10 conf]# docker安装redis docker pull redis /*下载*/ sudo docker images /*查看是否下载*/ mkdir -p /mydata/redis/conf [root@10 conf]# touch /mydata/redis/conf/redis.conf [root@10 conf]# cd /mydata/ [root@10 mydata]# ls mysql redis [root@10 mydata]# cd redis/ [root@10 redis]# ls conf [root@10 redis]# cd conf/ [root@10 conf]# ls redis.conf [root@10 conf]# [root@10 conf]# [root@10 conf]# touch redis.conf [root@10 conf]# docker run -p 6379:6379 --name redis \ > -v /mydata/redis/data:/data \ > -v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \ > -d redis redis-server /etc/redis/redis.conf 2c2e4fd67dee1072e9597041d218f9f24216c29c269b011c5dbfddff4787a8a7 [root@10 conf]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2c2e4fd67dee redis "docker-entrypoint.s…" 13 seconds ago Up 12 seconds 0.0.0.0:6379->6379/tcp redis be7139f81eab mysql:5.7 "docker-entrypoint.s…" 2 hours ago Up 30 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql [root@10 conf]# /*配置redis.conf*/ [root@10 conf]# pwd /mydata/redis/conf [root@10 conf]# ls redis.conf [root@10 conf]# vi redis.conf /*插入*/ appendonly yes [root@10 conf]# docker restart redis redis 下载VS Code https://code.visualstudio.com/Download 安装好 在扩展里面下载 Auto Close Tag Auto Rename Tag Chinese (Simplified) Language Pack for Visual Studio Code (需要重启,中文包) ESLint HTML CSS Support HTML Snippets JavaScript (ES6) code snippets Live Server open in browser Vetur #### 使用说明 /** * 1、如何使用Nacos作为配置中心统一管理配置 * * 1)、引入依赖, * * com.alibaba.cloud * spring-cloud-starter-alibaba-nacos-config * * 2)、创建一个bootstrap.properties。 * spring.application.name=gulimall-coupon * spring.cloud.nacos.config.server-addr=127.0.0.1:8848 * 3)、需要给配置中心默认添加一个叫 数据集(Data Id)gulimall-coupon.properties。默认规则,应用名.properties * 4)、给 应用名.properties 添加任何配置 * 5)、动态获取配置。 * @RefreshScope:动态获取并刷新配置 * @Value("${配置项的名}"):获取到配置。 * 如果配置中心和当前应用的配置文件中都配置了相同的项,优先使用配置中心的配置。 * * 2、细节 * 1)、命名空间:配置隔离; * 默认:public(保留空间);默认新增的所有配置都在public空间。 * 1、开发,测试,生产:利用命名空间来做环境隔离。 * 注意:在bootstrap.properties;配置上,需要使用哪个命名空间下的配置, * spring.cloud.nacos.config.namespace=9de62e44-cd2a-4a82-bf5c-95878bd5e871 * 2、每一个微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置 * * 2)、配置集:所有的配置的集合 * * 3)、配置集ID:类似文件名。 * Data ID:类似文件名 * * 4)、配置分组: * 默认所有的配置集都属于:DEFAULT_GROUP; * 1111,618,1212 * * 项目中的使用:每个微服务创建自己的命名空间,使用配置分组区分环境,dev,test,prod * * 3、同时加载多个配置集 * 1)、微服务任何配置信息,任何配置文件都可以放在配置中心中 * 2)、只需要在bootstrap.properties说明加载配置中心中哪些配置文件即可 * 3)、@Value,@ConfigurationProperties。。。 * 以前SpringBoot任何方法从配置文件中获取值,都能使用。 * 配置中心有的优先使用配置中心中的, * * /** * 1、整合MyBatis-Plus * 1)、导入依赖 * * com.baomidou * mybatis-plus-boot-starter * 3.2.0 * * 2)、配置 * 1、配置数据源; * 1)、导入数据库的驱动。https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-versions.html * 2)、在application.yml配置数据源相关信息 * 2、配置MyBatis-Plus; * 1)、使用@MapperScan * 2)、告诉MyBatis-Plus,sql映射文件位置 * * 2、逻辑删除 * 1)、配置全局的逻辑删除规则(省略) * 2)、配置逻辑删除的组件Bean(省略) * 3)、给Bean加上逻辑删除注解@TableLogic * * 3、JSR303 * 1)、给Bean添加校验注解:javax.validation.constraints,并定义自己的message提示 * 2)、开启校验功能@Valid * 效果:校验错误以后会有默认的响应; * 3)、给校验的bean后紧跟一个BindingResult,就可以获取到校验的结果 * 4)、分组校验(多场景的复杂校验) * 1)、 @NotBlank(message = "品牌名必须提交",groups = {AddGroup.class,UpdateGroup.class}) * 给校验注解标注什么情况需要进行校验 * 2)、@Validated({AddGroup.class}) * 3)、默认没有指定分组的校验注解@NotBlank,在分组校验情况@Validated({AddGroup.class})下不生效,只会在@Validated生效; * * 5)、自定义校验 * 1)、编写一个自定义的校验注解 * 2)、编写一个自定义的校验器 ConstraintValidator * 3)、关联自定义的校验器和自定义的校验注解 * @Documented * @Constraint(validatedBy = { ListValueConstraintValidator.class【可以指定多个不同的校验器,适配不同类型的校验】 }) * @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) * @Retention(RUNTIME) * public @interface ListValue { * * 4、统一的异常处理 * @ControllerAdvice * 1)、编写异常处理类,使用@ControllerAdvice。 * 2)、使用@ExceptionHandler标注方法可以处理的异常。 */ 前后端解决跨域问题:CORS策略------》跨域是指:浏览器不能执行其他网站的脚本,由浏览器的同源组策略造成的,是浏览器对JavaScript施加的安全策略 协议、域名、端口要相同 访问请求被拒绝-----》没有访问允许控制来源, 解决跨域:使用Nginx部署为同一域 静态请求 http://xxxx/aaaa 动态请求 http://xxxx/api/aaaa 跨域流程 非简单请求(put、delete)等,需要发送预检请求 浏览器 服务器 1.预检请求,OPTIONS-----> <--------2.相应允许跨域 3.发送真是数据--------> <--------4.相应数据 简单请求 某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”: 使用下列方法之一: GET HEAD POST 除了被用户代理自动设置的首部字段(例如 Connection ,User-Agent)和在 Fetch 规范中定义为 禁用首部名称 的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为: Accept Accept-Language Content-Language Content-Type (需要注意额外的限制) Content-Type 的值仅限于下列三者之一: text/plain multipart/form-data application/x-www-form-urlencoded ##****/*//*///*///*/逻辑删除 mybatis-plus----》》》》逻辑删除 使用方法: #步骤1: 配置com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig 例: application.yml mybatis-plus: global-config: db-config: logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) #步骤2: 实体类字段上加上@TableLogic注解 @TableLogic private Integer deleted; Gateway 网关 spring cloud 处理数据 requests/sec 32212.38 降低成本和安全风险 包括:协议配置、协议转发、安全策略、防刷、流量、监控日志等 提供一种简单有效的方式来对API进行路由,为他们提供切面 #使用阿里云服务的oss对象存储 1、存储空间 Bucket 存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间。 2、对象/文件 Object 对象是 OSS 存储数据的基本单元,也被称为OSS的文件。对象由元信息(Object Meta)、用户数据(Data)和文件名(Key)组成。对象由存储空间内部唯一的Key来标识。 3、地域 Region 地域表示 OSS 的数据中心所在物理位置。您可以根据费用、请求来源等综合选择数据存储的地域。详情请查看OSS已经开通的Region。 4、访问域名 Endpoint Endpoint 表示OSS对外服务的访问域名。OSS以HTTP RESTful API的形式对外提供服务,当访问不同地域的时候,需要不同的域名。通过内网和外网访问同一个地域所需要的域名也是不同的。具体的内容请参见各个Region对应的Endpoint。 5、访问密钥 AccessKey AccessKey,简称 AK,指的是访问身份验证中用到的AccessKeyId 和AccessKeySecret。OSS通过使用AccessKeyId 和AccessKeySecret对称加密的方法来验证某个请求的发送者身份。AccessKeyId用于标识用户,AccessKeySecret是用户用于加密签名字符串和OSS用来验证签名字符串的密钥,其中AccessKeySecret 必须保密。 ##服务端签名后直传 用户 ---->向应用服务器请求上传policy(防伪签名) ---->服务器 <-----应用服务器返回上传policy<----- ------>用户直接上传到oss------> OSS ##使用springcloud Alibaba----->alibaba cloud oss 对象存储 ##接入oss pom.xml 引入alicloud-oss starter com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery 在配置文件中配置oss服务对应的accesskey、secrekey和endpoint。 在java中自动注入 @Autowired private OSSClient OSSClient ###电商基本概念:spu:standard product unit 标准化产品单元:商品信息聚合的最小单元,是一组可复用、易检索 的标准化信息的集合,该集合描述了一个产品的特性 ###sku:库存量单元 ###品牌属性分组——父子组件交互 获取所有分类以及子分类 Get:/product/category/list/tree 1、选择三级分类,(参数名,查询,新增,批量删除)可以查找出分组id,组名,排序,描述, 父子组件传递数据 * 1)、子组件给父组件传递数据,事件机制; * 子组件给父组件发送一个事件,携带上数据。 * // this.$emit("事件名",携带的数据...可变数组) ### VO(value object) 值对象 通常用于业务层之间的数据传输,和 po(持久对象) 一样也是仅仅包含数据而已。但应是抽象出的业务对象,可以和表对应,业可以不, 根据业务需求,用new关键字创建,由cg回收 View object:视图对象; 接受页面处理完成的对象,封装成页面要用的数据 ### 11/28 发布商品——点击三级分未能类检索品牌名 前提了解:pubsubjs 一个利用JavaScript进行发布/订阅的库 实现顶底组件之间的通信 订阅消息/发布消息”的方法 在category-cascader.vue中 可以使用pubsub-js进行传值 this.PubSub.publish('catPath', v) 出现后台错误 解决方法:npm uninstall pubsub-js npm install pubsub-js --save category-cascader.vue import《组件名称》from'《组件路径》'; import PubSub from 'pubsub-js' PubSub.publish('catPath', v) ####采购流程 人工创建采购需求、库存预警创建采购需求——>人工合并、系统定时合并——>采购单——>分配——>采购人员——> 通知供应商或自主采购——>采购单入库——>添加库存 ####spu管理规格出现空白页ore404、400 400检查接口设计 404 src/router/index.js 修改 children: [ // 通过meta对象设置路由展示方式 // 1. isTab: 是否通过tab展示内容, true: 是, false: 否 // 2. iframeUrl: 是否通过iframe嵌套展示内容, '以http[s]://开头': 是, '': 否 // 提示: 如需要通过iframe嵌套展示内容, 但不通过tab打开, 请自行创建组件使用iframe处理! { path: '/home', component: _import('common/home'), name: 'home', meta: { title: '首页' } }, { path: '/theme', component: _import('common/theme'), name: 'theme', meta: { title: '主题' } }, { path: '/demo-echarts', component: _import('demo/echarts'), name: 'demo-echarts', meta: { title: 'demo-echarts', isTab: true } }, { path: '/demo-ueditor', component: _import('demo/ueditor'), name: 'demo-ueditor', meta: { title: 'demo-ueditor', isTab: true } }, { path: '/product-attrupdate', component: _import('modules/product/attrupdate'), name: 'attr-update', meta: { title: '规格维护', isTab: true } } ], ####Es——数组的扁平化处理 PUT my_index/_doc/1 { "group" : "fans", "user" : [ { "first" : "John", "last" : "Smith" }, { "first" : "Alice", "last" : "White" } ] } 扁平化处理 { "group" : "fans", "user.first" : [ "alice", "john" ], "user.last" : [ "smith", "white" ] } 检索(实际并没有Alice Smith ,但是会检索出到) { "match": { "user.first": "Alice" }}, { "match": { "user.last": "Smith" }} ####将静态资源放在nginx中 页面请求为动态资源 动静分离 静:图片、js、css等静态资源 动:服务器需要处理的请求 ##### 微服务——每一个服务都可以独立部署、运行、升级、独立自治 技术架构业务 ####Thymeleaf的特点 动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。 开箱即用:它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。 多方言支持:Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。 与SpringBoot完美整合,SpringBoot提供了Thymeleaf的默认配置,并且为Thymeleaf设置了视图解析器,我们可以像以前操作jsp一样来操作Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。 ####在首页页面 添加名称空间 * 5、模板引擎 * 1)、thymeleaf-starter: 关闭缓存 * 2)静态资源放在static文件夹下 路径访问 * 3)、页面放在templates下,直接访问,springboot,启动项目默认访问,index * 4)、页面修稿实际更新(不重启服务器) * 1、引入dev-tools(xml) * 2、ctrl+shift+F9 自动编译页面内容,热启动可能会出现代码配置bug ### 引入Nginx+Windows 项目微服务 客户 ————> Nginx ————> 网关 —————>商品服务、用户服务、检索服务、订单服务、购物车服务、(视图) ### Nginx+Windows搭建域名访问环境 windows->hosts文件 gulimall.com 虚拟机ip 本地客户 ——> search.gulimall.com ————>Nginx ——————>网关 -----> 微服务群 虚拟机ip item.gulimall.com 虚拟机ip member.gulimall.com 虚拟机ip nginx代理给网关的时候,会丢失请求的host信息 proxy_set_header Host $host 让nginx帮我们进行反向代理,所有来自原gulimall.com的请求,都转到商品服务 1、修改Windows的host文件 2、Nginx配置 Nginx conf.d cp default.conf gulimall.conf vi gulimall.conf server name:gulimall.com location: proxy_pass http://gulimall 本机的虚拟机地址 192.8.54.1:10000 请求上行 upstream guylimall{ server 192.168.56.1:88 路由请求 } 为了防止请求头丢失 proxy_set_header Hsot $host 配置到Nginx 转发给本地项目网关 网关在引用微服务群 ### 域名映射效果 • 请求接口 gulimall.com • 请求页面 gulimall.com • nginx直接代理给网关,网关判断 • 如果/api/****,转交给对应的服务器 • 如果是 满足域名,转交给对应的服务 ### 正向代理与反向代理 正向代理:如科学上网,隐藏客户端信息 反向代理:屏蔽内网服务器信息,负载均衡访问 ### 压力测试 有两种错误类型是: 内存泄漏,并发与同步。 有效的压力测试系统将应用以下这些关键条件:重复,并发,量级,随机变化。 ###1、性能指标  响应时间(Response Time: RT) 响应时间指用户从客户端发起一个请求开始,到客户端接收到从服务器端返回的响 应结束,整个过程所耗费的时间。  HPS(Hits Per Second) :每秒点击次数,单位是次/秒。  TPS(Transaction per Second):系统每秒处理交易数,单位是笔/秒。  QPS(Query per Second):系统每秒处理查询次数,单位是次/秒。 对于互联网业务中,如果某些业务有且仅有一个请求连接,那么 TPS=QPS=HPS,一 般情况下用 TPS 来衡量整个业务流程,用 QPS 来衡量接口查询次数,用 HPS 来表 示对服务器单击请求。  无论 TPS、QPS、HPS,此指标是衡量系统处理能力非常重要的指标,越大越好,根据经 验,一般情况下: 金融行业:1000TPS~50000TPS,不包括互联网化的活动 保险行业:100TPS~100000TPS,不包括互联网化的活动 制造行业:10TPS~5000TPS 互联网电子商务:10000TPS~1000000TPS 互联网中型网站:1000TPS~50000TPS 互联网小型网站:500TPS~10000TPS  最大响应时间(Max Response Time) 指用户发出请求或者指令到系统做出反应(响应) 的最大时间。  最少响应时间(Mininum ResponseTime) 指用户发出请求或者指令到系统做出反应(响 应)的最少时间。  90%响应时间(90% Response Time) 是指所有用户的响应时间进行排序,第 90%的响应时间。  从外部看,性能测试主要关注如下三个指标 吞吐量:每秒钟系统能够处理的请求数、任务数。 响应时间:服务处理一个请求或一个任务的耗时。 错误率:一批请求中结果出错的请求所占比例 #####2、JMeter 线程组参数详解:  线程数:虚拟用户数。一个虚拟用户占用一个进程或线程。设置多少虚拟用户数在这里 也就是设置多少个线程数。  Ramp-Up Period(in seconds)准备时长: 设置的虚拟用户数需要多长时间全部启动。 如果 线程数为 10,准备时长为 2,那么需要 2 秒钟启动 10 个线程,也就是每秒钟启动 5 个 线程。  循环次数:每个线程发送请求的次数。如果线程数为 10,循环次数为 100,那么每个线 程发送 100 次请求。总请求数为 10*100=1000 。如果勾选了“永远”,那么所有线程会 一直发送请求,一到选择停止运行脚本。  Delay Thread creation until needed:直到需要时延迟线程的创建。  调度器:设置线程组启动的开始时间和结束时间(配置调度器时,需要勾选循环次数为 永远)  持续时间(秒):测试持续时间,会覆盖结束时间  启动延迟(秒):测试延迟启动时间,会覆盖启动时间  启动时间:测试启动时间,启动延迟会覆盖它。当启动时间已过,手动只需测试时当前 时间也会覆盖它。  结束时间:测试结束时间,持续时间会覆盖它。 压测内容 压测线程数 吞吐量/s 90%响应时间 99%响应时间 Nginx 50 2335 11 944 Gateway 50 10367 8 31 简单服务 50 11341 8 17 首页一级菜单渲染 50 270(db,thymeleaf) 267 365 首页渲染(开缓存) 50 290 251 365 首页渲染(开缓存、 优化数据库、关日 志) 50 700 105 183 三级分类数据获取 50 2(db)/8(加索引) ... .. 三级分类(优化业 务) 50 111 571 896 三 级 分 类 ( 使 用 redis 作为缓存) 50 411 153 217 首页全量数据获取 50 7(静态资源) Nginx+Gateway 50 Gateway+简单服务 50 3126 30 125 全链路 50 800 88 310 ### 缓存 1、缓存使用  即时性、数据一致性要求不高的  访问量大且更新频率不高的数据(读多,写少) ### 缓存数据一致性-解决方案 • 无论是双写模式还是失效模式,都会导致缓存的不一致问题。即多个实例同时更新会出事。怎么办? • 1、如果是用户纬度数据(订单数据、用户数据),这种并发几率非常小,不用考虑这个问题,缓存数据加 上过期时间, 每隔一段时间触发读的主动更新即可 • 2、如果是菜单,商品介绍等基础数据,也可以去使用canal订阅binlog的方式。 • 3、缓存数据+过期时间也足够解决大部分业务对于缓存的要求。 • 4、通过加锁保证并发读写,写写的时候按顺序排好队。读读无所谓。所以适合使用读写锁。 (业务不关心 脏数据,允许临时脏数据可忽略); • 总结:• 我们能放入缓存的数据本就不应该是实时性、一致性要求超高的。所以缓存数据的时候加上过期时间, 保 证每天拿到当前最新数据即可。 • 我们不应该过度设计,增加系统的复杂性 • 遇到实时性、一致性要求高的数据,就应该查数据库,即使慢点 #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)