谷粒商城筆記合集
分布式基礎(chǔ)篇 | 分布式高級(jí)篇 | 高可用集群篇 |
---|---|---|
===簡(jiǎn)介&環(huán)境搭建=== | ===Elasticsearch=== | |
項(xiàng)目簡(jiǎn)介與分布式概念(第一、二章) | Elasticsearch:全文檢索(第一章) | |
基礎(chǔ)環(huán)境搭建(第三章) | ===商品服務(wù)開發(fā)=== | |
===整合SpringCloud=== | 商品服務(wù) & 商品上架(第二章) | |
整合SpringCloud、SpringCloud alibaba(第四、五章) | ===商城首頁(yè)開發(fā)=== | |
===前端知識(shí)=== | 商城業(yè)務(wù):首頁(yè)整合、Nginx 域名訪問(wèn)、性能優(yōu)化與壓力測(cè)試 (第三、四、五章) | |
前端開發(fā)基礎(chǔ)知識(shí)(第六章) | 緩存與分布式鎖(第六章) | |
===商品服務(wù)開發(fā)=== | ===商城檢索開發(fā)=== | |
商品服務(wù)開發(fā):基礎(chǔ)概念、三級(jí)分類(第七、八章) | 商城業(yè)務(wù):商品檢索(第七章) | |
商品服務(wù)開發(fā):品牌管理(第九章) | ||
商品服務(wù)開發(fā):屬性分組、平臺(tái)屬性(第十、十一章) | ||
商品服務(wù):商品維護(hù)(第十二、十三章) | ||
===倉(cāng)儲(chǔ)服務(wù)開發(fā)=== | ||
倉(cāng)儲(chǔ)服務(wù):倉(cāng)庫(kù)維護(hù)(第十四章) | ||
基礎(chǔ)篇總結(jié)(第十五章) |
三、商城業(yè)務(wù) & 首頁(yè)整合??????
3.1 前端渲染說(shuō)明??????
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties
-
templates 下的視圖頁(yè)面只能通過(guò)controller返回。訪問(wèn)項(xiàng)目根地址的歡迎頁(yè)默認(rèn)返回 classpath:/templates/index.html。
-
如果controller返回的不是json數(shù)據(jù),而是一個(gè)字符串。那么 springmvc 的視圖解析器就會(huì)根據(jù)前后綴進(jìn)行拼串找到并返回視圖頁(yè)面
-
靜態(tài)資源存放路徑:classpath:/META-INF/resources/、classpath:/resources/、classpath:/static/、classpath:/public/。可直接訪問(wèn)
-
項(xiàng)目架構(gòu)
3.2 thymeleaf 語(yǔ)法
3.2.1 簡(jiǎn)單表達(dá)式
- 變量表達(dá)式:
${...}
- 選擇變量表達(dá)式:
*{...}
- 消息表達(dá)式:
#{...}
- 鏈接網(wǎng)址表達(dá)式:
@{...}
- 片段表達(dá)式:
~{...}
3.2.2 文字
- 文本文字:
'one text'
,'Another one!'
,… - 數(shù)字文字:
0
,34
,3.0
,12.3
,… - 布爾文字:
true
,false
- 空文本:
null
- 文字標(biāo)記:
one
,sometext
,main
,…
3.2.3 文本操作
- 字符串連接:
+
- 文字替換:
|The name is ${name}|
3.2.4 算術(shù)運(yùn)算
- 二元運(yùn)算符:
+
,-
,*
,/
,%
- 減號(hào)(一元運(yùn)算符):
-
3.2.5 布爾運(yùn)算
- 二元運(yùn)算符:
and
,or
- 布爾取反(一元運(yùn)算符):
!
,not
3.2.6 比較和平等
- 比較器:
>
,<
,>=
,<=
(gt
,lt
,ge
,le
) - 相等運(yùn)算符:
==
,!=
(eq
,ne
)
3.2.7 條件運(yùn)算符
- 如果-那么:
(if) ? (then)
- 如果-那么-否則:
(if) ? (then) : (else)
- 默認(rèn):
(value) ?: (defaultvalue)
3.2.8 特殊令牌
- 無(wú)操作:
_
3.3 API:整合 thymeleaf 渲染首頁(yè)??
3.3.1 需求分析
開發(fā)傳統(tǒng)Java WEB工程時(shí),我們可以使用JSP頁(yè)面模板語(yǔ)言,但是在SpringBoot中已經(jīng)不推薦使用了。SpringBoot支持如下頁(yè)面模板語(yǔ)言
- Thymeleaf
- FreeMarker
- Velocity
- Groovy
- JSP
thymeleaf 官網(wǎng):https://www.thymeleaf.org/
官網(wǎng)文檔給出了 語(yǔ)法、相關(guān)標(biāo)簽 如何使用的步驟,由于官網(wǎng)文檔都是英文,英文文檔閱讀能力好的同學(xué)可以選擇閱讀,英文不好的同學(xué)可以選擇中文文檔進(jìn)行學(xué)習(xí),為此我在網(wǎng)上找到了相關(guān)的中文文檔:http://note.youdao.com/noteshare?id=7771a96e9031b30b91ed55c50528e918
3.3.2 整合??
-
在商品微服務(wù)的 pom.xml 中引入thymeleaf依賴
<!-- thymeleaf模板引擎 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
-
修改配置文件,關(guān)閉 thymeleaf緩存:application.yml
spring: thymeleaf: cache: false
-
拷貝前端資源到指定目錄
-
修改項(xiàng)目結(jié)構(gòu)
3.4 整合 dev-tools??
-
在商品微服務(wù)的 pom.xml 中引入dev-tools依賴
<!-- devtools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
-
讓頁(yè)面修改實(shí)時(shí)生效:CTRL+F9、CTRL+SHIFT+F9
3.5 API:渲染首頁(yè)分類數(shù)據(jù)??
3.5.1 一級(jí)分類數(shù)據(jù)
-
創(chuàng)建首頁(yè)跳轉(zhuǎn)controller,首頁(yè)渲染一級(jí)分類數(shù)據(jù):cn/lzwei/bilimall/product/web/IndexController.java
@Controller public class IndexController { @Resource CategoryService categoryService; @GetMapping(value = {"/","/index.html"}) public String index(Model model){ //首頁(yè)渲染:獲取一級(jí)分類數(shù)據(jù) List<CategoryEntity> categoryEntities=categoryService.getCategoryLevel1(); model.addAttribute("category",categoryEntities); return "index"; } }
-
CategoryService:首頁(yè)渲染,獲取一級(jí)分類數(shù)據(jù)
public interface CategoryService extends IService<CategoryEntity> { /** * 首頁(yè)渲染:獲取一級(jí)分類數(shù)據(jù) */ List<CategoryEntity> getCategoryLevel1(); }
-
CategoryServiceImpl:首頁(yè)渲染,獲取一級(jí)分類數(shù)據(jù)
@Service("categoryService") public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService { /** * 首頁(yè)渲染:獲取一級(jí)分類數(shù)據(jù) */ @Override public List<CategoryEntity> getCategoryLevel1() { List<CategoryEntity> categoryEntities = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0)); return categoryEntities; } }
-
在 /template/index.htnl 中添加 thymeleaf 屬性命名空間
<html lang="en" xmlns:th="http://www.thymeleaf.org">
-
修改 /template/index.html,渲染頁(yè)面一級(jí)分類數(shù)據(jù)
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <body> <header> <!--輪播主體內(nèi)容--> <div class="header_main"> <div class="header_banner"> <div class="header_main_left"> <ul> <li> <a href="#" class="header_main_left_a" th:attr="ctg-data=${category.catId}" th:each="category : ${categorys}" th:text="${category.name}"><b>家用電器</b></a> </li> </ul> </div> ... </div> </div> </header> </body> </html>
3.4.3 二、三級(jí) 分類
-
首頁(yè)渲染時(shí)發(fā)送請(qǐng)求到當(dāng)前服務(wù)獲取分類數(shù)據(jù):src/main/resources/static/index/js/catalogLoader.js
$(function(){ /* 修改分類數(shù)據(jù)請(qǐng)求路徑 */ $.getJSON("index/catalog.json",function (data) { ... }); });
-
分析數(shù)據(jù)結(jié)構(gòu)
{ "1": [ { "catalog1Id": "1", "catalog3List": [ { "catalog2Id": "1", "id": "1", "name": "電子書" }, ... ], "id": "1", "name": "電子書刊" }, ... ], ... }
-
web/IndexController.java:獲取分類數(shù)據(jù):用于渲染二級(jí)、三級(jí)分類
@Controller public class IndexController { @Resource CategoryService categoryService; /** * 獲取分類數(shù)據(jù):用于渲染二級(jí)、三級(jí)分類 */ @ResponseBody @GetMapping(value = "/index/catalog.json") public Map<String, List<CategoryLevel2Vo>> getCategoryLevel2(){ Map<String, List<CategoryLevel2Vo>> categorys=categoryService.getCategoryLevel2(); return categorys; } }
-
CategoryService:獲取分類數(shù)據(jù):用于渲染二級(jí)、三級(jí)分類
public interface CategoryService extends IService<CategoryEntity> { /** * 獲取分類數(shù)據(jù):用于渲染二級(jí)、三級(jí)分類 */ Map<String, List<CategoryLevel2Vo>> getCategoryLevel2(); }
-
CategoryServiceImpl:獲取分類數(shù)據(jù):用于渲染二級(jí)、三級(jí)分類
@Service("categoryService") public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService { /** * 獲取分類數(shù)據(jù):用于渲染二級(jí)、三級(jí)分類 */ @Override public Map<String, List<CategoryLevel2Vo>> getCategoryLevel2() { //1.獲取一級(jí)分類:將一級(jí)分類轉(zhuǎn)換為map進(jìn)行遍歷,自定義key、value List<CategoryEntity> categoryLevel1s = this.getCategoryLevel1(); Map<String, List<CategoryLevel2Vo>> collect=null; if(categoryLevel1s!=null){ collect = categoryLevel1s.stream().collect(Collectors.toMap(level1 -> level1.getCatId().toString(), level1 -> { //2.通過(guò)一級(jí)分類id獲取二級(jí)分類列表進(jìn)行遍歷:封裝成CategoryLevel2Vo集合 List<CategoryEntity> level2s = this.list(new QueryWrapper<CategoryEntity>().eq("parent_cid", level1.getCatId())); List<CategoryLevel2Vo> Level2Vos = null; if (level2s != null) { //遍歷二級(jí)分類:封裝成CategoryLevel2Vo Level2Vos = level2s.stream().map(level2 -> { CategoryLevel2Vo categoryLevel2Vo = new CategoryLevel2Vo(level2.getCatId().toString(), level2.getName(), level1.getCatId().toString(), null); //3.通過(guò)二級(jí)分類id獲取三級(jí)分類列表:封裝成CategoryLevel3Vo集合 List<CategoryEntity> level3s = this.list(new QueryWrapper<CategoryEntity>().eq("parent_cid", level2.getCatId())); if (level3s != null) { //遍歷三級(jí)分類:封裝成CategoryLevel3Vo List<CategoryLevel2Vo.CategoryLevel3Vo> level3Vos = level3s.stream().map(level3 -> { CategoryLevel2Vo.CategoryLevel3Vo categoryLevel3Vo = new CategoryLevel2Vo.CategoryLevel3Vo(level2.getCatId().toString(), level3.getCatId().toString(), level3.getName()); return categoryLevel3Vo; }).collect(Collectors.toList()); categoryLevel2Vo.setCatalog3List(level3Vos); } return categoryLevel2Vo; }).collect(Collectors.toList()); } return Level2Vos; })); } return collect; } }
四、商城業(yè)務(wù) & Nginx 域名訪問(wèn)??
4.1 前言
4.1.1 正向代理 與 反向代理
4.1.2 需求分析
4.1.3 Nginx 配置概述
http://nginx.org/en/docs/
4.2 內(nèi)網(wǎng)穿透服務(wù)器配置(行不通)
由于Nginx跑在云服務(wù)器上,所以打算實(shí)現(xiàn)內(nèi)網(wǎng)穿透:??????行不通,域名訪問(wèn) 公網(wǎng):80 時(shí)要求域名需要備案??????
瀏覽器bilimall.com—>云服務(wù)器:80(Nginx)—>云服務(wù)器:88(http內(nèi)網(wǎng)穿透端口)—>本地:88(網(wǎng)關(guān)服務(wù))
-
修改云服務(wù)器安全組開放對(duì)應(yīng)端口、關(guān)閉云服務(wù)器內(nèi)部防火墻(systemctl stop firewalld)
-
在云服務(wù)下載 frp 服務(wù)端,或者通過(guò)科學(xué)的方法在github上拉比較快:https://github.com/fatedier/frp
[root@tencent opt]# wget https://github.com/fatedier/frp/releases/download/v0.37.0/frp_0.37.0_linux_amd64.tar.gz
-
將壓縮包解壓到當(dāng)前目錄,進(jìn)入文件夾查看文件列表
- “frps”、“frps_full.ini”、"frps.ini"是放在服務(wù)器端運(yùn)行的可執(zhí)行文件和配置文件
- “frpc”、“frpc_full.ini”、"frpc.ini"是放在客戶端端運(yùn)行的可執(zhí)行文件和配置文件
[root@tencent opt]# tar -zxvf frp_0.37.0_linux_amd64.tar.gz [root@tencent opt]# cd frp_0.37.0_linux_amd64/ [root@tencent frp_0.37.0_linux_amd64]# ll
-
修改服務(wù)端配置。注意:配置項(xiàng)中用到的端口,需要在服務(wù)器上開啟
- “bind_addr”:服務(wù)器本地IP,不改。
- “bind_port”:frp監(jiān)聽端口。
- “token”:驗(yàn)證碼
- “dashboard_port”:frp 圖形化控制面板服務(wù)端口
- “dashboard_user”、“dashboard_pwd”:登錄控制面板的賬戶密碼。
[common] bind_addr=0.0.0.0 bind_port = 7777 #作為http映射的端口:即訪問(wèn) 云服務(wù)器:88 ,實(shí)現(xiàn)訪問(wèn)內(nèi)網(wǎng)服務(wù)。內(nèi)網(wǎng)服務(wù) vhost_http_port = 88 token=****** dashboard_port=8888 dashboard_user=admin dashboard_pwd=******
-
給frp所在目錄下的frp文件開通可執(zhí)行權(quán)限
[root@tencent frp_0.37.0_linux_amd64]# chmod 755 ./frps
-
配置frp后臺(tái)服務(wù)
[root@tencent frp_0.37.0_linux_amd64]# sudo vim /lib/systemd/system/frps.service [Unit] Description=fraps service After=network.target syslog.target Wants=network.target [Service] Type=simple #啟動(dòng)服務(wù)的命令(此處寫你的frps的實(shí)際安裝目錄) ExecStart=/opt/frp_0.37.0_linux_amd64/frps -c /opt/frp_0.37.0_linux_amd64/frps.ini [Install] WantedBy=multi-user.target
-
啟動(dòng) frps,打開開機(jī)啟動(dòng)
[root@tencent frp_0.37.0_linux_amd64]# systemctl start frps [root@tencent frp_0.37.0_linux_amd64]# systemctl enable frps Created symlink from /etc/systemd/system/multi-user.target.wants/frps.service to /usr/lib/systemd/system/frps.service.
-
訪問(wèn)控制面板:http://云服務(wù)器ip:控制面板服務(wù)端口
-
下載frp客戶端:https://github.com/fatedier/frp/releases?page=2
-
解壓下載后的壓縮包,并修改配置文件:frpc.ini
#注意:相關(guān)參數(shù)需要與服務(wù)端相互對(duì)應(yīng) [common] server_addr = 云服務(wù)器IP server_port = 7777 token=****** #這里表示將云服務(wù)器的88端口的所有請(qǐng)求映射到本地88端口 [web] type=http local_ip=127.0.0.1 local_port=88 custom_domains=114.132.162.129 #localtions=/
-
客戶端運(yùn)行
-
命令行方式
nohup .\frpc.exe -c .\frpc.ini >/dev/null 2>&1 &
-
腳本方式,在安裝目錄下創(chuàng)建文件:xxx.bat
@echo off if "%1" == "h" goto begin mshta vbscript:createobject("wscript.shell").run("""%~nx0"" h",0)(window.close)&&exit :begin REM .\frpc.exe -c .\frpc.ini
-
-
配置成功
4.3 Nginx反向代理:云服務(wù)器(行不通)
配置HTTPS服務(wù)器文檔:http://nginx.org/en/docs/http/load_balancing.html
HTTP負(fù)載均衡文檔:http://nginx.org/en/docs/http/configuring_https_servers.html
負(fù)載均衡其他細(xì)節(jié)文檔:http://www.nginx.com/blog/load-balancing-with-nginx-plus-part-2/
這里使用域名 bilimall.com 訪問(wèn)到云服務(wù)器
-
修改本地域名映射文件:C:\Windows\System32\drivers\etc\hosts
注意:可以將該文件拖到桌面修改,然后再拖回原文件夾??赡苄枰D(zhuǎn)成txt文件才可被修改,之后再重命名回來(lái)
#注意這里找到云服務(wù)器80端口,即nginx服務(wù) 114.132.162.129 bilimall.com
-
為 云服務(wù)器的nginx 配置上游服務(wù)器,上游服務(wù)為云服務(wù)器的88端口,88端口已內(nèi)網(wǎng)穿透到本地網(wǎng)關(guān)服務(wù)
[root@tencent ~]# vim /mydata/nginx/conf/nginx.conf ... http { ... upstream bilimall{ server 114.132.162.129:88; } }
-
為 云服務(wù)器的nginx 配置反向代理,將訪問(wèn)nginx的所有服務(wù)轉(zhuǎn)發(fā)到上游服務(wù)器
server { listen 80; server_name bilimall.com; location / { proxy_set_header Host $host; proxy_pass http://bilimall; } ... }
-
重啟 nginx容器實(shí)例
-
瀏覽器訪問(wèn):bilimall.com/api/product/attrattrgrouprelation/list
4.4 Nginx反向代理:本地(最終方案??)
-
修改本地域名映射文件:C:\Windows\System32\drivers\etc\hosts
注意:可以將該文件拖到桌面修改,然后再拖回原文件夾??赡苄枰D(zhuǎn)成txt文件才可被修改,之后再重命名回來(lái)
#注意這里找到本地80端口,即nginx服務(wù) 192.168.100.1 bilimall.com
-
下載Windows版本的nginx安裝包:http://nginx.org/en/download.html
-
將安裝包解壓到本地:F:\software\Nginx\
-
為 本地nginx 配置上游服務(wù)器和反向代理,上游服務(wù)為本地的網(wǎng)關(guān)服務(wù),將訪問(wèn)nginx的所有請(qǐng)求轉(zhuǎn)發(fā)到上游服務(wù)器:F:\software\Nginx\conf\nginx.conf
達(dá)到訪問(wèn)本機(jī)80端口(nginx服務(wù)),轉(zhuǎn)發(fā)到本地網(wǎng)關(guān)服務(wù)根據(jù)規(guī)則進(jìn)行路由的功能
... http { #添加下列配置:注意此配置為windows本地的nginx配置 upstream bilimall{ server 192.168.100.1:88; } #建議拷貝一份原來(lái)的進(jìn)行修改:注意此配置為windows本地的nginx配置 server { listen 80; server_name bilimall.com; location / { proxy_set_header Host $host; proxy_pass http://bilimall; } ... } ... }
-
啟動(dòng)命令行窗口,進(jìn)入nginx安裝目錄啟動(dòng)nginx
start nginx #開啟nginx服務(wù) nginx.exe -s stop #關(guān)閉nginx服務(wù),快速停止nginx,可能并不保存相關(guān)信息 nginx.exe -s quit #關(guān)閉nginx服務(wù),完整有序的停止nginx,并保存相關(guān)信息 nginx.exe -s reload #重載nginx服務(wù),當(dāng)你改變了nginx配置信息并需要重新載入這些配置時(shí)可以使用此命令重載nginx taskkill /F /IM nginx.exe > nul #強(qiáng)關(guān)nginx服務(wù)器
-
瀏覽器訪問(wèn):bilimall.com/api/product/attrattrgrouprelation/list
4.5 網(wǎng)關(guān)服務(wù):配置域名訪問(wèn)商城系統(tǒng)??
-
在 網(wǎng)關(guān)服務(wù) 的配置文件中添加域名路由規(guī)則,實(shí)現(xiàn)域名訪問(wèn)到商城系統(tǒng):application.yaml
spring: cloud: gateway: routes: - id: bilimall_route uri: lb://bilimall-product predicates: - Host=**.bilimall.com,bilimall.com
五、性能優(yōu)化與壓力測(cè)試??
5.1 概述
壓力測(cè)試考察當(dāng)前軟硬件環(huán)境下系統(tǒng)所能承受住的最大負(fù)荷并幫助找出系統(tǒng)的瓶頸所在,壓測(cè)都是為了系統(tǒng)在線上的處理能力和穩(wěn)定性維持在一個(gè)標(biāo)準(zhǔn)范圍內(nèi),做到心中有數(shù)。
使用壓力測(cè)試,我們有希望找到很多種用其他測(cè)試方法更難發(fā)現(xiàn)的錯(cuò)誤,有兩種錯(cuò)誤類型是:內(nèi)存泄漏、并發(fā)與同步
有效的壓力測(cè)試系統(tǒng)將應(yīng)用以下這些關(guān)鍵條件:重復(fù)、并發(fā)、量級(jí)、隨機(jī)變化
5.2 性能指標(biāo)
吞吐量大:系統(tǒng)支持高并發(fā)
響應(yīng)時(shí)間:越短說(shuō)明接口性能越好
SQL 耗時(shí):越小越好、一般情況下微妙級(jí)別
命中率:越高越好、一般情況下不能低于95%
鎖等待次數(shù):越低越好、等待時(shí)間越短越好
-
響應(yīng)時(shí)間(Response Time:RT)
響應(yīng)時(shí)間指用戶從客戶端發(fā)起一個(gè)請(qǐng)求開始,到客戶端接收到服務(wù)器端返回的響應(yīng)結(jié)束,整個(gè)過(guò)程所耗費(fèi)的時(shí)間
-
HPS(Hits Per Second) :每秒點(diǎn)擊次數(shù),單位是次/秒
-
TPS(Transaction per Second):系統(tǒng)每秒處理交易數(shù),單位是筆/秒
-
QPS (Query perSecond) :系統(tǒng)每秒處理查詢次數(shù),單位是次/秒。對(duì)于互聯(lián)網(wǎng)業(yè)務(wù)中,如果某些業(yè)務(wù)有且僅有一個(gè)請(qǐng)求連接,那么TPS=QPS=HPS,一般情況下用TPS來(lái)衡量整個(gè)業(yè)務(wù)流程,用QPS來(lái)衡量接口查詢次數(shù),用HPS來(lái)表示對(duì)服務(wù)器單擊請(qǐng)求。
-
無(wú)論TPS、QPS、HPS,此指標(biāo)是衡量系統(tǒng)處理能力非常重要的指標(biāo),越大越好,根據(jù)經(jīng)驗(yàn),一般情況下:
- 金融行業(yè): 1000TPS~50000TPS, 不包括互聯(lián)網(wǎng)化的活動(dòng)
- 保險(xiǎn)行業(yè): 100TPS-100000TPS, 不包括互聯(lián)網(wǎng)化的活動(dòng)
- 制造行業(yè): 10TPS~5000TPS
- 互聯(lián)網(wǎng)電子商務(wù): 10000TPS~1000000TPS
- 互聯(lián)網(wǎng)中型網(wǎng)站: 1000TPS~50000TPS
- 互聯(lián)網(wǎng)小型網(wǎng)站: 500TPS~10000TPS
-
最大響應(yīng)時(shí)間(Max Response Time) :指用戶發(fā)出請(qǐng)求或者指令到系統(tǒng)做出反應(yīng)(響應(yīng))的最大時(shí)間。
-
最少響應(yīng)時(shí)間 (Mininum ResponseTime):指用戶發(fā)出請(qǐng)求或者指令到系統(tǒng)做出反應(yīng)(響應(yīng))的最少時(shí)間
-
90%響應(yīng)時(shí)間(90% Response Time): 是指所有用戶的響應(yīng)時(shí)間進(jìn)行排序、第90%的響應(yīng)時(shí)間
-
從外部看、性能測(cè)試主要關(guān)注如下三個(gè)指標(biāo):
- 吞吐量:每秒鐘系統(tǒng)能夠處理的請(qǐng)求數(shù)、任務(wù)數(shù)
- 響應(yīng)時(shí)間:服務(wù)處理一個(gè)請(qǐng)求或一個(gè)任務(wù)的耗時(shí)
- 錯(cuò)誤率:一批請(qǐng)求中結(jié)果出錯(cuò)的請(qǐng)求所占比例
5.3 JMeter
5.3.1 安裝
jmeter官網(wǎng):https://jmeter.apache.org/
-
下載安裝包
-
解壓后進(jìn)入bin目錄點(diǎn)擊啟動(dòng)腳本,并更換顯示語(yǔ)言:F:\software\Jmeter\bin\jemter.bat
5.3.2 壓測(cè)示例
-
在示例測(cè)試計(jì)劃中添加線程組
-
添加 HTTP 請(qǐng)求
-
添加 監(jiān)聽器
-
啟動(dòng)壓測(cè),查看測(cè)試結(jié)果
-
結(jié)果樹
-
匯總報(bào)告
-
聚合報(bào)告
-
匯總圖
-
5.3.3 問(wèn)題解決
影響性能考慮點(diǎn)
- 數(shù)據(jù)庫(kù),應(yīng)用程序,中間件(tomcat、Nginx),網(wǎng)絡(luò)和操作系統(tǒng)等方面
- 首先考慮自己的應(yīng)用屬于 CPU密集型 還是 IO密集型
可能的異常:JMeter Address Already in use
到 90% 以上,則可以說(shuō)明服務(wù)器有問(wèn)題,壓力機(jī)沒(méi)有問(wèn)題。
windows本身提供的端口訪問(wèn)機(jī)制的問(wèn)題
Windows提供給TCP/IP 鏈接的端口為1024-5000,并且要四分鐘來(lái)循環(huán)回收他們。就導(dǎo)致我們?cè)诙虝r(shí)間內(nèi)跑大量的請(qǐng)求時(shí)將端口占滿了。
- cmd中,用regedit命令打開注冊(cè)表
- 在HKEY_ LOCAL MACHINE\SYSTEMCurrentControlSet\Services Tcpip\Parameters下
- 如果是分布式運(yùn)行的話,控制機(jī)器和負(fù)載機(jī)器都需要這樣操作哦
- 右擊parameters,新建一個(gè)新的DWORD(32位)值(D),名字為 MaxUserPort。然后雙擊 MaxUserPort,基數(shù)選擇十進(jìn)制,輸入數(shù)值數(shù)據(jù)為65534
- 右擊parameters,新建一個(gè)新的DWORD(32位)值(D),名字為 TCPTimedWaitDelay。然后雙擊 TCPTimedWaitDelay,基數(shù)選擇十進(jìn)制,輸入數(shù)值數(shù)據(jù)為30
- 修改配置完畢之后記得重啟機(jī)器才會(huì)生效
5.3 JVM 性能監(jiān)控
5.3.1 Jvm 內(nèi)存模型
5.3.2 堆
5.3.3 jvisualvm
監(jiān)控內(nèi)存泄漏,跟蹤垃圾回收,執(zhí)行時(shí)內(nèi)存、cpu分析,線程分析…
- 運(yùn)行:正在運(yùn)行的
- 休眠:sleep
- 等待:wait
- 駐留:線程池里面的空閑線程
- 監(jiān)視:阻塞的線程,正在等待鎖
安裝jvisualvm
https://visualvm.github.io/download.html
-
進(jìn)入官網(wǎng)下載地址,下載相應(yīng)版本的安裝包
-
解壓安裝包,修改配置文件:F:\software\Java\visualvm_215\etc\visualvm.conf
#添加下列配置:指定自己jdk的安裝目錄 visualvm_jdkhome="F:\software\Java\jdk-17.0.5"
-
雙擊啟動(dòng)腳本啟動(dòng) jvisualvm:F:\software\Java\visualvm_215\bin\visualvm.exe
-
如果沒(méi)有反應(yīng)可能是因?yàn)閖dk安裝目錄下存在jre文件夾,可以選擇刪除獲取移動(dòng)到別的地方
安裝插件
插件更新地址,根據(jù)版本選擇地址:https://visualvm.github.io/pluginscenters.html
-
打開插件窗口
-
安裝 Visual GC
-
重新啟動(dòng) jvisualvm
5.4 壓力測(cè)試
測(cè)試nginx,gateway,簡(jiǎn)單服務(wù)等中單個(gè)服務(wù)以及服務(wù)結(jié)合的性能:吞吐量/ms、90%響應(yīng)時(shí)間/ms、99%響應(yīng)時(shí)間/ms
壓測(cè)內(nèi)容 | 壓測(cè)線程數(shù) | 吞吐量/ms | 90%響應(yīng)時(shí)間/ms | 99%響應(yīng)時(shí)間/ms |
---|---|---|---|---|
Nginx | 50 | 2335 | 11 | 944 |
GateWay | 50 | 10367 | 8 | 31 |
簡(jiǎn)單服務(wù) | 50 | 11341 | 8 | 17 |
Gateway+簡(jiǎn)單服務(wù) | 50 | 3126 | 30 | 125 |
全鏈路 | 50 | 800 | 88 | 310 |
首頁(yè):一級(jí)菜單渲染 | 50 | 270(db,themleaf渲染,日志) | 267 | 365 |
三級(jí)數(shù)據(jù)獲取 | 50 | 2(db,業(yè)務(wù)代碼) | …(24000) | …(25000) |
首頁(yè):全量數(shù)據(jù) | 50 | 7(靜態(tài)資源) |
5.5 性能優(yōu)化:索引優(yōu)化??
中間件越多,性能損失越大,大多都損失在了中間之間的網(wǎng)絡(luò)交互:
- 優(yōu)化中間件吞吐量
- 提供之間的傳輸效率:更好的網(wǎng)線,更好的網(wǎng)卡,更好的傳輸協(xié)議…
業(yè)務(wù):
- db:添加索引
- 模板的渲染速度:開啟緩存
- cpu:降低日志等級(jí)
壓測(cè)內(nèi)容 | 壓測(cè)線程數(shù) | 吞吐量/ms | 90%響應(yīng)時(shí)間/ms | 99%響應(yīng)時(shí)間/ms |
---|---|---|---|---|
首頁(yè):一級(jí)菜單渲染(開themleaf緩存) | 50 | 270(290) | 267(251) | 365(365) |
首頁(yè):一級(jí)菜單渲染(開themleaf緩存、優(yōu)化數(shù)據(jù)庫(kù),降低日志級(jí)別) | 50 | 270(700) | 267(105) | 365(183) |
三級(jí)數(shù)據(jù)獲?。▋?yōu)化數(shù)據(jù)庫(kù),降低日志級(jí)別) | 50 | 2(8) |
5.6 性能優(yōu)化:nginx 動(dòng)靜分離??
業(yè)務(wù):
- 靜態(tài)資源:動(dòng)靜分離
壓測(cè)內(nèi)容 | 壓測(cè)線程數(shù) | 吞吐量/ms | 90%響應(yīng)時(shí)間/ms | 99%響應(yīng)時(shí)間/ms |
---|---|---|---|---|
首頁(yè):全量數(shù)據(jù)(開themleaf緩存、優(yōu)化數(shù)據(jù)庫(kù),關(guān)日志,動(dòng)靜分離) | 50 | 7(11) | ||
首頁(yè):全量數(shù)據(jù)(開themleaf緩存、優(yōu)化數(shù)據(jù)庫(kù),關(guān)日志,動(dòng)靜分離,jvm內(nèi)存) | 200 | 7(14) |
-
將 商品服務(wù) resources/static/ 下的靜態(tài)資源拷貝到 nginx中,并刪除商品服務(wù)下的靜態(tài)資源:F:\software\Nginx\html\static\
-
首頁(yè)返回后下載商品服務(wù)中靜態(tài)資源 resources/static/index/css/swiper-3.4.2.min.css 的路徑為:http://bilimall.com/index/css/swiper-3.4.2.min.css
<link rel="stylesheet" href="index/css/swiper-3.4.2.min.css">
-
修改首頁(yè)中 所有 靜態(tài)資源請(qǐng)求的路徑,請(qǐng)求 nginx中的靜態(tài)資源。重啟商品服務(wù)
<link rel="stylesheet" href="index/css/swiper-3.4.2.min.css"> <!-- 例如將上面修改為: --> <link rel="stylesheet" href="/static/index/css/swiper-3.4.2.min.css">
-
修改nginx配置文件:F:\software\Nginx\conf\nginx.conf
... http { upstream bilimall{ server 192.168.100.1:88; } server { listen 80; server_name bilimall.com; #增加下列配置:注意此配置為windows本地的nginx配置 location /static/ { root html; location / { proxy_set_header Host $host; proxy_pass http://bilimall; } ... } ... }
-
重啟nginx,分離成功
5.7 性能優(yōu)化:業(yè)務(wù)代碼??
業(yè)務(wù):
- IO:減少數(shù)據(jù)庫(kù)IO
壓測(cè)內(nèi)容 | 壓測(cè)線程數(shù) | 吞吐量/ms | 90%響應(yīng)時(shí)間/ms | 99%響應(yīng)時(shí)間/ms |
---|---|---|---|---|
三級(jí)數(shù)據(jù)獲?。?font color="blue">業(yè)務(wù)代碼減少數(shù)據(jù)庫(kù)IO) | 50 | 2(111) | 24000(571) | 25000(896) |
-
修改 商品服務(wù) 中首頁(yè)獲取三級(jí)分類數(shù)據(jù)的業(yè)務(wù)代碼,減少數(shù)據(jù)庫(kù)IO:cn.lzwei.bilimall.product.service.impl.CategoryServiceImpl文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-753102.html
@Service("categoryService") public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService { /** * 獲取分類數(shù)據(jù):用于渲染二級(jí)、三級(jí)分類 */ @Override public Map<String, List<CategoryLevel2Vo>> getCategoryLevel2() { //**************************緩存所有三級(jí)分類數(shù)據(jù)************************************** List<CategoryEntity> categoryEntities = baseMapper.selectList(null); //1.獲取一級(jí)分類:將一級(jí)分類轉(zhuǎn)換為map進(jìn)行遍歷,自定義key、value List<CategoryEntity> categoryLevel1s = getParent_cid(categoryEntities,0l); Map<String, List<CategoryLevel2Vo>> collect=null; if(categoryLevel1s!=null){ collect = categoryLevel1s.stream().collect(Collectors.toMap(level1 -> level1.getCatId().toString(), level1 -> { //2.通過(guò)一級(jí)分類id獲取二級(jí)分類列表進(jìn)行遍歷:封裝成CategoryLevel2Vo集合 List<CategoryEntity> level2s = getParent_cid(categoryEntities,level1.getCatId()); List<CategoryLevel2Vo> Level2Vos = null; if (level2s != null) { //遍歷二級(jí)分類:封裝成CategoryLevel2Vo Level2Vos = level2s.stream().map(level2 -> { CategoryLevel2Vo categoryLevel2Vo = new CategoryLevel2Vo(level2.getCatId().toString(), level2.getName(), level1.getCatId().toString(), null); //3.通過(guò)二級(jí)分類id獲取三級(jí)分類列表:封裝成CategoryLevel3Vo集合 List<CategoryEntity> level3s = getParent_cid(categoryEntities,level2.getCatId()); if (level3s != null) { //遍歷三級(jí)分類:封裝成CategoryLevel3Vo List<CategoryLevel2Vo.CategoryLevel3Vo> level3Vos = level3s.stream().map(level3 -> { CategoryLevel2Vo.CategoryLevel3Vo categoryLevel3Vo = new CategoryLevel2Vo.CategoryLevel3Vo(level2.getCatId().toString(), level3.getCatId().toString(), level3.getName()); return categoryLevel3Vo; }).collect(Collectors.toList()); categoryLevel2Vo.setCatalog3List(level3Vos); } return categoryLevel2Vo; }).collect(Collectors.toList()); } return Level2Vos; })); } return collect; } //通過(guò) parent_id 獲取分類數(shù)據(jù) private List<CategoryEntity> getParent_cid(List<CategoryEntity> categoryEntities,Long parentId) { List<CategoryEntity> collect = categoryEntities.stream().filter(item -> item.getParentCid().equals(parentId) ).collect(Collectors.toList()); return collect; } }
-
重啟服務(wù)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-753102.html
到了這里,關(guān)于【谷粒商城高級(jí)篇】商城業(yè)務(wù):首頁(yè)整合、Nginx 域名訪問(wèn)、性能優(yōu)化與壓力測(cè)試的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!