From 8044b8057778e545787f69e76e3865982b81a7e7 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 2 Feb 2024 04:56:49 +0000
Subject: [PATCH] Deploy to GitHub pages
---
404.html | 46 +++
CNAME | 1 +
about-the-author/index.html | 46 +++
about-the-author/personal-life/index.html | 46 +++
about-the-author/personal-life/wewe.html | 46 +++
about-the-author/works/index.html | 46 +++
...\344\272\272\344\275\234\345\223\201.html" | 46 +++
ads.txt | 1 +
article/index.html | 77 ++++
...\346\236\266\346\236\204.html-Td7kF-9n.js" | 1 +
...\346\236\266\346\236\204.html-cD88aaBU.js" | 1 +
...\346\224\271\347\211\210.html-rwQzBlk1.js" | 1 +
...\346\224\271\347\211\210.html-tUYTH5tb.js" | 80 ++++
assets/1mysql.html-Ei_7f_WQ.js | 1 +
assets/1mysql.html-_FE7EY_e.js | 1 +
...\344\275\277\347\224\250.html-2hMFeeJS.js" | 1 +
...\344\275\277\347\224\250.html-qm2pGUZ0.js" | 241 ++++++++++++
assets/2017.html-MDg2apnF.js | 1 +
assets/2017.html-zfvjl-5A.js | 1 +
assets/2018.html-XhKmceXA.js | 1 +
assets/2018.html-pd4XfNXB.js | 1 +
assets/2019.html-QgZCLsLC.js | 1 +
assets/2019.html-znm2eQc3.js | 1 +
...\344\273\273\345\212\241.html-HLLS9x6l.js" | 71 ++++
...\344\273\273\345\212\241.html-qFez5clX.js" | 1 +
...\347\263\273\347\273\237.html-pWJ6ghVV.js" | 1 +
...\347\263\273\347\273\237.html-rdybAcfJ.js" | 224 ++++++++++++
assets/404.html-F74GSICT.js | 1 +
assets/404.html-WhIsgby4.js | 1 +
...\351\203\250\347\275\262.html-6tnyAU-k.js" | 105 ++++++
...\351\203\250\347\275\262.html-Vk3PqneA.js" | 1 +
...\345\244\207\344\273\275.html-RXzoE_MH.js" | 65 ++++
...\345\244\207\344\273\275.html-cRo7CD_Q.js" | 1 +
...\346\217\222\344\273\266.html-553rUa1v.js" | 14 +
...\346\217\222\344\273\266.html-923LgNG1.js" | 1 +
...\345\210\206\346\236\220.html-hE6G3Tqn.js" | 1 +
...\345\210\206\346\236\220.html-kXuTnRoS.js" | 1 +
...\344\274\230\345\214\226.html-3n6tdjL9.js" | 1 +
...\344\274\230\345\214\226.html-YAx6WK4Q.js" | 1 +
...\345\217\202\346\225\260.html-RmR4uDpi.js" | 1 +
...\345\217\202\346\225\260.html-_zG0M5-i.js" | 33 ++
...\344\275\277\347\224\250.html-C4jpqxXi.js" | 1 +
...\344\275\277\347\224\250.html-V7I--Ipk.js" | 54 +++
assets/aop.html-rc4rLz6V.js | 1 +
assets/aop.html-vlpDYLuE.js | 61 ++++
assets/app-BDpQ7oW_.js | 247 +++++++++++++
assets/chatgpt.html-soLgBokY.js | 1 +
assets/chatgpt.html-tmuTnMCN.js | 110 ++++++
assets/devops-ping-tai.html-1QswvRRV.js | 246 +++++++++++++
assets/devops-ping-tai.html-kDtCSXpk.js | 1 +
assets/elastic-spark.html-yTkDwYPM.js | 1 +
assets/elastic-spark.html-ys8zTss9.js | 31 ++
...272\220\347\240\201debug.html-0y-mDJbS.js" | 1 +
...272\220\347\240\201debug.html-MPOlcYKm.js" | 1 +
assets/giscus-hHrgKA30.js | 66 ++++
assets/gitlab-ci.html-HyFv5Ls3.js | 1 +
assets/gitlab-ci.html-dr4MxX4e.js | 1 +
assets/icon/apple-icon-152.png | Bin 0 -> 3086 bytes
assets/icon/chrome-192.png | Bin 0 -> 3760 bytes
assets/icon/chrome-512.png | Bin 0 -> 9230 bytes
assets/icon/chrome-mask-192.png | Bin 0 -> 4079 bytes
assets/icon/chrome-mask-512.png | Bin 0 -> 9208 bytes
assets/icon/guide-maskable.png | Bin 0 -> 1691 bytes
assets/icon/guide-monochrome.png | Bin 0 -> 1465 bytes
assets/icon/ms-icon-144.png | Bin 0 -> 3445 bytes
assets/index.html-1PklmZ2g.js | 1 +
assets/index.html-1sFnb2Lj.js | 1 +
assets/index.html-1trTdh4U.js | 1 +
assets/index.html-2xQqwR-V.js | 1 +
assets/index.html-3mbB5C3H.js | 1 +
assets/index.html-48vkkelG.js | 1 +
assets/index.html-5KP2soWP.js | 1 +
assets/index.html-5Ud_mAI1.js | 1 +
assets/index.html-5mbY1w6w.js | 1 +
assets/index.html-8MJuJxlA.js | 1 +
assets/index.html-90zxtr19.js | 1 +
assets/index.html-99A78MjC.js | 1 +
assets/index.html-DLDIhIzm.js | 1 +
assets/index.html-Dlgh3iE3.js | 1 +
assets/index.html-EL40ihRZ.js | 1 +
assets/index.html-FEPMx79S.js | 1 +
assets/index.html-IB-VG-Mp.js | 1 +
assets/index.html-IZIHDPXq.js | 1 +
assets/index.html-Ibbd0oto.js | 1 +
assets/index.html-KA0_6BkE.js | 1 +
assets/index.html-LxuTaAGt.js | 1 +
assets/index.html-NPk7ZlMe.js | 1 +
assets/index.html-N_67P6-s.js | 1 +
assets/index.html-NrD26gEP.js | 1 +
assets/index.html-NupEPZnP.js | 1 +
assets/index.html-P7BZhZZ3.js | 1 +
assets/index.html-Prj9iPTA.js | 1 +
assets/index.html-Rmp6Dnhx.js | 1 +
assets/index.html-SLeyy5iI.js | 1 +
assets/index.html-T5wPpx5i.js | 1 +
assets/index.html-TQjoPWRe.js | 1 +
assets/index.html-TuBE6nT4.js | 1 +
assets/index.html-VBS4h1m3.js | 1 +
assets/index.html-VH5_9vnr.js | 1 +
assets/index.html-VZNNIAqy.js | 1 +
assets/index.html-W7NDSfQJ.js | 1 +
assets/index.html-Wy8VVR2w.js | 1 +
assets/index.html-XRBVnkdY.js | 1 +
assets/index.html-XULjGA2d.js | 1 +
assets/index.html-_qUKpQt2.js | 1 +
assets/index.html-bIaAM2PA.js | 1 +
assets/index.html-cMYV1G54.js | 1 +
assets/index.html-eHm_BaZP.js | 1 +
assets/index.html-ge6-rWX_.js | 1 +
assets/index.html-h9DDJPFu.js | 1 +
assets/index.html-iUEVv6c6.js | 1 +
assets/index.html-j3N_gv-O.js | 1 +
assets/index.html-k7gT6RRu.js | 1 +
assets/index.html-m97a0bAY.js | 1 +
assets/index.html-mNLKf94V.js | 1 +
assets/index.html-pTK8tT0u.js | 1 +
assets/index.html-r9GuP2yb.js | 1 +
assets/index.html-sgH7oDMT.js | 1 +
assets/index.html-t2KDSwiJ.js | 1 +
assets/index.html-tMixJPN7.js | 1 +
assets/index.html-vgYoWX9F.js | 1 +
assets/index.html-w8XwDCrF.js | 1 +
assets/index.html-xgoJibcf.js | 1 +
assets/index.html-yuZKtvix.js | 1 +
assets/index.html-zEn3PTqR.js | 1 +
assets/index.html-zS2O51Oq.js | 1 +
assets/index.html-zdhpQIq5.js | 1 +
assets/jenkins-x.html-MktcI56z.js | 1 +
assets/jenkins-x.html-gi90zyZ8.js | 1 +
assets/kafka.html-p9lSBY-U.js | 1 +
assets/kafka.html-vXPGDb5r.js | 1 +
assets/main.html-gMstwCzy.js | 1 +
assets/main.html-s2aQ0VEN.js | 1 +
assets/photoswipe.esm-08_zHRDQ.js | 4 +
...\347\274\223\345\255\230.html--dFiuCqw.js" | 93 +++++
...\347\274\223\345\255\230.html-B4MmbAQF.js" | 1 +
...\347\274\223\345\255\230.html-rKUKwNSH.js" | 1 +
...\347\274\223\345\255\230.html-vh2fHF7B.js" | 96 +++++
assets/serverlog.html-ib9svlbN.js | 1 +
assets/serverlog.html-tI2y9coc.js | 3 +
assets/spark on k8s operator.html-Uq_G4U-U.js | 1 +
assets/spark on k8s operator.html-xMGCveTO.js | 73 ++++
assets/starcraft-ai.html-jENBJ0MN.js | 1 +
assets/starcraft-ai.html-p5HRu5Fy.js | 1 +
assets/style-U4CVPIhO.css | 1 +
assets/tekton.html-7q40Qc0_.js | 1 +
assets/tekton.html-_o4_9OHV.js | 1 +
assets/tesla.html-NKqgulgY.js | 30 ++
assets/tesla.html-NVSkMPRC.js | 1 +
assets/tiktok2023.html-VVmqvR2f.js | 1 +
assets/tiktok2023.html-vNmuRchL.js | 1 +
assets/webflux.html-BMCSAQQq.js | 1 +
assets/webflux.html-PgcG3rG7.js | 1 +
assets/wewe.html-WVS44t7L.js | 1 +
assets/wewe.html-dxhYsqpt.js | 1 +
assets/zookeeper.html-LJ6qa5Y9.js | 1 +
assets/zookeeper.html-YcPoe8IG.js | 1 +
...\350\257\246\350\247\243.html-NGfX8s6C.js" | 1 +
...\350\257\246\350\247\243.html-yIULGMSO.js" | 300 +++++++++++++++
...\350\277\207\347\250\213.html-2GlqVzrR.js" | 9 +
...\350\277\207\347\250\213.html-Fez3X8xk.js" | 1 +
...\344\275\234\345\223\201.html-HGTJItSS.js" | 1 +
...\344\275\234\345\223\201.html-Hz6pe8Pm.js" | 1 +
...\345\261\217\351\232\234.html-S6Jp2mo3.js" | 1 +
...\345\261\217\351\232\234.html-YpsEGPcG.js" | 1 +
...\347\272\277\347\250\213.html-S_l2wKz7.js" | 60 +++
...\347\272\277\347\250\213.html-aSy3Jyqy.js" | 1 +
...\351\231\220\346\265\201.html-SsVfGmol.js" | 1 +
...\351\231\220\346\265\201.html-sbydyYPs.js" | 54 +++
...\346\212\223\345\217\226.html-DyyYunsJ.js" | 1 +
...\346\212\223\345\217\226.html-oolMetg1.js" | 122 +++++++
...\347\274\223\345\255\230.html-D5OE_lZE.js" | 1 +
...\347\274\223\345\255\230.html-GSdRVX9_.js" | 1 +
bdunion.txt | 1 +
bigdata/index.html | 46 +++
bigdata/spark/elastic-spark.html | 76 ++++
bigdata/spark/index.html | 46 +++
category/index.html | 46 +++
cloudnative/index.html | 46 +++
...csearch\346\272\220\347\240\201debug.html" | 46 +++
database/elasticsearch/index.html | 46 +++
...\347\250\213\350\257\246\350\247\243.html" | 345 ++++++++++++++++++
database/index.html | 46 +++
database/mysql/1mysql.html | 46 +++
database/mysql/index.html | 46 +++
...\345\272\223\347\274\223\345\255\230.html" | 46 +++
database/redis/index.html | 46 +++
.../redis/redis\347\274\223\345\255\230.html" | 141 +++++++
devops/devops-ping-tai.html | 291 +++++++++++++++
devops/gitlab-ci.html | 46 +++
devops/index.html | 46 +++
devops/jenkins-x.html | 46 +++
devops/tekton.html | 46 +++
donate/index.html | 46 +++
favicon.ico | Bin 0 -> 21722 bytes
index.html | 46 +++
interview/index.html | 46 +++
interview/tiktok2023.html | 46 +++
...\344\274\230\345\217\202\346\225\260.html" | 78 ++++
...t Prometheus\344\275\277\347\224\250.html" | 99 +++++
java/SpringBoot/aop.html | 106 ++++++
java/SpringBoot/index.html | 46 +++
java/SpringBoot/webflux.html | 46 +++
java/index.html | 46 +++
java/serverlog.html | 48 +++
...\344\274\230\350\277\207\347\250\213.html" | 54 +++
...\344\270\216\346\236\266\346\236\204.html" | 46 +++
...\347\273\210\346\224\271\347\211\210.html" | 125 +++++++
...\347\232\204\344\275\277\347\224\250.html" | 286 +++++++++++++++
...\346\227\266\344\273\273\345\212\241.html" | 116 ++++++
...\345\277\227\347\263\273\347\273\237.html" | 269 ++++++++++++++
...\347\276\244\351\203\250\347\275\262.html" | 150 ++++++++
...\345\272\223\345\244\207\344\273\275.html" | 110 ++++++
...\347\232\204\346\217\222\344\273\266.html" | 59 +++
...\346\204\237\345\210\206\346\236\220.html" | 46 +++
...\350\203\275\344\274\230\345\214\226.html" | 46 +++
.../index.html" | 46 +++
...\345\255\230\345\261\217\351\232\234.html" | 46 +++
...\346\213\237\347\272\277\347\250\213.html" | 105 ++++++
...\345\274\217\351\231\220\346\265\201.html" | 99 +++++
kubernetes/index.html | 46 +++
kubernetes/spark on k8s operator.html | 118 ++++++
life/2017.html | 46 +++
life/2018.html | 46 +++
life/2019.html | 46 +++
life/index.html | 46 +++
link/index.html | 46 +++
link/main.html | 46 +++
logo.png | Bin 0 -> 21722 bytes
logo.svg | 101 +++++
middleware/index.html | 46 +++
middleware/kafka/index.html | 46 +++
middleware/kafka/kafka.html | 46 +++
middleware/zookeeper/index.html | 46 +++
middleware/zookeeper/zookeeper.html | 46 +++
open-source-project/index.html | 46 +++
others/chatgpt.html | 155 ++++++++
others/index.html | 46 +++
others/starcraft-ai.html | 46 +++
others/tesla.html | 75 ++++
...\351\230\205\346\212\223\345\217\226.html" | 167 +++++++++
redis/index.html | 46 +++
"redis/redis\347\274\223\345\255\230.html" | 138 +++++++
robots.txt | 5 +
sitemap.xml | 3 +
sitemap.xsl | 152 ++++++++
star/index.html | 46 +++
tag/index.html | 46 +++
timeline/index.html | 46 +++
249 files changed, 8565 insertions(+)
create mode 100644 404.html
create mode 100644 CNAME
create mode 100644 about-the-author/index.html
create mode 100644 about-the-author/personal-life/index.html
create mode 100644 about-the-author/personal-life/wewe.html
create mode 100644 about-the-author/works/index.html
create mode 100644 "about-the-author/works/\344\270\252\344\272\272\344\275\234\345\223\201.html"
create mode 100644 ads.txt
create mode 100644 article/index.html
create mode 100644 "assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-Td7kF-9n.js"
create mode 100644 "assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-cD88aaBU.js"
create mode 100644 "assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-rwQzBlk1.js"
create mode 100644 "assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-tUYTH5tb.js"
create mode 100644 assets/1mysql.html-Ei_7f_WQ.js
create mode 100644 assets/1mysql.html-_FE7EY_e.js
create mode 100644 "assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-2hMFeeJS.js"
create mode 100644 "assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-qm2pGUZ0.js"
create mode 100644 assets/2017.html-MDg2apnF.js
create mode 100644 assets/2017.html-zfvjl-5A.js
create mode 100644 assets/2018.html-XhKmceXA.js
create mode 100644 assets/2018.html-pd4XfNXB.js
create mode 100644 assets/2019.html-QgZCLsLC.js
create mode 100644 assets/2019.html-znm2eQc3.js
create mode 100644 "assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-HLLS9x6l.js"
create mode 100644 "assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-qFez5clX.js"
create mode 100644 "assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-pWJ6ghVV.js"
create mode 100644 "assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-rdybAcfJ.js"
create mode 100644 assets/404.html-F74GSICT.js
create mode 100644 assets/404.html-WhIsgby4.js
create mode 100644 "assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-6tnyAU-k.js"
create mode 100644 "assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-Vk3PqneA.js"
create mode 100644 "assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-RXzoE_MH.js"
create mode 100644 "assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-cRo7CD_Q.js"
create mode 100644 "assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-553rUa1v.js"
create mode 100644 "assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-923LgNG1.js"
create mode 100644 "assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-hE6G3Tqn.js"
create mode 100644 "assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-kXuTnRoS.js"
create mode 100644 "assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-3n6tdjL9.js"
create mode 100644 "assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-YAx6WK4Q.js"
create mode 100644 "assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-RmR4uDpi.js"
create mode 100644 "assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-_zG0M5-i.js"
create mode 100644 "assets/Spring Boot Prometheus\344\275\277\347\224\250.html-C4jpqxXi.js"
create mode 100644 "assets/Spring Boot Prometheus\344\275\277\347\224\250.html-V7I--Ipk.js"
create mode 100644 assets/aop.html-rc4rLz6V.js
create mode 100644 assets/aop.html-vlpDYLuE.js
create mode 100644 assets/app-BDpQ7oW_.js
create mode 100644 assets/chatgpt.html-soLgBokY.js
create mode 100644 assets/chatgpt.html-tmuTnMCN.js
create mode 100644 assets/devops-ping-tai.html-1QswvRRV.js
create mode 100644 assets/devops-ping-tai.html-kDtCSXpk.js
create mode 100644 assets/elastic-spark.html-yTkDwYPM.js
create mode 100644 assets/elastic-spark.html-ys8zTss9.js
create mode 100644 "assets/elasticsearch\346\272\220\347\240\201debug.html-0y-mDJbS.js"
create mode 100644 "assets/elasticsearch\346\272\220\347\240\201debug.html-MPOlcYKm.js"
create mode 100644 assets/giscus-hHrgKA30.js
create mode 100644 assets/gitlab-ci.html-HyFv5Ls3.js
create mode 100644 assets/gitlab-ci.html-dr4MxX4e.js
create mode 100644 assets/icon/apple-icon-152.png
create mode 100644 assets/icon/chrome-192.png
create mode 100644 assets/icon/chrome-512.png
create mode 100644 assets/icon/chrome-mask-192.png
create mode 100644 assets/icon/chrome-mask-512.png
create mode 100644 assets/icon/guide-maskable.png
create mode 100644 assets/icon/guide-monochrome.png
create mode 100644 assets/icon/ms-icon-144.png
create mode 100644 assets/index.html-1PklmZ2g.js
create mode 100644 assets/index.html-1sFnb2Lj.js
create mode 100644 assets/index.html-1trTdh4U.js
create mode 100644 assets/index.html-2xQqwR-V.js
create mode 100644 assets/index.html-3mbB5C3H.js
create mode 100644 assets/index.html-48vkkelG.js
create mode 100644 assets/index.html-5KP2soWP.js
create mode 100644 assets/index.html-5Ud_mAI1.js
create mode 100644 assets/index.html-5mbY1w6w.js
create mode 100644 assets/index.html-8MJuJxlA.js
create mode 100644 assets/index.html-90zxtr19.js
create mode 100644 assets/index.html-99A78MjC.js
create mode 100644 assets/index.html-DLDIhIzm.js
create mode 100644 assets/index.html-Dlgh3iE3.js
create mode 100644 assets/index.html-EL40ihRZ.js
create mode 100644 assets/index.html-FEPMx79S.js
create mode 100644 assets/index.html-IB-VG-Mp.js
create mode 100644 assets/index.html-IZIHDPXq.js
create mode 100644 assets/index.html-Ibbd0oto.js
create mode 100644 assets/index.html-KA0_6BkE.js
create mode 100644 assets/index.html-LxuTaAGt.js
create mode 100644 assets/index.html-NPk7ZlMe.js
create mode 100644 assets/index.html-N_67P6-s.js
create mode 100644 assets/index.html-NrD26gEP.js
create mode 100644 assets/index.html-NupEPZnP.js
create mode 100644 assets/index.html-P7BZhZZ3.js
create mode 100644 assets/index.html-Prj9iPTA.js
create mode 100644 assets/index.html-Rmp6Dnhx.js
create mode 100644 assets/index.html-SLeyy5iI.js
create mode 100644 assets/index.html-T5wPpx5i.js
create mode 100644 assets/index.html-TQjoPWRe.js
create mode 100644 assets/index.html-TuBE6nT4.js
create mode 100644 assets/index.html-VBS4h1m3.js
create mode 100644 assets/index.html-VH5_9vnr.js
create mode 100644 assets/index.html-VZNNIAqy.js
create mode 100644 assets/index.html-W7NDSfQJ.js
create mode 100644 assets/index.html-Wy8VVR2w.js
create mode 100644 assets/index.html-XRBVnkdY.js
create mode 100644 assets/index.html-XULjGA2d.js
create mode 100644 assets/index.html-_qUKpQt2.js
create mode 100644 assets/index.html-bIaAM2PA.js
create mode 100644 assets/index.html-cMYV1G54.js
create mode 100644 assets/index.html-eHm_BaZP.js
create mode 100644 assets/index.html-ge6-rWX_.js
create mode 100644 assets/index.html-h9DDJPFu.js
create mode 100644 assets/index.html-iUEVv6c6.js
create mode 100644 assets/index.html-j3N_gv-O.js
create mode 100644 assets/index.html-k7gT6RRu.js
create mode 100644 assets/index.html-m97a0bAY.js
create mode 100644 assets/index.html-mNLKf94V.js
create mode 100644 assets/index.html-pTK8tT0u.js
create mode 100644 assets/index.html-r9GuP2yb.js
create mode 100644 assets/index.html-sgH7oDMT.js
create mode 100644 assets/index.html-t2KDSwiJ.js
create mode 100644 assets/index.html-tMixJPN7.js
create mode 100644 assets/index.html-vgYoWX9F.js
create mode 100644 assets/index.html-w8XwDCrF.js
create mode 100644 assets/index.html-xgoJibcf.js
create mode 100644 assets/index.html-yuZKtvix.js
create mode 100644 assets/index.html-zEn3PTqR.js
create mode 100644 assets/index.html-zS2O51Oq.js
create mode 100644 assets/index.html-zdhpQIq5.js
create mode 100644 assets/jenkins-x.html-MktcI56z.js
create mode 100644 assets/jenkins-x.html-gi90zyZ8.js
create mode 100644 assets/kafka.html-p9lSBY-U.js
create mode 100644 assets/kafka.html-vXPGDb5r.js
create mode 100644 assets/main.html-gMstwCzy.js
create mode 100644 assets/main.html-s2aQ0VEN.js
create mode 100644 assets/photoswipe.esm-08_zHRDQ.js
create mode 100644 "assets/redis\347\274\223\345\255\230.html--dFiuCqw.js"
create mode 100644 "assets/redis\347\274\223\345\255\230.html-B4MmbAQF.js"
create mode 100644 "assets/redis\347\274\223\345\255\230.html-rKUKwNSH.js"
create mode 100644 "assets/redis\347\274\223\345\255\230.html-vh2fHF7B.js"
create mode 100644 assets/serverlog.html-ib9svlbN.js
create mode 100644 assets/serverlog.html-tI2y9coc.js
create mode 100644 assets/spark on k8s operator.html-Uq_G4U-U.js
create mode 100644 assets/spark on k8s operator.html-xMGCveTO.js
create mode 100644 assets/starcraft-ai.html-jENBJ0MN.js
create mode 100644 assets/starcraft-ai.html-p5HRu5Fy.js
create mode 100644 assets/style-U4CVPIhO.css
create mode 100644 assets/tekton.html-7q40Qc0_.js
create mode 100644 assets/tekton.html-_o4_9OHV.js
create mode 100644 assets/tesla.html-NKqgulgY.js
create mode 100644 assets/tesla.html-NVSkMPRC.js
create mode 100644 assets/tiktok2023.html-VVmqvR2f.js
create mode 100644 assets/tiktok2023.html-vNmuRchL.js
create mode 100644 assets/webflux.html-BMCSAQQq.js
create mode 100644 assets/webflux.html-PgcG3rG7.js
create mode 100644 assets/wewe.html-WVS44t7L.js
create mode 100644 assets/wewe.html-dxhYsqpt.js
create mode 100644 assets/zookeeper.html-LJ6qa5Y9.js
create mode 100644 assets/zookeeper.html-YcPoe8IG.js
create mode 100644 "assets/\343\200\220elasticsearch\343\200\221\346\220\234\347\264\242\350\277\207\347\250\213\350\257\246\350\247\243.html-NGfX8s6C.js"
create mode 100644 "assets/\343\200\220elasticsearch\343\200\221\346\220\234\347\264\242\350\277\207\347\250\213\350\257\246\350\247\243.html-yIULGMSO.js"
create mode 100644 "assets/\344\270\200\346\254\241jvm\350\260\203\344\274\230\350\277\207\347\250\213.html-2GlqVzrR.js"
create mode 100644 "assets/\344\270\200\346\254\241jvm\350\260\203\344\274\230\350\277\207\347\250\213.html-Fez3X8xk.js"
create mode 100644 "assets/\344\270\252\344\272\272\344\275\234\345\223\201.html-HGTJItSS.js"
create mode 100644 "assets/\344\270\252\344\272\272\344\275\234\345\223\201.html-Hz6pe8Pm.js"
create mode 100644 "assets/\345\206\205\345\255\230\345\261\217\351\232\234.html-S6Jp2mo3.js"
create mode 100644 "assets/\345\206\205\345\255\230\345\261\217\351\232\234.html-YpsEGPcG.js"
create mode 100644 "assets/\345\234\250 Spring 6 \344\270\255\344\275\277\347\224\250\350\231\232\346\213\237\347\272\277\347\250\213.html-S_l2wKz7.js"
create mode 100644 "assets/\345\234\250 Spring 6 \344\270\255\344\275\277\347\224\250\350\231\232\346\213\237\347\272\277\347\250\213.html-aSy3Jyqy.js"
create mode 100644 "assets/\345\237\272\344\272\216kubernetes\347\232\204\345\210\206\345\270\203\345\274\217\351\231\220\346\265\201.html-SsVfGmol.js"
create mode 100644 "assets/\345\237\272\344\272\216kubernetes\347\232\204\345\210\206\345\270\203\345\274\217\351\231\220\346\265\201.html-sbydyYPs.js"
create mode 100644 "assets/\345\271\277\345\267\236\345\233\276\344\271\246\351\246\206\345\200\237\351\230\205\346\212\223\345\217\226.html-DyyYunsJ.js"
create mode 100644 "assets/\345\271\277\345\267\236\345\233\276\344\271\246\351\246\206\345\200\237\351\230\205\346\212\223\345\217\226.html-oolMetg1.js"
create mode 100644 "assets/\346\225\260\346\215\256\345\272\223\347\274\223\345\255\230.html-D5OE_lZE.js"
create mode 100644 "assets/\346\225\260\346\215\256\345\272\223\347\274\223\345\255\230.html-GSdRVX9_.js"
create mode 100644 bdunion.txt
create mode 100644 bigdata/index.html
create mode 100644 bigdata/spark/elastic-spark.html
create mode 100644 bigdata/spark/index.html
create mode 100644 category/index.html
create mode 100644 cloudnative/index.html
create mode 100644 "database/elasticsearch/elasticsearch\346\272\220\347\240\201debug.html"
create mode 100644 database/elasticsearch/index.html
create mode 100644 "database/elasticsearch/\343\200\220elasticsearch\343\200\221\346\220\234\347\264\242\350\277\207\347\250\213\350\257\246\350\247\243.html"
create mode 100644 database/index.html
create mode 100644 database/mysql/1mysql.html
create mode 100644 database/mysql/index.html
create mode 100644 "database/mysql/\346\225\260\346\215\256\345\272\223\347\274\223\345\255\230.html"
create mode 100644 database/redis/index.html
create mode 100644 "database/redis/redis\347\274\223\345\255\230.html"
create mode 100644 devops/devops-ping-tai.html
create mode 100644 devops/gitlab-ci.html
create mode 100644 devops/index.html
create mode 100644 devops/jenkins-x.html
create mode 100644 devops/tekton.html
create mode 100644 donate/index.html
create mode 100644 favicon.ico
create mode 100644 index.html
create mode 100644 interview/index.html
create mode 100644 interview/tiktok2023.html
create mode 100644 "java/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html"
create mode 100644 "java/SpringBoot/Spring Boot Prometheus\344\275\277\347\224\250.html"
create mode 100644 java/SpringBoot/aop.html
create mode 100644 java/SpringBoot/index.html
create mode 100644 java/SpringBoot/webflux.html
create mode 100644 java/index.html
create mode 100644 java/serverlog.html
create mode 100644 "java/\344\270\200\346\254\241jvm\350\260\203\344\274\230\350\277\207\347\250\213.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/2.Lucene\347\232\204\344\275\277\347\224\250.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/3.\345\256\232\346\227\266\344\273\273\345\212\241.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/4.\346\227\245\345\277\227\347\263\273\347\273\237.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html"
create mode 100644 "java/\344\270\252\344\272\272\347\275\221\347\253\231/index.html"
create mode 100644 "java/\345\206\205\345\255\230\345\261\217\351\232\234.html"
create mode 100644 "java/\345\234\250 Spring 6 \344\270\255\344\275\277\347\224\250\350\231\232\346\213\237\347\272\277\347\250\213.html"
create mode 100644 "java/\345\237\272\344\272\216kubernetes\347\232\204\345\210\206\345\270\203\345\274\217\351\231\220\346\265\201.html"
create mode 100644 kubernetes/index.html
create mode 100644 kubernetes/spark on k8s operator.html
create mode 100644 life/2017.html
create mode 100644 life/2018.html
create mode 100644 life/2019.html
create mode 100644 life/index.html
create mode 100644 link/index.html
create mode 100644 link/main.html
create mode 100644 logo.png
create mode 100644 logo.svg
create mode 100644 middleware/index.html
create mode 100644 middleware/kafka/index.html
create mode 100644 middleware/kafka/kafka.html
create mode 100644 middleware/zookeeper/index.html
create mode 100644 middleware/zookeeper/zookeeper.html
create mode 100644 open-source-project/index.html
create mode 100644 others/chatgpt.html
create mode 100644 others/index.html
create mode 100644 others/starcraft-ai.html
create mode 100644 others/tesla.html
create mode 100644 "others/\345\271\277\345\267\236\345\233\276\344\271\246\351\246\206\345\200\237\351\230\205\346\212\223\345\217\226.html"
create mode 100644 redis/index.html
create mode 100644 "redis/redis\347\274\223\345\255\230.html"
create mode 100644 robots.txt
create mode 100644 sitemap.xml
create mode 100644 sitemap.xsl
create mode 100644 star/index.html
create mode 100644 tag/index.html
create mode 100644 timeline/index.html
diff --git a/404.html b/404.html
new file mode 100644
index 00000000..4bf03c99
--- /dev/null
+++ b/404.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+ 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/CNAME b/CNAME
new file mode 100644
index 00000000..2f77233b
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+wenzhihuai.com
\ No newline at end of file
diff --git a/about-the-author/index.html b/about-the-author/index.html
new file mode 100644
index 00000000..0ee2f872
--- /dev/null
+++ b/about-the-author/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+ 关于我 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/about-the-author/personal-life/index.html b/about-the-author/personal-life/index.html
new file mode 100644
index 00000000..901cb9f8
--- /dev/null
+++ b/about-the-author/personal-life/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+ Personal Life | 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/about-the-author/personal-life/wewe.html b/about-the-author/personal-life/wewe.html
new file mode 100644
index 00000000..b011bee9
--- /dev/null
+++ b/about-the-author/personal-life/wewe.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+ 自我介绍 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/about-the-author/works/index.html b/about-the-author/works/index.html
new file mode 100644
index 00000000..aeda2d3a
--- /dev/null
+++ b/about-the-author/works/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+ Works | 个人博客
+
+
+
+
+
+
+
+
+
diff --git "a/about-the-author/works/\344\270\252\344\272\272\344\275\234\345\223\201.html" "b/about-the-author/works/\344\270\252\344\272\272\344\275\234\345\223\201.html"
new file mode 100644
index 00000000..c9300738
--- /dev/null
+++ "b/about-the-author/works/\344\270\252\344\272\272\344\275\234\345\223\201.html"
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+ 小程序 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/ads.txt b/ads.txt
new file mode 100644
index 00000000..be5a5540
--- /dev/null
+++ b/ads.txt
@@ -0,0 +1 @@
+google.com, pub-9037099208128116, DIRECT, f08c47fec0942fa0
\ No newline at end of file
diff --git a/article/index.html b/article/index.html
new file mode 100644
index 00000000..09a625ad
--- /dev/null
+++ b/article/index.html
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+ 文章 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git "a/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-Td7kF-9n.js" "b/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-Td7kF-9n.js"
new file mode 100644
index 00000000..e01101d9
--- /dev/null
+++ "b/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-Td7kF-9n.js"
@@ -0,0 +1 @@
+import{_ as l,r as o,o as i,c as a,a as e,d as t,b as n,e as s}from"./app-BDpQ7oW_.js";const h={},c=e("h1",{id:"_1-历史与架构",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_1-历史与架构","aria-hidden":"true"},"#"),t(" 1.历史与架构")],-1),_={href:"http://www.wenzhihuai.com/",target:"_blank",rel:"noopener noreferrer"},d={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"},g=e("br",null,null,-1),u=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/600-20240126113210252.png",alt:"",tabindex:"0"}),e("figcaption")],-1),b={href:"http://www.wenzhihuai.com/weibonlp.html",target:"_blank",rel:"noopener noreferrer"},p=e("br",null,null,-1),f=e("br",null,null,-1),m={href:"https://github.com/Zephery/newblog/blob/master/doc/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.md",target:"_blank",rel:"noopener noreferrer"},w=e("br",null,null,-1),E={href:"https://github.com/Zephery/newblog/blob/master/doc/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.md",target:"_blank",rel:"noopener noreferrer"},B=e("br",null,null,-1),x={href:"https://github.com/Zephery/newblog/blob/master/doc/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.md",target:"_blank",rel:"noopener noreferrer"},k=e("br",null,null,-1),v={href:"https://github.com/Zephery/baidutongji/blob/master/README.md",target:"_blank",rel:"noopener noreferrer"},A=e("br",null,null,-1),y={href:"https://github.com/Zephery/newblog/blob/master/doc/6.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.md",target:"_blank",rel:"noopener noreferrer"},z=e("br",null,null,-1),C=e("li",null,[t("[数据库]"),e("br")],-1),P=e("li",null,[t("使用机器学习对微博进行分析"),e("br")],-1),S=e("li",null,[t("网站性能优化"),e("br")],-1),V=e("li",null,[t("SEO优化"),e("br")],-1),I=e("h2",{id:"_1-建站故事与网站架构",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_1-建站故事与网站架构","aria-hidden":"true"},"#"),t(" 1.建站故事与网站架构")],-1),j=e("h3",{id:"_1-1建站过程",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_1-1建站过程","aria-hidden":"true"},"#"),t(" 1.1建站过程")],-1),H={href:"http://www.yangqq.com/",target:"_blank",rel:"noopener noreferrer"},M=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/500.png",alt:"",tabindex:"0"}),e("figcaption")],-1),Z=e("p",null,"第二版的界面确实是这样的,只是把图片的切换变成了wowslider,也是简单的用bootstrap和pagehelper做了下分页,现在的最终版保留了它的header,然后评论框使用了多说(超级怀念多说)。后端也由原来的ssh变成了ssm,之后加上了lucene来对文章进行索引。之后,随着多说要关闭了,突然之间有很多div都不适应了(我写死了的。。。),再一次,没法看,不想看,一怒之下再次推翻重做,变成了现在这个版本。",-1),F={href:"https://tale.biezhi.me",target:"_blank",rel:"noopener noreferrer"},q={href:"https://yusi123.com",target:"_blank",rel:"noopener noreferrer"},G=e("br",null,null,-1),J=e("br",null,null,-1),R=e("h3",{id:"_1-2-网站整体技术架构",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_1-2-网站整体技术架构","aria-hidden":"true"},"#"),t(" 1.2 网站整体技术架构")],-1),D=e("p",null,"最终版的技术架构图如下:",-1),L=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/awfawefwefwef.png",alt:"",tabindex:"0"}),e("figcaption")],-1),N={href:"http://jinnianshilongnian.iteye.com/blog/1594806",target:"_blank",rel:"noopener noreferrer"},T=s('运行流程分析
浏览器发送http请求。/blogdetail.html?blogid=1。 tomcat容器初始化,顺序为context-param>listener>filter>servlet,此时,spring中的bean还没有被注入的,不建议在此处加载bean,网站声明了两个类(IPFilter和CacheControlFilter),IPFilter用来拦截IP,CacheControlFilter用来缓存。 初始化Spring。 DispatcherServlet——>HandlerMapping进行请求到处理的映射,HandlerMapping将“/blogdetail”路径直接映射到名字为“/blogdetail”的Bean进行处理,即BlogController。 自定义拦截器,其中BaseIntercepter实现了HandleInterceptor的接口,用来记录每次访问的链接以及后台响应的时间。 DispatcherServlet——> SimpleControllerHandlerAdapter,SimpleControllerHandlerAdapter将HandlerExecutionChain中的处理器适配为BlogController。 BlogController执行查询,取得结果集返回数据。 blogdetail(ModelAndView的逻辑视图名)——>InternalResourceViewResolver, InternalResourceViewResolver使用JstlView,具体视图页面在/blogdetail.jsp。 JstlView(/blogdetail.jsp)——>渲染,将在处理器传入的模型数据(blog=Blog!)在视图中展示出来。 返回响应。 1.3 日志系统 日志系统架构如下:
',6),U={href:"http://www.wenzhihuai.com/log.html",target:"_blank",rel:"noopener noreferrer"},K=e("br",null,null,-1),Q=e("br",null,null,-1),X=e("h3",{id:"_1-4-【有点意思】自然语言处理",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_1-4-【有点意思】自然语言处理","aria-hidden":"true"},"#"),t(" 1.4 【有点意思】自然语言处理")],-1),O={href:"http://www.wenzhihuai.com/weibonlp.html",target:"_blank",rel:"noopener noreferrer"},W=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/QQ截图20170825141127.png",alt:"",tabindex:"0"}),e("figcaption")],-1),Y=e("h2",{id:"总结",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#总结","aria-hidden":"true"},"#"),t(" 总结"),e("br")],-1),$={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"};function ee(te,re){const r=o("ExternalLinkIcon");return i(),a("div",null,[c,e("p",null,[t("各位大佬瞄一眼"),e("a",_,[t("我的个人网站"),n(r)]),t("呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址"),e("a",d,[t("https://github.com/Zephery/newblog"),n(r)]),t(" 。"),g,t(" 大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。")]),u,e("p",null,[t("由原本的ssh变成ssm,再变成ssm+shiro+lucene,到现在的前后台分离。前台使用ssm+lucene,后台使用spring boot+shiro。其中,使用pagehelper作为分页,lucene用来搜索和自动补全,使用百度统计的API做了个日志系统,统计pv和uv什么的,同时,还有使用了JMX来观察JVM的使用和cpu的使用率,机器学习方面,使用了adaboost和朴素贝叶斯对微博进行分类,有兴趣的可以点点"),e("a",b,[t("有点意思"),n(r)]),t("这个页面。"),p,t(" 本文从下面这几个方面来讲讲网站的建立:"),f]),e("ol",null,[e("li",null,[e("a",m,[t("建站故事与网站架构"),n(r)]),w]),e("li",null,[e("a",E,[t("lucene搜索的使用"),n(r)]),B]),e("li",null,[e("a",x,[t("使用quartz来定时备份数据库"),n(r)]),k]),e("li",null,[e("a",v,[t("使用百度统计api做日志系统"),n(r)]),A]),e("li",null,[e("a",y,[t("Nginx小集群的搭建"),n(r)]),z]),C,P,S,V]),I,j,e("p",null,[t("起初,是因为学习的时候老是找不到什么好玩而又有挑战性的项目,看着struts、spring、hibernate的书,全都是一些小项目,做了感觉也没啥意义,有时候在博客园看到别人还有自己的网站,特羡慕,最终就选择了自己做一个个人网站。期初刚学的ssh,于是开始了自己的ssh搭建个人网站的行程,但是对于一个后端的人来说,前端是个大问题啊。。。。所以初版的时候差不多全是纯生的html、css、js,至少发博客这个功能实现了,但是确实没法看。前前后后折腾了一个多月,决定推翻重做,到百度看看别人怎么做的。首先看到的是"),e("a",H,[t("杨青"),n(r)]),t("的网站,已经好几年没更新了,前端的代码看起来比较简单,也是自己能够掌握的,但是不够美观,继续找,在模板之家发现了一个高大上的模板。")]),M,Z,e("p",null,[t("最终版本在考虑时,也找了很多模板,影响深刻的是"),e("a",F,[t("tale"),n(r)]),t("和"),e("a",q,[t("欲思"),n(r)]),t("这两个主题,期中,tale使用的是java语言写的,刚知道的那一刻我就没好感了,java后端我是要自己全部写的,tale这个页面简洁但是不够炫,而且内容量太低,可能就只是个纯博客,之后发现了欲思,拓展性强,只可惜没有静态的版本,后台是纯生的PHP(嗯,PHP是世界上最好的语言),看了看,没事,保存网页,前端自己改,后端自己全部重写,最终变成了现在这个版本,虽然拼接的时候各种css、js混入。。。。还好在做网站性能优化的时候差不多全部去掉了。最终版加入redis、quartz、shiro等,还有python机器学习、flask的restful api,可谓是大杂烩了。"),G,t(" 页面看着还算凑合,至少不是那种看都看不过去的那种了,但是仔细看看,还是有不少问题的,比如瀑布流,还有排版什么的。只能等自己什么时候想认真学学前端的东西了。"),J,t(" 已经部署在腾讯云服务器上,存储使用了七牛云的cdn。")]),R,D,L,e("p",null,[t("网站核心主要采用Spring SpringMVC和Mybatis,下图是当访问一篇博客的时候的运行流程,参考了"),e("a",N,[t("张开涛"),n(r)]),t("的博客。")]),T,e("p",null,[e("a",U,[t("日志系统"),n(r)]),t("曾经尝试采用过ELK,实时监控实在是让人不能不称赞,本地也跑起来了,但是一到服务器,卡卡卡,毕竟(1Ghz CPU、1G内存),只能放弃ELK,采用百度统计。百度统计提供了Tongji API供开发者使用,只是有次数限制,2000/日,实时的话实在有点低,只能统计前几天的PV、UV等开放出来。其实这个存放在mysql也行,不过这些零碎的数据还是放在redis中,方便管理。"),K,t(" 出了日志系统,自己对服务器的一些使用率也是挺关心的,毕竟服务器配置太低,于是利用了使用了tomcat的JMX来对CPU和jvm使用情况进行监控,这两个都是实时的。出了这两个,对内存的分配做了监控,Eden、Survivor、Tenured的使用情况。"),Q]),X,e("p",null,[t("本人大学里的毕业设计就是基于AdaBoost算法的情感分类,学到的东西还是要经常拿出来看看,要不然真的浪费了我这么久努力做的毕业设计啊。构建了一个基本的情感分类小系统,每天抓取微博进行分类存储在MySql上,并使用flask提供Restful API给java调用,可以点击"),e("a",O,[t("这里"),n(r)]),t("尝试(请忽略Google的图片)。目前分类效果不是很明显,准确率大概只有百分之70%,因为训练样本只有500条(找不到训练样本),机器学习真的太依赖样本的标注。这个,只能请教各位路人大神指导指导了。")]),W,Y,e("p",null,[t("断断续续,也总算做了一个能拿得出手仍要遮遮掩掩才能给别人看的网站,哈哈哈哈哈,也劳烦各位帮忙找找bug。前前后后从初学Java EE就一直设想的事也还算有了个了结,以后要多多看书,写点精品文章。PS:"),e("a",$,[t("GitHub上求给个Star"),n(r)]),t(",以后面试能讲讲这个网站。")])])}const le=l(h,[["render",ee],["__file","1.历史与架构.html.vue"]]);export{le as default};
diff --git "a/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-cD88aaBU.js" "b/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-cD88aaBU.js"
new file mode 100644
index 00000000..a9b80f88
--- /dev/null
+++ "b/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-cD88aaBU.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-59449ba0","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html","title":"1.历史与架构","lang":"zh-CN","frontmatter":{"description":"1.历史与架构 各位大佬瞄一眼我的个人网站呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。 大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"1.历史与架构"}],["meta",{"property":"og:description","content":"1.历史与架构 各位大佬瞄一眼我的个人网站呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。 大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"1.历史与架构\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"1.建站故事与网站架构","slug":"_1-建站故事与网站架构","link":"#_1-建站故事与网站架构","children":[{"level":3,"title":"1.1建站过程","slug":"_1-1建站过程","link":"#_1-1建站过程","children":[]},{"level":3,"title":"1.2 网站整体技术架构","slug":"_1-2-网站整体技术架构","link":"#_1-2-网站整体技术架构","children":[]},{"level":3,"title":"1.3 日志系统","slug":"_1-3-日志系统","link":"#_1-3-日志系统","children":[]},{"level":3,"title":"1.4 【有点意思】自然语言处理","slug":"_1-4-【有点意思】自然语言处理","link":"#_1-4-【有点意思】自然语言处理","children":[]}]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":6.79,"words":2038},"filePathRelative":"java/个人网站/1.历史与架构.md","localizedDate":"2024年2月2日","excerpt":" 1.历史与架构 \\n各位大佬瞄一眼我的个人网站 呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。 \\n大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。
","autoDesc":true}');export{e as data};
diff --git "a/assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-rwQzBlk1.js" "b/assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-rwQzBlk1.js"
new file mode 100644
index 00000000..7b467a4c
--- /dev/null
+++ "b/assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-rwQzBlk1.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-2626dfde","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/10.%E5%8E%86%E6%97%B68%E5%B9%B4%E6%9C%80%E7%BB%88%E6%94%B9%E7%89%88.html","title":"10.历时8年最终改版","lang":"zh-CN","frontmatter":{"description":"10.历时8年最终改版 不知不觉,自建站https://www.wenzhihuai.com已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。有时候因为要用服务器搞一些别的东西,直接没有备份数据库就重装,导致不少文章丢失,虽然别的平台可能零散分布。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/10.%E5%8E%86%E6%97%B68%E5%B9%B4%E6%9C%80%E7%BB%88%E6%94%B9%E7%89%88.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"10.历时8年最终改版"}],["meta",{"property":"og:description","content":"10.历时8年最终改版 不知不觉,自建站https://www.wenzhihuai.com已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。有时候因为要用服务器搞一些别的东西,直接没有备份数据库就重装,导致不少文章丢失,虽然别的平台可能零散分布。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"10.历时8年最终改版\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、博客的安装","slug":"一、博客的安装","link":"#一、博客的安装","children":[]},{"level":2,"title":"二、配置","slug":"二、配置","link":"#二、配置","children":[]},{"level":2,"title":"三、为文章增加评论","slug":"三、为文章增加评论","link":"#三、为文章增加评论","children":[]},{"level":2,"title":"四、博客的部署","slug":"四、博客的部署","link":"#四、博客的部署","children":[]},{"level":2,"title":"五、Github pages自定义域名","slug":"五、github-pages自定义域名","link":"#五、github-pages自定义域名","children":[]},{"level":2,"title":"六、Typora图床","slug":"六、typora图床","link":"#六、typora图床","children":[]},{"level":2,"title":"七、为自己的内容增加收入","slug":"七、为自己的内容增加收入","link":"#七、为自己的内容增加收入","children":[]},{"level":2,"title":"常见问题","slug":"常见问题","link":"#常见问题","children":[]}],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":5.78,"words":1733},"filePathRelative":"java/个人网站/10.历时8年最终改版.md","localizedDate":"2024年2月2日","excerpt":" 10.历时8年最终改版 \\n不知不觉,自建站https://www.wenzhihuai.com 已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。有时候因为要用服务器搞一些别的东西,直接没有备份数据库就重装,导致不少文章丢失,虽然别的平台可能零散分布。
","autoDesc":true}');export{e as data};
diff --git "a/assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-tUYTH5tb.js" "b/assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-tUYTH5tb.js"
new file mode 100644
index 00000000..54421ed6
--- /dev/null
+++ "b/assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-tUYTH5tb.js"
@@ -0,0 +1,80 @@
+import{_ as p,r as o,o as i,c as l,a as n,d as s,b as e,e as t}from"./app-BDpQ7oW_.js";const c={},u=n("h1",{id:"_10-历时8年最终改版",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_10-历时8年最终改版","aria-hidden":"true"},"#"),s(" 10.历时8年最终改版")],-1),r={href:"https://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},d=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/images/600-20240126113210252-20240131213935629.png",alt:"早年的网站截图",tabindex:"0"}),n("figcaption",null,"早年的网站截图")],-1),g={href:"https://github.com/Zephery/MyWebsite",target:"_blank",rel:"noopener noreferrer"},h=n("h2",{id:"一、博客的安装",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#一、博客的安装","aria-hidden":"true"},"#"),s(" 一、博客的安装")],-1),k={href:"https://v2.vuepress.vuejs.org/zh/",target:"_blank",rel:"noopener noreferrer"},v={href:"https://theme-hope.vuejs.press/zh/",target:"_blank",rel:"noopener noreferrer"},m=n("h2",{id:"二、配置",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#二、配置","aria-hidden":"true"},"#"),s(" 二、配置")],-1),b={href:"https://github.com/Snailclimb/JavaGuide",target:"_blank",rel:"noopener noreferrer"},_=t(` {
+ text: "Redis" ,
+ prefix: "redis/" ,
+ icon: "redis" ,
+ collapsible: false ,
+ children: "structure"
+ } ,
+
三、为文章增加评论 `,2),f={href:"https://plugin-comment2.vuejs.press/guide/",target:"_blank",rel:"noopener noreferrer"},q=t(`一定要开启discussions 然后去config.ts配置插件。
commentPlugin({
+ provider: "Giscus",
+ comment: true, //启用评论功能
+ repo: "Zephery/MyWebsite", //远程仓库
+ repoId: "MDEwOlJlcG9zaXRvcnkyMDM2MDIyMDQ=", //对应自己的仓库Id
+ category: "General",
+ categoryId: "DIC_kwDODCK5HM4Ccp32" //对应自己的分类Id
+ }),
+
即可在页面上看到效果
颜色可自定义 四、博客的部署 `,6),y={href:"https://v2.vuepress.vuejs.org/zh/guide/deployment.html#github-pages",target:"_blank",rel:"noopener noreferrer"},w={href:"https://v2.vuepress.vuejs.org/zh/guide/deployment.html#github-pages",target:"_blank",rel:"noopener noreferrer"},x=n("h2",{id:"五、github-pages自定义域名",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#五、github-pages自定义域名","aria-hidden":"true"},"#"),s(" 五、Github pages自定义域名")],-1),z={href:"http://xn--githubiozephery-cn3z988bnu0amu6hnw1b.github.io",target:"_blank",rel:"noopener noreferrer"},A=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/github/image-20240201144459067.png",alt:"pages的配置",tabindex:"0"}),n("figcaption",null,"pages的配置")],-1),B={href:"http://xn--wenzhihuai-ws2p67c924ax4be9ycx3b0xbdw7n.xn--comzephery-vd6qh05l.github.io",target:"_blank",rel:"noopener noreferrer"},E={href:"https://myssl.com/dns_check.html?checking=caa#dns_check",target:"_blank",rel:"noopener noreferrer"},D=t(`DNS诊断工具 上面的custom domain配置好了之后,但DNS一直没有校验正确,原因是CAA没有正确解析,需要加上即可。
0 issue "trust-provider.com"
+0 issuewild "trust-provider.com"
+
CAA记录解析 之后就可以看到Github Pages的DNS校验成功,并且可以强制开启https了。
六、Typora图床 `,6),N={href:"https://blog.svend.cc/upic/tutorials/tencent_cos/",target:"_blank",rel:"noopener noreferrer"},j=n("h2",{id:"七、为自己的内容增加收入",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#七、为自己的内容增加收入","aria-hidden":"true"},"#"),s(" 七、为自己的内容增加收入")],-1),S={href:"https://www.sofineday.com/vuepress-vue-google-adsense.html",target:"_blank",rel:"noopener noreferrer"},G=t(`# js 模板引擎 mustache 用法
+
+< ArticleTopAd> </ ArticleTopAd>
+
+## 一. 使用步骤
+
每一篇文章都要新增显然不符合懒惰的人,下面是个人尝试的解决办法,用的是vuepress2提供的slots插槽。
谷歌广告adsense 上面的目的是为了获取data-ad-client和data-ad-slot,其中,data-ad-slot为广告单元,不一样。并且,配置完之后可能需要等一个小时才会生效,不要着急。
docs/.vuepress/config.ts
head: [
+ [
+ "script",
+ {
+ "data-ad-client": "ca-pub-9037099208128116",
+ async: true,
+ src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
+ }
+ ],
+]
+
+...
+alias: {
+ "@theme-hope/components/NormalPage": path.resolve(
+ __dirname,
+ "./components/NormalPage.vue",
+ ),
+},
+
+
docs/.vuepress/components/NormalPage.vue
< template>
+ < normal-page>
+ < template #contentBefore >
+ < ins class = " adsbygoogle"
+ style = " display : block; text-align : center; width : 90%; margin : 0 auto; "
+ data-ad-layout = " in-article"
+ data-ad-format = " fluid"
+ data-ad-client = " ca-pub-9037099208128116"
+ data-ad-slot = " 8206550629" > </ ins>
+ </ template>
+ </ normal-page>
+</ template>
+< script>
+import NormalPage from "vuepress-theme-hope/components/NormalPage.js" ;
+
+export default {
+ name : "adsense-inline" ,
+ components : {
+ 'normal-page' : NormalPage,
+ } ,
+ mounted ( ) {
+ this . adsenseAddLoad ( ) ;
+ } ,
+ methods : {
+ adsenseAddLoad ( ) {
+ let inlineScript = document. createElement ( "script" ) ;
+ inlineScript. type = "text/javascript" ;
+ inlineScript. text = '(adsbygoogle = window.adsbygoogle || []).push({});'
+ document. getElementsByTagName ( 'body' ) [ 0 ] . appendChild ( inlineScript) ;
+ }
+ }
+}
+ </ script>
+
+
+< style lang = " scss" scoped >
+ </ style>
+
+
`,8),C={href:"https://theme-hope.vuejs.press/zh/demo/slot.html",target:"_blank",rel:"noopener noreferrer"},M=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/github/image-20240201151218077.png",alt:"出现的广告",tabindex:"0"}),n("figcaption",null,"出现的广告")],-1),P=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/github/image-20240201151334064.png",alt:"谷歌广告收入",tabindex:"0"}),n("figcaption",null,"谷歌广告收入")],-1),I=n("p",null,"收入虽然低,但是基本上个人没有成本,只需要域名的85块钱。",-1),T=n("h2",{id:"常见问题",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#常见问题","aria-hidden":"true"},"#"),s(" 常见问题")],-1),L={href:"https://support.google.com/adsense/thread/149452399/%E4%B8%BA%E4%BB%80%E4%B9%88%E5%B9%BF%E5%91%8A%E4%B8%8D%E8%83%BD%E6%AD%A3%E5%B8%B8%E6%98%BE%E7%A4%BA%EF%BC%9F?hl=zh-Hans",target:"_blank",rel:"noopener noreferrer"},V=n("p",null,'"建议多写原创高质量的文章出来,AdSense才会匹配出合适的广告,用户感兴趣了才会浏览量增加,你才会有更多的广告收入。"',-1),W=n("p",null,"还是得多写一写优质的文章。",-1),Z=n("p",null,"最后,多帮忙点一下个人网站的广告吧,感恩",-1),F={href:"https://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},J={href:"https://github.com/Zephery/MyWebsite",target:"_blank",rel:"noopener noreferrer"};function H(O,R){const a=o("ExternalLinkIcon");return i(),l("div",null,[u,n("p",null,[s("不知不觉,自建站"),n("a",r,[s("https://www.wenzhihuai.com"),e(a)]),s("已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。有时候因为要用服务器搞一些别的东西,直接没有备份数据库就重装,导致不少文章丢失,虽然别的平台可能零散分布。")]),d,n("p",null,[s("总体而言,自建站对学习知识,了解整个建站的原理能够起到非常重要的作用,但是维护成本实在是太高了,每个月要支付服务器的费用,而且一旦想拿服务器来做点什么,都得提防一下会不会造成破坏。最终还是选择采用vuepress2来重构一下自建站,毕竟把markdown放到github,把图片放到cos里减少了不少的维护量。下面是使用vuepress2建站的"),n("a",g,[s("代码地址"),e(a)]),s("。")]),h,n("p",null,[s("具体"),n("a",k,[s("vuepress2官网"),e(a)]),s("讲解的很详细了,不用再处理什么,按照步骤创建一个项目即可,为了网站的美观,个人使用了"),n("a",v,[s("theme hope"),e(a)]),s("这款主题。")]),m,n("p",null,[s("导航栏、侧边栏官网也有详细的讲解,也不再阐述,需要注意的是自动目录,之前看"),n("a",b,[s("JavaGuide"),e(a)]),s("的样式,他那边的每篇文章都需要写一次ts文件(children),后来发现官网可以把children设置为structure,即可实现根据md文件生成侧边栏目录。注意的是,这里不是根据markdown的文件名来目录名,而是取markdown文件的标题。")]),_,n("p",null,[n("a",f,[s("vuepress-plugin-comment2"),e(a)]),s(",使用了Giscus,Giscus绑定了github账号,所以可以从一定程度上防止被别人刷广告,需要再个人的项目Settings->General把Discussions这个选项给勾选上。")]),q,n("p",null,[s("官网也有讲解部署的情况,具体可以看官网"),n("a",y,[s("Github Pages"),e(a)]),s(",整体上看速度还是挺慢的,可以尝试去gitee上部署看一下,之后就可以在pages通过域名访问了。需要在项目下创建.github/workflows/docs.yml文件,具体配置参考"),n("a",w,[s("官网"),e(a)]),s(",不需做任何改动。")]),x,n("p",null,[n("a",z,[s("github自带的io域名zephery.github.io"),e(a)]),s(",做为一名开发,肯定是用自己的域名是比较好的。需要注意下中间的红色框,前面的是分支,后面的是你项目的路径。一般默认即可,不用修改。")]),A,n("p",null,[s("购买域名->域名解析,"),n("a",B,[s("即把我的个人域名wenzhihuai.com指向zephery.github.io"),e(a)]),s("(通过cname)即可,然后开启强制https。如果DNS一直没有校验通过,那么可能是CAA的原因。通过"),n("a",E,[s("DNS诊断工具"),e(a)]),s("来判断。")]),D,n("p",null,[s("之前的图床使用的是七牛云和又拍云,都有免费的额度吧,不过看情况未来前景似乎经营不太好,目前改用了腾讯云。存储容量50GB,每个月外网访问流量10GB,满足个人网站使用。具体的配置过程比较简单,就不再阐述了,可以直接看"),n("a",N,[s("uPic"),e(a)]),s("的官方介绍。")]),j,n("p",null,[s("有钱才有写作的动力,之前的网站开启了几年的捐赠,总共都没有收到过50块钱,只能从广告这一处想想办法,百度、腾讯广告似乎都不支持个人网站,谷歌可以。配置谷歌广告,网上的教程不少,例如: "),n("a",S,[s("vuepress配置谷歌广告-通过vue-google-adsense库"),e(a)]),s(",缺点是,大部分的文章都是需要在自己的markdown文件中新增特定的标识符。比如:")]),G,n("p",null,[s("本地是没办法进行调试的,可以从"),n("a",C,[s("官网插槽演示"),e(a)]),s("的文章中用div进行调试,等修改完毕发布之后,即可在自己的网站上看到相关的广告和收入(浏览器要把封禁广告的插件关闭)。")]),M,P,I,T,n("p",null,[n("a",L,[s("为什么广告不能正常显示?"),e(a)])]),V,W,Z,n("p",null,[s("网站地址:"),n("a",F,[s("https://www.wenzhihuai.com"),e(a)])]),n("p",null,[s("源码地址:"),n("a",J,[s("https://github.com/Zephery/MyWebsite"),e(a)])])])}const Q=p(c,[["render",H],["__file","10.历时8年最终改版.html.vue"]]);export{Q as default};
diff --git a/assets/1mysql.html-Ei_7f_WQ.js b/assets/1mysql.html-Ei_7f_WQ.js
new file mode 100644
index 00000000..d20a814e
--- /dev/null
+++ b/assets/1mysql.html-Ei_7f_WQ.js
@@ -0,0 +1 @@
+import{_ as t,o as s,c as a,a as e,d as i}from"./app-BDpQ7oW_.js";const c={},n=e("h1",{id:"mysql",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#mysql","aria-hidden":"true"},"#"),i(" mysql")],-1),o=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/img.png",alt:"img",tabindex:"0"}),e("figcaption",null,"img")],-1),l=[n,o];function r(_,m){return s(),a("div",null,l)}const h=t(c,[["render",r],["__file","1mysql.html.vue"]]);export{h as default};
diff --git a/assets/1mysql.html-_FE7EY_e.js b/assets/1mysql.html-_FE7EY_e.js
new file mode 100644
index 00000000..19647a40
--- /dev/null
+++ b/assets/1mysql.html-_FE7EY_e.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-aa93dec0","path":"/database/mysql/1mysql.html","title":"mysql","lang":"zh-CN","frontmatter":{"description":"mysql img","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/database/mysql/1mysql.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"mysql"}],["meta",{"property":"og:description","content":"mysql img"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-29T15:54:09.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-29T15:54:09.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"mysql\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-29T15:54:09.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1706092222000,"updatedTime":1706543649000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":3}]},"readingTime":{"minutes":0.02,"words":5},"filePathRelative":"database/mysql/1mysql.md","localizedDate":"2024年1月24日","excerpt":" mysql \\nimg \\n","autoDesc":true}');export{e as data};
diff --git "a/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-2hMFeeJS.js" "b/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-2hMFeeJS.js"
new file mode 100644
index 00000000..880ceb60
--- /dev/null
+++ "b/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-2hMFeeJS.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-058e4a4b","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html","title":"2.Lucene的使用","lang":"zh-CN","frontmatter":{"description":"2.Lucene的使用 首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"2.Lucene的使用"}],["meta",{"property":"og:description","content":"2.Lucene的使用 首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2.Lucene的使用\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":3,"title":"Lucene的整体架构","slug":"lucene的整体架构","link":"#lucene的整体架构","children":[]},{"level":3,"title":"搜索引擎的几个重要概念:","slug":"搜索引擎的几个重要概念","link":"#搜索引擎的几个重要概念","children":[]},{"level":3,"title":"Lucene中的几个概念","slug":"lucene中的几个概念","link":"#lucene中的几个概念","children":[]},{"level":3,"title":"lucene在本网站的使用:","slug":"lucene在本网站的使用","link":"#lucene在本网站的使用","children":[]},{"level":2,"title":"一、搜索","slug":"一、搜索","link":"#一、搜索","children":[]},{"level":2,"title":"二、lucene自动补全","slug":"二、lucene自动补全","link":"#二、lucene自动补全","children":[]}],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":6.82,"words":2046},"filePathRelative":"java/个人网站/2.Lucene的使用.md","localizedDate":"2024年2月2日","excerpt":" 2.Lucene的使用 \\n首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。
","autoDesc":true}');export{e as data};
diff --git "a/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-qm2pGUZ0.js" "b/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-qm2pGUZ0.js"
new file mode 100644
index 00000000..ac60e403
--- /dev/null
+++ "b/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-qm2pGUZ0.js"
@@ -0,0 +1,241 @@
+import{_ as e,r as o,o as c,c as l,a as n,d as s,b as t,e as p}from"./app-BDpQ7oW_.js";const i={},u=n("h1",{id:"_2-lucene的使用",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_2-lucene的使用","aria-hidden":"true"},"#"),s(" 2.Lucene的使用")],-1),r={href:"http://www.wenzhihuai.com/",target:"_blank",rel:"noopener noreferrer"},k={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"},d=p(` Lucene的整体架构 image 搜索引擎的几个重要概念: 倒排索引:将文档中的词作为关键字,建立词与文档的映射关系,通过对倒排索引的检索,可以根据词快速获取包含这个词的文档列表。倒排索引一般需要对句子做去除停用词。
停用词:在一段句子中,去掉之后对句子的表达意向没有印象的词语,如“非常”、“如果”,中文中主要包括冠词,副词等。
排序:搜索引擎在对一个关键词进行搜索时,可能会命中许多文档,这个时候,搜索引擎就需要快速的查找的用户所需要的文档,因此,相关度大的结果需要进行排序,这个设计到搜索引擎的相关度算法。
Lucene中的几个概念 文档(Document):文档是一系列域的组合,文档的域则代表一系列域文档相关的内容。 域(Field):每个文档可以包含一个或者多个不同名称的域。 词(Term):Term是搜索的基本单元,与Field相对应,包含了搜索的域的名称和关键词。 查询(Query):一系列Term的条件组合,成为TermQuery,但也有可能是短语查询等。 分词器(Analyzer):主要是用来做分词以及去除停用词的处理。 索引的建立
索引的搜索
lucene在本网站的使用: 搜索 2. 自动分词 一、搜索 注意:本文使用最新的lucene,版本6.6.0。lucene的版本更新很快,每跨越一次大版本,使用方式就不一样。首先需要导入lucene所使用的包。使用maven:
< dependency>
+ < groupId> org. apache. lucene< / groupId>
+ < artifactId> lucene- core< / artifactId> < ! -- lucene核心-- >
+ < version> ${ lucene. version} < / version>
+< / dependency>
+< dependency>
+ < groupId> org. apache. lucene< / groupId>
+ < artifactId> lucene- analyzers- common< / artifactId> < ! -- 分词器-- >
+ < version> ${ lucene. version} < / version>
+< / dependency>
+< dependency>
+ < groupId> org. apache. lucene< / groupId>
+ < artifactId> lucene- analyzers- smartcn< / artifactId> < ! -- 中文分词器-- >
+ < version> ${ lucene. version} < / version>
+< / dependency>
+< dependency>
+ < groupId> org. apache. lucene< / groupId>
+ < artifactId> lucene- queryparser< / artifactId> < ! -- 格式化-- >
+ < version> ${ lucene. version} < / version>
+< / dependency>
+< dependency>
+ < groupId> org. apache. lucene< / groupId>
+ < artifactId> lucene- highlighter< / artifactId> < ! -- lucene高亮-- >
+ < version> ${ lucene. version} < / version>
+< / dependency>
+
构建索引 Directory dir = FSDirectory . open ( Paths . get ( "blog_index" ) ) ;
+SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer ( ) ;
+IndexWriterConfig config = new IndexWriterConfig ( analyzer) ;
+IndexWriter writer = new IndexWriter ( dir, config) ;
+Document doc = new Document ( ) ;
+doc. add ( new TextField ( "title" , blog. getTitle ( ) , Field. Store . YES ) ) ;
+doc. add ( new TextField ( "content" , Jsoup . parse ( blog. getContent ( ) ) . text ( ) , Field. Store . YES ) ) ;
+writer. addDocument ( doc) ;
+writer. close ( ) ;
+
更新与删除 IndexWriter writer = getWriter ( ) ;
+Document doc = new Document ( ) ;
+doc. add ( new TextField ( "title" , blog. getTitle ( ) , Field. Store . YES ) ) ;
+doc. add ( new TextField ( "content" , Jsoup . parse ( blog. getContent ( ) ) . text ( ) , Field. Store . YES ) ) ;
+writer. updateDocument ( new Term ( "blogid" , String . valueOf ( blog. getBlogid ( ) ) ) , doc) ;
+writer. close ( ) ;
+
查询 private static void search_index ( String keyword) {
+ try {
+ Directory dir = FSDirectory . open ( Paths . get ( "blog_index" ) ) ;
+ IndexReader reader = DirectoryReader . open ( dir) ;
+ IndexSearcher searcher = new IndexSearcher ( reader) ;
+ SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer ( ) ;
+ QueryParser parser = new QueryParser ( "content" , analyzer) ;
+ Query query = parser. parse ( keyword) ;
+ TopDocs docs = searcher. search ( query, 10 ) ;
+ for ( ScoreDoc scoreDoc : docs. scoreDocs) {
+ Document doc = searcher. doc ( scoreDoc. doc) ;
+ System . out. println ( doc. get ( "title" ) ) ;
+ }
+ reader. close ( ) ;
+ } catch ( IOException | ParseException e) {
+ logger. error ( e. toString ( ) ) ;
+ }
+}
+
高亮 Fragmenter fragmenter = new SimpleSpanFragmenter ( scorer) ;
+SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter ( "<b><font color='red'>" , "</font></b>" ) ;
+Highlighter highlighter = new Highlighter ( simpleHTMLFormatter, scorer) ;
+highlighter. setTextFragmenter ( fragmenter) ;
+for ( ScoreDoc scoreDoc : docs. scoreDocs) {
+ Document doc = searcher. doc ( scoreDoc. doc) ;
+ String title = doc. get ( "title" ) ;
+ TokenStream tokenStream = analyzer. tokenStream ( "title" , new StringReader ( title) ) ;
+ String hTitle = highlighter. getBestFragment ( tokenStream, title) ;
+ System . out. println ( hTitle) ;
+}
+
结果
< b> < font color = ' red' > Java</ font> </ b> 堆.栈和常量池 笔记
+
分页 目前lucene分页的方式主要有两种: (1). 每次都全部查询,然后通过截取获得所需要的记录。由于采用了分词与倒排索引,所有速度是足够快的,但是在数据量过大的时候,占用内存过大,容易造成内存溢出 (2). 使用searchAfter把数据保存在缓存里面,然后再去取。这种方式对大量的数据友好,但是当数据量比较小的时候,速度会相对慢。 lucene中使用searchafter来筛选顺序 ScoreDoc lastBottom = null ;
+BooleanQuery. Builder booleanQuery = new BooleanQuery. Builder ( ) ;
+QueryParser parser1 = new QueryParser ( "title" , analyzer) ;
+Query query1 = parser1. parse ( q) ;
+booleanQuery. add ( query1, BooleanClause. Occur . SHOULD ) ;
+TopDocs hits = search. searchAfter ( lastBottom, booleanQuery. build ( ) , pagehits) ;
+
`,27),m={start:"6"},v=n("br",null,null,-1),g={href:"https://github.com/Zephery/newblog/blob/master/src/main/java/com/myblog/lucene/BlogIndex.java",target:"_blank",rel:"noopener noreferrer"},b=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/images/bervererfwaefewf20170903200915.png",alt:"",tabindex:"0"}),n("figcaption")],-1),y=n("h2",{id:"二、lucene自动补全",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#二、lucene自动补全","aria-hidden":"true"},"#"),s(" 二、lucene自动补全")],-1),h=n("p",null,"百度、谷歌等在输入文字的时候会弹出补全框,如下图:",-1),w=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/images/QQ截图20170728102929.png",alt:"",tabindex:"0"}),n("figcaption")],-1),f={href:"https://github.com/xdan/autocomplete/",target:"_blank",rel:"noopener noreferrer"},x=n("br",null,null,-1),_={href:"http://iamyida.iteye.com/blog/2205114",target:"_blank",rel:"noopener noreferrer"},S={href:"http://blog.csdn.net/u011389474/article/details/69458445",target:"_blank",rel:"noopener noreferrer"},q=p(` 使用: 导入maven包 < dependency>
+ < groupId> org.apache.lucene</ groupId>
+ < artifactId> lucene-suggest</ artifactId>
+ < version> 6.6.0</ version>
+</ dependency>
+
如果想将结果反序列化,声明实体类的时候要加上: public class Blog implements Serializable {
+
实现InputIterator接口 InputIterator的几个方法:
+long weight():返回的权重值,大小会影响排序,默认是1L
+BytesRef payload():对某个对象进行序列化
+boolean hasPayloads():是否有设置payload信息
+Set<BytesRef> contexts():存入context,context里可以是任意的自定义数据,一般用于数据过滤
+boolean hasContexts():判断是否有下一个,默认为false
+
public class BlogIterator implements InputIterator {
+
+ private static final Logger logger = LoggerFactory . getLogger ( BlogIterator . class ) ;
+ private Iterator < Blog > blogIterator;
+ private Blog currentBlog;
+
+ public BlogIterator ( Iterator < Blog > blogIterator) {
+ this . blogIterator = blogIterator;
+ }
+
+ @Override
+ public boolean hasContexts ( ) {
+ return true ;
+ }
+
+ @Override
+ public boolean hasPayloads ( ) {
+ return true ;
+ }
+
+ public Comparator < BytesRef > getComparator ( ) {
+ return null ;
+ }
+
+ @Override
+ public BytesRef next ( ) {
+ if ( blogIterator. hasNext ( ) ) {
+ currentBlog = blogIterator. next ( ) ;
+ try {
+
+ return new BytesRef ( Jsoup . parse ( currentBlog. getTitle ( ) ) . text ( ) . getBytes ( "utf8" ) ) ;
+ } catch ( Exception e) {
+ e. printStackTrace ( ) ;
+ return null ;
+ }
+ } else {
+ return null ;
+ }
+ }
+
+
+ @Override
+ public BytesRef payload ( ) {
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream ( ) ;
+ ObjectOutputStream out = new ObjectOutputStream ( bos) ;
+ out. writeObject ( currentBlog) ;
+ out. close ( ) ;
+ BytesRef bytesRef = new BytesRef ( bos. toByteArray ( ) ) ;
+ return bytesRef;
+ } catch ( IOException e) {
+ logger. error ( "" , e) ;
+ return null ;
+ }
+ }
+
+
+ @Override
+ public Set < BytesRef > contexts ( ) {
+ try {
+ Set < BytesRef > regions = new HashSet < BytesRef > ( ) ;
+ regions. add ( new BytesRef ( currentBlog. getTitle ( ) . getBytes ( "UTF8" ) ) ) ;
+ return regions;
+ } catch ( UnsupportedEncodingException e) {
+ throw new RuntimeException ( "Couldn't convert to UTF-8" ) ;
+ }
+ }
+
+
+ @Override
+ public long weight ( ) {
+ return currentBlog. getHits ( ) ;
+ }
+}
+
ajax 建立索引
+@Override
+public void ajaxbuild ( ) {
+ try {
+ Directory dir = FSDirectory . open ( Paths . get ( "autocomplete" ) ) ;
+ SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer ( ) ;
+ AnalyzingInfixSuggester suggester = new AnalyzingInfixSuggester ( dir, analyzer) ;
+
+ List < Blog > blogs = blogMapper. getAllBlog ( ) ;
+ suggester. build ( new BlogIterator ( blogs. iterator ( ) ) ) ;
+ } catch ( IOException e) {
+ System . err. println ( "Error!" ) ;
+ }
+}
+
查找 因为有些文章的标题是一样的,先对list排序,将标题短的放前面,长的放后面,然后使用LinkHashSet来存储。 @Override
+public Set < String > ajaxsearch ( String keyword) {
+ try {
+ Directory dir = FSDirectory . open ( Paths . get ( "autocomplete" ) ) ;
+ SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer ( ) ;
+ AnalyzingInfixSuggester suggester = new AnalyzingInfixSuggester ( dir, analyzer) ;
+ List < String > list = lookup ( suggester, keyword) ;
+ list. sort ( new Comparator < String > ( ) {
+ @Override
+ public int compare ( String o1, String o2) {
+ if ( o1. length ( ) > o2. length ( ) ) {
+ return 1 ;
+ } else {
+ return - 1 ;
+ }
+ }
+ } ) ;
+ Set < String > set = new LinkedHashSet < > ( ) ;
+ for ( String string : list) {
+ set. add ( string) ;
+ }
+ ssubSet ( set, 7 ) ;
+ return set;
+ } catch ( IOException e) {
+ System . err. println ( "Error!" ) ;
+ return null ;
+ }
+}
+
controller层 @RequestMapping ( "ajaxsearch" )
+public void ajaxsearch ( HttpServletRequest request, HttpServletResponse response) throws IOException {
+ String keyword = request. getParameter ( "keyword" ) ;
+ if ( StringUtils . isEmpty ( keyword) ) {
+ return ;
+ }
+ Set < String > set = blogService. ajaxsearch ( keyword) ;
+ Gson gson = new Gson ( ) ;
+ response. getWriter ( ) . write ( gson. toJson ( set) ) ;
+}
+
`,14),j={start:"7"},I=n("br",null,null,-1),B={href:"https://github.com/xdan/autocomplete",target:"_blank",rel:"noopener noreferrer"},z=p(`< link rel= "stylesheet" href= "js/autocomplete/jquery.autocomplete.css" >
+< script src= "js/autocomplete/jquery.autocomplete.js" type= "text/javascript" > < / script>
+< script type= "text/javascript" >
+
+ $ ( '#remote_input' ) . autocomplete ( {
+ source : [
+ {
+ url : "ajaxsearch.html?keyword=%QUERY%" ,
+ type : 'remote'
+ }
+ ]
+ } ) ;
+
+< / script>
+
效果: `,2),D={id:"欢迎访问我的个人网站",tabindex:"-1"},T=n("a",{class:"header-anchor",href:"#欢迎访问我的个人网站","aria-hidden":"true"},"#",-1),F={href:"http://www.wenzhihuai.com/",target:"_blank",rel:"noopener noreferrer"},O=n("br",null,null,-1),R={href:"https://www.ibm.com/developerworks/cn/java/j-lo-lucene1/",target:"_blank",rel:"noopener noreferrer"},E={href:"http://iamyida.iteye.com/blog/2205114",target:"_blank",rel:"noopener noreferrer"};function L(C,A){const a=o("ExternalLinkIcon");return c(),l("div",null,[u,n("p",null,[s("首先,帮忙点击一下我的网站"),n("a",r,[s("http://www.wenzhihuai.com/"),t(a)]),s(" 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址"),n("a",k,[s("https://github.com/Zephery/newblog"),t(a)]),s(" 。")]),d,n("ol",m,[n("li",null,[s("使用效果"),v,s(" 全部代码放在"),n("a",g,[s("这里"),t(a)]),s(",代码写的不太好,光从代码规范上就不咋地。在网页上的使用效果如下:")])]),b,y,h,w,n("p",null,[s("在搭建lucene自动补全的时候,也有考虑过使用SQL语句中使用like来进行,主要还是like对数据库压力会大,而且相关度没有lucene的高。主要使用了官方suggest库以及"),n("a",f,[s("autocompelte.js"),t(a)]),s("这个插件。"),x,s(" suggest的原理"),n("a",_,[s("看这"),t(a)]),s(",以及索引结构"),n("a",S,[s("看这"),t(a)]),s("。")]),q,n("ol",j,[n("li",null,[s("ajax来提交请求"),I,s(" autocomplete.js源代码与介绍:"),n("a",B,[s("https://github.com/xdan/autocomplete"),t(a)])])]),z,n("h4",D,[T,s(" 欢迎访问我的"),n("a",F,[s("个人网站"),t(a)])]),n("p",null,[s("参考:"),O,n("a",R,[s("https://www.ibm.com/developerworks/cn/java/j-lo-lucene1/"),t(a)])]),n("p",null,[n("a",E,[s("http://iamyida.iteye.com/blog/2205114"),t(a)])])])}const H=e(i,[["render",L],["__file","2.Lucene的使用.html.vue"]]);export{H as default};
diff --git a/assets/2017.html-MDg2apnF.js b/assets/2017.html-MDg2apnF.js
new file mode 100644
index 00000000..b86cf336
--- /dev/null
+++ b/assets/2017.html-MDg2apnF.js
@@ -0,0 +1 @@
+import{_ as r,r as o,o as h,c as p,a as e,d as i,b as t,e as n}from"./app-BDpQ7oW_.js";const c={},g=e("h1",{id:"_2017",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2017","aria-hidden":"true"},"#"),i(" 2017")],-1),s=e("p",null,[i("2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。"),e("br"),i(" 17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?")],-1),d=e("figure",null,[e("img",{src:"http://image.wenzhihuai.com/images/20171231044153.png",alt:"",tabindex:"0"}),e("figcaption")],-1),u=e("p",null,"回到学校,待了几天,那个整天给别人灌毒鸡汤的人还是不着急找工作:该有的时候总会有的啦,然后继续打游戏、那个天天喊着吃麻辣香锅的人,记忆中好像今年都没有吃上,哈哈、厕所还是那样偶尔炸一下,嗯,感觉一切都很熟悉,只是,我有了点伤感,毕竟身边又要换一群不认识的人了。考完试,终于能回广东了,一年没回了,开心不得了,更多的是,为了那个喜欢了好几年没有表白的妹纸,之前从没想过真的能每天跟一个妹纸道晚安,秒回,但是,对她,我还真做到了。1月份的广州,不热不冷,空气很清新,比北京、天津那股泥土味好多了,只是,我被拒了,男闺蜜还是男闺蜜,备胎还是备胎,那会还没想过放弃,直到...",-1),f={href:"http://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},l=n(' 疲惫的面试历程 2月份底开始慢慢投简历,跑招聘会,深圳招聘的太少了,那就去广州,大学城,于是,开始了自己一周两天都在广深往返。有的公司笔试要跑一次广州,一面要跑一次,二面还要跑一次,每次看着路费,真的承受不起,但是有希望就行。乐观之下,到来的是一重又一重的打击。
**数码,很看好的公司,在广州也算是老品牌了,笔试的时候面试官没有带够卷子,就拿了大数据的做,还过了,面试的时候被面到union和union all的区别,答反了,还有left join和right join的原理,一脸懵逼,过后去了百度搜了搜,这东西哪来的原理?
然后是个企业建站的,笔试完了,面试官照着题问然后没说啥就让我走了,额,我好像还没自我介绍呢。
有点想回北京了,往北京投了一份,A轮公司,月薪10k,过了,觉得自己技术应该不差吧,不过还是拒了,因为一想起那里满脑子都是雾霾。
没事没事,下一家,某游戏公司,笔试过了,一面也过了,然后被问flume收集的时候断网处理机制、MD5和RSA原理、Angulajs和Vuejs用没用过、千万级的数据是如何存储的?额,跟你们想的一样,我一道也答出来,然后就挂了,面试官跟我说,你要是来早三个月这些都会啦,说的我很紧张,广东的同学都那么强么?
这个时候还没质疑自己的技术,去了趟深圳某家小公司,金融的,HR问我是不是培训过来的,心里开始突然间好苦涩,大学花那么多时间学习居然被别人用来和培训机构的人相提并论,笔试不知从哪整来的英文逻辑题,做完了然后上机笔试,做不出来不能见面试官,开始感觉这公司有点。。。。还是撤了撤了。
突然感觉面试面的绝望,是自己的问题么?是自己技术太菜了么?开始怀疑自己,感觉也是,已经3月份底了,毕竟别人都在实习,而我已经离职3个月没工作了,但是那些问题不是有点离谱了,一开始是开始心态爆炸觉得怎么可以对应届生问这些问题,不应该是基础么?算法什么的,后来是无奈了,开始上网搜各种不沾边的技术。
还有其他的面试。。。有的工资不高(6K不到),有的面试问题全答对就因为说了有点想做大数据就不要你,有的聊得很欢快却没消息,有的说招java但是笔试一道java题都没有全是前端的,有的打着互联网实际却是外包的公司。。。。 4月初真的很绝望很绝望,不想跟别人说话,是不是很可笑,一个从北京B+轮的公司回广东,面试近15个,居然只能拿到2个offer,其中之一国企外包的,都不知说什么好。13号要拍毕业照了,没有回去,大学四年,毕竟大家个个圈子之间没什么交流,没什么友谊,果然,整个专业的人只有2/3的人去拍了毕业照。4月23号,拉勾网深圳站,梦想着市集,抱着一点点的小希望,去投了5个,结果一个面试邀请都没有,换之而来的是一片绝望、黑暗。。。。
感情、我们毕业了 5月初回学校了赶毕业设计,回学校也是,天天往图书馆跑,为了面试,毕业设计拉下太多了。悠闲的时候,总会想起我喜欢的那个人,过的怎么样了,微信一开,好像自己被屏蔽了还是被删了?这三个月来的面试打击,真的不知道怎么应对,我更不知道怎么跟她聊天,以至于慢慢隔离,这段感情,或许只有我知道自己有多心疼,只有我自己sb得一点点的呵护着。想起上次跟她聊天是4月中,还是她提了个问题其他什么都没问,彼此之前已经没有关心了。删了吧删了吧,就这样一句再见都没有说,一句“祝福”都没有说。 5月底遇到两次还算开心的事,导师问我要不要评优秀论文,不是很想折腾,拒了,导师仍旧劝我,只是写个3页的小总结而已,评上的话能留图书馆收藏。另一个件是珍爱网打电话过来说我一面过了,什么时候二面,天啊,3月份一面,5月底才通知,心里想骂,但是真的好开心好开心,黑暗中的光芒,泪奔。。。。约到了6月15号面试。 6月初开始自己的回家倒计时,请那唯一一个跟我好的妹纸吃饭,忙完答辩,然后是优秀论文的小报告,13号下午交了上去,再回到宿舍,空无一人,一遍忍着不要悲伤,一遍收拾东西,然后向每个宿舍敲门,告别,一个人拖着行李箱,嗯,我要淡定。
准备了有点久,我以为自己准备好了,15号,深圳,珍爱网,被问到:有没有JVM调优经验 ?ZK是如何保持一致性的?有没有写过ELK索引经验?谈谈你对dubbo的理解。。。事后,得知自己没有过。心态真的炸了,通宵打了两天游戏。月底得知,优秀论文也没有被评上,已经没有骂人吐槽的想法,只是哦的一声,6月,宣告了自己春招结束,宣告自己要去外包,同时也宣告自己大学这些努力全部白费,跟那个灌毒鸡汤天天打游戏的人同一起跑线。
996的工作 七月初入职的时候,问了问那些一起应届入职的同学,跟别人交流一下面试被问的问题,只有线程池,JVM回收算法,他们也没用过,我无奈,为什么我被问到的,全是Angularjs、MD5加密算法、ZK一致性原理这种奇葩的问题。。。。。
',16),m={href:"http://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},_=n('决心先好好呆着,学习学习,把公司的产品业务技术专研专研,7、8月份是挺开心的,没怎么加班,虽然下班我都留在公司学习,虽然公司的产品不咋地,但是还是有可学之处的,随后,我没想到的是,公司要实行996,,,9月份至12月,每天都是改bug,开发模块,写业务,全都是增删改查,没有涉及redis、rabbitmq,就真的只有使用Hibernate、spring,而做出的东西,要使用JDK6来运行,至今都能看到sun的类。每天的状态就是累累累,我们组还不是最惨的,隔壁项目组,一周通宵两次,9月到10都是如此,国庆加班,每次经过他们组,我都觉得自己还算是幸福。很厌恶这种不把员工当人看的行为,有同事调侃,明年估计我们这些应届过来的,是不是要走掉2/3的人?疯狂加班的代价是牺牲积极性,我问过那些一周通宵两次的人,敲代码,程序员你喜欢这份工作么?不喜欢!!!有那么一两次,实在是太累了,我都感觉自己有点不行了,想离职,可是,会有公司要我么?会有公司不问那些奇葩的问题么?
双十一,花了500多买了十本书,神书啊,计算机届的圣经啊,然而至今一本都没看完,甚至是都没怎么翻,每天下班回去之后就是9点半了,烧水,洗澡,洗衣服,近11点了,躺床上,一遍看书一遍看鹌鹑直播,一小时才翻几页,996真的太累了,实在看不下书。经过这几个月的加班,感觉自己技术增长为负数,也病了几次,同学见我,都感觉我老了不少,心里不平,可是又没有什么办法。
孤独 珠江新城,一年四季都那么美,今晚应该又是万人一起倒计时了吧?已经好久没跟别人一起出去玩过了。今年貌似得了自闭症?社交全靠黄段子。想找人出门走走,然而手机已经没有那种几年的朋友,大学同学一个都不在,哈哈哈,别人说社交软件让人离得更近,我怎么发现我自己一个好朋友都没有了呢,哭笑ing。或许是自己的确不善于跟别人保持联系吧,这个要改,一定要改!!! 远看:
近看:
题外话: 有些时候,遇到不顺,感觉自己不是神,没必要忍住,就开始宣泄自己的情绪,比如疯狂打游戏,只能这样度过了吧。 今年听过最多的一句话,你好厉害,你好牛逼==我感觉也是,可惜,要被业务耽误了不少时间吧。。 《企业IT架构转型之道》是今年最好的架构图书,没有之一。
期望 想起初中,老师让我在黑板写自己的英文作文,好像是信件,描述什么状况来这?最后夸了夸我在文章后面加的一段大概是劝别人不要悲伤要灿烂。也想起一个故事,二战以后,德国满目疮痍,他们处在这样一个凄惨的境地,还能想到在桌上摆设一些花,就一定能在废墟上重建家园。我所看到的是即使在再黑暗的状态下,要永远抱着希望。明年要更加努力的学习,而不是工作,是该挽留一些人了,多运动。说了那么多,其实,我只希望自己的运气不要再差了,再差就没法活了。人在遇到不顺的时候,往往最难过的一关便是自己。哈哈哈,只能学我那个同学给自己灌毒鸡汤了。加油加油↖(^ω^)↗
',13);function b(w,x){const a=o("ExternalLinkIcon");return h(),p("div",null,[g,s,d,u,e("p",null,[i("春节期间,把自己的"),e("a",f,[i("网站"),t(a)]),i("整理了一下,看了看JVM和并发的知识,偶尔刷刷牛客网的题,觉得自己没多大问题了,跟同学出发,去深圳,我并没有一个做马化腾、马云的梦,但是我想,要做出点东西,至少,不是个平庸的人。投了几个,第一个面试,知道是培训兼外包后果断弃了,春招还没开始,再多准备准备,有时间就往深圳图书馆里跑,找个位置,静静的复习,那会,感觉自己一定能去个大公司吧,搞搞分布式、大数据之类的~")]),l,e("p",null,[i("没有环境,就自己创造,下班有时间就改改自己的网站"),e("a",m,[i("http://www.wenzhihuai.com"),t(a)]),i(",GitHub目前有154个star了,感觉也是个小作品吧,把常用的Java技术栈(RabbitMQ、MongoDB等)加了上去,虽然没啥使用场景,但是自己好好努力吧,毕竟高并发、高可用是自己的梦想。今年GitHub自己的提交次数。")]),_])}const k=r(c,[["render",b],["__file","2017.html.vue"]]);export{k as default};
diff --git a/assets/2017.html-zfvjl-5A.js b/assets/2017.html-zfvjl-5A.js
new file mode 100644
index 00000000..4ea17957
--- /dev/null
+++ b/assets/2017.html-zfvjl-5A.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-22e4234a","path":"/life/2017.html","title":"2017","lang":"zh-CN","frontmatter":{"description":"2017 2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。 17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/life/2017.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"2017"}],["meta",{"property":"og:description","content":"2017 2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。 17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-26T04:53:47.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-26T04:53:47.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2017\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-26T04:53:47.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1706066758000,"updatedTime":1706244827000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":11.22,"words":3366},"filePathRelative":"life/2017.md","localizedDate":"2024年1月24日","excerpt":" 2017 \\n2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。 \\n17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?
\\n ","autoDesc":true}');export{e as data};
diff --git a/assets/2018.html-XhKmceXA.js b/assets/2018.html-XhKmceXA.js
new file mode 100644
index 00000000..0a0be2a7
--- /dev/null
+++ b/assets/2018.html-XhKmceXA.js
@@ -0,0 +1 @@
+import{_ as t,r,o,c as h,a as e,d as a,b as n,e as c}from"./app-BDpQ7oW_.js";const s={},l=e("h1",{id:"_2018",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2018","aria-hidden":"true"},"#"),a(" 2018")],-1),d=e("p",null,"年底老姐结婚,跑回家去了,忙着一直没写,本来想回深圳的时候空余的时候写写,没想到一直加班,嗯,9点半下班那种,偶尔也趁着间隙的时间,一段一段的凑着吧。",-1),p={href:"https://www.cnblogs.com/w1570631036/p/8158284.html",target:"_blank",rel:"noopener noreferrer"},g=e("h2",{id:"心惊胆战的裸辞经历",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#心惊胆战的裸辞经历","aria-hidden":"true"},"#"),a(" 心惊胆战的裸辞经历")],-1),f=e("br",null,null,-1),_={href:"https://www.cnblogs.com/w1570631036/p/8549333.html",target:"_blank",rel:"noopener noreferrer"},u=c('and ... 广州拜拜,晚上人少的时候,跟妹纸去珠江新城真的很美好
工作工作 入职的时候是做日志收集的,就是flume+kafka+es这一套,遇到了不少大佬,嗯,感觉挺好的,打算好好干,一个半月后不知怎么滴,被拉去做容器云了,然后就开始了天天调jenkins、gitlab这些没什么用的api,开始了增删改查的历程,很烦,研究jenkins、gitlab对于自己的技术没什么提升,又不得不做,而且大小周+加班这么做,回到家自己看java、netty、golang的书籍,可是没项目做没实践,过几个月就忘光了,有段时间真的很烦很烦,根本不想工作,天天调api,而且是jenkins、gitlab这些没什么卵用的api,至今也没找到什么办法。。。。 公司发展太快,也实在让人不知所措,一不小心部门被架空了,什么预兆都没有,被分到其他部门,然后发现这个部门领导内斗真的是,“三国争霸”吧,无奈成为炮灰,不同的领导不同的要求,安安静静敲个代码怎么这么难。。。。 去年的学习拉下了不少,文章也写的少了,总写那些入门的文章确实没有什么意思,买的书虽然没有17年的多吧,不过也不少了,也看了挺多本书的,虽然我还是不满意自己的阅读量。 这几年要开始抓准一个框架了,好好专研一下,也要开始学习一下go了,希望能参与一些github的项目,好好努力吧。
跑步跑步 平时没事总是宅在家里打游戏,差不多持续到下半年吧,那会打游戏去楼下吃东西的时候老是觉得眼神恍惚,盯着电子产品太多了,然后就跟别人跑步去了,每周去一次人才公园,跑步健身,人才公园真的是深圳跑步最好的一个地方了,桥上总有一群摄影师,好想在深圳湾买一套房子,看了看房价,算了算了,深圳的房,真的贵的离谱。19年也要多多运动,健康第一健康第一。
Others 拿到了深圳户口,全程只花了15天,感谢学妹and家人 买了第一台MacBook Pro,对于Java的我真心不好用 盼了好几年的老姐结婚,18年终于了解了这心事 养了只猫,在经历了好几个月的早起之后,晚上睡觉锁厨房,终于安分了,对不起了哈哈哈 2019 想不起来还有什么要说的了,毕竟程序员,好像每天的生活都一样,就展望一下19年吧。今年,最最重要的是家里人以及身边还有所有人都健健康康的,哈哈哈。然后是安安静静的敲代码~~就酱
',13);function m(b,w){const i=r("ExternalLinkIcon");return o(),h("div",null,[l,d,e("p",null,[a("想着17年12月31号写的那篇文章"),e("a",p,[a("https://www.cnblogs.com/w1570631036/p/8158284.html"),n(i)]),a(",感叹18年还算恢复了点。")]),g,e("p",null,[a("其实校招过去的那家公司,真的不是很喜欢,996、技术差、产品差,实在受不了,春节前提出了离职,老大也挽留了下,以“来了个阿里的带我们重构,能学不了东西”来挽留,虽然我对技术比较痴迷,但离职去深圳的决心还是没有动摇,嗯,就这么开始了自己的裸辞过程。3月8号拿到离职,回公司的时候跟跟同事吹吹水,吃个饭,某同事还喊:“周末来公司玩玩么,我给你开门”,哈哈哈,泼出去的水,回不去了,偶尔有点伤感。"),f,a(" 去深圳面试,第一家随手记,之前超级想去这家公司的,金融这一块,有钱,只可惜,没过,一面面试官一直夸我,我觉得稳了,二面没转过来,就这么挂了,有点不甘心吧,在这,感谢那个内推我的人吧,"),e("a",_,[a("面经在这"),n(i)]),a(",之后就是大大小小的面试,联想、恒大、期待金融什么的,都没拿到offer,裸辞真的慌得一比,一天没工作,感觉一年没有工作没人要的样子。。。。没面试就跑去广州图书馆,复习,反思,一天一天的过着,回家就去楼下吃烧烤,打游戏,2点3点才睡觉,boss直聘、拉勾网见一个问一个,迷迷糊糊慌慌张张,那段期间真的想有点把所有书卖掉回家啃老的想法,好在最后联系了一家公司,电商、大小周,知乎上全是差评,不过评价的都不是技术的,更重要的是,岗位是中间件的,嗯,去吧。")]),u])}const k=t(s,[["render",m],["__file","2018.html.vue"]]);export{k as default};
diff --git a/assets/2018.html-pd4XfNXB.js b/assets/2018.html-pd4XfNXB.js
new file mode 100644
index 00000000..87f5292d
--- /dev/null
+++ b/assets/2018.html-pd4XfNXB.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-1f7a720c","path":"/life/2018.html","title":"2018","lang":"zh-CN","frontmatter":{"description":"2018 年底老姐结婚,跑回家去了,忙着一直没写,本来想回深圳的时候空余的时候写写,没想到一直加班,嗯,9点半下班那种,偶尔也趁着间隙的时间,一段一段的凑着吧。 想着17年12月31号写的那篇文章https://www.cnblogs.com/w1570631036/p/8158284.html,感叹18年还算恢复了点。 心惊胆战的裸辞经历","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/life/2018.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"2018"}],["meta",{"property":"og:description","content":"2018 年底老姐结婚,跑回家去了,忙着一直没写,本来想回深圳的时候空余的时候写写,没想到一直加班,嗯,9点半下班那种,偶尔也趁着间隙的时间,一段一段的凑着吧。 想着17年12月31号写的那篇文章https://www.cnblogs.com/w1570631036/p/8158284.html,感叹18年还算恢复了点。 心惊胆战的裸辞经历"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-26T04:53:47.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-26T04:53:47.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2018\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-26T04:53:47.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"心惊胆战的裸辞经历","slug":"心惊胆战的裸辞经历","link":"#心惊胆战的裸辞经历","children":[]},{"level":2,"title":"工作工作","slug":"工作工作","link":"#工作工作","children":[]},{"level":2,"title":"跑步跑步","slug":"跑步跑步","link":"#跑步跑步","children":[]},{"level":2,"title":"Others","slug":"others","link":"#others","children":[]},{"level":2,"title":"2019","slug":"_2019","link":"#_2019","children":[]}],"git":{"createdTime":1706066758000,"updatedTime":1706244827000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":4.35,"words":1306},"filePathRelative":"life/2018.md","localizedDate":"2024年1月24日","excerpt":" 2018 \\n年底老姐结婚,跑回家去了,忙着一直没写,本来想回深圳的时候空余的时候写写,没想到一直加班,嗯,9点半下班那种,偶尔也趁着间隙的时间,一段一段的凑着吧。
\\n想着17年12月31号写的那篇文章https://www.cnblogs.com/w1570631036/p/8158284.html ,感叹18年还算恢复了点。
\\n 心惊胆战的裸辞经历 ","autoDesc":true}');export{e as data};
diff --git a/assets/2019.html-QgZCLsLC.js b/assets/2019.html-QgZCLsLC.js
new file mode 100644
index 00000000..0491226b
--- /dev/null
+++ b/assets/2019.html-QgZCLsLC.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-1c10c0ce","path":"/life/2019.html","title":"2019","lang":"zh-CN","frontmatter":{"description":"2019 2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。 19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。 工作 从18年底开始吧,大概就知道领导对容器云这么快的完全架构设计错误,就是一个完完全全错误的产品,其他人也觉得有点很有问题,但老板就是固执不听,结果一个跑路,一个被压得懒得反抗,然后我一个人跟老板和项目经理怼了前前后后半年,真是惨啊,还要被骂,各种拉到小黑屋里批斗,一直在对他们强调:没有这么做的!!!然后被以年轻人,不懂事,不要抱怨,长大了以后就领会了怼回来,当时气得真是无语。。。。。自己调研的阿里云、腾讯云、青云,还有其他小公司的容器,发现真的只有我们这么设计,完全错误的方向,,,,直到老板走了之后,才开始决定重构,走上正轨。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/life/2019.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"2019"}],["meta",{"property":"og:description","content":"2019 2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。 19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。 工作 从18年底开始吧,大概就知道领导对容器云这么快的完全架构设计错误,就是一个完完全全错误的产品,其他人也觉得有点很有问题,但老板就是固执不听,结果一个跑路,一个被压得懒得反抗,然后我一个人跟老板和项目经理怼了前前后后半年,真是惨啊,还要被骂,各种拉到小黑屋里批斗,一直在对他们强调:没有这么做的!!!然后被以年轻人,不懂事,不要抱怨,长大了以后就领会了怼回来,当时气得真是无语。。。。。自己调研的阿里云、腾讯云、青云,还有其他小公司的容器,发现真的只有我们这么设计,完全错误的方向,,,,直到老板走了之后,才开始决定重构,走上正轨。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-26T04:53:47.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-26T04:53:47.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2019\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-26T04:53:47.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"工作","slug":"工作","link":"#工作","children":[]},{"level":2,"title":"学习","slug":"学习","link":"#学习","children":[]},{"level":2,"title":"感情","slug":"感情","link":"#感情","children":[]},{"level":2,"title":"运动","slug":"运动","link":"#运动","children":[]},{"level":2,"title":"其他","slug":"其他","link":"#其他","children":[]},{"level":2,"title":"2020展望","slug":"_2020展望","link":"#_2020展望","children":[]}],"git":{"createdTime":1706066758000,"updatedTime":1706244827000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":4.43,"words":1329},"filePathRelative":"life/2019.md","localizedDate":"2024年1月24日","excerpt":" 2019 \\n2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。 \\n19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。
\\n 工作 \\n从18年底开始吧,大概就知道领导对容器云这么快的完全架构设计错误,就是一个完完全全错误的产品,其他人也觉得有点很有问题,但老板就是固执不听,结果一个跑路,一个被压得懒得反抗,然后我一个人跟老板和项目经理怼了前前后后半年,真是惨啊,还要被骂,各种拉到小黑屋里批斗,一直在对他们强调:没有这么做的!!!然后被以年轻人,不懂事,不要抱怨,长大了以后就领会了怼回来,当时气得真是无语。。。。。自己调研的阿里云、腾讯云、青云,还有其他小公司的容器,发现真的只有我们这么设计,完全错误的方向,,,,直到老板走了之后,才开始决定重构,走上正轨。
","autoDesc":true}');export{e as data};
diff --git a/assets/2019.html-znm2eQc3.js b/assets/2019.html-znm2eQc3.js
new file mode 100644
index 00000000..8392246a
--- /dev/null
+++ b/assets/2019.html-znm2eQc3.js
@@ -0,0 +1 @@
+import{_ as e,o as a,c as i,e as r}from"./app-BDpQ7oW_.js";const t={},n=r(' 2019 2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。 19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。
工作 从18年底开始吧,大概就知道领导对容器云这么快的完全架构设计错误,就是一个完完全全错误的产品,其他人也觉得有点很有问题,但老板就是固执不听,结果一个跑路,一个被压得懒得反抗,然后我一个人跟老板和项目经理怼了前前后后半年,真是惨啊,还要被骂,各种拉到小黑屋里批斗,一直在对他们强调:没有这么做的!!!然后被以年轻人,不懂事,不要抱怨,长大了以后就领会了怼回来,当时气得真是无语。。。。。自己调研的阿里云、腾讯云、青云,还有其他小公司的容器,发现真的只有我们这么设计,完全错误的方向,,,,直到老板走了之后,才开始决定重构,走上正轨。
之后有了点起色,然后开始着重强调了DevOps的重要性,期初也没人理解,还被骂天天研究技术不干活。。。这东西没技术,但是真的是公司十分需要的公司好么!!可惜公司对这个产品很失望,也不给人,期间还说要暂停项目,唉,这么大的项目就给几个人怎么做,谁都不乐意,就这么过的很憋屈吧,开始了维护的日子。。。
工作上,蛮多人对我挺好的,领导,同事,不过有时候憋屈的时候还是有了点情绪化,有时候有点悲伤的想法,浮躁、暴躁,出去面试了几次,感觉不是自己能力不好,而是市场上的真的需要3+年以上的。。。。不过感觉自己能在这里憋屈的过了这么久,也是很佩服自己的,哈哈,用同事的话来说就是:当做游戏里的练级,锻炼自己哈哈哈
学习 项目的方向错误,导致自己写的代码都是很简单的增删改查,没有技术含量的那种,也最终导致自己浪费了不少时间,上半年算是很气愤吧,不想就这么浪费掉这些时间,虽然期间看了各种各样的东西,比如Netty、Go、操作系统什么的,最终发现,如果不在项目中使用的话,真的会忘,而且很快就忘掉,最后的还是决定学习项目相关度比较大的东西了,比如Go,如果项目不是很大,小项目的话,就用Go来写,这么做感觉提升还是挺大的。 过去一年往南山图书馆借了不少书,省了不少钱,虽然没怎么看,但我至少有个奋斗的心啊,哈哈哈哈哈哈哈哈,文章写得少了,因为感觉写不出好东西,总是入门的那种,不深,不值得学习,想想到时候把别人给坑了,也不好意思。 操作系统感觉还是要好好学学了,加油
Kubernetes就是未来的方向,有时候翻开源码看看,又不敢往下面看了,对底层不熟吧,今年要多多研究下Kubernetes的源码了,至于Spring那一套,也不知道该不该放弃,或者都学习一下?云原生就是趋势。
感情 吵架了,没心思写
运动 过去一年还是把运动算是坚持了下来,每个月必去深圳湾跑一次。还是没怎么睡好,工作感情上都有点不顺,加上自己本身就难以入睡,有时候躺床上就是怎么也睡不着,还长了痘痘,要跑去医院那种,可怕,老了,还是要早点睡觉,多走走多运动,好久没打羽毛球了,自己也不想有空的时候只会打游戏,今年继续加油,多运动吧。
还爬了两次南山
其他 看了周围蛮多同事去了腾讯阿里,有点心动,好想去csig,没到3年真的让人很抓狂。 过去一年过的蛮憋屈的,特别是工作不顺,加上跟女朋友吵架,心态爆炸。。。
2020展望 每年这个时候,都不敢有太大的期望了,祝大家都健健康康的,工作顺利!!
当然,如果有可能的话,我想去CSIG
',23),h=[n];function c(d,p){return a(),i("div",null,h)}const o=e(t,[["render",c],["__file","2019.html.vue"]]);export{o as default};
diff --git "a/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-HLLS9x6l.js" "b/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-HLLS9x6l.js"
new file mode 100644
index 00000000..d67ad88a
--- /dev/null
+++ "b/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-HLLS9x6l.js"
@@ -0,0 +1,71 @@
+import{_ as p,r as o,o as l,c,a as n,d as a,b as t,e}from"./app-BDpQ7oW_.js";const i={},u=e(' 3.定时任务 先看一下Quartz的架构图:
一.特点: 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求; 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式; 分布式和集群能力。 二.主要组成部分 JobDetail:需实现该接口定义的人物,其中JobExecutionContext提供了上下文的各种信息。 JobDetail:QUartz的执行任务的类,通过newInstance的反射机制实例化Job。 Trigger: Job的时间触发规则。主要有SimpleTriggerImpl和CronTriggerImpl两个实现类。 Calendar:org.quartz.Calendar和java.util.Calendar不同,它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一个日历时间点,无特殊说明后面的Calendar即指org.quartz.Calendar)。 Scheduler:由上图可以看出,Scheduler是Quartz独立运行的容器。其中,Trigger和JobDetail可以注册到Scheduler中。 ThreadPool:Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。 三、Quartz设计 ',8),r=n("br",null,null,-1),k={href:"http://www.quartz-scheduler.org/documentation/quartz-2.2.x/quick-start.html",target:"_blank",rel:"noopener noreferrer"},d=n("li",null,null,-1),g=e(` 四、使用 hello world!代码在这 本网站中使用quartz来对数据库进行备份,与Spring结合 (1)导入spring的拓展包,其协助spring集成第三方库:邮件服务、定时任务、缓存等。。。 < dependency>
+ < groupId> org.springframework</ groupId>
+ < artifactId> spring-context-support</ artifactId>
+ < version> 4.2.6.RELEASE</ version>
+</ dependency>
+
(2)导入quartz包
< dependency>
+ < groupId> org.quartz-scheduler</ groupId>
+ < artifactId> quartz</ artifactId>
+ < version> 2.3.0</ version>
+</ dependency>
+
(3)mysql远程备份 使用命令行工具仅仅需要一行:
mysqldump -u [username] -p[password] -h [hostip] database > file
+
但是java不能直接执行linux的命令,仍旧需要依赖第三方库ganymed
< dependency>
+ < groupId> ch.ethz.ganymed</ groupId>
+ < artifactId> ganymed-ssh2</ artifactId>
+ < version> 262</ version>
+</ dependency>
+
完整代码如下:
@Component ( "mysqlService" )
+public class MysqlUtil {
+ . . .
+ StringBuffer sb = new StringBuffer ( ) ;
+ sb. append ( "mysqldump -u " + username + " -p" + password + " -h " + host + " " +
+ database + " >" + file) ;
+ String sql = sb. toString ( ) ;
+ Connection connection = new Connection ( s_host) ;
+ connection. connect ( ) ;
+ boolean isAuth = connection. authenticateWithPassword ( s_username, s_password) ;
+ if ( ! isAuth) {
+ logger. error ( "server login error" ) ;
+ }
+ Session session = connection. openSession ( ) ;
+ session. execCommand ( sql) ;
+ InputStream stdout = new StreamGobbler ( session. getStdout ( ) ) ;
+ BufferedReader br = new BufferedReader ( new InputStreamReader ( stdout) ) ;
+ . . .
+}
+
(4)spring中配置quartz
< bean id = " jobDetail" class = " org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" >
+ < property name = " targetObject" ref = " mysqlService" />
+ < property name = " targetMethod" value = " exportDataBase" />
+</ bean>
+
+< bean id = " myTrigger" class = " org.springframework.scheduling.quartz.CronTriggerFactoryBean" >
+ < property name = " jobDetail" ref = " jobDetail" />
+
+ < property name = " cronExpression" value = " 0 59 2 ? * FRI" />
+</ bean>
+
+< bean id = " scheduler" class = " org.springframework.scheduling.quartz.SchedulerFactoryBean" >
+ < property name = " triggers" >
+ < list>
+ < ref bean = " myTrigger" />
+ </ list>
+ </ property>
+</ bean>
+
`,13),v={href:"https://github.com/Zephery/newblog/blob/master/src/main/java/com/myblog/util/MysqlUtil.java",target:"_blank",rel:"noopener noreferrer"},m=e(` Spring的高级特性之定时任务 java ee项目的定时任务中除了运行quartz之外,spring3+还提供了task,可以看做是一个轻量级的Quartz,而且使用起来比Quartz简单的多。
(1)spring配置文件中配置:
< task: annotation-driven/>
+
(2)最简单的例子,在所需要的函数上添加定时任务即可运行
@Scheduled ( fixedRate = 5000 )
+ public void reportCurrentTime ( ) {
+ System . out. println ( "每隔5秒运行一次" + sdf. format ( new Date ( ) ) ) ;
+ }
+
(3)运行的时候会报错:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.scheduling.TaskScheduler] is defined
+ at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:372)
+ at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
+ at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:192)
+ at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:171)
+ at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:86)
+ at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163)
+ at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136)
+ at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:380)
+
`,8),b=n("br",null,null,-1),h={href:"http://blog.csdn.net/oarsman/article/details/52801877",target:"_blank",rel:"noopener noreferrer"},q=n("br",null,null,-1),f={href:"http://stackoverflow.com/questions/31199888/spring-task-scheduler-no-qualifying-bean-of-type-org-springframework-scheduli",target:"_blank",rel:"noopener noreferrer"},y=n("br",null,null,-1),_=e(`1.尝试从配置中找到一个TaskScheduler Bean
2.寻找ScheduledExecutorService Bean
3.使用默认的scheduler 修改log4j.properties即可: log4j.logger.org.springframework.scheduling=INFO 其实这个功能不影响定时器的功能。 (4)结果:
每隔5秒运行一次14:44:34
+每隔5秒运行一次14:44:39
+每隔5秒运行一次14:44:44
+
`,4);function w(x,S){const s=o("ExternalLinkIcon");return l(),c("div",null,[u,n("ol",null,[n("li",null,[a("properties file"),r,n("a",k,[a("官网"),t(s)]),a("中表明:quartz中使用了quartz.properties来对quartz进行配置,并保留在其jar包中,如果没有定义则默认使用改文件。")]),d]),g,n("p",null,[a("(5)java完整文件"),n("a",v,[a("在这"),t(s)])]),m,n("p",null,[a("参考:"),b,a(" 1."),n("a",h,[a("http://blog.csdn.net/oarsman/article/details/52801877"),t(s)]),q,a(" 2."),n("a",f,[a("http://stackoverflow.com/questions/31199888/spring-task-scheduler-no-qualifying-bean-of-type-org-springframework-scheduli"),t(s)]),y,a(" Spring的定时任务调度器会尝试获取一个注册过的 task scheduler来做任务调度,它会尝试通过BeanFactory.getBean的方法来获取一个注册过的scheduler bean,获取的步骤如下:")]),_])}const z=p(i,[["render",w],["__file","3.定时任务.html.vue"]]);export{z as default};
diff --git "a/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-qFez5clX.js" "b/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-qFez5clX.js"
new file mode 100644
index 00000000..2356b492
--- /dev/null
+++ "b/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-qFez5clX.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-411fdbb2","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html","title":"3.定时任务","lang":"zh-CN","frontmatter":{"description":"3.定时任务 先看一下Quartz的架构图: 一.特点: 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求; 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式; 分布式和集群能力。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"3.定时任务"}],["meta",{"property":"og:description","content":"3.定时任务 先看一下Quartz的架构图: 一.特点: 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求; 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式; 分布式和集群能力。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.定时任务\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":3,"title":"一.特点:","slug":"一-特点","link":"#一-特点","children":[]},{"level":3,"title":"二.主要组成部分","slug":"二-主要组成部分","link":"#二-主要组成部分","children":[]},{"level":3,"title":"三、Quartz设计","slug":"三、quartz设计","link":"#三、quartz设计","children":[]},{"level":3,"title":"四、使用","slug":"四、使用","link":"#四、使用","children":[]},{"level":2,"title":"Spring的高级特性之定时任务","slug":"spring的高级特性之定时任务","link":"#spring的高级特性之定时任务","children":[]}],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":3.55,"words":1064},"filePathRelative":"java/个人网站/3.定时任务.md","localizedDate":"2024年2月2日","excerpt":" 3.定时任务 \\n先看一下Quartz的架构图:
\\n \\n 一.特点: \\n\\n强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求; \\n灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式; \\n分布式和集群能力。 \\n ","autoDesc":true}');export{e as data};
diff --git "a/assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-pWJ6ghVV.js" "b/assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-pWJ6ghVV.js"
new file mode 100644
index 00000000..1be5fbe2
--- /dev/null
+++ "b/assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-pWJ6ghVV.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-0d043462","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html","title":"4.日志系统.md","lang":"zh-CN","frontmatter":{"description":"4.日志系统.md 欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"4.日志系统.md"}],["meta",{"property":"og:description","content":"4.日志系统.md 欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.日志系统.md\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"1.网站代码安装","slug":"_1-网站代码安装","link":"#_1-网站代码安装","children":[]},{"level":2,"title":"2.根据API获取数据","slug":"_2-根据api获取数据","link":"#_2-根据api获取数据","children":[]},{"level":2,"title":"3.构建请求","slug":"_3-构建请求","link":"#_3-构建请求","children":[]},{"level":2,"title":"4.实际运用","slug":"_4-实际运用","link":"#_4-实际运用","children":[]},{"level":2,"title":"5.基本代码","slug":"_5-基本代码","link":"#_5-基本代码","children":[]},{"level":2,"title":"6.展示数据","slug":"_6-展示数据","link":"#_6-展示数据","children":[]}],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":9.64,"words":2891},"filePathRelative":"java/个人网站/4.日志系统.md","localizedDate":"2024年2月2日","excerpt":"\\n欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
","autoDesc":true}');export{e as data};
diff --git "a/assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-rdybAcfJ.js" "b/assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-rdybAcfJ.js"
new file mode 100644
index 00000000..6ca706fe
--- /dev/null
+++ "b/assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-rdybAcfJ.js"
@@ -0,0 +1,224 @@
+import{_ as e,r as o,o as c,c as i,a as n,d as s,b as t,e as p}from"./app-BDpQ7oW_.js";const l={},u={id:"_4-日志系统-md",tabindex:"-1"},r=n("a",{class:"header-anchor",href:"#_4-日志系统-md","aria-hidden":"true"},"#",-1),d={href:"http://4.xn--m6tr8kvwwlxb.md",target:"_blank",rel:"noopener noreferrer"},k={href:"http://www.wenzhihuai.com/",target:"_blank",rel:"noopener noreferrer"},v={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"},m={href:"https://tongji.baidu.com/web/welcome/login",target:"_blank",rel:"noopener noreferrer"},b={href:"https://www.umeng.com/",target:"_blank",rel:"noopener noreferrer"},g=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/images/300.png",alt:"",tabindex:"0"}),n("figcaption")],-1),h={href:"http://www.wenzhihuai.com/log.html",target:"_blank",rel:"noopener noreferrer"},_=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/images/20170918090524.png",alt:"",tabindex:"0"}),n("figcaption")],-1),y=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/images/20170918090534.png",alt:"",tabindex:"0"}),n("figcaption")],-1),q=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/images/20170918090546.png",alt:"",tabindex:"0"}),n("figcaption")],-1),f={href:"https://github.com/Zephery/baidutongji",target:"_blank",rel:"noopener noreferrer"},w=p(` 1.网站代码安装 先在百度统计 中注册登录之后,进入管理页面,新增网站,然后在代码管理中获取安装代码,大部分人的代码都是类似的,除了hm.js?后面的参数,是记录该网站的唯一标识。
< script>
+var _hmt = _hmt || [ ] ;
+( function ( ) {
+ var hm = document. createElement ( "script" ) ;
+ hm. src = "https://hm.baidu.com/hm.js?code" ;
+ var s = document. getElementsByTagName ( "script" ) [ 0 ] ;
+ s. parentNode. insertBefore ( hm, s) ;
+} ) ( ) ;
+ </ script>
+
同时,需要在申请其他设置->数据导出服务中开通数据导出服务,百度统计Tongji API可以为网站接入者提供便捷的获取网站流量数据的通道。
至此,我们获得了username、password、token,然后开始使用三个参数来获取数据。
2.根据API获取数据 `,7),x={href:"https://tongji.baidu.com/dataapi/file/TongjiApiFile.pdf",target:"_blank",rel:"noopener noreferrer"},j=n("br",null,null,-1),I={href:"https://api.baidu.com/json/tongji/v1/ReportService/getData",target:"_blank",rel:"noopener noreferrer"},z={href:"https://tongji.baidu.com/dataapi/file/TongjiApiFile.pdf",title:"百度统计",target:"_blank",rel:"noopener noreferrer"},T=n("br",null,null,-1),A=p(`参数名称 参数类型 描述 method string 要查询的报告 start_date string 查询起始时间 end_date string 查询结束时间 metrics string 自定义指标
其中,参数start_date和end_date的规定为:yyyyMMdd,这里我们使用python的原生库,datetime、time,获取昨天的时间以及前七天的日期。
today = datetime. date. today( )
+yesterday = today - datetime. timedelta( days= 1 )
+fifteenago = today - datetime. timedelta( days= 7 )
+end, start = str ( yesterday) . replace( "-" , "" ) , str ( fifteenago) . replace( "-" , "" )
+
3.构建请求 说明:siteId可以根据个人百度统计的链接获取,也可以使用Tongji API的第一个接口列表获取用户的站点列表。首先,我们构建一个类,由于username、password、token都是通用的,所以我们将它设置为构造方法的参数。
class Baidu ( object ) :
+ def __init__ ( self, siteId, username, password, token) :
+ self. siteId = siteId
+ self. username = username
+ self. password = password
+ self. token = token
+
然后构建一个共同的方法,用来获取提交数据之后返回的结果,其中提供了4个可变参数,分别是(start_date:起始日期,end_date:结束日期,method:方法,metrics:指标),返回的是字节,最后需要decode("utf-8")一下变成字符:
def getresult ( self, start_date, end_date, method, metrics) :
+ body = { "header" : { "account_type" : 1 , "password" : self. password, "token" : self. token,
+ "username" : self. username} ,
+ "body" : { "siteId" : self. siteId, "method" : method, "start_date" : start_date,
+ "end_date" : end_date,
+ "metrics" : metrics} }
+ data = bytes ( json. dumps( body) , 'utf8' )
+ req = urllib. request. Request( base_url, data)
+ response = urllib. request. urlopen( req)
+ the_page = response. read( )
+ return the_page. decode( "utf-8" )
+
`,8),P={href:"https://github.com/Zephery/baidutongji/blob/master/baidu.py",target:"_blank",rel:"noopener noreferrer"},Z=n("h2",{id:"_4-实际运用",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_4-实际运用","aria-hidden":"true"},"#"),s(" 4.实际运用")],-1),E=n("p",null,"(1)需要使用其他参数怎么办",-1),R=n("figure",null,[n("img",{src:"https://github-images.wenzhihuai.com/images/20170919091911.png",alt:"",tabindex:"0"}),n("figcaption")],-1),V={href:"http://www.jianshu.com/p/98f7e34845b5",target:"_blank",rel:"noopener noreferrer"},B=p(`def getresult ( self, start_date, end_date, method, metrics, ** kw) :
+ base_url = "https://api.baidu.com/json/tongji/v1/ReportService/getData"
+ body = { "header" : { "account_type" : 1 , "password" : self. password, "token" : self. token,
+ "username" : self. username} ,
+ "body" : { "siteId" : self. siteId, "method" : method, "start_date" : start_date,
+ "end_date" : end_date, "metrics" : metrics} }
+ for key in kw:
+ body[ 'body' ] [ key] = kw[ key]
+
使用方式:
result = self. getresult( start, end, "source/all/a" ,
+ "pv_count,visitor_count,avg_visit_time" , viewType= 'visitor' )
+
(2)获取的数据如何解析 百度统计返回的结果比较简洁而又反人类,以获取概览中的pv_count,visitor_count,ip_count,bounce_ratio,avg_visit_time为例子:
result = bd. getresult( start, end, "overview/getTimeTrendRpt" ,
+ "pv_count,visitor_count,ip_count,bounce_ratio,avg_visit_time" )
+
返回的结果是:
[[['2017/09/12'], ['2017/09/13'], ['2017/09/14'], ['2017/09/15'], ['2017/09/16'], ['2017/09/17'], ['2017/09/18']],
+[[422, 76, 76, 41.94, 221],
+ [284, 67, 65, 50.63, 215],
+ [67, 23, 22, 52.17, 153],
+ [104, 13, 13, 36.36, 243],
+ [13, 4, 4, 33.33, 66],
+ [73, 7, 6, 37.5, 652],
+ [63, 11, 11, 33.33, 385]
+ ], [], []]
+
即:翻译成人话就是:
[[[date1,date2,...]],
+ [[date1的pv_count, date1的visitor_count, date1的ip_count, date1的bounce_ratio, date1的avg_visit_time],
+ [date2的pv_count, date2的visitor_count, date2的ip_count, date2的bounce_ratio, date2的avg_visit_time],
+ ...,[]
+ ],[],[]]
+
极其反人类的设计。还好用的python,python数组的特性实在太强了。出了可以运用[x for x in range]这类语法之外,还能与三元符(x if y else x+1,如果y成立,那么结果是x,如果y不成立,那么结果是x+1)一起使用,这里注意:如果当天访问量为0,其返回的json结果是'--',所以要判断是不是为'--',归0化,才能在折线图等各种图上显示。下面是pv_count的例子:
pv_count = [ x[ 0 ] if x[ 0 ] != '--' else 0 for x in result[ 1 ] ]
+
(3)每周限制2000次 在开通数据导出服务的时候,不知道大家有没有注意到它的说明,即我们是不能实时监控的,只能将它放在临时数据库中,这里我们选择了Redis,并在centos里定义一个定时任务,每天全部更新一次即可。
python中redis的使用方法很简单,连接跟mysql类似:
+pool = redis. ConnectionPool( host= 'your host ip' , port= port, password= 'your auth' )
+r = redis. Redis( connection_pool= pool)
+
本网站使用redis的数据结构只有set,方法也很简单,就是定义一个key,然后value是数组的字符串获取json。
ip_count = [ x[ 2 ] if x[ 2 ] != '--' else 0 for x in result[ 1 ] ]
+r. set ( "ip_count" , ip_count)
+
+name = [ item[ 0 ] [ 'name' ] for item in data[ 0 ] ]
+count = 0
+tojson = [ ]
+for item in data[ 1 ] :
+ temp = { }
+ temp[ "name" ] = name[ count]
+ temp[ "pv_count" ] = item[ 0 ]
+ temp[ "visitor_count" ] = item[ 1 ]
+ temp[ "average_stay_time" ] = item[ 2 ]
+ tojson. append( temp)
+ count = count + 1
+r. set ( "rukouyemian" , json. dumps( tojson[ : 5 ] ) )
+
5.基本代码 `,18),S={href:"https://github.com/Zephery/baidutongji/blob/master/demo.py",target:"_blank",rel:"noopener noreferrer"},L=p(`import json
+import time
+import datetime
+import urllib. parse
+import urllib. request
+
+base_url = "https://api.baidu.com/json/tongji/v1/ReportService/getData"
+
+class Baidu ( object ) :
+ def __init__ ( self, siteId, username, password, token) :
+ self. siteId = siteId
+ self. username = username
+ self. password = password
+ self. token = token
+
+ def getresult ( self, start_date, end_date, method, metrics, ** kw) :
+ base_url = "https://api.baidu.com/json/tongji/v1/ReportService/getData"
+ body = { "header" : { "account_type" : 1 , "password" : self. password, "token" : self. token,
+ "username" : self. username} ,
+ "body" : { "siteId" : self. siteId, "method" : method, "start_date" : start_date,
+ "end_date" : end_date, "metrics" : metrics} }
+ for key in kw:
+ body[ 'body' ] [ key] = kw[ key]
+ data = bytes ( json. dumps( body) , 'utf8' )
+ req = urllib. request. Request( base_url, data)
+ response = urllib. request. urlopen( req)
+ the_page = response. read( )
+ return the_page. decode( "utf-8" )
+
+if __name__ == '__main__' :
+
+ today = datetime. date. today( )
+ yesterday = today - datetime. timedelta( days= 1 )
+ fifteenago = today - datetime. timedelta( days= 7 )
+ end, start = str ( yesterday) . replace( "-" , "" ) , str ( fifteenago) . replace( "-" , "" )
+
+ bd = Baidu( yoursiteid, "username" , "password" , "token" )
+ result = bd. getresult( start, end, "overview/getTimeTrendRpt" ,
+ "pv_count,visitor_count,ip_count,bounce_ratio,avg_visit_time" )
+ result = json. loads( result)
+ base = result[ "body" ] [ "data" ] [ 0 ] [ "result" ] [ "items" ]
+ print ( base)
+
+
6.展示数据 `,2),$={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"},D=n("br",null,null,-1),N=n("br",null,null,-1),O=p(`String pv_count = jedis. get ( "pv_count" ) ;
+String visitor_count = jedis. get ( "visitor_count" ) ;
+mv. addObject ( "pv_count" , pv_count) ;
+mv. addObject ( "visitor_count" , visitor_count) ;
+
jsp中的使用如下:
< div class = " panel-heading" style = " background-color : rgba ( 187, 255, 255, 0.7) " >
+ < div class = " card-title" >
+ < strong> PV和UV折线图</ strong>
+
+
+ < div class = " panel-body" >
+ < div id = " linecontainer" style = " width : auto; height : 330px" >
+ < script>
+ var chart = new Highcharts. Chart ( 'linecontainer' , {
+ title : {
+ text : null
+ } ,
+ credits : {
+ enabled : false
+ } ,
+ xAxis : {
+ categories : ${ daterange}
+ } ,
+ yAxis : {
+ title : {
+ text : '次数'
+ } ,
+ plotLines : [ {
+ value : 0 ,
+ width : 1 ,
+ color : '#808080'
+ } ]
+ } ,
+ tooltip : {
+ valueSuffix : '次'
+ } ,
+ legend : {
+ borderWidth : 0 ,
+ align : "center" ,
+ verticalAlign : "top" ,
+ x : 0 ,
+ y : 0
+ } ,
+ series : [ {
+ name : 'pv' ,
+ data : ${ pv_count}
+ } , {
+ name : 'uv' ,
+ data : ${ visitor_count}
+ } ]
+ } )
+ </ script>
+
效果如下:
(2)地域访问量 在python代码中先获取地域的数据,其结果如下,百度统计跟echarts都是百度的,果然,自家人对自己人的支持真是特别友好的。
[{'pv_count': 649, 'pv_ratio': 7, 'visitor_count': 2684, 'name': '广东'}, {'pv_count': 2, 'pv_ratio': 2, 'visitor_count': 76, 'name': '四川'}, {'pv_count': 1, 'pv_ratio': 1, 'visitor_count': 3, 'name': '江苏'}]
+
`,7),C=n("strong",null,"地域图",-1),G={href:"http://echarts.baidu.com/download-map.html",target:"_blank",rel:"noopener noreferrer"},H={href:"http://echarts.baidu.com/download.html",target:"_blank",rel:"noopener noreferrer"},M=n("br",null,null,-1),K=p(`<script type="text/javascript">
+ var myChart = echarts.init(document.getElementById('diyu'));
+ option = {
+ tooltip: {
+ trigger: 'item'
+ },
+ legend: {
+ orient: 'vertical',
+ left: 'left'
+ },
+ visualMap: {
+ min: 0,
+ max:\${diyumax},
+ left: 'left',
+ top: 'bottom',
+ text: ['高', '低'], // 文本,默认为数值文本
+ calculable: true
+ },
+ toolbox: {
+ show: true,
+ orient: 'vertical',
+ left: 'right',
+ top: 'center',
+ feature: {
+ dataView: {readOnly: false},
+ restore: {},
+ saveAsImage: {}
+ }
+ },
+ series: [
+ {
+ name: '访问量',
+ type: 'map',
+ mapType: 'china',
+ roam: false,
+ label: {
+ normal: {
+ show: true
+ },
+ emphasis: {
+ show: true
+ }
+ },
+ data: [
+ <c:forEach var="diyu" items="\${diyu}">
+ {name: '\${diyu.name}', value: \${to.pv_count}},
+ </c:forEach>
+ ]
+ }
+ ]
+ };
+ myChart.setOption(option);
+</script>
+
结果如下:
结语 `,3),U=n("br",null,null,-1),F={href:"http://www.wenzhihuai.com/log.html",target:"_blank",rel:"noopener noreferrer"},Y=n("br",null,null,-1),J={href:"http://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},W=n("br",null,null,-1),Q={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"},X=n("br",null,null,-1),nn={href:"https://github.com/Zephery/baidutongji",target:"_blank",rel:"noopener noreferrer"},sn=n("br",null,null,-1);function an(tn,pn){const a=o("ExternalLinkIcon");return c(),i("div",null,[n("h1",u,[r,s(),n("a",d,[s("4.日志系统.md"),t(a)])]),n("p",null,[s("欢迎访问我的网站"),n("a",k,[s("http://www.wenzhihuai.com/"),t(a)]),s(" 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址"),n("a",v,[s("https://github.com/Zephery/newblog"),t(a)]),s(" 。")]),n("p",null,[s("建立网站少不了日志系统,用来查看网站的访问次数、停留时间、抓取量、目录抓取统计、页面抓取统计等,其中,最常用的方法还是使用ELK,但是,本网站的服务器配置实在太低了(1GHZ、2G内存),压根就跑不起ELK,所以只能寻求其他方式,目前最常用的有"),n("a",m,[s("百度统计"),t(a)]),s("和"),n("a",b,[s("友盟"),t(a)]),s(",这里,本人使用的是百度统计,提供了API给开发者使用,能够将自己所需要的图表移植到自己的网站上。日志是网站及其重要的文件,通过对日志进行统计、分析、综合,就能有效地掌握网站运行状况,发现和排除错误原因,了解客户访问分布等,更好的加强系统的维护和管理。下面是我的百度统计的概览页面:")]),g,n("p",null,[s("企业级的网站日志不能公开,但是我的是个人网站,用来跟大家一起学习的,所以,需要将百度的统计页面展示出来,但是,百度并不提供日志的图像,只提供API给开发者调用,而且还限制访问次数,一天不能超过2000次,这个对于实时统计来说,确实不够,所以只能展示前几天的访问统计。这里的日志系统分为三个步骤:1.API获取数据;2.存储数据;3.展示数据。页面效果如下,也可以点开我的网站的"),n("a",h,[s("日志系统"),t(a)]),s(":")]),_,y,q,n("p",null,[s("百度统计提供了Tongji API的Java和Python版本,这两个版本及其复杂,可用性极低,所以,本人用Python写了个及其简单的通用版本,整体只有28行,代码在这,"),n("a",f,[s("https://github.com/Zephery/baidutongji"),t(a)]),s("。下面是具体过程")]),w,n("p",null,[n("a",x,[s("官网的API"),t(a)]),s("详细的记录了接口的参数以及解释,"),j,s(" 链接:"),n("a",I,[s("https://api.baidu.com/json/tongji/v1/ReportService/getData"),t(a)]),s(",详细的官方报告请访问官网"),n("a",z,[s("TongjiApi"),t(a)]),T,s(" 所需参数(必须):")]),A,n("p",null,[s("至此,python获取百度统计的过程基本就没了,没错,就是那么简简单单的几行,完整代码见"),n("a",P,[s("https://github.com/Zephery/baidutongji/blob/master/baidu.py"),t(a)]),s(",但是,想要实现获取各种数据,仍需要做很多工作。")]),Z,E,R,n("p",null,[s("python中提供了个可变参数来解决这一烦恼,详细请看"),n("a",V,[s("http://www.jianshu.com/p/98f7e34845b5"),t(a)]),s(",可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple,而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。")]),B,n("p",null,[s("下面是基本的使用代码,完整的使用代码就不贴了,有兴趣可以去我的github上看看,"),n("a",S,[s("完整代码"),t(a)]),s(",希望能给个star哈哈哈,感谢")]),L,n("p",null,[s("在将数据存进redis中之后,我们需要在博客中使用这些数据来制作图表。在"),n("a",$,[s("newblog"),t(a)]),s("中使用方式也很简单,大概就是使用jedis读取数据,然后使用echarts或者highcharts展示。其中折线图以及线型图我都使用了highcharts,确实比echarts好看的多,但是地域图还是选择了echarts,毕竟中国的产品还是对中国的支持较好。"),D,s(" (1)PV、UV折线图"),N,s(" 以图表PV、UV为例,由于存储进redis的是一个数组,所以,可以直接从redis中读取然后放到一个attribute里即可:")]),O,n("p",null,[s("地域图目前支持最好的还是百度的echarts,使用方法见echarts的官网吧,这里不再阐述,展示"),C,s("的时候需要获取下载两个文件,"),n("a",G,[s("china.js"),t(a)]),s("(其提供了js和json,这里使用的js),"),n("a",H,[s("echarts.js"),t(a)]),s("。"),M,s(" 部分代码:")]),K,n("p",null,[s("网上关于日志系统的几乎都是ELK,对于小网站的,隐私不是很重要的还是可以用用百度统计的,这套系统也折磨了我挺久的,特别是它那反人类的返回数据。期初本来是想使用百度统计的,后来考虑了一下ELK,尝试之后发现,服务器配置跑不起来,还是安安稳稳的使用了百度统计,于此做成了这个系统,美观度还是不高,颜色需要优化一下。最后,希望能在GitHub上给我个star吧。"),U,s(" 日志系统地址:"),n("a",F,[s("http://www.wenzhihuai.com/log.html"),t(a)]),Y,s(" 个人网站网址:"),n("a",J,[s("http://www.wenzhihuai.com"),t(a)]),W,s(" 个人网站代码地址:"),n("a",Q,[s("https://github.com/Zephery/newblog"),t(a)]),X,s(" 百度统计python代码地址:"),n("a",nn,[s("https://github.com/Zephery/baidutongji"),t(a)]),sn,s(" 万分感谢")])])}const on=e(l,[["render",an],["__file","4.日志系统.html.vue"]]);export{on as default};
diff --git a/assets/404.html-F74GSICT.js b/assets/404.html-F74GSICT.js
new file mode 100644
index 00000000..501d25ee
--- /dev/null
+++ b/assets/404.html-F74GSICT.js
@@ -0,0 +1 @@
+import{_ as e,o as c,c as t}from"./app-BDpQ7oW_.js";const _={};function o(r,n){return c(),t("div")}const a=e(_,[["render",o],["__file","404.html.vue"]]);export{a as default};
diff --git a/assets/404.html-WhIsgby4.js b/assets/404.html-WhIsgby4.js
new file mode 100644
index 00000000..ffb11d95
--- /dev/null
+++ b/assets/404.html-WhIsgby4.js
@@ -0,0 +1 @@
+const t=JSON.parse('{"key":"v-3706649a","path":"/404.html","title":"","lang":"zh-CN","frontmatter":{"layout":"NotFound","description":"","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/404.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"article:author","content":"Zephery"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"\\"}"]]},"headers":[],"git":{},"readingTime":{"minutes":0,"words":0},"filePathRelative":null,"excerpt":"","autoDesc":true}');export{t as data};
diff --git "a/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-6tnyAU-k.js" "b/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-6tnyAU-k.js"
new file mode 100644
index 00000000..14b48549
--- /dev/null
+++ "b/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-6tnyAU-k.js"
@@ -0,0 +1,105 @@
+import{_ as l,r,o,c as i,a,d as n,b as s,e}from"./app-BDpQ7oW_.js";const p={},c={id:"_5-小集群部署-md",tabindex:"-1"},u=a("a",{class:"header-anchor",href:"#_5-小集群部署-md","aria-hidden":"true"},"#",-1),m={href:"http://5.xn--yet863fjea402eswg.md",target:"_blank",rel:"noopener noreferrer"},d={href:"http://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},Q={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"},g=a("br",null,null,-1),T=a("h1",{id:"nginx负载均衡",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#nginx负载均衡","aria-hidden":"true"},"#"),n(" nginx负载均衡")],-1),h=a("br",null,null,-1),f={href:"http://jinnianshilongnian.iteye.com/",target:"_blank",rel:"noopener noreferrer"},v=a("figure",null,[a("img",{src:"https://github-images.wenzhihuai.com/images/20171018044732.png",alt:"",tabindex:"0"}),a("figcaption")],-1),k=a("p",null,"本站并没有那么多的服务器,目前只有两台,搭建不了那么大型的架构,就简陋的用两台服务器来模拟一下负载均衡的搭建。下图是本站的简单架构:",-1),x=a("figure",null,[a("img",{src:"https://github-images.wenzhihuai.com/images/20171018051437.png",alt:"",tabindex:"0"}),a("figcaption")],-1),_=a("p",null,"其中服务器A(119.23.46.71)为深圳节点,服务器B(47.95.10.139)为北京节点,搭建Nginx之后流量是这么走的:user->A->B-A->user或者user->A->user,第一条中A将请求转发给B,然后B返回的是其运行结果的静态资源。因为这里仅仅是用来学习,所以请不要考虑因为地域导致延时的问题。。。。下面是过程。",-1),b=a("h2",{id:"_1-1-nginx的安装",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#_1-1-nginx的安装","aria-hidden":"true"},"#"),n(" 1.1 Nginx的安装")],-1),q={href:"https://pkgs.org/download/nginx",target:"_blank",rel:"noopener noreferrer"},w=e(`启动后页面如下:
记一下常用命令
启动nginx,由于是采用rpm方式,所以环境变量什么的都配置好了。
+[root@beijingali ~]# nginx #启动nginx
+[root@beijingali ~]# nginx -s reload #重启nginx
+[root@beijingali ~]# nginx -t #校验nginx配置文件
+nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
+nginx: configuration file /etc/nginx/nginx.conf test is successful
+
1.2 Nginx的配置 1.2.1 负载均衡算法 `,7),y=a("br",null,null,-1),H=a("br",null,null,-1),L=a("br",null,null,-1),z=a("br",null,null,-1),M={href:"http://blog.csdn.net/qh_java/article/details/45955923",target:"_blank",rel:"noopener noreferrer"},D=e(`http{
+ ...
+ upstream backend {
+ hash $uri;
+ # 北京节点
+ server 47.95.10.139:8080;
+ # 深圳节点
+ server 119.23.46.71:8080;
+ }
+
+ server {
+ ...
+ location / {
+ root html;
+ index index.html index.htm;
+ proxy_pass http://backend;
+ ...
+ }
+ ...
+
1.2.2 日志格式 之前有使用过ELK来跟踪日志,所以将日志格式化成了json的格式,这里贴一下吧
...
+ log_format main '{"@timestamp":"$time_iso8601",'
+ '"host":"$server_addr",'
+ '"clientip":"$remote_addr",'
+ '"size":$body_bytes_sent,'
+ '"responsetime":$request_time,'
+ '"upstreamtime":"$upstream_response_time",'
+ '"upstreamhost":"$upstream_addr",'
+ '"http_host":"$host",'
+ '"url":"$uri",'
+ '"xff":"$http_x_forwarded_for",'
+ '"referer":"$http_referer",'
+ '"agent":"$http_user_agent",'
+ '"status":"$status"}';
+ access_log logs/access.log main;
+ ...
+
1.2.3 HTTP反向代理 `,5),Z={href:"http://wwww.wenzhihuai.xn--com-5s0em31hr0u",target:"_blank",rel:"noopener noreferrer"},S={href:"http://119.23.46.71:8080",target:"_blank",rel:"noopener noreferrer"},j={href:"http://blog.csdn.net/bao19901210/article/details/52537279",target:"_blank",rel:"noopener noreferrer"},$={class:"MathJax",jax:"SVG",style:{position:"relative"}},F={style:{"vertical-align":"-0.464ex"},xmlns:"http://www.w3.org/2000/svg",width:"109.704ex",height:"2.161ex",role:"img",focusable:"false",viewBox:"0 -750 48489.1 955","aria-hidden":"true"},C=e('变 量 拿 到 的 将 是 反 向 代 理 服 务 器 的 地 址 。 是 可 以 获 得 用 户 的 真 实 的 , 也 就 是 说 使 用 ',1),E=[C],I=a("mjx-assistive-mml",{unselectable:"on",display:"inline"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("mi",null,"r"),a("mi",null,"e"),a("mi",null,"m"),a("mi",null,"o"),a("mi",null,"t"),a("msub",null,[a("mi",null,"e"),a("mi",null,"a")]),a("mi",null,"d"),a("mi",null,"d"),a("mi",null,"r"),a("mi",{mathvariant:"normal"},"变"),a("mi",{mathvariant:"normal"},"量"),a("mi",{mathvariant:"normal"},"拿"),a("mi",{mathvariant:"normal"},"到"),a("mi",{mathvariant:"normal"},"的"),a("mi",{mathvariant:"normal"},"将"),a("mi",{mathvariant:"normal"},"是"),a("mi",{mathvariant:"normal"},"反"),a("mi",{mathvariant:"normal"},"向"),a("mi",{mathvariant:"normal"},"代"),a("mi",{mathvariant:"normal"},"理"),a("mi",{mathvariant:"normal"},"服"),a("mi",{mathvariant:"normal"},"务"),a("mi",{mathvariant:"normal"},"器"),a("mi",{mathvariant:"normal"},"的"),a("mi",null,"i"),a("mi",null,"p"),a("mi",{mathvariant:"normal"},"地"),a("mi",{mathvariant:"normal"},"址"),a("mo",{"data-mjx-pseudoscript":"true"},"”"),a("mrow",{"data-mjx-texclass":"ORD"},[a("mo",null,"。")]),a("mi",null,"n"),a("mi",null,"g"),a("mi",null,"i"),a("mi",null,"n"),a("mi",null,"x"),a("mi",{mathvariant:"normal"},"是"),a("mi",{mathvariant:"normal"},"可"),a("mi",{mathvariant:"normal"},"以"),a("mi",{mathvariant:"normal"},"获"),a("mi",{mathvariant:"normal"},"得"),a("mi",{mathvariant:"normal"},"用"),a("mi",{mathvariant:"normal"},"户"),a("mi",{mathvariant:"normal"},"的"),a("mi",{mathvariant:"normal"},"真"),a("mi",{mathvariant:"normal"},"实"),a("mi",null,"i"),a("mi",null,"p"),a("mi",{mathvariant:"normal"},"的"),a("mi",null,","),a("mi",{mathvariant:"normal"},"也"),a("mi",{mathvariant:"normal"},"就"),a("mi",{mathvariant:"normal"},"是"),a("mi",{mathvariant:"normal"},"说"),a("mi",null,"n"),a("mi",null,"g"),a("mi",null,"i"),a("mi",null,"n"),a("mi",null,"x"),a("mi",{mathvariant:"normal"},"使"),a("mi",{mathvariant:"normal"},"用")])],-1),P=e(` location / {
+ root html;
+ index index.html index.htm;
+ proxy_pass http://backend;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Host $host;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ }
+
(1)proxy_set_header X-real-ip $remote_addr; 其中这个X-real-ip是一个自定义的变量名,名字可以随意取,这样做完之后,用户的真实ip就被放在X-real-ip这个变量里了,然后,在web端可以这样获取: request.getAttribute("X-real-ip")
(2)proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
`,3),R={class:"MathJax",jax:"SVG",style:{position:"relative"}},B={style:{"vertical-align":"-0.452ex"},xmlns:"http://www.w3.org/2000/svg",width:"49.321ex",height:"2.149ex",role:"img",focusable:"false",viewBox:"0 -750 21800 950","aria-hidden":"true"},A=a("g",{stroke:"currentColor",fill:"currentColor","stroke-width":"0",transform:"scale(1,-1)"},[a("g",{"data-mml-node":"math"},[a("g",{"data-mml-node":"merror","data-mjx-error":"Double subscripts: use braces to clarify",title:"Double subscripts: use braces to clarify"},[a("rect",{"data-background":"true",width:"21800",height:"950",y:"-200"}),a("title",null,"Double subscripts: use braces to clarify"),a("g",{"data-mml-node":"mtext",style:{"font-family":"serif"}},[a("text",{"data-variant":"-explicitFont",transform:"scale(1,-1)","font-size":"884px"},"proxy_add_x_forwarded_for一起使用。 ")])])])],-1),N=[A],X=a("mjx-assistive-mml",{unselectable:"on",display:"inline"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("merror",{"data-mjx-error":"Double subscripts: use braces to clarify",title:"Double subscripts: use braces to clarify"},[a("mtext",null,"proxy_add_x_forwarded_for一起使用。 ")])])],-1),V={class:"MathJax",jax:"SVG",style:{position:"relative"}},O={style:{"vertical-align":"-0.452ex"},xmlns:"http://www.w3.org/2000/svg",width:"90.95ex",height:"2.149ex",role:"img",focusable:"false",viewBox:"0 -750 40200 950","aria-hidden":"true"},G=a("g",{stroke:"currentColor",fill:"currentColor","stroke-width":"0",transform:"scale(1,-1)"},[a("g",{"data-mml-node":"math"},[a("g",{"data-mml-node":"merror","data-mjx-error":"Double subscripts: use braces to clarify",title:"Double subscripts: use braces to clarify"},[a("rect",{"data-background":"true",width:"40200",height:"950",y:"-200"}),a("title",null,"Double subscripts: use braces to clarify"),a("g",{"data-mml-node":"mtext",style:{"font-family":"serif"}},[a("text",{"data-variant":"-explicitFont",transform:"scale(1,-1)","font-size":"884px"},"proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,")])])])],-1),J=[G],U=a("mjx-assistive-mml",{unselectable:"on",display:"inline"},[a("math",{xmlns:"http://www.w3.org/1998/Math/MathML"},[a("merror",{"data-mjx-error":"Double subscripts: use braces to clarify",title:"Double subscripts: use braces to clarify"},[a("mtext",null,"proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,")])])],-1),K=a("h4",{id:"_1-2-4-https",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#_1-2-4-https","aria-hidden":"true"},"#"),n(),a("strong",null,"1.2.4 HTTPS")],-1),W={href:"https://baike.baidu.com/item/https/285356?fr=aladdin",target:"_blank",rel:"noopener noreferrer"},Y=e(`首先需要下载证书,放在nginx.conf相同目录下,nginx上的配置也需要有所改变,在nginx.conf中设置listen 443 ssl;开启https。然后配置证书和私钥:
ssl_certificate 1_www.wenzhihuai.com_bundle.crt; #主要文件路径
+ ssl_certificate_key 2_www.wenzhihuai.com.key;
+ ssl_session_timeout 5m; # 超时时间
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #按照这个协议配置
+ ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;#按照这个套件配置
+ ssl_prefer_server_ciphers on;
+
至此,可以使用https来访问了。https带来的安全性(保证信息安全、识别钓鱼网站等)是http远远不能比拟的,目前大部分网站都是实现全站https,还能将http自动重定向为https,此处,需要在server中添加rewrite ^(.*) https://$server_name$1 permanent;即可
1.2.5 失败重试 配置好了负载均衡之后,如果有一台服务器挂了怎么办?nginx中提供了可配置的服务器存活的识别,主要是通过max_fails失败请求次数,fail_timeout超时时间,weight为权重,下面的配置的意思是当服务器超时10秒,并失败了两次的时候,nginx将认为上游服务器不可用,将会摘掉上游服务器,fail_timeout时间后会再次将该服务器加入到存活上游服务器列表进行重试
upstream backend_server {
+ server 10.23.46.71:8080 max_fails=2 fail_timeout=10s weight=1;
+ server 47.95.10.139:8080 max_fails=2 fail_timeout=10s weight=1;
+}
+
session共享 `,8),aa={href:"http://blog.csdn.net/qh_java/article/details/45955923",target:"_blank",rel:"noopener noreferrer"},na=a("br",null,null,-1),ta=a("br",null,null,-1),sa=a("br",null,null,-1),ea=a("br",null,null,-1),oa={href:"https://docs.spring.io/spring-session/docs/2.0.0.BUILD-SNAPSHOT/reference/html5/",target:"_blank",rel:"noopener noreferrer"},ia=e(`首先,添加相关依赖
< dependency>
+ < groupId> org.springframework.session</ groupId>
+ < artifactId> spring-session-data-redis</ artifactId>
+ < version> 1.3.1.RELEASE</ version>
+ < type> pom</ type>
+ </ dependency>
+ < dependency>
+ < groupId> redis.clients</ groupId>
+ < artifactId> jedis</ artifactId>
+ < version> \${jedis.version}</ version>
+ </ dependency>
+
新建一个session.xml,然后在spring的配置文件中添加该文件,然后在session.xml中添加:
+ < bean id = " jedisPoolConfig" class = " redis.clients.jedis.JedisPoolConfig" >
+ </ bean>
+
+ < bean id = " jedisConnectionFactory"
+ class = " org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
+ < property name = " hostName" value = " \${host}" />
+ < property name = " port" value = " \${port}" />
+ < property name = " password" value = " \${password}" />
+ < property name = " timeout" value = " \${timeout}" />
+ < property name = " poolConfig" ref = " jedisPoolConfig" />
+ < property name = " usePool" value = " true" />
+ </ bean>
+
+ < bean id = " redisTemplate" class = " org.springframework.data.redis.core.StringRedisTemplate" >
+ < property name = " connectionFactory" ref = " jedisConnectionFactory" />
+ </ bean>
+
+
+ < bean id = " redisHttpSessionConfiguration"
+ class = " org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" >
+ < property name = " maxInactiveIntervalInSeconds" value = " 1800" />
+ </ bean>
+
然后我们需要保证servlet容器(tomcat)针对每一个请求都使用springSessionRepositoryFilter来拦截
< filter>
+ < filter-name> springSessionRepositoryFilter</ filter-name>
+ < filter-class> org.springframework.web.filter.DelegatingFilterProxy</ filter-class>
+</ filter>
+< filter-mapping>
+ < filter-name> springSessionRepositoryFilter</ filter-name>
+ < url-pattern> /*</ url-pattern>
+ < dispatcher> REQUEST</ dispatcher>
+ < dispatcher> ERROR</ dispatcher>
+</ filter-mapping>
+
配置完成,使用RedisDesktopManager查看结果:
测试: `,9),la={href:"http://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},ra=a("br",null,null,-1),pa=a("figure",null,[a("img",{src:"https://github-images.wenzhihuai.com/images/20171105050714.png",alt:"",tabindex:"0"}),a("figcaption")],-1),ca=a("p",null,"访问技术杂谈页面,此时nginx将请求转发到119.23.46.71服务器,session为28424f91-5bc5-4bba-99ec-f725401d7318。",-1),ua=a("figure",null,[a("img",{src:"https://github-images.wenzhihuai.com/images/20171105050757.png",alt:"",tabindex:"0"}),a("figcaption")],-1),ma=a("p",null,"点击生活笔记页面,转发到的服务器为47.95.10.139,session为28424f91-5bc5-4bba-99ec-f725401d7318,与上面相同。session已保持一致。",-1),da=a("figure",null,[a("img",{src:"https://github-images.wenzhihuai.com/images/20171105050849.png",alt:"",tabindex:"0"}),a("figcaption")],-1),Qa=a("strong",null,"值得注意的是:同一个浏览器,在没有关闭的情况下,即使通过域名访问和ip访问得到的session是不同的。",-1),ga=a("br",null,null,-1),Ta=a("br",null,null,-1),ha={href:"http://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},fa=a("br",null,null,-1),va={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"};function ka(xa,_a){const t=r("ExternalLinkIcon");return o(),i("div",null,[a("h1",c,[u,n(),a("a",m,[n("5.小集群部署.md"),s(t)])]),a("p",null,[n("欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:"),a("a",d,[n("http://www.wenzhihuai.com"),s(t)]),n(",个人网站代码地址:"),a("a",Q,[n("https://github.com/Zephery/newblog"),s(t)]),n("。"),g,n(" 洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。")]),T,a("p",null,[n("一般情况下,当单实例无法支撑起用户的请求时,就需要就行扩容,部署的服务器可以分机房、分地域。而分地域会导致请求分配到太远的地区,比如:深圳的用户却访问到了北京的节点,然后还得从北京返回处理之后的数据,光是来回就至少得30ms。这部分可以通过智能DNS(就近访问)解决。而分机房,需要将请求合理的分配到不同的服务器,这部分就是我们所需要处理的。"),h,n(" 通常,负载均衡分为硬件和软件两种,硬件层的比较牛逼,将4-7层负载均衡功能做到一个硬件里面,如F5,梭子鱼等。目前主流的软件负载均衡分为四层和七层,LVS属于四层负载均衡,工作在tcp/ip协议栈上,通过修改网络包的ip地址和端口来转发, 由于效率比七层高,一般放在架构的前端。七层的负载均衡有nginx, haproxy, apache等,虽然nginx自1.9.0版本后也开始支持四层的负载均衡,但是暂不讨论(我木有硬件条件)。下图来自"),a("a",f,[n("张开涛"),s(t)]),n("的《亿级流量网站架构核心技术》")]),v,k,x,_,b,a("p",null,[n("可以选择tar.gz、yum、rpm安装等,这里,由于编译、nginx配置比较复杂,要是没有把握还是使用rpm来安装吧,比较简单。从"),a("a",q,[n("https://pkgs.org/download/nginx"),s(t)]),n("可以找到最新的rpm包,然后rpm -ivh 文件,然后在命令行中输入nginx即可启动,可以使用netstat检查一下端口。")]),w,a("p",null,[n("Nginx常用的算法有:"),y,n(" (1)round-robin:轮询,nginx默认的算法,从词语上可以看出,轮流访问服务器,也可以通过weight来控制访问次数。"),H,n(" (2)ip_hash:根据访客的ip,一个ip地址对应一个服务器。"),L,n(" (3)hash算法:hash算法常用的方式有根据uri、动态指定的consistent_key两种。"),z,n(" 使用hash算法的缺点是当添加服务器的时候,只有少部分的uri能够被重新分配到新的服务器。这里,本站使用的是hash uri的算法,将不同的uri分配到不同的服务器,但是由于是不同的服务器,tomcat中的session是不一致,解决办法是"),a("a",M,[n("tomcat session"),s(t)]),n("的共享。额。。。可惜本站目前没有什么能够涉及到登陆什么session的问题。")]),D,a("p",null,[n("配置完上流服务器之后,需要配置Http的代理,将请求的端口转发到proxy_pass设定的上流服务器,即当我们访问"),a("a",Z,[n("http://wwww.wenzhihuai.com的时候"),s(t)]),n(",请求会被转发到backend中配置的服务器,此处为http://47.95.10.139:8080或者"),a("a",S,[n("http://119.23.46.71:8080"),s(t)]),n("。但是,仔细注意之后,我们会发现,tomcat中的访问日志ip来源都是127.0.0.1,相当于本地访问自己的资源。由于后台中有处理ip的代码,对客户端的ip、访问uri等记录下来,所以需要设置nginx来获取用户的实际ip,参考"),a("a",j,[n("nginx 配置"),s(t)]),n("。参考文中的一句话:经过反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过"),a("mjx-container",$,[(o(),i("svg",F,E)),I]),n("remote_addr变量时获得的是用户的真实ip,如果我们想要在web端获得用户的真实ip,就必须在nginx这里作一个赋值操作,如下:")]),P,a("p",null,[n("X-Forwarded-For:squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,这个不是默认有的,其经过代理转发之后,格式为client1, proxy1, proxy2,如果想通过这个变量来获取用户的ip,那么需要和"),a("mjx-container",R,[(o(),i("svg",B,N)),X]),n("proxy_add_x_forwarded_for:现在的"),a("mjx-container",V,[(o(),i("svg",O,J)),U]),n("remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了“用户的真实ip,第一台nginx的ip”。")]),K,a("p",null,[a("a",W,[n("HTTPS"),s(t)]),n("(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。一般情况下,能通过服务器的ssh来生成ssl证书,但是如果使用是自己的,一般浏览器(谷歌、360等)都会报证书不安全的错误,正常用户都不敢访问吧==,所以现在使用的是腾讯跟别的机构颁发的:")]),Y,a("p",null,[n("分布式情况下难免会要解决session共享的问题,目前推荐的方法基本上都是使用redis,网上查找的方法目前流行的有下面四种,参考自"),a("a",aa,[n("tomcat 集群中 session 共"),s(t)]),n(":"),na,n(" 1.使用 filter 方法存储。(推荐,因为它的服务器使用范围比较多,不仅限于tomcat ,而且实现的原理比较简单容易控制。)"),ta,n(" 2.使用 tomcat sessionmanager 方法存储。(直接配置即可)"),sa,n(" 3.使用 terracotta 服务器共享。(不知道,不了解)"),ea,n(" 4.使用spring-session。(spring的一个小项目,其原理也和第一种基本一致)")]),a("p",null,[n("本站使用spring-session,毕竟是spring下的子项目,学习下还是挺好的。参考"),a("a",oa,[n("Spring-Session官网"),s(t)]),n("。官方文档提供了spring-boot、spring等例子,可以参考参考。目前最新版本是2.0.0,不同版本使用方式不同,建议看官网的文档吧。")]),ia,a("p",null,[n("访问"),a("a",la,[n("http://www.wenzhihuai.com"),s(t)]),ra,n(" tail -f localhost_access_log.2017-11-05.txt查看日志,然后清空一下当前记录")]),pa,ca,ua,ma,da,a("p",null,[Qa,ga,n(" 欢迎访问我的个人网站O(∩_∩)O哈哈~希望能给个star"),Ta,n(" 个人网站网址:"),a("a",ha,[n("http://www.wenzhihuai.com"),s(t)]),fa,n(" 个人网站代码地址:"),a("a",va,[n("https://github.com/Zephery/newblog"),s(t)])])])}const qa=l(p,[["render",ka],["__file","5.小集群部署.html.vue"]]);export{qa as default};
diff --git "a/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-Vk3PqneA.js" "b/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-Vk3PqneA.js"
new file mode 100644
index 00000000..43dad5b7
--- /dev/null
+++ "b/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-Vk3PqneA.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-6094ea20","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html","title":"5.小集群部署.md","lang":"zh-CN","frontmatter":{"description":"5.小集群部署.md 欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com,个人网站代码地址:https://github.com/Zephery/newblog。 洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"5.小集群部署.md"}],["meta",{"property":"og:description","content":"5.小集群部署.md 欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com,个人网站代码地址:https://github.com/Zephery/newblog。 洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"5.小集群部署.md\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"1.1 Nginx的安装","slug":"_1-1-nginx的安装","link":"#_1-1-nginx的安装","children":[]},{"level":2,"title":"1.2 Nginx的配置","slug":"_1-2-nginx的配置","link":"#_1-2-nginx的配置","children":[]},{"level":2,"title":"测试:","slug":"测试","link":"#测试","children":[]}],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":9.5,"words":2849},"filePathRelative":"java/个人网站/5.小集群部署.md","localizedDate":"2024年2月2日","excerpt":"\\n欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com ,个人网站代码地址:https://github.com/Zephery/newblog 。 \\n洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。
","autoDesc":true}');export{e as data};
diff --git "a/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-RXzoE_MH.js" "b/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-RXzoE_MH.js"
new file mode 100644
index 00000000..dd3b69fb
--- /dev/null
+++ "b/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-RXzoE_MH.js"
@@ -0,0 +1,65 @@
+import{_ as a,r as l,o as r,c as d,a as i,d as e,b as s,e as t}from"./app-BDpQ7oW_.js";const m={},c=t(` 6.数据库备份 先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地:
由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下:
果然,36ms。。。看起来挺小的,但是对比一下sql执行语句的时间:
大部分都能在10ms内完成,而最长的语句是insert语句,可见,由于异地导致的36ms延时还是比较大的,捣鼓了一下,最后还是选择换个架构,每个服务器读取自己的数据库,然后数据库底层做一下主主复制,让数据同步。最终架构如下:
一、MySql的复制 数据库复制的基本问题就是让一台服务器的数据与其他服务器保持同步。MySql目前支持两种复制方式:基于行的复制和基于语句的复制,这两者的基本过程都是在主库上记录二进制的日志、在备库上重放日志的方式来实现异步的数据复制。其过程分为三步: (1)master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events); (2)slave将master的binary log events拷贝到它的中继日志(relay log); (3)slave重做中继日志中的事件,将改变反映它自己的数据。
该过程的第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。 下一步就是slave将master的binary log拷贝到它自己的中继日志。首先,slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。 SQL slave thread处理该过程的最后一步。SQL线程从中继日志读取事件,更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。 此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。 MySql的基本复制方式有主从复制、主主复制,主主复制即把主从复制的配置倒过来再配置一遍即可,下面的配置则是主从复制的过程,到时候可自行改为主主复制。其他的架构如:一主库多备库、环形复制、树或者金字塔型都是基于这两种方式,可参考《高性能MySql》。
二、配置过程 2.1 创建所用的复制账号 由于是个自己的小网站,就不做过多的操作了,直接使用root账号
2.2 配置master 接下来要对mysql的serverID,日志位置,复制方式等进行操作,使用vim打开my.cnf。
[client]
+default-character-set=utf8
+
+[mysqld]
+character_set_server=utf8
+init_connect= SET NAMES utf8
+
+datadir=/var/lib/mysql
+socket=/var/lib/mysql/mysql.sock
+
+symbolic-links=0
+
+log-error=/var/log/mysqld.log
+pid-file=/var/run/mysqld/mysqld.pid
+
+# master
+log-bin=mysql-bin
+# 设为基于行的复制
+binlog-format=ROW
+# 设置server的唯一id
+server-id=2
+# 忽略的数据库,不使用备份
+binlog-ignore-db=information_schema
+binlog-ignore-db=cluster
+binlog-ignore-db=mysql
+# 要进行备份的数据库
+binlog-do-db=myblog
+
重启Mysql之后,查看主库状态,show master status。
其中,File为日志文件,指定Slave从哪个日志文件开始读复制数据,Position为偏移,从哪个POSITION号开始读,Binlog_Do_DB为要备份的数据库。
2.3 配置slave 从库的配置跟主库类似,vim /etc/my.cnf配置从库信息。
+[client]
+default-character-set=utf8
+
+[mysqld]
+character_set_server=utf8
+init_connect= SET NAMES utf8
+
+datadir=/var/lib/mysql
+socket=/var/lib/mysql/mysql.sock
+
+symbolic-links=0
+
+log-error=/var/log/mysqld.log
+pid-file=/var/run/mysqld/mysqld.pid
+
+# slave
+log-bin=mysql-bin
+# 服务器唯一id
+server-id=3
+# 不备份的数据库
+binlog-ignore-db=information_schema
+binlog-ignore-db=cluster
+binlog-ignore-db=mysql
+# 需要备份的数据库
+replicate-do-db=myblog
+# 其他相关信息
+slave-skip-errors=all
+slave-net-timeout=60
+# 开启中继日志
+relay_log = mysql-relay-bin
+#
+log_slave_updates = 1
+# 防止改变数据
+read_only = 1
+
重启slave,同时启动复制,还需要调整一下命令。
mysql> CHANGE MASTER TO MASTER_HOST = '119.23.46.71', MASTER_USER = 'root', MASTER_PASSWORD = 'helloroot', MASTER_PORT = 3306, MASTER_LOG_FILE = 'mysql-bin.000009', MASTER_LOG_POS = 346180;
+
+
可以看见slave已经开始进行同步了。我们使用show slave status\\G来查看slave的状态。
其中日志文件和POSITION不一致是合理的,配置好了的话,即使重启,也不会影响到主从复制的配置。
某天在Github上漂游,发现了阿里的canal,同时才知道上面这个业务是叫异地跨机房同步,早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求。不过早期的数据库同步业务,主要是基于trigger的方式获取增量变更,不过从2010年开始,阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务。下面是基本的原理:
原理相对比较简单:
1.canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议 2.mysql master收到dump请求,开始推送binary log给slave(也就是canal) 3.canal解析binary log对象(原始为byte流)
`,34),v={href:"https://github.com/alibaba/canal",target:"_blank",rel:"noopener noreferrer"},o=i("figure",null,[i("img",{src:"https://github-images.wenzhihuai.com/images/20171120100237.png",alt:"",tabindex:"0"}),i("figcaption")],-1),b={href:"https://github.com/alibaba/otter",target:"_blank",rel:"noopener noreferrer"},u=i("p",null,"公司又要996了,实在是忙不过来,感觉自己写的还是急躁了点,困==",-1);function g(h,p){const n=l("ExternalLinkIcon");return r(),d("div",null,[c,i("p",null,[e("其中,配置过程如下:"),i("a",v,[e("https://github.com/alibaba/canal"),s(n)]),e(",可以搭配Zookeeper使用。在ZKUI中能够查看到节点:")]),o,i("p",null,[e("一般情况下,还要配合阿里的另一个开源产品使用"),i("a",b,[e("otter"),s(n)]),e(",相关文档还是找找GitHub吧,个人搭建完了之后,用起来还是不如直接使用mysql的主主复制,而且异地机房同步这种大企业才有的业务。")]),u])}const _=a(m,[["render",g],["__file","6.数据库备份.html.vue"]]);export{_ as default};
diff --git "a/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-cRo7CD_Q.js" "b/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-cRo7CD_Q.js"
new file mode 100644
index 00000000..089ea95c
--- /dev/null
+++ "b/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-cRo7CD_Q.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-68e11d4e","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html","title":"6.数据库备份","lang":"zh-CN","frontmatter":{"description":"6.数据库备份 先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地: 由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下:","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"6.数据库备份"}],["meta",{"property":"og:description","content":"6.数据库备份 先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地: 由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下:"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"6.数据库备份\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":3,"title":"2.1 创建所用的复制账号","slug":"_2-1-创建所用的复制账号","link":"#_2-1-创建所用的复制账号","children":[]},{"level":3,"title":"2.2 配置master","slug":"_2-2-配置master","link":"#_2-2-配置master","children":[]},{"level":3,"title":"2.3 配置slave","slug":"_2-3-配置slave","link":"#_2-3-配置slave","children":[]}],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":5.77,"words":1732},"filePathRelative":"java/个人网站/6.数据库备份.md","localizedDate":"2024年2月2日","excerpt":" 6.数据库备份 \\n先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地:
\\n \\n由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下:
","autoDesc":true}');export{e as data};
diff --git "a/assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-553rUa1v.js" "b/assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-553rUa1v.js"
new file mode 100644
index 00000000..a11d515c
--- /dev/null
+++ "b/assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-553rUa1v.js"
@@ -0,0 +1,14 @@
+import{_ as i,r as o,o as r,c as l,a as e,d as n,b as a,e as s}from"./app-BDpQ7oW_.js";const h={},c=e("h1",{id:"_7-那些牛逼的插件",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_7-那些牛逼的插件","aria-hidden":"true"},"#"),n(" 7.那些牛逼的插件")],-1),p={href:"http://www.wenzhihuai.com/",target:"_blank",rel:"noopener noreferrer"},d={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"},u=e("br",null,null,-1),g=e("br",null,null,-1),_=e("br",null,null,-1),m=e("br",null,null,-1),b=e("br",null,null,-1),f={href:"http://3.Editor.md",target:"_blank",rel:"noopener noreferrer"},w=e("br",null,null,-1),k=e("br",null,null,-1),E=e("br",null,null,-1),v=e("br",null,null,-1),x=e("br",null,null,-1),B=e("h2",{id:"wowslider",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#wowslider","aria-hidden":"true"},"#"),n(" wowslider")],-1),y={href:"http://wowslider.com/",target:"_blank",rel:"noopener noreferrer"},z={href:"https://github.com/WOWSlider/WOWSlider",target:"_blank",rel:"noopener noreferrer"},A={href:"http://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},C=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/20171121023427.png",alt:"",tabindex:"0"}),e("figcaption")],-1),j={href:"https://fonts.googleapis.com/css?family=Arimo&subset=latin,cyrillic,latin-ext%EF%BC%8C%E7%94%B1%E4%BA%8E%E4%B8%80%E8%88%AC%E7%94%A8%E6%88%B7%E4%B8%8D%E8%83%BD%E8%AE%BF%E9%97%AE%E8%B0%B7%E6%AD%8C%EF%BC%8C%E4%BC%9A%E5%AF%BC%E8%87%B4%E7%BD%91%E9%A1%B5%E5%8A%A0%E8%BD%BD%E9%80%9F%E5%BA%A6%E5%8F%8A%E5%85%B6%E7%BC%93%E6%85%A2%EF%BC%8C%E6%89%80%E4%BB%A5%EF%BC%8C%E5%8E%BB%E6%8E%89%E4%B8%BA%E5%A6%99",target:"_blank",rel:"noopener noreferrer"},D=e("h2",{id:"畅言",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#畅言","aria-hidden":"true"},"#"),n(" 畅言")],-1),S={href:"http://www.wenzhihuai.com/board.html",target:"_blank",rel:"noopener noreferrer"},F=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/20171121024358.png",alt:"",tabindex:"0"}),e("figcaption")],-1),W={id:"editor-md",tabindex:"-1"},Z=e("a",{class:"header-anchor",href:"#editor-md","aria-hidden":"true"},"#",-1),H={href:"http://Editor.md",target:"_blank",rel:"noopener noreferrer"},R=e("br",null,null,-1),G={href:"https://github.com/pandao/editor.md",target:"_blank",rel:"noopener noreferrer"},O=s('代码样式,这一点是不如WORDPRESS的插件了,不过已经可以了。
图表 目前最常用的是highcharts跟echart,目前个人博客中的日志系统主要还是采用了highcharts,主要还是颜色什么的格调比较相符吧,其次是因为对echarts印象不太友好,比如下面做这张,打开网页后,缩小浏览器,百度的地域图却不能自适应,出现了越界,而highcharts的全部都能自适应调整。想起有次面试,我说我用的highcharts,面试官一脸嫌弃。。。(网上这么多人鄙视百度是假的?)
不过地图确确实实是echarts的优势,毕竟还是自家的东西了解自家,不过前段时间去看了看echarts的官网,已经不提供下载了。如果有需要,还是去csdn上搜索吧,或者替换为highmap。
百度分享 ',9),P={href:"http://www.jiathis.com/",target:"_blank",rel:"noopener noreferrer"},I={href:"http://share.baidu.com/code/advance#tools",target:"_blank",rel:"noopener noreferrer"},N=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/20171121022116.png",alt:"",tabindex:"0"}),e("figcaption")],-1),V={href:"https://github.com/Zephery/newblog/blob/master/src/main/webapp/board.jsp",target:"_blank",rel:"noopener noreferrer"},M=s(`#share a {
+ width : 34px;
+ height : 34px;
+ padding : 0;
+ margin : 6px;
+ border-radius : 25px;
+ transition : all .4s;
+}
+
+#share a.bds_qzone {
+ background : url ( http://image.wenzhihuai.com/t_QQZone.png) no-repeat;
+ background-size : 34px 34px;
+}
+
改完之后的效果。
瀑布流 `,4),Q={href:"https://www.zhihu.com/question/20653270",target:"_blank",rel:"noopener noreferrer"},q=e("a",{href:""},"waterfall.js",-1),L=e("a",{href:""},"masory.js",-1),U=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/20171125103716.png",alt:"",tabindex:"0"}),e("figcaption")],-1),J=e("h2",{id:"天气插件",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#天气插件","aria-hidden":"true"},"#"),n(" 天气插件")],-1),T={href:"http://cj.weather.com.cn/",target:"_blank",rel:"noopener noreferrer"},K={href:"https://www.seniverse.com/widget/intro",target:"_blank",rel:"noopener noreferrer"},X=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/20171125105127.png",alt:"",tabindex:"0"}),e("figcaption")],-1),Y=e("h2",{id:"标签云",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#标签云","aria-hidden":"true"},"#"),n(" 标签云")],-1),$=e("p",null,"标签云,弄得好的话应该说是一个网站的点缀。现在好像比较流行3D的标签云?像下面这种。",-1),ee=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/20171127033202.png",alt:"",tabindex:"0"}),e("figcaption")],-1),ne={href:"https://github.com/Zephery/newblog/blob/master/src/main/webapp/css/newlypublished.css",target:"_blank",rel:"noopener noreferrer"},te=e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/20171127033945.png",alt:"",tabindex:"0"}),e("figcaption")],-1),ae=e("h1",{id:"总结",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#总结","aria-hidden":"true"},"#"),n(" 总结")],-1),se=e("p",null,[n("作为一个后端人员,调css和js真是痛苦==,好在坚持下来了,虽然还是很多不足,以后有时间慢慢改。说了那么多,感觉自己还是菜的抠脚。"),e("br"),n(" 题外话,搭建一个博客,对于一个新近程序员来说真的是锻炼自己的一个好机会,能够认识到从前端、java后台、linux、jvm等等知识,只是真的有点耗时间(还不如把时间耗在Spring源码),如果不采用别人的框架的话,付出的代价还是蛮大的(所以不要鄙视我啦)。没有什么能够一举两得,看自己的取舍吧。加油💪(ง •_•)ง")],-1),ie={href:"http://www.wenzhihuai.com/",target:"_blank",rel:"noopener noreferrer"},oe={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"};function re(le,he){const t=o("ExternalLinkIcon");return r(),l("div",null,[c,e("p",null,[n("欢迎访问我的网站"),e("a",p,[n("http://www.wenzhihuai.com/"),a(t)]),n(" 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址"),e("a",d,[n("https://github.com/Zephery/newblog"),a(t)]),n(" 。"),u,n(" 建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Java的程序员,前端的东西一碰脑子就有“我又不是前端,浪费时间在这合适么?”这种想法,捣鼓来捣鼓去,做出的东西实在是没法看,我就觉得,如果自己的“产品”连自己都看不下去了,那还好意思给别人看?特别是留言板那块,初版的页面简直low的要死。所以,还是踏踏实实的“站在巨人的肩膀上”吧,改用别人的插件。但不要纯粹的使用别人的博客模板了,如hexo,wordpress这些,就算是自己拼凑过来的也比这些强。下面是本博客中所用到的插件,给大家介绍介绍,共同学习学习。"),g,n(" 本站主要用到的插件有:"),_,n(" 1.wowslider"),m,n(" 2.畅言"),b,e("a",f,[n("3.Editor.md"),a(t)]),w,n(" 4.highchart、echart"),k,n(" 5.百度分享"),E,n(" 6.waterfall.js"),v,n(" 7.心知天气"),x,n(" 8.标签云")]),B,e("p",null,[n("可能是我这网站中最炫的东西了,图片能够自动像幻灯片一样自动滚动,让网站的首页一看起来就高大上,简直就是建站必备的东西,而且安装也及其简单,有兴趣可以点击"),e("a",y,[n("官网"),a(t)]),n("看看。GitHub里也开放了"),e("a",z,[n("源代码"),a(t)]),n("。安装过程:自己选择“幻灯片”切换效果,保存为html就行了,WORDPREESS中好像有集成这个插件的,做的还更好。感兴趣可以点击"),e("a",A,[n("我的博客首页"),a(t)]),n("看一看。")]),C,e("p",null,[e("strong",null,[n("不过还有个值得注意的问题,就是wowslider里面带有一个googleapis的服务,即"),e("a",j,[n("https://fonts.googleapis.com/css?family=Arimo&subset=latin,cyrillic,latin-ext,由于一般用户不能访问谷歌,会导致网页加载速度及其缓慢,所以,去掉为妙"),a(t)])])]),D,e("p",null,[n("作为社交评论的工具,虽然说表示还是想念以前的多说,但是畅言现在做得还是好了,有评论审核,评论导出导入等功能,如果浏览量大的话,还能提供广告服务,让站长也能拿到一丢丢的广告费。本博客中使用了畅言的基本评论、获取某篇文章评论数的功能。可以到我这里"),e("a",S,[n("留言"),a(t)]),n("哈")]),F,e("h2",W,[Z,n(),e("a",H,[n("Editor.md"),a(t)])]),e("p",null,[n("一款能将markdown解析为html的插件,国人的作品,博客的文章编辑器一开始想使用的是markdown,想法是:写文章、保存数据库都是markdown格式的,保存在数据库中,读取时有需要解析markdown,这个过程是有点耗时的,但是相比把html式的网页保存在数据库中友好点吧,因为如果一篇文章比较长的话,转成html的格式,光是大小估计也得超过几十kb?所以,还是本人选择的是一切都用源markdown。"),R,e("a",G,[n("editor.md"),a(t)]),n(",是一款开源的、可嵌入的 Markdown 在线编辑器(组件),基于 CodeMirror、jQuery 和 Marked 构建。页面看起来还是美观的,相比WORDPRESS的那些牛逼插件还差那么一点点,不过从普通人的眼光来看,应该是可以的了。此处,我用它作为解析网页的利器,还有就是后台编辑也是用的这个。")]),O,e("p",null,[n("作为一个以博客为主的网站,免不了使用一些社会化分享的工具,目前主要是"),e("a",P,[n("jiathis"),a(t)]),n("和百度分享,这两者的ui都是相似的(丑爆了)。凭我个人的感觉,jiathis加载实在是太过于缓慢,这点是无法让人忍受的,只好投靠百度。百度分享类似于jiathis,安装也很简单,具体见官网"),e("a",I,[n("http://share.baidu.com/code/advance#tools"),a(t)]),n("。一直点点点,配置完之后,就是下图这种,丑爆了是不是?")]),N,e("p",null,[n("好在对它的美观改变不是很难,此处参考了别人的UI设计,原作者我忘记怎么联系他了。其原理主要是使用图片来替换掉原本的东西。完整的源码可以点击"),e("a",V,[n("此处"),a(t)]),n("。")]),M,e("p",null,[n("有段时间,瀑布流特别流行?还有段时间,瀑布流开始遭到各种抵制。。。"),e("a",Q,[n("看看知乎的人怎么说"),a(t)]),n(",大部分人不喜欢的原因是让人觉得视觉疲劳,不过瀑布流最大的好处还是有的:提高发现好图的效率以及图片列表页极强的视觉感染力。没错,我还是想把自己的网站弄得铉一些==,所以采用了瀑布流(不过效果不是很好,某些浏览器甚至加载出错),这个大bug有时间再改,毕竟花了很多时间做的这个,效果确实不咋地。目前主要的瀑布流有"),q,n("和"),L,n("。这一块目前还不是很完善,希望能得到各位大佬的指点。")]),U,J,e("p",null,[n("此类咨询服务还是网上还是挺多的,这一块不知道是不是所谓的“画蛇添足”这部分,主要是我觉得网站右边这部分老是少了点什么,所以加上了天气插件。目前常用的天气插件有"),e("a",T,[n("中国天气网"),a(t)]),n(","),e("a",K,[n("心知天气"),a(t)]),n("等。安装方式见各自的官网,这里不再阐述,我使用的是心知天气。注意:心知天气限制流量的,一个小时内只能使用400次,如果超出了会失效,当然也可以付费使用。")]),X,Y,$,ee,e("p",null,[n("从个人的网站风格来看,比较适应PHP形式的,有点颜色而又不绚丽的即可,之前用的跟分类的一样的样式,即双纵列的样式,美观度还行,虽然老是感觉有点怪怪的,如果某个标签的字数过长怎么办,岂不是要顶出div了。所以还是选择换另一种风格,最终偶然一次找到了下面这种,能够自适应宽度,颜色虽然鲜艳了点(以后有空再调一下吧),源码见"),e("a",ne,[n("style.css"),a(t)]),n("。 下图为目前的标签页。")]),te,ae,se,e("p",null,[n("欢迎访问我的网站"),e("a",ie,[n("http://www.wenzhihuai.com/"),a(t)]),n(" 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址"),e("a",oe,[n("https://github.com/Zephery/newblog"),a(t)]),n(" 。")])])}const pe=i(h,[["render",re],["__file","7.那些牛逼的插件.html.vue"]]);export{pe as default};
diff --git "a/assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-923LgNG1.js" "b/assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-923LgNG1.js"
new file mode 100644
index 00000000..34c3e2cc
--- /dev/null
+++ "b/assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-923LgNG1.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-1f1952ea","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html","title":"7.那些牛逼的插件","lang":"zh-CN","frontmatter":{"description":"7.那些牛逼的插件 欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。 建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Java的程序员,前端的东西一碰脑子就有“我又不是前端,浪费时间在这合适么?”这种想法,捣鼓来捣鼓去,做出的东西实在是没法看,我就觉得,如果自己的“产品”连自己都看不下去了,那还好意思给别人看?特别是留言板那块,初版的页面简直low的要死。所以,还是踏踏实实的“站在巨人的肩膀上”吧,改用别人的插件。但不要纯粹的使用别人的博客模板了,如hexo,wordpress这些,就算是自己拼凑过来的也比这些强。下面是本博客中所用到的插件,给大家介绍介绍,共同学习学习。 本站主要用到的插件有: 1.wowslider 2.畅言 3.Editor.md 4.highchart、echart 5.百度分享 6.waterfall.js 7.心知天气 8.标签云","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"7.那些牛逼的插件"}],["meta",{"property":"og:description","content":"7.那些牛逼的插件 欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。 建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Java的程序员,前端的东西一碰脑子就有“我又不是前端,浪费时间在这合适么?”这种想法,捣鼓来捣鼓去,做出的东西实在是没法看,我就觉得,如果自己的“产品”连自己都看不下去了,那还好意思给别人看?特别是留言板那块,初版的页面简直low的要死。所以,还是踏踏实实的“站在巨人的肩膀上”吧,改用别人的插件。但不要纯粹的使用别人的博客模板了,如hexo,wordpress这些,就算是自己拼凑过来的也比这些强。下面是本博客中所用到的插件,给大家介绍介绍,共同学习学习。 本站主要用到的插件有: 1.wowslider 2.畅言 3.Editor.md 4.highchart、echart 5.百度分享 6.waterfall.js 7.心知天气 8.标签云"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"7.那些牛逼的插件\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"wowslider","slug":"wowslider","link":"#wowslider","children":[]},{"level":2,"title":"畅言","slug":"畅言","link":"#畅言","children":[]},{"level":2,"title":"Editor.md","slug":"editor-md","link":"#editor-md","children":[]},{"level":2,"title":"图表","slug":"图表","link":"#图表","children":[]},{"level":2,"title":"百度分享","slug":"百度分享","link":"#百度分享","children":[]},{"level":2,"title":"瀑布流","slug":"瀑布流","link":"#瀑布流","children":[]},{"level":2,"title":"天气插件","slug":"天气插件","link":"#天气插件","children":[]},{"level":2,"title":"标签云","slug":"标签云","link":"#标签云","children":[]}],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":7.24,"words":2173},"filePathRelative":"java/个人网站/7.那些牛逼的插件.md","localizedDate":"2024年2月2日","excerpt":" 7.那些牛逼的插件 \\n欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。 \\n建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Java的程序员,前端的东西一碰脑子就有“我又不是前端,浪费时间在这合适么?”这种想法,捣鼓来捣鼓去,做出的东西实在是没法看,我就觉得,如果自己的“产品”连自己都看不下去了,那还好意思给别人看?特别是留言板那块,初版的页面简直low的要死。所以,还是踏踏实实的“站在巨人的肩膀上”吧,改用别人的插件。但不要纯粹的使用别人的博客模板了,如hexo,wordpress这些,就算是自己拼凑过来的也比这些强。下面是本博客中所用到的插件,给大家介绍介绍,共同学习学习。 \\n本站主要用到的插件有: \\n1.wowslider \\n2.畅言 \\n3.Editor.md \\n4.highchart、echart \\n5.百度分享 \\n6.waterfall.js \\n7.心知天气 \\n8.标签云
","autoDesc":true}');export{e as data};
diff --git "a/assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-hE6G3Tqn.js" "b/assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-hE6G3Tqn.js"
new file mode 100644
index 00000000..e9917df8
--- /dev/null
+++ "b/assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-hE6G3Tqn.js"
@@ -0,0 +1 @@
+import{_,o as t,c as a,a as e,d as c}from"./app-BDpQ7oW_.js";const o={},r=e("h1",{id:"_8-基于贝叶斯的情感分析",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_8-基于贝叶斯的情感分析","aria-hidden":"true"},"#"),c(" 8.基于贝叶斯的情感分析")],-1),s=[r];function n(d,i){return t(),a("div",null,s)}const l=_(o,[["render",n],["__file","8.基于贝叶斯的情感分析.html.vue"]]);export{l as default};
diff --git "a/assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-kXuTnRoS.js" "b/assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-kXuTnRoS.js"
new file mode 100644
index 00000000..2c40b198
--- /dev/null
+++ "b/assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-kXuTnRoS.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-6dc450d0","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/8.%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%9A%84%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90.html","title":"8.基于贝叶斯的情感分析","lang":"zh-CN","frontmatter":{"description":"8.基于贝叶斯的情感分析","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/8.%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%9A%84%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"8.基于贝叶斯的情感分析"}],["meta",{"property":"og:description","content":"8.基于贝叶斯的情感分析"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"8.基于贝叶斯的情感分析\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":0.04,"words":11},"filePathRelative":"java/个人网站/8.基于贝叶斯的情感分析.md","localizedDate":"2024年2月2日","excerpt":" 8.基于贝叶斯的情感分析 \\n","autoDesc":true}');export{e as data};
diff --git "a/assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-3n6tdjL9.js" "b/assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-3n6tdjL9.js"
new file mode 100644
index 00000000..2220f258
--- /dev/null
+++ "b/assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-3n6tdjL9.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-44460f42","path":"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html","title":"9.网站性能优化","lang":"zh-CN","frontmatter":{"description":"9.网站性能优化","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"9.网站性能优化"}],["meta",{"property":"og:description","content":"9.网站性能优化"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T04:56:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-02-02T04:56:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"9.网站性能优化\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T04:56:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1706849761000,"updatedTime":1706849761000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":0.02,"words":7},"filePathRelative":"java/个人网站/9.网站性能优化.md","localizedDate":"2024年2月2日","excerpt":" 9.网站性能优化 \\n","autoDesc":true}');export{e as data};
diff --git "a/assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-YAx6WK4Q.js" "b/assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-YAx6WK4Q.js"
new file mode 100644
index 00000000..24d721a1
--- /dev/null
+++ "b/assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-YAx6WK4Q.js"
@@ -0,0 +1 @@
+import{_,o as t,c as a,a as e,d as c}from"./app-BDpQ7oW_.js";const o={},r=e("h1",{id:"_9-网站性能优化",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_9-网站性能优化","aria-hidden":"true"},"#"),c(" 9.网站性能优化")],-1),s=[r];function n(d,i){return t(),a("div",null,s)}const l=_(o,[["render",n],["__file","9.网站性能优化.html.vue"]]);export{l as default};
diff --git "a/assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-RmR4uDpi.js" "b/assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-RmR4uDpi.js"
new file mode 100644
index 00000000..48bb1fe6
--- /dev/null
+++ "b/assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-RmR4uDpi.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-0a27b598","path":"/java/JVM%E8%B0%83%E4%BC%98%E5%8F%82%E6%95%B0.html","title":"JVM调优参数","lang":"zh-CN","frontmatter":{"description":"JVM调优参数 一、堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。 典型设置: java -Xmx3550m -Xms3550m -Xmn2g -Xss128k","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/JVM%E8%B0%83%E4%BC%98%E5%8F%82%E6%95%B0.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"JVM调优参数"}],["meta",{"property":"og:description","content":"JVM调优参数 一、堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。 典型设置: java -Xmx3550m -Xms3550m -Xmn2g -Xss128k"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-24T10:30:22.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-24T10:30:22.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"JVM调优参数\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-24T10:30:22.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、堆大小设置","slug":"一、堆大小设置","link":"#一、堆大小设置","children":[{"level":3,"title":"典型设置:","slug":"典型设置","link":"#典型设置","children":[]}]},{"level":2,"title":"二、回收器选择","slug":"二、回收器选择","link":"#二、回收器选择","children":[{"level":3,"title":"2.1 吞吐量优先的并行收集器","slug":"_2-1-吞吐量优先的并行收集器","link":"#_2-1-吞吐量优先的并行收集器","children":[]},{"level":3,"title":"2.2 响应时间优先的并发收集器","slug":"_2-2-响应时间优先的并发收集器","link":"#_2-2-响应时间优先的并发收集器","children":[]}]},{"level":2,"title":"三、辅助信息","slug":"三、辅助信息","link":"#三、辅助信息","children":[{"level":3,"title":"3.1 堆设置","slug":"_3-1-堆设置","link":"#_3-1-堆设置","children":[]},{"level":3,"title":"3.2 收集器设置","slug":"_3-2-收集器设置","link":"#_3-2-收集器设置","children":[]},{"level":3,"title":"3.3 垃圾回收统计信息","slug":"_3-3-垃圾回收统计信息","link":"#_3-3-垃圾回收统计信息","children":[]},{"level":3,"title":"3.4 并行收集器设置","slug":"_3-4-并行收集器设置","link":"#_3-4-并行收集器设置","children":[]},{"level":3,"title":"3.5 并发收集器设置","slug":"_3-5-并发收集器设置","link":"#_3-5-并发收集器设置","children":[]}]},{"level":2,"title":"四、调优总结","slug":"四、调优总结","link":"#四、调优总结","children":[{"level":3,"title":"4.1 年轻代大小选择","slug":"_4-1-年轻代大小选择","link":"#_4-1-年轻代大小选择","children":[]},{"level":3,"title":"4.2 年老代大小选择","slug":"_4-2-年老代大小选择","link":"#_4-2-年老代大小选择","children":[]},{"level":3,"title":"4.3 较小堆引起的碎片问题","slug":"_4-3-较小堆引起的碎片问题","link":"#_4-3-较小堆引起的碎片问题","children":[]}]}],"git":{"createdTime":1706066758000,"updatedTime":1706092222000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":9.13,"words":2739},"filePathRelative":"java/JVM调优参数.md","localizedDate":"2024年1月24日","excerpt":" JVM调优参数 \\n 一、堆大小设置 \\nJVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
\\n 典型设置: \\njava -Xmx3550m -Xms3550m -Xmn2g -Xss128k \\n
","autoDesc":true}');export{e as data};
diff --git "a/assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-_zG0M5-i.js" "b/assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-_zG0M5-i.js"
new file mode 100644
index 00000000..ff3d9b8a
--- /dev/null
+++ "b/assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-_zG0M5-i.js"
@@ -0,0 +1,33 @@
+import{_ as a,o as e,c as s,e as n}from"./app-BDpQ7oW_.js";const r={},i=n(` JVM调优参数 一、堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
典型设置: java -Xmx3550m -Xms3550m -Xmn2g -Xss128k
+
-Xmx3550m:设置JVM最大可用内存为3550M。 -Xms3550m:设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。 -Xmn2g:设置年轻代大小为2G。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。 -Xss128k: 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内 存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio = 4 -XX:SurvivorRatio = 4 -XX:MaxPermSize = 16m -XX:MaxTenuringThreshold = 0
+
-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 -XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6 -XX:MaxPermSize=16m:设置持久代大小为16m。 -XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
二、回收器选择 JVM给了三种选择:串行收集器、并行收集器、并发收集器,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器。默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数。JDK5.0以后,JVM会根据当前系统配置进行判断。
2.1 吞吐量优先的并行收集器 如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等。 典型配置:
java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads = 20
+
-XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。 -XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads = 20 -XX:+UseParallelOldGC
+
-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集。
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis = 100
+
-XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis = 100 -XX:+UseAdaptiveSizePolicy
+
-XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开。
2.2 响应时间优先的并发收集器 如上文所述,并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。 典型配置:
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads = 20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
+
-XX:+UseConcMarkSweepGC:设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置。 -XX:+UseParNewGC:设置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction = 5 -XX:+UseCMSCompactAtFullCollection
+
-XX:CMSFullGCsBeforeCompaction:由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。 -XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩。可能会影响性能,但是可以消除碎片
三、辅助信息 JVM提供了大量命令行参数,打印信息,供调试使用。主要有以下一些: -XX:+PrintGC 输出形式:[GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs]
-XX:+PrintGCDetails 输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]
-XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用 输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs] -XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中断的执行时间。可与上面混合使用 输出形式:Application time: 0.5291524 seconds -XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂停的时间。可与上面混合使用 输出形式:Total time for which application threads were stopped: 0.0468229 seconds -XX:PrintHeapAtGC:打印GC前后的详细堆栈信息 输出形式:
34.702: [GC {Heap before gc invocations=7:
+ def new generation total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)
+eden space 49152K, 99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)
+from space 6144K, 55% used [0x221d0000, 0x22527e10, 0x227d0000)
+ to space 6144K, 0% used [0x21bd0000, 0x21bd0000, 0x221d0000)
+ tenured generation total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)
+the space 69632K, 3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000)
+ compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
+ the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
+ ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
+ rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
+34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8:
+ def new generation total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)
+eden space 49152K, 0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)
+ from space 6144K, 55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)
+ to space 6144K, 0% used [0x221d0000, 0x221d0000, 0x227d0000)
+ tenured generation total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)
+the space 69632K, 4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000)
+ compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
+ the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
+ ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
+ rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
+}
+, 0.0757599 secs]
+
-Xloggc:filename:与上面几个配合使用,把相关日志信息记录到文件以便分析。常见配置汇总
3.1 堆设置 -Xms:初始堆大小 -Xmx:最大堆大小 -XX:NewSize=n:设置年轻代大小 -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4 -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 -XX:MaxPermSize=n:设置持久代大小
3.2 收集器设置 -XX:+UseSerialGC:设置串行收集器 -XX:+UseParallelGC:设置并行收集器 -XX:+UseParalledlOldGC:设置并行年老代收集器 -XX:+UseConcMarkSweepGC:设置并发收集器
3.3 垃圾回收统计信息 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:filename
3.4 并行收集器设置 -XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。 -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间 -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
3.5 并发收集器设置 -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。 -XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
四、调优总结 4.1 年轻代大小选择 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
4.2 年老代大小选择 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得: 并发垃圾收集信息 持久代并发收集次数 传统GC信息 花在年轻代和年老代回收上的时间比例 减少年轻代和年老代花费的时间,一般会提高应用的效率 吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
4.3 较小堆引起的碎片问题 因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他 会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么 并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置: -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。 -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩
`,49),l=[i];function d(p,t){return e(),s("div",null,l)}const o=a(r,[["render",d],["__file","JVM调优参数.html.vue"]]);export{o as default};
diff --git "a/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-C4jpqxXi.js" "b/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-C4jpqxXi.js"
new file mode 100644
index 00000000..519f020c
--- /dev/null
+++ "b/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-C4jpqxXi.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-16aa42ca","path":"/java/SpringBoot/Spring%20Boot%20Prometheus%E4%BD%BF%E7%94%A8.html","title":"Spring Boot Prometheus使用","lang":"zh-CN","frontmatter":{"description":"Spring Boot Prometheus使用 一、基本原理 Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/SpringBoot/Spring%20Boot%20Prometheus%E4%BD%BF%E7%94%A8.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"Spring Boot Prometheus使用"}],["meta",{"property":"og:description","content":"Spring Boot Prometheus使用 一、基本原理 Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-27T13:52:01.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-27T13:52:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Spring Boot Prometheus使用\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-27T13:52:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"(1)引入库","slug":"_1-引入库","link":"#_1-引入库","children":[]},{"level":2,"title":"(2)修改配置文件","slug":"_2-修改配置文件","link":"#_2-修改配置文件","children":[]},{"level":2,"title":"(3)抓包看一下metrics(可跳过)","slug":"_3-抓包看一下metrics-可跳过","link":"#_3-抓包看一下metrics-可跳过","children":[]}],"git":{"createdTime":1706363521000,"updatedTime":1706363521000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":3.49,"words":1046},"filePathRelative":"java/SpringBoot/Spring Boot Prometheus使用.md","localizedDate":"2024年1月27日","excerpt":" Spring Boot Prometheus使用 \\n 一、基本原理 \\nPrometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。
","autoDesc":true}');export{e as data};
diff --git "a/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-V7I--Ipk.js" "b/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-V7I--Ipk.js"
new file mode 100644
index 00000000..452bd75c
--- /dev/null
+++ "b/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-V7I--Ipk.js"
@@ -0,0 +1,54 @@
+import{_ as p,r as i,o,c,a as n,d as a,b as e,e as t}from"./app-BDpQ7oW_.js";const l={},u=t(` Spring Boot Prometheus使用 一、基本原理 Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。
image-20240127202704612 二、具体过程 Prometheus Daemon负责定时去目标上抓取metrics(指标)数据,每个抓取目标需要暴露一个http服务的接口给它定时抓取。Prometheus支持通过配置文件、文本文件、Zookeeper、Consul、DNS SRV Lookup等方式指定抓取目标。Prometheus采用PULL的方式进行监控,即服务器可以直接通过目标PULL数据或者间接地通过中间网关来Push数据。 Prometheus在本地存储抓取的所有数据,并通过一定规则进行清理和整理数据,并把得到的结果存储到新的时间序列中。 Prometheus通过PromQL和其他API可视化地展示收集的数据。Prometheus支持很多方式的图表可视化,例如Grafana、自带的Promdash以及自身提供的模版引擎等等。Prometheus还提供HTTP API的查询方式,自定义所需要的输出。 PushGateway支持Client主动推送metrics到PushGateway,而Prometheus只是定时去Gateway上抓取数据。 Alertmanager是独立于Prometheus的一个组件,可以支持Prometheus的查询语句,提供十分灵活的报警方式。 三、pull模式(prometheus主动拉取) <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-actuator</artifactId>
+</dependency>
+<dependency>
+ <groupId>io.micrometer</groupId>
+ <artifactId>micrometer-registry-prometheus</artifactId>
+</dependency>
+
management :
+ endpoints :
+ web :
+ exposure :
+ include : prometheus
+ metrics :
+ tags :
+ application : ${ spring.application.name}
+
之后查看/actuator/prometheus就可以看到
image-20240127202722776 `,11),r={href:"https://cloud.tencent.com/document/product/1416/56031%EF%BC%89",target:"_blank",rel:"noopener noreferrer"},d=t(` 四、主动上报(pushgateway) 大部分现实场景中,如果每增加一个服务,都需要开发去配置的话,不仅沟通成本高,也导致因配错而起的运维成本很高,采用主动上报方式比较简单,方便规避一些问题。
(1)引入库 主动上报除了需要引入spring-boot-starter-actuator、micrometer-registry-prometheus,还要引入simpleclient_pushgateway,三个都是必须的,少一个都不行。
< dependency>
+ < groupId> org.springframework.boot</ groupId>
+ < artifactId> spring-boot-starter-actuator</ artifactId>
+ </ dependency>
+ < dependency>
+ < groupId> io.micrometer</ groupId>
+ < artifactId> micrometer-registry-prometheus</ artifactId>
+ </ dependency>
+ < dependency>
+ < groupId> io.prometheus</ groupId>
+ < artifactId> simpleclient_pushgateway</ artifactId>
+ </ dependency>
+
(2)修改配置文件 之后,为了安全考虑,需要把endpoints的所有信息都关闭掉,免得被泄露出去。
management :
+ endpoints :
+
+ enabled-by-default : false
+ metrics :
+ tags :
+
+ application : ${ spring.application.name}
+ export :
+ prometheus :
+ pushgateway :
+ base-url : http: //xxxxx
+ push-rate : 20s
+ job : ${ spring.application.name}
+ enabled : true
+ username : xxxx
+ password : xxx
+ grouping-key :
+ instance : ${ HOSTNAME}
+
最好多看一眼/actuator,确认一下是否已经关闭endpoints
image-20240127202830908 (3)抓包看一下metrics(可跳过) 大致看了下 simpleclient_pushgateway和spring-boot-starter-actuator的源码,并没有对http的请求发起日志,调试的时候都不知道是不是正常上报过去了,只能采取抓包来研究下。
image-20240127202853218 image-20240127202944264 平均间隔5s左右,符合配置文件里的设置。
image-20240127203001776 五、Grafana `,17),g={href:"https://grafana.com/grafana/dashboards/4701%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%94%A8spring",target:"_blank",rel:"noopener noreferrer"},m={href:"https://grafana.com/grafana/dashboards/6756",target:"_blank",rel:"noopener noreferrer"},k=t(`image-20240127203024477 六、自定义监控上报 除了通用的封装好的指标之外,也可以自定义prometheus的监控。对于Spring Boot来说,只要如下代码即可实现:
@Resource
+ private MeterRegistry meterRegistry;
+
+ public void report ( ) {
+ meterRegistry. counter ( "指标" , "tag的名称" , "tag的值" ) . increment ( ) ;
+ }
+
也可以通过抓包来查看,以及在push-gateway上看到。
`,5);function h(v,b){const s=i("ExternalLinkIcon");return o(),c("div",null,[u,n("p",null,[a("腾讯云上面有个prometheus的服务,接入云原生监控还要配置一个Servicemonitor、PodMonitor等,详细的可以访问腾讯云的官方文档("),n("a",r,[a("https://cloud.tencent.com/document/product/1416/56031)"),e(s)])]),d,n("p",null,[a("对于java来说,常用的dashboard是"),n("a",g,[a("https://grafana.com/grafana/dashboards/4701,也可以用spring"),e(s)]),a(" boot的"),n("a",m,[a("https://grafana.com/grafana/dashboards/6756"),e(s)])]),k])}const y=p(l,[["render",h],["__file","Spring Boot Prometheus使用.html.vue"]]);export{y as default};
diff --git a/assets/aop.html-rc4rLz6V.js b/assets/aop.html-rc4rLz6V.js
new file mode 100644
index 00000000..f22d37cd
--- /dev/null
+++ b/assets/aop.html-rc4rLz6V.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-5089f9f3","path":"/java/SpringBoot/aop.html","title":"AOP","lang":"zh-CN","frontmatter":{"description":"AOP 一、概述 在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了。AOP关注的是横向的,而OOP的是纵向。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/SpringBoot/aop.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"AOP"}],["meta",{"property":"og:description","content":"AOP 一、概述 在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了。AOP关注的是横向的,而OOP的是纵向。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T06:53:42.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-30T06:53:42.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"AOP\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T06:53:42.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、概述","slug":"一、概述","link":"#一、概述","children":[{"level":3,"title":"1.1 特点","slug":"_1-1-特点","link":"#_1-1-特点","children":[]},{"level":3,"title":"1.2 AOP概述","slug":"_1-2-aop概述","link":"#_1-2-aop概述","children":[]}]},{"level":2,"title":"二、Spring中的AOP","slug":"二、spring中的aop","link":"#二、spring中的aop","children":[{"level":3,"title":"2.1 AspectJ支持5种类型的通知注解:","slug":"_2-1-aspectj支持5种类型的通知注解","link":"#_2-1-aspectj支持5种类型的通知注解","children":[]},{"level":3,"title":"2.2 Spring提供了4种实现AOP的方式:","slug":"_2-2-spring提供了4种实现aop的方式","link":"#_2-2-spring提供了4种实现aop的方式","children":[]}]},{"level":2,"title":"三、原理概述","slug":"三、原理概述","link":"#三、原理概述","children":[]},{"level":2,"title":"四、使用","slug":"四、使用","link":"#四、使用","children":[]},{"level":2,"title":"参考","slug":"参考","link":"#参考","children":[]}],"git":{"createdTime":1706596625000,"updatedTime":1706597622000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":7.17,"words":2150},"filePathRelative":"java/SpringBoot/aop.md","localizedDate":"2024年1月30日","excerpt":" AOP \\n 一、概述 \\n在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了。AOP关注的是横向的,而OOP的是纵向。
\\n ","autoDesc":true}');export{e as data};
diff --git a/assets/aop.html-vlpDYLuE.js b/assets/aop.html-vlpDYLuE.js
new file mode 100644
index 00000000..14fc9058
--- /dev/null
+++ b/assets/aop.html-vlpDYLuE.js
@@ -0,0 +1,61 @@
+import{_ as t,r as l,o,c as s,a as e,d as n,b as a,e as r}from"./app-BDpQ7oW_.js";const d={},c=r(' AOP 一、概述 在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了。AOP关注的是横向的,而OOP的是纵向。
Spring自2.0版本开始采用@AspectJ注解非常容易的定义一个切面。@AspectJ注解使用AspectJ切点表达式语法进行切点定义,可以通过切点函数、运算符、通配符等高级功能进行切点定义,拥有强大的连接点描述能力。
1.1 特点 AOP(Aspect Oriented Programming)面向切面编程,通过预编译方式和运行期动态代理实现程序功能的横向多模块统一控制的一种技术。AOP是OOP的补充,是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP可以分为静态织入与动态织入,静态织入即在编译前将需织入内容写入目标模块中,这样成本非常高。动态织入则不需要改变目标模块。Spring框架实现了AOP,使用注解配置完成AOP比使用XML配置要更加方便与直观。
1.2 AOP概述 Aspect :一个模块用来关注多个类的切面。在JAVA EE的应用中,事务是AOP的典型例子。Joinpoint(连接点) :所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.Pointcut(切入点) :所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.Advice(通知/增强) :所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)Introduction(引介) :引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.Target(目标对象) :代理的目标对象Weaving(织入) :是指把增强应用到目标对象来创建新的代理对象的过程.spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入.Proxy(代理) :一个类被AOP织入增强后,就产生一个结果代理类Aspect(切面): 是切入点和通知(引介)的结合
二、Spring中的AOP Spring实现AOP主要是由IOC容器来负责生成、管理的。其创建的方式有两种:
默认使用Java动态代理来创建AOP代理; 当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB。高版本的Spring会自动选择是使用动态代理还是CGLIB生成代理内容,当然我们也可以强制使用CGLIB生成代理,那就是aop:config 里面有一个"proxy-target-class"属性,这个属性值如果被设置为true,那么基于类的代理将起作用。 2.1 AspectJ支持5种类型的通知注解: [1] Before:前置通知,在方法执行之前执行 [2] After:后置通知,在方法执行之后执行 [3] AfterRunning:返回通知,在方法返回结果之后执行 [4] AfterThrowing:异常通知,在方法抛出异常之后执行 [5] Around:环绕通知,围绕着方法执行 其中,环绕通知是最常见的一种通知注解,特别是在缓存的使用中,例如:Spring-Cache中的使用,在service的方法中添加一个cache的注解,通过AOP来拦截,如果缓存中已经存在,则直接返回结果,如果没有,再进行service的访问。
2.2 Spring提供了4种实现AOP的方式: 经典的基于代理的AOP @AspectJ注解驱动的切面 纯POJO切面 注入式AspectJ切面 三、原理概述 Spring AOP的实现原理是基于动态织入的动态代理技术,而AspectJ则是静态织入,而动态代理技术又分为Java JDK动态代理和CGLIB动态代理,前者是基于反射技术的实现,后者是基于继承的机制实现。Spring AOP 在使用时机上也进行自动化调整,当有接口时会自动选择JDK动态代理技术,如果没有则选择CGLIB技术,当然Spring AOP的底层实现并没有这么简单,为更简便生成代理对象,Spring AOP 内部实现了一个专注于生成代理对象的工厂类,这样就避免了大量的手动编码,这点也是十分人性化的,但最核心的还是动态代理技术。从性能上来说,Spring AOP 虽然无需特殊编译器协助,但性能上并不优于AspectJ的静态织入,这点了解一下即可。
',19),m={href:"http://blog.csdn.net/javazejian/article/details/56267036/",target:"_blank",rel:"noopener noreferrer"},p=e("h2",{id:"四、使用",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#四、使用","aria-hidden":"true"},"#"),n(" 四、使用")],-1),g=e("br",null,null,-1),h={href:"http://www.cnblogs.com/xrq730/p/7003082.html",target:"_blank",rel:"noopener noreferrer"},u=e("br",null,null,-1),v={href:"http://blog.csdn.net/u014292162/article/details/52504633",target:"_blank",rel:"noopener noreferrer"},b=e("br",null,null,-1),_={href:"http://blog.csdn.net/javazejian/article/details/56267036/",target:"_blank",rel:"noopener noreferrer"},f={href:"http://www.wenzhihuai.com",target:"_blank",rel:"noopener noreferrer"},A=r(` 4.1 在Spring MVC中开启AOP
+ < aop: aspectj-autoproxy/>
+
4.2 定义一个切面 /**
+ * 可以使用 @Order 注解指定切面的优先级, 值越小优先级越高
+ */
+@Order(2)
+@Aspect
+@Component
+public class TimeInterceptor {
+}
+
4.3 声明一个切入点 @Pointcut("execution(* com.myblog.service.impl.BlogServiceImpl.*(..))")
+ public void pointcut() {
+ }
+
4.4 声明一个前置切点 @Before("pointcut()")
+ public void before(JoinPoint jp) {
+ logger.info(jp.getSignature().getName());
+ logger.info("----------前置通知----------");
+ }
+
4.5 声明一个后置切点 @After("pointcut()")
+ public void after(JoinPoint jp) {
+ logger.info("----------最终通知----------");
+ }
+
+
4.6 环绕通知 这里,特别要注意的是要抛出Throwable异常,否则方法执行报错的时候无法处理也无法查看
@Around("execution(* (com.myblog.service.impl.*+&&!com.myblog.service.impl.AsyncServiceImpl).*(..))")
+ public Object timeAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ Object obj = null;
+ Object[] args = joinPoint.getArgs();
+ long startTime = System.currentTimeMillis();
+ obj = joinPoint.proceed(args);
+ // 获取执行的方法名
+ long endTime = System.currentTimeMillis();
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
+ // 打印耗时的信息
+ this.printExecTime(methodName, startTime, endTime);
+ return obj;
+ }
+
4.7 返回结果通知 @AfterReturning(pointcut = "execution(* com.myblog.service.impl.BlogServiceImpl.*(..))", returning = "result")
+ public void afterReturning(JoinPoint jp, Object result) {
+ logger.info(jp.getSignature().getName());
+ logger.info("结果是:" + result);
+ logger.info("----------返回结果----------");
+ }
+
4.8 异常后通知 @AfterThrowing(pointcut = "execution(* com.myblog.service.impl.BlogServiceImpl.*(..))", throwing = "exp")
+ public void afterThrowing(JoinPoint jp, Exception exp) {
+ logger.info(jp.getSignature().getName());
+ logger.info("异常消息:" + exp.getMessage());
+ logger.info("----------异常通知----------");
+ }
+
4.9 结果 2018-02-04 17:22:46.287 [http-nio-9090-exec-3] INFO com.myblog.aspect.TimeInterceptor - getAllBlog
+2018-02-04 17:22:46.288 [http-nio-9090-exec-3] INFO com.myblog.aspect.TimeInterceptor - ----------前置通知----------
+2018-02-04 17:22:46.288 [http-nio-9090-exec-3] DEBUG com.myblog.dao.BlogMapper - Cache Hit Ratio [com.myblog.dao.BlogMapper]: 0.6
+2018-02-04 17:22:46.288 [http-nio-9090-exec-3] DEBUG com.myblog.dao.BlogMapper - Cache Hit Ratio [com.myblog.dao.BlogMapper]: 0.6666666666666666
+2018-02-04 17:22:46.289 [http-nio-9090-exec-3] INFO com.myblog.cache.EhRedisCache - ===========================Cache L1 (ehcache)
+2018-02-04 17:22:46.292 [http-nio-9090-exec-3] INFO com.myblog.aspect.TimeInterceptor - com.myblog.service.IBlogService.getAllBlog method take time: **5 ms**
+2018-02-04 17:22:46.292 [http-nio-9090-exec-3] INFO com.myblog.aspect.TimeInterceptor - ----------最终通知----------
+2018-02-04 17:22:46.292 [http-nio-9090-exec-3] INFO com.myblog.aspect.TimeInterceptor - getAllBlog
+2018-02-04 17:22:46.292 [http-nio-9090-exec-3] INFO com.myblog.aspect.TimeInterceptor - 结果是:Page{count=true, pageNum=1, pageSize=15, startRow=0, endRow=15, total=462, pages=31, countSignal=false, orderBy='null', orderByOnly=false, reasonable=true, pageSizeZero=true}
+2018-02-04 17:22:46.292 [http-nio-9090-exec-3] INFO com.myblog.aspect.TimeInterceptor - ----------返回结果----------
+2018-02-04 17:22:46.292 [http-nio-9090-exec-3] INFO com.myblog.cache.EhRedisCache - ===========================Cache L1 (ehcache) :{myCache}{com.myblog.service.impl.BlogServiceImpl.getBanner}={[ key = com.myblog.service.impl.BlogServiceImpl.getBanner, value=[com.myblog.model.Blog@2a5de6bc, com.myblog.model.Blog@544159b3, com.myblog.model.Blog@1de1421c, com.myblog.model.Blog@6dbb79bb, com.myblog.model.Blog@28160ab6], version=1, hitCount=2, CreationTime = 1517736161430, LastAccessTime = 1517736166292 ]}
+
由结果可以看到,整个方法的执行耗时5ms,算是客观吧,如果太大则要对其进行优化。
主要的源码在这:
`,21),x={href:"https://github.com/Zephery/newblog/blob/master/src/main/java/com/myblog/aspect/TimeInterceptor.java",target:"_blank",rel:"noopener noreferrer"},O=e("br",null,null,-1),P={href:"https://github.com/Zephery/newblog",target:"_blank",rel:"noopener noreferrer"},y=e("h2",{id:"参考",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#参考","aria-hidden":"true"},"#"),n(" 参考")],-1),S={href:"http://www.cnblogs.com/best/p/5736422.html",target:"_blank",rel:"noopener noreferrer"},I={href:"https://www.cnblogs.com/wang-meng/p/5641549.html#top",target:"_blank",rel:"noopener noreferrer"},B={href:"https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html",target:"_blank",rel:"noopener noreferrer"};function q(j,w){const i=l("ExternalLinkIcon");return o(),s("div",null,[c,e("p",null,[n("具体的原理请看"),e("a",m,[n("Spring AOP"),a(i)])]),p,e("p",null,[n("网上看别人写了很多入门的例子,自己就不再阐述了,毕竟自己还是菜,下面是关于AOP入门的资料:"),g,e("a",h,[n("我们为什么要使用AOP?"),a(i)]),u,e("a",v,[n("Spring中AOP的实现"),a(i)]),b,e("a",_,[n("关于AOP"),a(i)])]),e("p",null,[n("下面是自己在"),e("a",f,[n("个人网站"),a(i)]),n("中的使用,主要是用来统计一个方法的执行消耗了多少时间,需要引入aopalliance.jar、aspectj.weaver.jar 和 spring-aspects.jar的包。")]),A,e("p",null,[e("a",x,[n("TimeInterceptor"),a(i)])]),e("p",null,[n("也可以下载我的博客源码参考参考:"),O,e("a",P,[n("newblog"),a(i)])]),y,e("ol",null,[e("li",null,[e("a",S,[n("Spring学习总结——Spring实现AOP的多种方式"),a(i)])]),e("li",null,[e("a",I,[n("Spring AOP基础入门总结一"),a(i)])]),e("li",null,[e("a",B,[n("Spring AOP官方"),a(i)])])])])}const k=t(d,[["render",q],["__file","aop.html.vue"]]);export{k as default};
diff --git a/assets/app-BDpQ7oW_.js b/assets/app-BDpQ7oW_.js
new file mode 100644
index 00000000..a258aadb
--- /dev/null
+++ b/assets/app-BDpQ7oW_.js
@@ -0,0 +1,247 @@
+/**
+* @vue/shared v3.4.15
+* (c) 2018-present Yuxi (Evan) You and Vue contributors
+* @license MIT
+**/function sl(e,t){const n=new Set(e.split(","));return t?r=>n.has(r.toLowerCase()):r=>n.has(r)}const Ae={},un=[],Xe=()=>{},Vu=()=>!1,Zn=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),cl=e=>e.startsWith("onUpdate:"),Ie=Object.assign,ul=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},$u=Object.prototype.hasOwnProperty,de=(e,t)=>$u.call(e,t),Q=Array.isArray,Dn=e=>Jr(e)==="[object Map]",ju=e=>Jr(e)==="[object Set]",re=e=>typeof e=="function",oe=e=>typeof e=="string",Wr=e=>typeof e=="symbol",xe=e=>e!==null&&typeof e=="object",Ti=e=>(xe(e)||re(e))&&re(e.then)&&re(e.catch),Nu=Object.prototype.toString,Jr=e=>Nu.call(e),zu=e=>Jr(e).slice(8,-1),Hu=e=>Jr(e)==="[object Object]",dl=e=>oe(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Rn=sl(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Yr=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},qu=/-(\w)/g,Ge=Yr(e=>e.replace(qu,(t,n)=>n?n.toUpperCase():"")),Gu=/\B([A-Z])/g,wn=Yr(e=>e.replace(Gu,"-$1").toLowerCase()),An=Yr(e=>e.charAt(0).toUpperCase()+e.slice(1)),ma=Yr(e=>e?`on${An(e)}`:""),Ft=(e,t)=>!Object.is(e,t),ga=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},Uu=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Ku=e=>{const t=oe(e)?Number(e):NaN;return isNaN(t)?e:t};let ao;const Bi=()=>ao||(ao=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function fl(e){if(Q(e)){const t={};for(let n=0;n{if(n){const r=n.split(Ju);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function pl(e){let t="";if(oe(e))t=e;else if(Q(e))for(let n=0;n=2))break}this._dirtyLevel<2&&(this._dirtyLevel=0),Qt()}return this._dirtyLevel>=2}set dirty(t){this._dirtyLevel=t?2:0}run(){if(this._dirtyLevel=0,!this.active)return this.fn();let t=Rt,n=Ut;try{return Rt=!0,Ut=this,this._runnings++,lo(this),this.fn()}finally{oo(this),this._runnings--,Ut=n,Rt=t}}stop(){var t;this.active&&(lo(this),oo(this),(t=this.onStop)==null||t.call(this),this.active=!1)}}function rd(e){return e.value}function lo(e){e._trackId++,e._depsLength=0}function oo(e){if(e.deps&&e.deps.length>e._depsLength){for(let t=e._depsLength;t{const n=new Map;return n.cleanup=e,n.computed=t,n},Rr=new WeakMap,Kt=Symbol(""),ja=Symbol("");function Ue(e,t,n){if(Rt&&Ut){let r=Rr.get(e);r||Rr.set(e,r=new Map);let a=r.get(n);a||r.set(n,a=Fi(()=>r.delete(n))),Di(Ut,a)}}function kt(e,t,n,r,a,l){const o=Rr.get(e);if(!o)return;let s=[];if(t==="clear")s=[...o.values()];else if(n==="length"&&Q(e)){const c=Number(r);o.forEach((u,d)=>{(d==="length"||!Wr(d)&&d>=c)&&s.push(u)})}else switch(n!==void 0&&s.push(o.get(n)),t){case"add":Q(e)?dl(n)&&s.push(o.get("length")):(s.push(o.get(Kt)),Dn(e)&&s.push(o.get(ja)));break;case"delete":Q(e)||(s.push(o.get(Kt)),Dn(e)&&s.push(o.get(ja)));break;case"set":Dn(e)&&s.push(o.get(Kt));break}vl();for(const c of s)c&&Ri(c,2);ml()}function ad(e,t){var n;return(n=Rr.get(e))==null?void 0:n.get(t)}const ld=sl("__proto__,__v_isRef,__isVue"),Vi=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Wr)),io=od();function od(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=ce(this);for(let l=0,o=this.length;l{e[t]=function(...n){Zt(),vl();const r=ce(this)[t].apply(this,n);return ml(),Qt(),r}}),e}function id(e){const t=ce(this);return Ue(t,"has",e),t.hasOwnProperty(e)}class $i{constructor(t=!1,n=!1){this._isReadonly=t,this._shallow=n}get(t,n,r){const a=this._isReadonly,l=this._shallow;if(n==="__v_isReactive")return!a;if(n==="__v_isReadonly")return a;if(n==="__v_isShallow")return l;if(n==="__v_raw")return r===(a?l?yd:Hi:l?zi:Ni).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(r)?t:void 0;const o=Q(t);if(!a){if(o&&de(io,n))return Reflect.get(io,n,r);if(n==="hasOwnProperty")return id}const s=Reflect.get(t,n,r);return(Wr(n)?Vi.has(n):ld(n))||(a||Ue(t,"get",n),l)?s:De(s)?o&&dl(n)?s:s.value:xe(s)?a?Xt(s):Qn(s):s}}class ji extends $i{constructor(t=!1){super(!1,t)}set(t,n,r,a){let l=t[n];if(!this._shallow){const c=vn(l);if(!Mr(r)&&!vn(r)&&(l=ce(l),r=ce(r)),!Q(t)&&De(l)&&!De(r))return c?!1:(l.value=r,!0)}const o=Q(t)&&dl(n)?Number(n)e,Zr=e=>Reflect.getPrototypeOf(e);function gr(e,t,n=!1,r=!1){e=e.__v_raw;const a=ce(e),l=ce(t);n||(Ft(t,l)&&Ue(a,"get",t),Ue(a,"get",l));const{has:o}=Zr(a),s=r?gl:n?yl:Hn;if(o.call(a,t))return s(e.get(t));if(o.call(a,l))return s(e.get(l));e!==a&&e.get(t)}function br(e,t=!1){const n=this.__v_raw,r=ce(n),a=ce(e);return t||(Ft(e,a)&&Ue(r,"has",e),Ue(r,"has",a)),e===a?n.has(e):n.has(e)||n.has(a)}function _r(e,t=!1){return e=e.__v_raw,!t&&Ue(ce(e),"iterate",Kt),Reflect.get(e,"size",e)}function so(e){e=ce(e);const t=ce(this);return Zr(t).has.call(t,e)||(t.add(e),kt(t,"add",e,e)),this}function co(e,t){t=ce(t);const n=ce(this),{has:r,get:a}=Zr(n);let l=r.call(n,e);l||(e=ce(e),l=r.call(n,e));const o=a.call(n,e);return n.set(e,t),l?Ft(t,o)&&kt(n,"set",e,t):kt(n,"add",e,t),this}function uo(e){const t=ce(this),{has:n,get:r}=Zr(t);let a=n.call(t,e);a||(e=ce(e),a=n.call(t,e)),r&&r.call(t,e);const l=t.delete(e);return a&&kt(t,"delete",e,void 0),l}function fo(){const e=ce(this),t=e.size!==0,n=e.clear();return t&&kt(e,"clear",void 0,void 0),n}function yr(e,t){return function(r,a){const l=this,o=l.__v_raw,s=ce(o),c=t?gl:e?yl:Hn;return!e&&Ue(s,"iterate",Kt),o.forEach((u,d)=>r.call(a,c(u),c(d),l))}}function Er(e,t,n){return function(...r){const a=this.__v_raw,l=ce(a),o=Dn(l),s=e==="entries"||e===Symbol.iterator&&o,c=e==="keys"&&o,u=a[e](...r),d=n?gl:t?yl:Hn;return!t&&Ue(l,"iterate",c?ja:Kt),{next(){const{value:f,done:p}=u.next();return p?{value:f,done:p}:{value:s?[d(f[0]),d(f[1])]:d(f),done:p}},[Symbol.iterator](){return this}}}}function xt(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function fd(){const e={get(l){return gr(this,l)},get size(){return _r(this)},has:br,add:so,set:co,delete:uo,clear:fo,forEach:yr(!1,!1)},t={get(l){return gr(this,l,!1,!0)},get size(){return _r(this)},has:br,add:so,set:co,delete:uo,clear:fo,forEach:yr(!1,!0)},n={get(l){return gr(this,l,!0)},get size(){return _r(this,!0)},has(l){return br.call(this,l,!0)},add:xt("add"),set:xt("set"),delete:xt("delete"),clear:xt("clear"),forEach:yr(!0,!1)},r={get(l){return gr(this,l,!0,!0)},get size(){return _r(this,!0)},has(l){return br.call(this,l,!0)},add:xt("add"),set:xt("set"),delete:xt("delete"),clear:xt("clear"),forEach:yr(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(l=>{e[l]=Er(l,!1,!1),n[l]=Er(l,!0,!1),t[l]=Er(l,!1,!0),r[l]=Er(l,!0,!0)}),[e,n,t,r]}const[pd,hd,vd,md]=fd();function bl(e,t){const n=t?e?md:vd:e?hd:pd;return(r,a,l)=>a==="__v_isReactive"?!e:a==="__v_isReadonly"?e:a==="__v_raw"?r:Reflect.get(de(n,a)&&a in r?n:r,a,l)}const gd={get:bl(!1,!1)},bd={get:bl(!1,!0)},_d={get:bl(!0,!1)},Ni=new WeakMap,zi=new WeakMap,Hi=new WeakMap,yd=new WeakMap;function Ed(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function kd(e){return e.__v_skip||!Object.isExtensible(e)?0:Ed(zu(e))}function Qn(e){return vn(e)?e:_l(e,!1,cd,gd,Ni)}function qi(e){return _l(e,!1,dd,bd,zi)}function Xt(e){return _l(e,!0,ud,_d,Hi)}function _l(e,t,n,r,a){if(!xe(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const l=a.get(e);if(l)return l;const o=kd(e);if(o===0)return e;const s=new Proxy(e,o===2?r:n);return a.set(e,s),s}function dn(e){return vn(e)?dn(e.__v_raw):!!(e&&e.__v_isReactive)}function vn(e){return!!(e&&e.__v_isReadonly)}function Mr(e){return!!(e&&e.__v_isShallow)}function Gi(e){return dn(e)||vn(e)}function ce(e){const t=e&&e.__v_raw;return t?ce(t):e}function Ui(e){return Dr(e,"__v_skip",!0),e}const Hn=e=>xe(e)?Qn(e):e,yl=e=>xe(e)?Xt(e):e;class Ki{constructor(t,n,r,a){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this.effect=new hl(()=>t(this._value),()=>Mn(this,1),()=>this.dep&&Mi(this.dep)),this.effect.computed=this,this.effect.active=this._cacheable=!a,this.__v_isReadonly=r}get value(){const t=ce(this);return(!t._cacheable||t.effect.dirty)&&Ft(t._value,t._value=t.effect.run())&&Mn(t,2),El(t),t.effect._dirtyLevel>=1&&Mn(t,1),t._value}set value(t){this._setter(t)}get _dirty(){return this.effect.dirty}set _dirty(t){this.effect.dirty=t}}function wd(e,t,n=!1){let r,a;const l=re(e);return l?(r=e,a=Xe):(r=e.get,a=e.set),new Ki(r,a,l||!a,n)}function El(e){Rt&&Ut&&(e=ce(e),Di(Ut,e.dep||(e.dep=Fi(()=>e.dep=void 0,e instanceof Ki?e:void 0))))}function Mn(e,t=2,n){e=ce(e);const r=e.dep;r&&Ri(r,t)}function De(e){return!!(e&&e.__v_isRef===!0)}function X(e){return Wi(e,!1)}function mt(e){return Wi(e,!0)}function Wi(e,t){return De(e)?e:new Ad(e,t)}class Ad{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:ce(t),this._value=n?t:Hn(t)}get value(){return El(this),this._value}set value(t){const n=this.__v_isShallow||Mr(t)||vn(t);t=n?t:ce(t),Ft(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:Hn(t),Mn(this,2))}}function Wt(e){return De(e)?e.value:e}const Ld={get:(e,t,n)=>Wt(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const a=e[t];return De(a)&&!De(n)?(a.value=n,!0):Reflect.set(e,t,n,r)}};function Ji(e){return dn(e)?e:new Proxy(e,Ld)}class xd{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:n,set:r}=t(()=>El(this),()=>Mn(this));this._get=n,this._set=r}get value(){return this._get()}set value(t){this._set(t)}}function Yi(e){return new xd(e)}function Sd(e){const t=Q(e)?new Array(e.length):{};for(const n in e)t[n]=Zi(e,n);return t}class Td{constructor(t,n,r){this._object=t,this._key=n,this._defaultValue=r,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return ad(ce(this._object),this._key)}}class Bd{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function Ln(e,t,n){return De(e)?e:re(e)?new Bd(e):xe(e)&&arguments.length>1?Zi(e,t,n):X(e)}function Zi(e,t,n){const r=e[t];return De(r)?r:new Td(e,t,n)}/**
+* @vue/runtime-core v3.4.15
+* (c) 2018-present Yuxi (Evan) You and Vue contributors
+* @license MIT
+**/function Mt(e,t,n,r){let a;try{a=r?e(...r):e()}catch(l){Xn(l,t,n)}return a}function tt(e,t,n,r){if(re(e)){const l=Mt(e,t,n,r);return l&&Ti(l)&&l.catch(o=>{Xn(o,t,n)}),l}const a=[];for(let l=0;l>>1,a=Fe[r],l=Gn(a);lpt&&Fe.splice(t,1)}function Od(e){Q(e)?fn.push(...e):(!Ct||!Ct.includes(e,e.allowRecurse?Ht+1:Ht))&&fn.push(e),Xi()}function po(e,t,n=qn?pt+1:0){for(;nGn(n)-Gn(r));if(fn.length=0,Ct){Ct.push(...t);return}for(Ct=t,Ht=0;Hte.id==null?1/0:e.id,Dd=(e,t)=>{const n=Gn(e)-Gn(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function es(e){Na=!1,qn=!0,Fe.sort(Dd);try{for(pt=0;ptoe(h)?h.trim():h)),f&&(a=n.map(Uu))}let s,c=r[s=ma(t)]||r[s=ma(Ge(t))];!c&&l&&(c=r[s=ma(wn(t))]),c&&tt(c,e,6,a);const u=r[s+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[s])return;e.emitted[s]=!0,tt(u,e,6,a)}}function ts(e,t,n=!1){const r=t.emitsCache,a=r.get(e);if(a!==void 0)return a;const l=e.emits;let o={},s=!1;if(!re(e)){const c=u=>{const d=ts(u,t,!0);d&&(s=!0,Ie(o,d))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!l&&!s?(xe(e)&&r.set(e,null),null):(Q(l)?l.forEach(c=>o[c]=null):Ie(o,l),xe(e)&&r.set(e,o),o)}function Xr(e,t){return!e||!Zn(t)?!1:(t=t.slice(2).replace(/Once$/,""),de(e,t[0].toLowerCase()+t.slice(1))||de(e,wn(t))||de(e,t))}let et=null,ea=null;function Vr(e){const t=et;return et=e,ea=e&&e.type.__scopeId||null,t}function Md(e){ea=e}function Fd(){ea=null}function za(e,t=et,n){if(!t||e._n)return e;const r=(...a)=>{r._d&&Lo(-1);const l=Vr(t);let o;try{o=e(...a)}finally{Vr(l),r._d&&Lo(1)}return o};return r._n=!0,r._c=!0,r._d=!0,r}function ba(e){const{type:t,vnode:n,proxy:r,withProxy:a,props:l,propsOptions:[o],slots:s,attrs:c,emit:u,render:d,renderCache:f,data:p,setupState:h,ctx:g,inheritAttrs:w}=e;let k,b;const x=Vr(e);try{if(n.shapeFlag&4){const S=a||r,D=S;k=lt(d.call(D,S,f,l,h,p,g)),b=c}else{const S=t;k=lt(S.length>1?S(l,{attrs:c,slots:s,emit:u}):S(l,null)),b=t.props?c:Vd(c)}}catch(S){jn.length=0,Xn(S,e,1),k=Be(ht)}let _=k;if(b&&w!==!1){const S=Object.keys(b),{shapeFlag:D}=_;S.length&&D&7&&(o&&S.some(cl)&&(b=$d(b,o)),_=Vt(_,b))}return n.dirs&&(_=Vt(_),_.dirs=_.dirs?_.dirs.concat(n.dirs):n.dirs),n.transition&&(_.transition=n.transition),k=_,Vr(x),k}const Vd=e=>{let t;for(const n in e)(n==="class"||n==="style"||Zn(n))&&((t||(t={}))[n]=e[n]);return t},$d=(e,t)=>{const n={};for(const r in e)(!cl(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function jd(e,t,n){const{props:r,children:a,component:l}=e,{props:o,children:s,patchFlag:c}=t,u=l.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return r?ho(r,o,u):!!o;if(c&8){const d=t.dynamicProps;for(let f=0;fe.__isSuspense;function rs(e,t){t&&t.pendingBranch?Q(e)?t.effects.push(...e):t.effects.push(e):Od(e)}const Gd=Symbol.for("v-scx"),Ud=()=>he(Gd);function wl(e,t){return Al(e,null,t)}const kr={};function ye(e,t,n){return Al(e,t,n)}function Al(e,t,{immediate:n,deep:r,flush:a,once:l,onTrack:o,onTrigger:s}=Ae){if(t&&l){const L=t;t=(...U)=>{L(...U),D()}}const c=Oe,u=L=>r===!0?L:sn(L,r===!1?1:void 0);let d,f=!1,p=!1;if(De(e)?(d=()=>e.value,f=Mr(e)):dn(e)?(d=()=>u(e),f=!0):Q(e)?(p=!0,f=e.some(L=>dn(L)||Mr(L)),d=()=>e.map(L=>{if(De(L))return L.value;if(dn(L))return u(L);if(re(L))return Mt(L,c,2)})):re(e)?t?d=()=>Mt(e,c,2):d=()=>(h&&h(),tt(e,c,3,[g])):d=Xe,t&&r){const L=d;d=()=>sn(L())}let h,g=L=>{h=_.onStop=()=>{Mt(L,c,4),h=_.onStop=void 0}},w;if(nr)if(g=Xe,t?n&&tt(t,c,3,[d(),p?[]:void 0,g]):d(),a==="sync"){const L=Ud();w=L.__watcherHandles||(L.__watcherHandles=[])}else return Xe;let k=p?new Array(e.length).fill(kr):kr;const b=()=>{if(!(!_.active||!_.dirty))if(t){const L=_.run();(r||f||(p?L.some((U,$)=>Ft(U,k[$])):Ft(L,k)))&&(h&&h(),tt(t,c,3,[L,k===kr?void 0:p&&k[0]===kr?[]:k,g]),k=L)}else _.run()};b.allowRecurse=!!t;let x;a==="sync"?x=b:a==="post"?x=()=>ze(b,c&&c.suspense):(b.pre=!0,c&&(b.id=c.uid),x=()=>Qr(b));const _=new hl(d,Xe,x),S=Ii(),D=()=>{_.stop(),S&&ul(S.effects,_)};return t?n?b():k=_.run():a==="post"?ze(_.run.bind(_),c&&c.suspense):_.run(),w&&w.push(D),D}function Kd(e,t,n){const r=this.proxy,a=oe(e)?e.includes(".")?as(r,e):()=>r[e]:e.bind(r,r);let l;re(t)?l=t:(l=t.handler,n=t);const o=tr(this),s=Al(a,l.bind(r),n);return o(),s}function as(e,t){const n=t.split(".");return()=>{let r=e;for(let a=0;a0){if(n>=t)return e;n++}if(r=r||new Set,r.has(e))return e;if(r.add(e),De(e))sn(e.value,t,n,r);else if(Q(e))for(let a=0;a{sn(a,t,n,r)});else if(Hu(e))for(const a in e)sn(e[a],t,n,r);return e}function ft(e,t,n,r){const a=e.dirs,l=t&&t.dirs;for(let o=0;o{e.isMounted=!0}),na(()=>{e.isUnmounting=!0}),e}const Ze=[Function,Array],os={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Ze,onEnter:Ze,onAfterEnter:Ze,onEnterCancelled:Ze,onBeforeLeave:Ze,onLeave:Ze,onAfterLeave:Ze,onLeaveCancelled:Ze,onBeforeAppear:Ze,onAppear:Ze,onAfterAppear:Ze,onAppearCancelled:Ze},Wd={name:"BaseTransition",props:os,setup(e,{slots:t}){const n=tn(),r=ls();let a;return()=>{const l=t.default&&Ll(t.default(),!0);if(!l||!l.length)return;let o=l[0];if(l.length>1){for(const w of l)if(w.type!==ht){o=w;break}}const s=ce(e),{mode:c}=s;if(r.isLeaving)return _a(o);const u=mo(o);if(!u)return _a(o);const d=Un(u,s,r,n);Kn(u,d);const f=n.subTree,p=f&&mo(f);let h=!1;const{getTransitionKey:g}=u.type;if(g){const w=g();a===void 0?a=w:w!==a&&(a=w,h=!0)}if(p&&p.type!==ht&&(!qt(u,p)||h)){const w=Un(p,s,r,n);if(Kn(p,w),c==="out-in")return r.isLeaving=!0,w.afterLeave=()=>{r.isLeaving=!1,n.update.active!==!1&&(n.effect.dirty=!0,n.update())},_a(o);c==="in-out"&&u.type!==ht&&(w.delayLeave=(k,b,x)=>{const _=is(r,p);_[String(p.key)]=p,k[It]=()=>{b(),k[It]=void 0,delete d.delayedLeave},d.delayedLeave=x})}return o}}},Jd=Wd;function is(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function Un(e,t,n,r){const{appear:a,mode:l,persisted:o=!1,onBeforeEnter:s,onEnter:c,onAfterEnter:u,onEnterCancelled:d,onBeforeLeave:f,onLeave:p,onAfterLeave:h,onLeaveCancelled:g,onBeforeAppear:w,onAppear:k,onAfterAppear:b,onAppearCancelled:x}=t,_=String(e.key),S=is(n,e),D=($,R)=>{$&&tt($,r,9,R)},L=($,R)=>{const j=R[1];D($,R),Q($)?$.every(ne=>ne.length<=1)&&j():$.length<=1&&j()},U={mode:l,persisted:o,beforeEnter($){let R=s;if(!n.isMounted)if(a)R=w||s;else return;$[It]&&$[It](!0);const j=S[_];j&&qt(e,j)&&j.el[It]&&j.el[It](),D(R,[$])},enter($){let R=c,j=u,ne=d;if(!n.isMounted)if(a)R=k||c,j=b||u,ne=x||d;else return;let N=!1;const ee=$[wr]=Se=>{N||(N=!0,Se?D(ne,[$]):D(j,[$]),U.delayedLeave&&U.delayedLeave(),$[wr]=void 0)};R?L(R,[$,ee]):ee()},leave($,R){const j=String(e.key);if($[wr]&&$[wr](!0),n.isUnmounting)return R();D(f,[$]);let ne=!1;const N=$[It]=ee=>{ne||(ne=!0,R(),ee?D(g,[$]):D(h,[$]),$[It]=void 0,S[j]===e&&delete S[j])};S[j]=e,p?L(p,[$,N]):N()},clone($){return Un($,t,n,r)}};return U}function _a(e){if(er(e))return e=Vt(e),e.children=null,e}function mo(e){return er(e)?e.children?e.children[0]:void 0:e}function Kn(e,t){e.shapeFlag&6&&e.component?Kn(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Ll(e,t=!1,n){let r=[],a=0;for(let l=0;l1)for(let l=0;l!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function F(e){re(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:a=200,timeout:l,suspensible:o=!0,onError:s}=e;let c=null,u,d=0;const f=()=>(d++,c=null,p()),p=()=>{let h;return c||(h=c=t().catch(g=>{if(g=g instanceof Error?g:new Error(String(g)),s)return new Promise((w,k)=>{s(g,()=>w(f()),()=>k(g),d+1)});throw g}).then(g=>h!==c&&c?c:(g&&(g.__esModule||g[Symbol.toStringTag]==="Module")&&(g=g.default),u=g,g)))};return V({name:"AsyncComponentWrapper",__asyncLoader:p,get __asyncResolved(){return u},setup(){const h=Oe;if(u)return()=>ya(u,h);const g=x=>{c=null,Xn(x,h,13,!r)};if(o&&h.suspense||nr)return p().then(x=>()=>ya(x,h)).catch(x=>(g(x),()=>r?Be(r,{error:x}):null));const w=X(!1),k=X(),b=X(!!a);return a&&setTimeout(()=>{b.value=!1},a),l!=null&&setTimeout(()=>{if(!w.value&&!k.value){const x=new Error(`Async component timed out after ${l}ms.`);g(x),k.value=x}},l),p().then(()=>{w.value=!0,h.parent&&er(h.parent.vnode)&&(h.parent.effect.dirty=!0,Qr(h.parent.update))}).catch(x=>{g(x),k.value=x}),()=>{if(w.value&&u)return ya(u,h);if(k.value&&r)return Be(r,{error:k.value});if(n&&!b.value)return Be(n)}}})}function ya(e,t){const{ref:n,props:r,children:a,ce:l}=t.vnode,o=Be(e,r,a);return o.ref=n,o.ce=l,delete t.vnode.ce,o}const er=e=>e.type.__isKeepAlive;function Yd(e,t){ss(e,"a",t)}function Zd(e,t){ss(e,"da",t)}function ss(e,t,n=Oe){const r=e.__wdc||(e.__wdc=()=>{let a=n;for(;a;){if(a.isDeactivated)return;a=a.parent}return e()});if(ta(t,r,n),n){let a=n.parent;for(;a&&a.parent;)er(a.parent.vnode)&&Qd(r,t,n,a),a=a.parent}}function Qd(e,t,n,r){const a=ta(t,e,r,!0);ra(()=>{ul(r[t],a)},n)}function ta(e,t,n=Oe,r=!1){if(n){const a=n[e]||(n[e]=[]),l=t.__weh||(t.__weh=(...o)=>{if(n.isUnmounted)return;Zt();const s=tr(n),c=tt(t,n,e,o);return s(),Qt(),c});return r?a.unshift(l):a.push(l),l}}const At=e=>(t,n=Oe)=>(!nr||e==="sp")&&ta(e,(...r)=>t(...r),n),Xd=At("bm"),Ee=At("m"),e1=At("bu"),cs=At("u"),na=At("bum"),ra=At("um"),t1=At("sp"),n1=At("rtg"),r1=At("rtc");function a1(e,t=Oe){ta("ec",e,t)}const Ha=e=>e?ws(e)?Bl(e)||e.proxy:Ha(e.parent):null,Vn=Ie(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Ha(e.parent),$root:e=>Ha(e.root),$emit:e=>e.emit,$options:e=>xl(e),$forceUpdate:e=>e.f||(e.f=()=>{e.effect.dirty=!0,Qr(e.update)}),$nextTick:e=>e.n||(e.n=en.bind(e.proxy)),$watch:e=>Kd.bind(e)}),Ea=(e,t)=>e!==Ae&&!e.__isScriptSetup&&de(e,t),l1={get({_:e},t){const{ctx:n,setupState:r,data:a,props:l,accessCache:o,type:s,appContext:c}=e;let u;if(t[0]!=="$"){const h=o[t];if(h!==void 0)switch(h){case 1:return r[t];case 2:return a[t];case 4:return n[t];case 3:return l[t]}else{if(Ea(r,t))return o[t]=1,r[t];if(a!==Ae&&de(a,t))return o[t]=2,a[t];if((u=e.propsOptions[0])&&de(u,t))return o[t]=3,l[t];if(n!==Ae&&de(n,t))return o[t]=4,n[t];qa&&(o[t]=0)}}const d=Vn[t];let f,p;if(d)return t==="$attrs"&&Ue(e,"get",t),d(e);if((f=s.__cssModules)&&(f=f[t]))return f;if(n!==Ae&&de(n,t))return o[t]=4,n[t];if(p=c.config.globalProperties,de(p,t))return p[t]},set({_:e},t,n){const{data:r,setupState:a,ctx:l}=e;return Ea(a,t)?(a[t]=n,!0):r!==Ae&&de(r,t)?(r[t]=n,!0):de(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(l[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:a,propsOptions:l}},o){let s;return!!n[o]||e!==Ae&&de(e,o)||Ea(t,o)||(s=l[0])&&de(s,o)||de(r,o)||de(Vn,o)||de(a.config.globalProperties,o)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:de(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function go(e){return Q(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let qa=!0;function o1(e){const t=xl(e),n=e.proxy,r=e.ctx;qa=!1,t.beforeCreate&&bo(t.beforeCreate,e,"bc");const{data:a,computed:l,methods:o,watch:s,provide:c,inject:u,created:d,beforeMount:f,mounted:p,beforeUpdate:h,updated:g,activated:w,deactivated:k,beforeDestroy:b,beforeUnmount:x,destroyed:_,unmounted:S,render:D,renderTracked:L,renderTriggered:U,errorCaptured:$,serverPrefetch:R,expose:j,inheritAttrs:ne,components:N,directives:ee,filters:Se}=t;if(u&&i1(u,r,null),o)for(const ae in o){const W=o[ae];re(W)&&(r[ae]=W.bind(n))}if(a){const ae=a.call(n,n);xe(ae)&&(e.data=Qn(ae))}if(qa=!0,l)for(const ae in l){const W=l[ae],rt=re(W)?W.bind(n,n):re(W.get)?W.get.bind(n,n):Xe,Lt=!re(W)&&re(W.set)?W.set.bind(n):Xe,ut=E({get:rt,set:Lt});Object.defineProperty(r,ae,{enumerable:!0,configurable:!0,get:()=>ut.value,set:Ne=>ut.value=Ne})}if(s)for(const ae in s)us(s[ae],r,n,ae);if(c){const ae=re(c)?c.call(n):c;Reflect.ownKeys(ae).forEach(W=>{it(W,ae[W])})}d&&bo(d,e,"c");function J(ae,W){Q(W)?W.forEach(rt=>ae(rt.bind(n))):W&&ae(W.bind(n))}if(J(Xd,f),J(Ee,p),J(e1,h),J(cs,g),J(Yd,w),J(Zd,k),J(a1,$),J(r1,L),J(n1,U),J(na,x),J(ra,S),J(t1,R),Q(j))if(j.length){const ae=e.exposed||(e.exposed={});j.forEach(W=>{Object.defineProperty(ae,W,{get:()=>n[W],set:rt=>n[W]=rt})})}else e.exposed||(e.exposed={});D&&e.render===Xe&&(e.render=D),ne!=null&&(e.inheritAttrs=ne),N&&(e.components=N),ee&&(e.directives=ee)}function i1(e,t,n=Xe){Q(e)&&(e=Ga(e));for(const r in e){const a=e[r];let l;xe(a)?"default"in a?l=he(a.from||r,a.default,!0):l=he(a.from||r):l=he(a),De(l)?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>l.value,set:o=>l.value=o}):t[r]=l}}function bo(e,t,n){tt(Q(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function us(e,t,n,r){const a=r.includes(".")?as(n,r):()=>n[r];if(oe(e)){const l=t[e];re(l)&&ye(a,l)}else if(re(e))ye(a,e.bind(n));else if(xe(e))if(Q(e))e.forEach(l=>us(l,t,n,r));else{const l=re(e.handler)?e.handler.bind(n):t[e.handler];re(l)&&ye(a,l,e)}}function xl(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:a,optionsCache:l,config:{optionMergeStrategies:o}}=e.appContext,s=l.get(t);let c;return s?c=s:!a.length&&!n&&!r?c=t:(c={},a.length&&a.forEach(u=>$r(c,u,o,!0)),$r(c,t,o)),xe(t)&&l.set(t,c),c}function $r(e,t,n,r=!1){const{mixins:a,extends:l}=t;l&&$r(e,l,n,!0),a&&a.forEach(o=>$r(e,o,n,!0));for(const o in t)if(!(r&&o==="expose")){const s=s1[o]||n&&n[o];e[o]=s?s(e[o],t[o]):t[o]}return e}const s1={data:_o,props:yo,emits:yo,methods:On,computed:On,beforeCreate:$e,created:$e,beforeMount:$e,mounted:$e,beforeUpdate:$e,updated:$e,beforeDestroy:$e,beforeUnmount:$e,destroyed:$e,unmounted:$e,activated:$e,deactivated:$e,errorCaptured:$e,serverPrefetch:$e,components:On,directives:On,watch:u1,provide:_o,inject:c1};function _o(e,t){return t?e?function(){return Ie(re(e)?e.call(this,this):e,re(t)?t.call(this,this):t)}:t:e}function c1(e,t){return On(Ga(e),Ga(t))}function Ga(e){if(Q(e)){const t={};for(let n=0;n1)return n&&re(t)?t.call(r&&r.proxy):t}}function p1(e,t,n,r=!1){const a={},l={};Dr(l,aa,1),e.propsDefaults=Object.create(null),fs(e,t,a,l);for(const o in e.propsOptions[0])o in a||(a[o]=void 0);n?e.props=r?a:qi(a):e.type.props?e.props=a:e.props=l,e.attrs=l}function h1(e,t,n,r){const{props:a,attrs:l,vnode:{patchFlag:o}}=e,s=ce(a),[c]=e.propsOptions;let u=!1;if((r||o>0)&&!(o&16)){if(o&8){const d=e.vnode.dynamicProps;for(let f=0;f{c=!0;const[p,h]=ps(f,t,!0);Ie(o,p),h&&s.push(...h)};!n&&t.mixins.length&&t.mixins.forEach(d),e.extends&&d(e.extends),e.mixins&&e.mixins.forEach(d)}if(!l&&!c)return xe(e)&&r.set(e,un),un;if(Q(l))for(let d=0;d-1,h[1]=w<0||g-1||de(h,"default"))&&s.push(f)}}}const u=[o,s];return xe(e)&&r.set(e,u),u}function Eo(e){return e[0]!=="$"}function ko(e){const t=e&&e.toString().match(/^\s*(function|class) (\w+)/);return t?t[2]:e===null?"null":""}function wo(e,t){return ko(e)===ko(t)}function Ao(e,t){return Q(t)?t.findIndex(n=>wo(n,e)):re(t)&&wo(t,e)?0:-1}const hs=e=>e[0]==="_"||e==="$stable",Sl=e=>Q(e)?e.map(lt):[lt(e)],v1=(e,t,n)=>{if(t._n)return t;const r=za((...a)=>Sl(t(...a)),n);return r._c=!1,r},vs=(e,t,n)=>{const r=e._ctx;for(const a in e){if(hs(a))continue;const l=e[a];if(re(l))t[a]=v1(a,l,r);else if(l!=null){const o=Sl(l);t[a]=()=>o}}},ms=(e,t)=>{const n=Sl(t);e.slots.default=()=>n},m1=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=ce(t),Dr(t,"_",n)):vs(t,e.slots={})}else e.slots={},t&&ms(e,t);Dr(e.slots,aa,1)},g1=(e,t,n)=>{const{vnode:r,slots:a}=e;let l=!0,o=Ae;if(r.shapeFlag&32){const s=t._;s?n&&s===1?l=!1:(Ie(a,t),!n&&s===1&&delete a._):(l=!t.$stable,vs(t,a)),o=t}else t&&(ms(e,t),o={default:1});if(l)for(const s in a)!hs(s)&&o[s]==null&&delete a[s]};function Nr(e,t,n,r,a=!1){if(Q(e)){e.forEach((p,h)=>Nr(p,t&&(Q(t)?t[h]:t),n,r,a));return}if(Fn(r)&&!a)return;const l=r.shapeFlag&4?Bl(r.component)||r.component.proxy:r.el,o=a?null:l,{i:s,r:c}=e,u=t&&t.r,d=s.refs===Ae?s.refs={}:s.refs,f=s.setupState;if(u!=null&&u!==c&&(oe(u)?(d[u]=null,de(f,u)&&(f[u]=null)):De(u)&&(u.value=null)),re(c))Mt(c,s,12,[o,d]);else{const p=oe(c),h=De(c),g=e.f;if(p||h){const w=()=>{if(g){const k=p?de(f,c)?f[c]:d[c]:c.value;a?Q(k)&&ul(k,l):Q(k)?k.includes(l)||k.push(l):p?(d[c]=[l],de(f,c)&&(f[c]=d[c])):(c.value=[l],e.k&&(d[e.k]=c.value))}else p?(d[c]=o,de(f,c)&&(f[c]=o)):h&&(c.value=o,e.k&&(d[e.k]=o))};a||g?w():(w.id=-1,ze(w,n))}}}let St=!1;const b1=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",_1=e=>e.namespaceURI.includes("MathML"),Ar=e=>{if(b1(e))return"svg";if(_1(e))return"mathml"},Lr=e=>e.nodeType===8;function y1(e){const{mt:t,p:n,o:{patchProp:r,createText:a,nextSibling:l,parentNode:o,remove:s,insert:c,createComment:u}}=e,d=(_,S)=>{if(!S.hasChildNodes()){n(null,_,S),Fr(),S._vnode=_;return}St=!1,f(S.firstChild,_,null,null,null),Fr(),S._vnode=_,St&&console.error("Hydration completed but contains mismatches.")},f=(_,S,D,L,U,$=!1)=>{const R=Lr(_)&&_.data==="[",j=()=>w(_,S,D,L,U,R),{type:ne,ref:N,shapeFlag:ee,patchFlag:Se}=S;let Te=_.nodeType;S.el=_,Se===-2&&($=!1,S.dynamicChildren=null);let J=null;switch(ne){case mn:Te!==3?S.children===""?(c(S.el=a(""),o(_),_),J=_):J=j():(_.data!==S.children&&(St=!0,_.data=S.children),J=l(_));break;case ht:x(_)?(J=l(_),b(S.el=_.content.firstChild,_,D)):Te!==8||R?J=j():J=l(_);break;case $n:if(R&&(_=l(_),Te=_.nodeType),Te===1||Te===3){J=_;const ae=!S.children.length;for(let W=0;W{$=$||!!S.dynamicChildren;const{type:R,props:j,patchFlag:ne,shapeFlag:N,dirs:ee,transition:Se}=S,Te=R==="input"||R==="option";if(Te||ne!==-1){ee&&ft(S,null,D,"created");let J=!1;if(x(_)){J=gs(L,Se)&&D&&D.vnode.props&&D.vnode.props.appear;const W=_.content.firstChild;J&&Se.beforeEnter(W),b(W,_,D),S.el=_=W}if(N&16&&!(j&&(j.innerHTML||j.textContent))){let W=h(_.firstChild,S,_,D,L,U,$);for(;W;){St=!0;const rt=W;W=W.nextSibling,s(rt)}}else N&8&&_.textContent!==S.children&&(St=!0,_.textContent=S.children);if(j)if(Te||!$||ne&48)for(const W in j)(Te&&(W.endsWith("value")||W==="indeterminate")||Zn(W)&&!Rn(W)||W[0]===".")&&r(_,W,null,j[W],void 0,void 0,D);else j.onClick&&r(_,"onClick",null,j.onClick,void 0,void 0,D);let ae;(ae=j&&j.onVnodeBeforeMount)&&Qe(ae,D,S),ee&&ft(S,null,D,"beforeMount"),((ae=j&&j.onVnodeMounted)||ee||J)&&rs(()=>{ae&&Qe(ae,D,S),J&&Se.enter(_),ee&&ft(S,null,D,"mounted")},L)}return _.nextSibling},h=(_,S,D,L,U,$,R)=>{R=R||!!S.dynamicChildren;const j=S.children,ne=j.length;for(let N=0;N{const{slotScopeIds:R}=S;R&&(U=U?U.concat(R):R);const j=o(_),ne=h(l(_),S,j,D,L,U,$);return ne&&Lr(ne)&&ne.data==="]"?l(S.anchor=ne):(St=!0,c(S.anchor=u("]"),j,ne),ne)},w=(_,S,D,L,U,$)=>{if(St=!0,S.el=null,$){const ne=k(_);for(;;){const N=l(_);if(N&&N!==ne)s(N);else break}}const R=l(_),j=o(_);return s(_),n(null,S,j,R,D,L,Ar(j),U),R},k=(_,S="[",D="]")=>{let L=0;for(;_;)if(_=l(_),_&&Lr(_)&&(_.data===S&&L++,_.data===D)){if(L===0)return l(_);L--}return _},b=(_,S,D)=>{const L=S.parentNode;L&&L.replaceChild(_,S);let U=D;for(;U;)U.vnode.el===S&&(U.vnode.el=U.subTree.el=_),U=U.parent},x=_=>_.nodeType===1&&_.tagName.toLowerCase()==="template";return[d,f]}const ze=rs;function E1(e){return k1(e,y1)}function k1(e,t){const n=Bi();n.__VUE__=!0;const{insert:r,remove:a,patchProp:l,createElement:o,createText:s,createComment:c,setText:u,setElementText:d,parentNode:f,nextSibling:p,setScopeId:h=Xe,insertStaticContent:g}=e,w=(v,m,A,C=null,T=null,O=null,H=void 0,P=null,M=!!m.dynamicChildren)=>{if(v===m)return;v&&!qt(v,m)&&(C=B(v),Ne(v,T,O,!0),v=null),m.patchFlag===-2&&(M=!1,m.dynamicChildren=null);const{type:I,ref:G,shapeFlag:Z}=m;switch(I){case mn:k(v,m,A,C);break;case ht:b(v,m,A,C);break;case $n:v==null&&x(m,A,C,H);break;case Je:N(v,m,A,C,T,O,H,P,M);break;default:Z&1?D(v,m,A,C,T,O,H,P,M):Z&6?ee(v,m,A,C,T,O,H,P,M):(Z&64||Z&128)&&I.process(v,m,A,C,T,O,H,P,M,K)}G!=null&&T&&Nr(G,v&&v.ref,O,m||v,!m)},k=(v,m,A,C)=>{if(v==null)r(m.el=s(m.children),A,C);else{const T=m.el=v.el;m.children!==v.children&&u(T,m.children)}},b=(v,m,A,C)=>{v==null?r(m.el=c(m.children||""),A,C):m.el=v.el},x=(v,m,A,C)=>{[v.el,v.anchor]=g(v.children,m,A,C,v.el,v.anchor)},_=({el:v,anchor:m},A,C)=>{let T;for(;v&&v!==m;)T=p(v),r(v,A,C),v=T;r(m,A,C)},S=({el:v,anchor:m})=>{let A;for(;v&&v!==m;)A=p(v),a(v),v=A;a(m)},D=(v,m,A,C,T,O,H,P,M)=>{m.type==="svg"?H="svg":m.type==="math"&&(H="mathml"),v==null?L(m,A,C,T,O,H,P,M):R(v,m,T,O,H,P,M)},L=(v,m,A,C,T,O,H,P)=>{let M,I;const{props:G,shapeFlag:Z,transition:Y,dirs:te}=v;if(M=v.el=o(v.type,O,G&&G.is,G),Z&8?d(M,v.children):Z&16&&$(v.children,M,null,C,T,ka(v,O),H,P),te&&ft(v,null,C,"created"),U(M,v,v.scopeId,H,C),G){for(const be in G)be!=="value"&&!Rn(be)&&l(M,be,null,G[be],O,v.children,C,T,Me);"value"in G&&l(M,"value",null,G.value,O),(I=G.onVnodeBeforeMount)&&Qe(I,C,v)}te&&ft(v,null,C,"beforeMount");const le=gs(T,Y);le&&Y.beforeEnter(M),r(M,m,A),((I=G&&G.onVnodeMounted)||le||te)&&ze(()=>{I&&Qe(I,C,v),le&&Y.enter(M),te&&ft(v,null,C,"mounted")},T)},U=(v,m,A,C,T)=>{if(A&&h(v,A),C)for(let O=0;O{for(let I=M;I{const P=m.el=v.el;let{patchFlag:M,dynamicChildren:I,dirs:G}=m;M|=v.patchFlag&16;const Z=v.props||Ae,Y=m.props||Ae;let te;if(A&&Nt(A,!1),(te=Y.onVnodeBeforeUpdate)&&Qe(te,A,m,v),G&&ft(m,v,A,"beforeUpdate"),A&&Nt(A,!0),I?j(v.dynamicChildren,I,P,A,C,ka(m,T),O):H||W(v,m,P,null,A,C,ka(m,T),O,!1),M>0){if(M&16)ne(P,m,Z,Y,A,C,T);else if(M&2&&Z.class!==Y.class&&l(P,"class",null,Y.class,T),M&4&&l(P,"style",Z.style,Y.style,T),M&8){const le=m.dynamicProps;for(let be=0;be{te&&Qe(te,A,m,v),G&&ft(m,v,A,"updated")},C)},j=(v,m,A,C,T,O,H)=>{for(let P=0;P{if(A!==C){if(A!==Ae)for(const P in A)!Rn(P)&&!(P in C)&&l(v,P,A[P],null,H,m.children,T,O,Me);for(const P in C){if(Rn(P))continue;const M=C[P],I=A[P];M!==I&&P!=="value"&&l(v,P,I,M,H,m.children,T,O,Me)}"value"in C&&l(v,"value",A.value,C.value,H)}},N=(v,m,A,C,T,O,H,P,M)=>{const I=m.el=v?v.el:s(""),G=m.anchor=v?v.anchor:s("");let{patchFlag:Z,dynamicChildren:Y,slotScopeIds:te}=m;te&&(P=P?P.concat(te):te),v==null?(r(I,A,C),r(G,A,C),$(m.children||[],A,G,T,O,H,P,M)):Z>0&&Z&64&&Y&&v.dynamicChildren?(j(v.dynamicChildren,Y,A,T,O,H,P),(m.key!=null||T&&m===T.subTree)&&bs(v,m,!0)):W(v,m,A,G,T,O,H,P,M)},ee=(v,m,A,C,T,O,H,P,M)=>{m.slotScopeIds=P,v==null?m.shapeFlag&512?T.ctx.activate(m,A,C,H,M):Se(m,A,C,T,O,H,M):Te(v,m,M)},Se=(v,m,A,C,T,O,H)=>{const P=v.component=O1(v,C,T);if(er(v)&&(P.ctx.renderer=K),D1(P),P.asyncDep){if(T&&T.registerDep(P,J),!v.el){const M=P.subTree=Be(ht);b(null,M,m,A)}}else J(P,v,m,A,T,O,H)},Te=(v,m,A)=>{const C=m.component=v.component;if(jd(v,m,A))if(C.asyncDep&&!C.asyncResolved){ae(C,m,A);return}else C.next=m,Pd(C.update),C.effect.dirty=!0,C.update();else m.el=v.el,C.vnode=m},J=(v,m,A,C,T,O,H)=>{const P=()=>{if(v.isMounted){let{next:G,bu:Z,u:Y,parent:te,vnode:le}=v;{const ln=_s(v);if(ln){G&&(G.el=le.el,ae(v,G,H)),ln.asyncDep.then(()=>{v.isUnmounted||P()});return}}let be=G,we;Nt(v,!1),G?(G.el=le.el,ae(v,G,H)):G=le,Z&&ga(Z),(we=G.props&&G.props.onVnodeBeforeUpdate)&&Qe(we,te,G,le),Nt(v,!0);const Pe=ba(v),at=v.subTree;v.subTree=Pe,w(at,Pe,f(at.el),B(at),v,T,O),G.el=Pe.el,be===null&&Nd(v,Pe.el),Y&&ze(Y,T),(we=G.props&&G.props.onVnodeUpdated)&&ze(()=>Qe(we,te,G,le),T)}else{let G;const{el:Z,props:Y}=m,{bm:te,m:le,parent:be}=v,we=Fn(m);if(Nt(v,!1),te&&ga(te),!we&&(G=Y&&Y.onVnodeBeforeMount)&&Qe(G,be,m),Nt(v,!0),Z&&ke){const Pe=()=>{v.subTree=ba(v),ke(Z,v.subTree,v,T,null)};we?m.type.__asyncLoader().then(()=>!v.isUnmounted&&Pe()):Pe()}else{const Pe=v.subTree=ba(v);w(null,Pe,A,C,v,T,O),m.el=Pe.el}if(le&&ze(le,T),!we&&(G=Y&&Y.onVnodeMounted)){const Pe=m;ze(()=>Qe(G,be,Pe),T)}(m.shapeFlag&256||be&&Fn(be.vnode)&&be.vnode.shapeFlag&256)&&v.a&&ze(v.a,T),v.isMounted=!0,m=A=C=null}},M=v.effect=new hl(P,Xe,()=>Qr(I),v.scope),I=v.update=()=>{M.dirty&&M.run()};I.id=v.uid,Nt(v,!0),I()},ae=(v,m,A)=>{m.component=v;const C=v.vnode.props;v.vnode=m,v.next=null,h1(v,m.props,C,A),g1(v,m.children,A),Zt(),po(v),Qt()},W=(v,m,A,C,T,O,H,P,M=!1)=>{const I=v&&v.children,G=v?v.shapeFlag:0,Z=m.children,{patchFlag:Y,shapeFlag:te}=m;if(Y>0){if(Y&128){Lt(I,Z,A,C,T,O,H,P,M);return}else if(Y&256){rt(I,Z,A,C,T,O,H,P,M);return}}te&8?(G&16&&Me(I,T,O),Z!==I&&d(A,Z)):G&16?te&16?Lt(I,Z,A,C,T,O,H,P,M):Me(I,T,O,!0):(G&8&&d(A,""),te&16&&$(Z,A,C,T,O,H,P,M))},rt=(v,m,A,C,T,O,H,P,M)=>{v=v||un,m=m||un;const I=v.length,G=m.length,Z=Math.min(I,G);let Y;for(Y=0;YG?Me(v,T,O,!0,!1,Z):$(m,A,C,T,O,H,P,M,Z)},Lt=(v,m,A,C,T,O,H,P,M)=>{let I=0;const G=m.length;let Z=v.length-1,Y=G-1;for(;I<=Z&&I<=Y;){const te=v[I],le=m[I]=M?Pt(m[I]):lt(m[I]);if(qt(te,le))w(te,le,A,null,T,O,H,P,M);else break;I++}for(;I<=Z&&I<=Y;){const te=v[Z],le=m[Y]=M?Pt(m[Y]):lt(m[Y]);if(qt(te,le))w(te,le,A,null,T,O,H,P,M);else break;Z--,Y--}if(I>Z){if(I<=Y){const te=Y+1,le=teY)for(;I<=Z;)Ne(v[I],T,O,!0),I++;else{const te=I,le=I,be=new Map;for(I=le;I<=Y;I++){const Ke=m[I]=M?Pt(m[I]):lt(m[I]);Ke.key!=null&&be.set(Ke.key,I)}let we,Pe=0;const at=Y-le+1;let ln=!1,to=0;const Bn=new Array(at);for(I=0;I=at){Ne(Ke,T,O,!0);continue}let dt;if(Ke.key!=null)dt=be.get(Ke.key);else for(we=le;we<=Y;we++)if(Bn[we-le]===0&&qt(Ke,m[we])){dt=we;break}dt===void 0?Ne(Ke,T,O,!0):(Bn[dt-le]=I+1,dt>=to?to=dt:ln=!0,w(Ke,m[dt],A,null,T,O,H,P,M),Pe++)}const no=ln?w1(Bn):un;for(we=no.length-1,I=at-1;I>=0;I--){const Ke=le+I,dt=m[Ke],ro=Ke+1{const{el:O,type:H,transition:P,children:M,shapeFlag:I}=v;if(I&6){ut(v.component.subTree,m,A,C);return}if(I&128){v.suspense.move(m,A,C);return}if(I&64){H.move(v,m,A,K);return}if(H===Je){r(O,m,A);for(let Z=0;ZP.enter(O),T);else{const{leave:Z,delayLeave:Y,afterLeave:te}=P,le=()=>r(O,m,A),be=()=>{Z(O,()=>{le(),te&&te()})};Y?Y(O,le,be):be()}else r(O,m,A)},Ne=(v,m,A,C=!1,T=!1)=>{const{type:O,props:H,ref:P,children:M,dynamicChildren:I,shapeFlag:G,patchFlag:Z,dirs:Y}=v;if(P!=null&&Nr(P,null,A,v,!0),G&256){m.ctx.deactivate(v);return}const te=G&1&&Y,le=!Fn(v);let be;if(le&&(be=H&&H.onVnodeBeforeUnmount)&&Qe(be,m,v),G&6)mr(v.component,A,C);else{if(G&128){v.suspense.unmount(A,C);return}te&&ft(v,null,m,"beforeUnmount"),G&64?v.type.remove(v,m,A,T,K,C):I&&(O!==Je||Z>0&&Z&64)?Me(I,m,A,!1,!0):(O===Je&&Z&384||!T&&G&16)&&Me(M,m,A),C&&rn(v)}(le&&(be=H&&H.onVnodeUnmounted)||te)&&ze(()=>{be&&Qe(be,m,v),te&&ft(v,null,m,"unmounted")},A)},rn=v=>{const{type:m,el:A,anchor:C,transition:T}=v;if(m===Je){an(A,C);return}if(m===$n){S(v);return}const O=()=>{a(A),T&&!T.persisted&&T.afterLeave&&T.afterLeave()};if(v.shapeFlag&1&&T&&!T.persisted){const{leave:H,delayLeave:P}=T,M=()=>H(A,O);P?P(v.el,O,M):M()}else O()},an=(v,m)=>{let A;for(;v!==m;)A=p(v),a(v),v=A;a(m)},mr=(v,m,A)=>{const{bum:C,scope:T,update:O,subTree:H,um:P}=v;C&&ga(C),T.stop(),O&&(O.active=!1,Ne(H,v,m,A)),P&&ze(P,m),ze(()=>{v.isUnmounted=!0},m),m&&m.pendingBranch&&!m.isUnmounted&&v.asyncDep&&!v.asyncResolved&&v.suspenseId===m.pendingId&&(m.deps--,m.deps===0&&m.resolve())},Me=(v,m,A,C=!1,T=!1,O=0)=>{for(let H=O;Hv.shapeFlag&6?B(v.component.subTree):v.shapeFlag&128?v.suspense.next():p(v.anchor||v.el);let q=!1;const z=(v,m,A)=>{v==null?m._vnode&&Ne(m._vnode,null,null,!0):w(m._vnode||null,v,m,null,null,null,A),q||(q=!0,po(),Fr(),q=!1),m._vnode=v},K={p:w,um:Ne,m:ut,r:rn,mt:Se,mc:$,pc:W,pbc:j,n:B,o:e};let ve,ke;return t&&([ve,ke]=t(K)),{render:z,hydrate:ve,createApp:f1(z,ve)}}function ka({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function Nt({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function gs(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function bs(e,t,n=!1){const r=e.children,a=t.children;if(Q(r)&&Q(a))for(let l=0;l>1,e[n[s]]0&&(t[r]=n[l-1]),n[l]=r)}}for(l=n.length,o=n[l-1];l-- >0;)n[l]=o,o=t[o];return n}function _s(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:_s(t)}const A1=e=>e.__isTeleport,Je=Symbol.for("v-fgt"),mn=Symbol.for("v-txt"),ht=Symbol.for("v-cmt"),$n=Symbol.for("v-stc"),jn=[];let ot=null;function L1(e=!1){jn.push(ot=e?null:[])}function x1(){jn.pop(),ot=jn[jn.length-1]||null}let Wn=1;function Lo(e){Wn+=e}function ys(e){return e.dynamicChildren=Wn>0?ot||un:null,x1(),Wn>0&&ot&&ot.push(e),e}function av(e,t,n,r,a,l){return ys(la(e,t,n,r,a,l,!0))}function S1(e,t,n,r,a){return ys(Be(e,t,n,r,a,!0))}function Ka(e){return e?e.__v_isVNode===!0:!1}function qt(e,t){return e.type===t.type&&e.key===t.key}const aa="__vInternal",Es=({key:e})=>e??null,Or=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?oe(e)||De(e)||re(e)?{i:et,r:e,k:t,f:!!n}:e:null);function la(e,t=null,n=null,r=0,a=null,l=e===Je?0:1,o=!1,s=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Es(t),ref:t&&Or(t),scopeId:ea,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:l,patchFlag:r,dynamicProps:a,dynamicChildren:null,appContext:null,ctx:et};return s?(Tl(c,n),l&128&&e.normalize(c)):n&&(c.shapeFlag|=oe(n)?8:16),Wn>0&&!o&&ot&&(c.patchFlag>0||l&6)&&c.patchFlag!==32&&ot.push(c),c}const Be=T1;function T1(e,t=null,n=null,r=0,a=null,l=!1){if((!e||e===zd)&&(e=ht),Ka(e)){const s=Vt(e,t,!0);return n&&Tl(s,n),Wn>0&&!l&&ot&&(s.shapeFlag&6?ot[ot.indexOf(e)]=s:ot.push(s)),s.patchFlag|=-2,s}if($1(e)&&(e=e.__vccOpts),t){t=B1(t);let{class:s,style:c}=t;s&&!oe(s)&&(t.class=pl(s)),xe(c)&&(Gi(c)&&!Q(c)&&(c=Ie({},c)),t.style=fl(c))}const o=oe(e)?1:qd(e)?128:A1(e)?64:xe(e)?4:re(e)?2:0;return la(e,t,n,r,a,o,l,!0)}function B1(e){return e?Gi(e)||aa in e?Ie({},e):e:null}function Vt(e,t,n=!1){const{props:r,ref:a,patchFlag:l,children:o}=e,s=t?C1(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:s,key:s&&Es(s),ref:t&&t.ref?n&&a?Q(a)?a.concat(Or(t)):[a,Or(t)]:Or(t):a,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:o,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Je?l===-1?16:l|16:l,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Vt(e.ssContent),ssFallback:e.ssFallback&&Vt(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function ks(e=" ",t=0){return Be(mn,null,e,t)}function lv(e,t){const n=Be($n,null,e);return n.staticCount=t,n}function lt(e){return e==null||typeof e=="boolean"?Be(ht):Q(e)?Be(Je,null,e.slice()):typeof e=="object"?Pt(e):Be(mn,null,String(e))}function Pt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Vt(e)}function Tl(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(Q(t))n=16;else if(typeof t=="object")if(r&65){const a=t.default;a&&(a._c&&(a._d=!1),Tl(e,a()),a._c&&(a._d=!0));return}else{n=32;const a=t._;!a&&!(aa in t)?t._ctx=et:a===3&&et&&(et.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else re(t)?(t={default:t,_ctx:et},n=32):(t=String(t),r&64?(n=16,t=[ks(t)]):n=8);e.children=t,e.shapeFlag|=n}function C1(...e){const t={};for(let n=0;nOe||et;let zr,Wa;{const e=Bi(),t=(n,r)=>{let a;return(a=e[n])||(a=e[n]=[]),a.push(r),l=>{a.length>1?a.forEach(o=>o(l)):a[0](l)}};zr=t("__VUE_INSTANCE_SETTERS__",n=>Oe=n),Wa=t("__VUE_SSR_SETTERS__",n=>nr=n)}const tr=e=>{const t=Oe;return zr(e),e.scope.on(),()=>{e.scope.off(),zr(t)}},xo=()=>{Oe&&Oe.scope.off(),zr(null)};function ws(e){return e.vnode.shapeFlag&4}let nr=!1;function D1(e,t=!1){t&&Wa(t);const{props:n,children:r}=e.vnode,a=ws(e);p1(e,n,a,t),m1(e,r);const l=a?R1(e,t):void 0;return t&&Wa(!1),l}function R1(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=Ui(new Proxy(e.ctx,l1));const{setup:r}=n;if(r){const a=e.setupContext=r.length>1?F1(e):null,l=tr(e);Zt();const o=Mt(r,e,0,[e.props,a]);if(Qt(),l(),Ti(o)){if(o.then(xo,xo),t)return o.then(s=>{So(e,s,t)}).catch(s=>{Xn(s,e,0)});e.asyncDep=o}else So(e,o,t)}else As(e,t)}function So(e,t,n){re(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:xe(t)&&(e.setupState=Ji(t)),As(e,n)}let To;function As(e,t,n){const r=e.type;if(!e.render){if(!t&&To&&!r.render){const a=r.template||xl(e).template;if(a){const{isCustomElement:l,compilerOptions:o}=e.appContext.config,{delimiters:s,compilerOptions:c}=r,u=Ie(Ie({isCustomElement:l,delimiters:s},o),c);r.render=To(a,u)}}e.render=r.render||Xe}{const a=tr(e);Zt();try{o1(e)}finally{Qt(),a()}}}function M1(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return Ue(e,"get","$attrs"),t[n]}}))}function F1(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return M1(e)},slots:e.slots,emit:e.emit,expose:t}}function Bl(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Ji(Ui(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Vn)return Vn[n](e)},has(t,n){return n in t||n in Vn}}))}function V1(e,t=!0){return re(e)?e.displayName||e.name:e.name||t&&e.__name}function $1(e){return re(e)&&"__vccOpts"in e}const E=(e,t)=>wd(e,t,nr);function i(e,t,n){const r=arguments.length;return r===2?xe(t)&&!Q(t)?Ka(t)?Be(e,null,[t]):Be(e,t):Be(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&Ka(n)&&(n=[n]),Be(e,t,n))}const j1="3.4.15";/**
+* @vue/runtime-dom v3.4.15
+* (c) 2018-present Yuxi (Evan) You and Vue contributors
+* @license MIT
+**/const N1="http://www.w3.org/2000/svg",z1="http://www.w3.org/1998/Math/MathML",Ot=typeof document<"u"?document:null,Bo=Ot&&Ot.createElement("template"),H1={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const a=t==="svg"?Ot.createElementNS(N1,e):t==="mathml"?Ot.createElementNS(z1,e):Ot.createElement(e,n?{is:n}:void 0);return e==="select"&&r&&r.multiple!=null&&a.setAttribute("multiple",r.multiple),a},createText:e=>Ot.createTextNode(e),createComment:e=>Ot.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Ot.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,a,l){const o=n?n.previousSibling:t.lastChild;if(a&&(a===l||a.nextSibling))for(;t.insertBefore(a.cloneNode(!0),n),!(a===l||!(a=a.nextSibling)););else{Bo.innerHTML=r==="svg"?`${e} `:r==="mathml"?`${e} `:e;const s=Bo.content;if(r==="svg"||r==="mathml"){const c=s.firstChild;for(;c.firstChild;)s.appendChild(c.firstChild);s.removeChild(c)}t.insertBefore(s,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},Tt="transition",Cn="animation",gn=Symbol("_vtc"),Yt=(e,{slots:t})=>i(Jd,xs(e),t);Yt.displayName="Transition";const Ls={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},q1=Yt.props=Ie({},os,Ls),zt=(e,t=[])=>{Q(e)?e.forEach(n=>n(...t)):e&&e(...t)},Co=e=>e?Q(e)?e.some(t=>t.length>1):e.length>1:!1;function xs(e){const t={};for(const N in e)N in Ls||(t[N]=e[N]);if(e.css===!1)return t;const{name:n="v",type:r,duration:a,enterFromClass:l=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:s=`${n}-enter-to`,appearFromClass:c=l,appearActiveClass:u=o,appearToClass:d=s,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:h=`${n}-leave-to`}=e,g=G1(a),w=g&&g[0],k=g&&g[1],{onBeforeEnter:b,onEnter:x,onEnterCancelled:_,onLeave:S,onLeaveCancelled:D,onBeforeAppear:L=b,onAppear:U=x,onAppearCancelled:$=_}=t,R=(N,ee,Se)=>{Bt(N,ee?d:s),Bt(N,ee?u:o),Se&&Se()},j=(N,ee)=>{N._isLeaving=!1,Bt(N,f),Bt(N,h),Bt(N,p),ee&&ee()},ne=N=>(ee,Se)=>{const Te=N?U:x,J=()=>R(ee,N,Se);zt(Te,[ee,J]),Io(()=>{Bt(ee,N?c:l),_t(ee,N?d:s),Co(Te)||Po(ee,r,w,J)})};return Ie(t,{onBeforeEnter(N){zt(b,[N]),_t(N,l),_t(N,o)},onBeforeAppear(N){zt(L,[N]),_t(N,c),_t(N,u)},onEnter:ne(!1),onAppear:ne(!0),onLeave(N,ee){N._isLeaving=!0;const Se=()=>j(N,ee);_t(N,f),Ts(),_t(N,p),Io(()=>{N._isLeaving&&(Bt(N,f),_t(N,h),Co(S)||Po(N,r,k,Se))}),zt(S,[N,Se])},onEnterCancelled(N){R(N,!1),zt(_,[N])},onAppearCancelled(N){R(N,!0),zt($,[N])},onLeaveCancelled(N){j(N),zt(D,[N])}})}function G1(e){if(e==null)return null;if(xe(e))return[wa(e.enter),wa(e.leave)];{const t=wa(e);return[t,t]}}function wa(e){return Ku(e)}function _t(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[gn]||(e[gn]=new Set)).add(t)}function Bt(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[gn];n&&(n.delete(t),n.size||(e[gn]=void 0))}function Io(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let U1=0;function Po(e,t,n,r){const a=e._endId=++U1,l=()=>{a===e._endId&&r()};if(n)return setTimeout(l,n);const{type:o,timeout:s,propCount:c}=Ss(e,t);if(!o)return r();const u=o+"end";let d=0;const f=()=>{e.removeEventListener(u,p),l()},p=h=>{h.target===e&&++d>=c&&f()};setTimeout(()=>{d(n[g]||"").split(", "),a=r(`${Tt}Delay`),l=r(`${Tt}Duration`),o=Oo(a,l),s=r(`${Cn}Delay`),c=r(`${Cn}Duration`),u=Oo(s,c);let d=null,f=0,p=0;t===Tt?o>0&&(d=Tt,f=o,p=l.length):t===Cn?u>0&&(d=Cn,f=u,p=c.length):(f=Math.max(o,u),d=f>0?o>u?Tt:Cn:null,p=d?d===Tt?l.length:c.length:0);const h=d===Tt&&/\b(transform|all)(,|$)/.test(r(`${Tt}Property`).toString());return{type:d,timeout:f,propCount:p,hasTransform:h}}function Oo(e,t){for(;e.lengthDo(n)+Do(e[r])))}function Do(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Ts(){return document.body.offsetHeight}function K1(e,t,n){const r=e[gn];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const W1=Symbol("_vod"),J1=Symbol("");function Y1(e,t,n){const r=e.style,a=r.display,l=oe(n);if(n&&!l){if(t&&!oe(t))for(const o in t)n[o]==null&&Ja(r,o,"");for(const o in n)Ja(r,o,n[o])}else if(l){if(t!==n){const o=r[J1];o&&(n+=";"+o),r.cssText=n}}else t&&e.removeAttribute("style");W1 in e&&(r.display=a)}const Ro=/\s*!important$/;function Ja(e,t,n){if(Q(n))n.forEach(r=>Ja(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Z1(e,t);Ro.test(n)?e.setProperty(wn(r),n.replace(Ro,""),"important"):e[r]=n}}const Mo=["Webkit","Moz","ms"],Aa={};function Z1(e,t){const n=Aa[t];if(n)return n;let r=Ge(t);if(r!=="filter"&&r in e)return Aa[t]=r;r=An(r);for(let a=0;aLa||(af.then(()=>La=0),La=Date.now());function of(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;tt(sf(r,n.value),t,5,[r])};return n.value=e,n.attached=lf(),n}function sf(e,t){if(Q(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>a=>!a._stopped&&r&&r(a))}else return t}const jo=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,cf=(e,t,n,r,a,l,o,s,c)=>{const u=a==="svg";t==="class"?K1(e,r,u):t==="style"?Y1(e,n,r):Zn(t)?cl(t)||nf(e,t,n,r,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):uf(e,t,r,u))?X1(e,t,r,l,o,s,c):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Q1(e,t,r,u))};function uf(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&jo(t)&&re(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const a=e.tagName;if(a==="IMG"||a==="VIDEO"||a==="CANVAS"||a==="SOURCE")return!1}return jo(t)&&oe(n)?!1:t in e}const Bs=new WeakMap,Cs=new WeakMap,Hr=Symbol("_moveCb"),No=Symbol("_enterCb"),Is={name:"TransitionGroup",props:Ie({},q1,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=tn(),r=ls();let a,l;return cs(()=>{if(!a.length)return;const o=e.moveClass||`${e.name||"v"}-move`;if(!mf(a[0].el,n.vnode.el,o))return;a.forEach(pf),a.forEach(hf);const s=a.filter(vf);Ts(),s.forEach(c=>{const u=c.el,d=u.style;_t(u,o),d.transform=d.webkitTransform=d.transitionDuration="";const f=u[Hr]=p=>{p&&p.target!==u||(!p||/transform$/.test(p.propertyName))&&(u.removeEventListener("transitionend",f),u[Hr]=null,Bt(u,o))};u.addEventListener("transitionend",f)})}),()=>{const o=ce(e),s=xs(o);let c=o.tag||Je;a=l,l=t.default?Ll(t.default()):[];for(let u=0;udelete e.mode;Is.props;const ff=Is;function pf(e){const t=e.el;t[Hr]&&t[Hr](),t[No]&&t[No]()}function hf(e){Cs.set(e,e.el.getBoundingClientRect())}function vf(e){const t=Bs.get(e),n=Cs.get(e),r=t.left-n.left,a=t.top-n.top;if(r||a){const l=e.el.style;return l.transform=l.webkitTransform=`translate(${r}px,${a}px)`,l.transitionDuration="0s",e}}function mf(e,t,n){const r=e.cloneNode(),a=e[gn];a&&a.forEach(s=>{s.split(/\s+/).forEach(c=>c&&r.classList.remove(c))}),n.split(/\s+/).forEach(s=>s&&r.classList.add(s)),r.style.display="none";const l=t.nodeType===1?t:t.parentNode;l.appendChild(r);const{hasTransform:o}=Ss(r);return l.removeChild(r),o}const gf=Ie({patchProp:cf},H1);let xa,zo=!1;function bf(){return xa=zo?xa:E1(gf),zo=!0,xa}const _f=(...e)=>{const t=bf().createApp(...e),{mount:n}=t;return t.mount=r=>{const a=Ef(r);if(a)return n(a,!0,yf(a))},t};function yf(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Ef(e){return oe(e)?document.querySelector(e):e}const kf="modulepreload",wf=function(e){return"/"+e},Ho={},y=function(t,n,r){let a=Promise.resolve();if(n&&n.length>0){const l=document.getElementsByTagName("link");a=Promise.all(n.map(o=>{if(o=wf(o),o in Ho)return;Ho[o]=!0;const s=o.endsWith(".css"),c=s?'[rel="stylesheet"]':"";if(!!r)for(let f=l.length-1;f>=0;f--){const p=l[f];if(p.href===o&&(!s||p.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${o}"]${c}`))return;const d=document.createElement("link");if(d.rel=s?"stylesheet":kf,s||(d.as="script",d.crossOrigin=""),d.href=o,document.head.appendChild(d),s)return new Promise((f,p)=>{d.addEventListener("load",f),d.addEventListener("error",()=>p(new Error(`Unable to preload CSS for ${o}`)))})}))}return a.then(()=>t()).catch(l=>{const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=l,window.dispatchEvent(o),!o.defaultPrevented)throw l})},Af={"v-8daa1a0e":()=>y(()=>import("./index.html-tMixJPN7.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-728c3a8f":()=>y(()=>import("./index.html-t2KDSwiJ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-cfe8b6c8":()=>y(()=>import("./index.html-N_67P6-s.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2e25198a":()=>y(()=>import("./index.html-2xQqwR-V.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-71fde78e":()=>y(()=>import("./index.html-zEn3PTqR.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-580db9be":()=>y(()=>import("./devops-ping-tai.html-kDtCSXpk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-06d5cd4c":()=>y(()=>import("./gitlab-ci.html-HyFv5Ls3.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-132efcd1":()=>y(()=>import("./jenkins-x.html-gi90zyZ8.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1a2ca7a7":()=>y(()=>import("./tekton.html-7q40Qc0_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-50cb12f2":()=>y(()=>import("./index.html-mNLKf94V.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-091223ce":()=>y(()=>import("./tiktok2023.html-VVmqvR2f.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0a27b598":()=>y(()=>import("./JVM调优参数.html-RmR4uDpi.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-60eda44c":()=>y(()=>import("./serverlog.html-ib9svlbN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-399e07b6":()=>y(()=>import("./一次jvm调优过程.html-Fez3X8xk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-660266c1":()=>y(()=>import("./内存屏障.html-YpsEGPcG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-90f2343c":()=>y(()=>import("./在 Spring 6 中使用虚拟线程.html-aSy3Jyqy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0b5d4df0":()=>y(()=>import("./基于kubernetes的分布式限流.html-SsVfGmol.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-21e54510":()=>y(()=>import("./index.html-k7gT6RRu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-57ae83ac":()=>y(()=>import("./spark on k8s operator.html-Uq_G4U-U.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-22e4234a":()=>y(()=>import("./2017.html-zfvjl-5A.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1f7a720c":()=>y(()=>import("./2018.html-pd4XfNXB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1c10c0ce":()=>y(()=>import("./2019.html-QgZCLsLC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b0e413b8":()=>y(()=>import("./main.html-s2aQ0VEN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-258f309e":()=>y(()=>import("./index.html-xgoJibcf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-510415f9":()=>y(()=>import("./chatgpt.html-soLgBokY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-68e0ce3f":()=>y(()=>import("./starcraft-ai.html-jENBJ0MN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3c114a75":()=>y(()=>import("./tesla.html-NVSkMPRC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-90e5bb66":()=>y(()=>import("./广州图书馆借阅抓取.html-DyyYunsJ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-dc384366":()=>y(()=>import("./index.html-5Ud_mAI1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-70796e0a":()=>y(()=>import("./redis缓存.html-B4MmbAQF.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-43e9e6b0":()=>y(()=>import("./wewe.html-dxhYsqpt.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-33bd146f":()=>y(()=>import("./个人作品.html-HGTJItSS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-04e32b44":()=>y(()=>import("./elastic-spark.html-yTkDwYPM.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d73a9aee":()=>y(()=>import("./elasticsearch源码debug.html-MPOlcYKm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3f2a15ee":()=>y(()=>import("./【elasticsearch】搜索过程详解.html-NGfX8s6C.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-aa93dec0":()=>y(()=>import("./1mysql.html-_FE7EY_e.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0a0b7a54":()=>y(()=>import("./数据库缓存.html-D5OE_lZE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-137d5dcc":()=>y(()=>import("./redis缓存.html-rKUKwNSH.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-16aa42ca":()=>y(()=>import("./Spring Boot Prometheus使用.html-C4jpqxXi.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5089f9f3":()=>y(()=>import("./aop.html-rc4rLz6V.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7586af98":()=>y(()=>import("./webflux.html-BMCSAQQq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-59449ba0":()=>y(()=>import("./1.历史与架构.html-cD88aaBU.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2626dfde":()=>y(()=>import("./10.历时8年最终改版.html-rwQzBlk1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-058e4a4b":()=>y(()=>import("./2.Lucene的使用.html-2hMFeeJS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-411fdbb2":()=>y(()=>import("./3.定时任务.html-qFez5clX.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0d043462":()=>y(()=>import("./4.日志系统.html-pWJ6ghVV.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6094ea20":()=>y(()=>import("./5.小集群部署.html-Vk3PqneA.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-68e11d4e":()=>y(()=>import("./6.数据库备份.html-cRo7CD_Q.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1f1952ea":()=>y(()=>import("./7.那些牛逼的插件.html-923LgNG1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6dc450d0":()=>y(()=>import("./8.基于贝叶斯的情感分析.html-kXuTnRoS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-44460f42":()=>y(()=>import("./9.网站性能优化.html-3n6tdjL9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d7d7df80":()=>y(()=>import("./kafka.html-vXPGDb5r.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7d9b9318":()=>y(()=>import("./zookeeper.html-YcPoe8IG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3706649a":()=>y(()=>import("./404.html-WhIsgby4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-71b3ae87":()=>y(()=>import("./index.html-vgYoWX9F.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-14c69af4":()=>y(()=>import("./index.html-yuZKtvix.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-14e6315a":()=>y(()=>import("./index.html-T5wPpx5i.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-14e6501c":()=>y(()=>import("./index.html-Ibbd0oto.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-25b47c13":()=>y(()=>import("./index.html-zdhpQIq5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5d3e6196":()=>y(()=>import("./index.html-SLeyy5iI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3e13af88":()=>y(()=>import("./index.html-sgH7oDMT.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-60fc7530":()=>y(()=>import("./index.html-5KP2soWP.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-02bc92be":()=>y(()=>import("./index.html-8MJuJxlA.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-380c630d":()=>y(()=>import("./index.html-TuBE6nT4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-21ba2ec8":()=>y(()=>import("./index.html-DLDIhIzm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2921a50f":()=>y(()=>import("./index.html-NupEPZnP.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-862c4448":()=>y(()=>import("./index.html-j3N_gv-O.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0b6dfb7c":()=>y(()=>import("./index.html-Dlgh3iE3.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a32329e6":()=>y(()=>import("./index.html-NPk7ZlMe.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4d194044":()=>y(()=>import("./index.html-Prj9iPTA.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6e21a4b2":()=>y(()=>import("./index.html-VZNNIAqy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5bc93818":()=>y(()=>import("./index.html-KA0_6BkE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-744d024e":()=>y(()=>import("./index.html-48vkkelG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e52c881c":()=>y(()=>import("./index.html-IZIHDPXq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-154dc4c4":()=>y(()=>import("./index.html-XULjGA2d.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-01560935":()=>y(()=>import("./index.html-P7BZhZZ3.js"),__vite__mapDeps([])).then(({data:e})=>e)},Lf=JSON.parse('{"base":"/","lang":"zh-CN","title":"个人博客","description":"个人博客","head":[["script",{"defer":"defer","async":"async","src":"//cpro.baidustatic.com/cpro/ui/cm.js"}],["script",{"data-ad-client":"ca-pub-9037099208128116","async":true,"src":"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"}],["meta",{"name":"robots","content":"all"}],["meta",{"name":"author","content":"个人博客"}],["meta",{"http-equiv":"Cache-Control","content":"no-cache, no-store, must-revalidate"}],["meta",{"http-equiv":"Pragma","content":"no-cache"}],["meta",{"http-equiv":"Expires","content":"0"}],["meta",{"name":"keywords","content":"Java基础, 多线程, JVM, 虚拟机, 数据库, MySQL, Spring, Redis, MyBatis, 系统设计, 分布式, RPC, 高可用, 高并发"}],["meta",{"name":"description","content":"Java基础, 多线程, JVM, 虚拟机, 数据库, MySQL, Spring, Redis, MyBatis, 系统设计, 分布式, RPC, 高可用, 高并发"}],["meta",{"name":"apple-mobile-web-app-capable","content":"yes"}],["script",{},"var _hmt = _hmt || [];\\n (function() {\\n var hm = document.createElement(\\"script\\");\\n hm.src = \\"https://hm.baidu.com/hm.js?e580b8db831811a4aaf4a8f3e30034dc\\";\\n var s = document.getElementsByTagName(\\"script\\")[0]; \\n s.parentNode.insertBefore(hm, s);\\n })();"],["link",{"rel":"icon","href":"/favicon.ico"}]],"locales":{}}');var xf=([e,t,n])=>e==="meta"&&t.name?`${e}.${t.name}`:["title","base"].includes(e)?e:e==="template"&&t.id?`${e}.${t.id}`:JSON.stringify([e,t,n]),Sf=e=>{const t=new Set,n=[];return e.forEach(r=>{const a=xf(r);t.has(a)||(t.add(a),n.push(r))}),n},Tf=e=>e[0]==="/"?e:`/${e}`,Ps=e=>e[e.length-1]==="/"||e.endsWith(".html")?e:`${e}/`,xn=e=>/^(https?:)?\/\//.test(e),Bf=/.md((\?|#).*)?$/,qr=(e,t="/")=>!!(xn(e)||e.startsWith("/")&&!e.startsWith(t)&&!Bf.test(e)),Os=e=>/^[a-z][a-z0-9+.-]*:/.test(e),Cl=e=>Object.prototype.toString.call(e)==="[object Object]",Il=e=>e[e.length-1]==="/"?e.slice(0,-1):e,Ds=e=>e[0]==="/"?e.slice(1):e,Cf=(e,t)=>{const n=Object.keys(e).sort((r,a)=>{const l=a.split("/").length-r.split("/").length;return l!==0?l:a.length-r.length});for(const r of n)if(t.startsWith(r))return r;return"/"};const Rs={"v-8daa1a0e":F(()=>y(()=>import("./index.html-FEPMx79S.js"),__vite__mapDeps([]))),"v-728c3a8f":F(()=>y(()=>import("./index.html-bIaAM2PA.js"),__vite__mapDeps([]))),"v-cfe8b6c8":F(()=>y(()=>import("./index.html-h9DDJPFu.js"),__vite__mapDeps([]))),"v-2e25198a":F(()=>y(()=>import("./index.html-pTK8tT0u.js"),__vite__mapDeps([]))),"v-71fde78e":F(()=>y(()=>import("./index.html-zS2O51Oq.js"),__vite__mapDeps([]))),"v-580db9be":F(()=>y(()=>import("./devops-ping-tai.html-1QswvRRV.js"),__vite__mapDeps([]))),"v-06d5cd4c":F(()=>y(()=>import("./gitlab-ci.html-dr4MxX4e.js"),__vite__mapDeps([]))),"v-132efcd1":F(()=>y(()=>import("./jenkins-x.html-MktcI56z.js"),__vite__mapDeps([]))),"v-1a2ca7a7":F(()=>y(()=>import("./tekton.html-_o4_9OHV.js"),__vite__mapDeps([]))),"v-50cb12f2":F(()=>y(()=>import("./index.html-VBS4h1m3.js"),__vite__mapDeps([]))),"v-091223ce":F(()=>y(()=>import("./tiktok2023.html-vNmuRchL.js"),__vite__mapDeps([]))),"v-0a27b598":F(()=>y(()=>import("./JVM调优参数.html-_zG0M5-i.js"),__vite__mapDeps([]))),"v-60eda44c":F(()=>y(()=>import("./serverlog.html-tI2y9coc.js"),__vite__mapDeps([]))),"v-399e07b6":F(()=>y(()=>import("./一次jvm调优过程.html-2GlqVzrR.js"),__vite__mapDeps([]))),"v-660266c1":F(()=>y(()=>import("./内存屏障.html-S6Jp2mo3.js"),__vite__mapDeps([]))),"v-90f2343c":F(()=>y(()=>import("./在 Spring 6 中使用虚拟线程.html-S_l2wKz7.js"),__vite__mapDeps([]))),"v-0b5d4df0":F(()=>y(()=>import("./基于kubernetes的分布式限流.html-sbydyYPs.js"),__vite__mapDeps([]))),"v-21e54510":F(()=>y(()=>import("./index.html-IB-VG-Mp.js"),__vite__mapDeps([]))),"v-57ae83ac":F(()=>y(()=>import("./spark on k8s operator.html-xMGCveTO.js"),__vite__mapDeps([]))),"v-22e4234a":F(()=>y(()=>import("./2017.html-MDg2apnF.js"),__vite__mapDeps([]))),"v-1f7a720c":F(()=>y(()=>import("./2018.html-XhKmceXA.js"),__vite__mapDeps([]))),"v-1c10c0ce":F(()=>y(()=>import("./2019.html-znm2eQc3.js"),__vite__mapDeps([]))),"v-b0e413b8":F(()=>y(()=>import("./main.html-gMstwCzy.js"),__vite__mapDeps([]))),"v-258f309e":F(()=>y(()=>import("./index.html-1PklmZ2g.js"),__vite__mapDeps([]))),"v-510415f9":F(()=>y(()=>import("./chatgpt.html-tmuTnMCN.js"),__vite__mapDeps([]))),"v-68e0ce3f":F(()=>y(()=>import("./starcraft-ai.html-p5HRu5Fy.js"),__vite__mapDeps([]))),"v-3c114a75":F(()=>y(()=>import("./tesla.html-NKqgulgY.js"),__vite__mapDeps([]))),"v-90e5bb66":F(()=>y(()=>import("./广州图书馆借阅抓取.html-oolMetg1.js"),__vite__mapDeps([]))),"v-dc384366":F(()=>y(()=>import("./index.html-3mbB5C3H.js"),__vite__mapDeps([]))),"v-70796e0a":F(()=>y(()=>import("./redis缓存.html--dFiuCqw.js"),__vite__mapDeps([]))),"v-43e9e6b0":F(()=>y(()=>import("./wewe.html-WVS44t7L.js"),__vite__mapDeps([]))),"v-33bd146f":F(()=>y(()=>import("./个人作品.html-Hz6pe8Pm.js"),__vite__mapDeps([]))),"v-04e32b44":F(()=>y(()=>import("./elastic-spark.html-ys8zTss9.js"),__vite__mapDeps([]))),"v-d73a9aee":F(()=>y(()=>import("./elasticsearch源码debug.html-0y-mDJbS.js"),__vite__mapDeps([]))),"v-3f2a15ee":F(()=>y(()=>import("./【elasticsearch】搜索过程详解.html-yIULGMSO.js"),__vite__mapDeps([]))),"v-aa93dec0":F(()=>y(()=>import("./1mysql.html-Ei_7f_WQ.js"),__vite__mapDeps([]))),"v-0a0b7a54":F(()=>y(()=>import("./数据库缓存.html-GSdRVX9_.js"),__vite__mapDeps([]))),"v-137d5dcc":F(()=>y(()=>import("./redis缓存.html-vh2fHF7B.js"),__vite__mapDeps([]))),"v-16aa42ca":F(()=>y(()=>import("./Spring Boot Prometheus使用.html-V7I--Ipk.js"),__vite__mapDeps([]))),"v-5089f9f3":F(()=>y(()=>import("./aop.html-vlpDYLuE.js"),__vite__mapDeps([]))),"v-7586af98":F(()=>y(()=>import("./webflux.html-PgcG3rG7.js"),__vite__mapDeps([]))),"v-59449ba0":F(()=>y(()=>import("./1.历史与架构.html-Td7kF-9n.js"),__vite__mapDeps([]))),"v-2626dfde":F(()=>y(()=>import("./10.历时8年最终改版.html-tUYTH5tb.js"),__vite__mapDeps([]))),"v-058e4a4b":F(()=>y(()=>import("./2.Lucene的使用.html-qm2pGUZ0.js"),__vite__mapDeps([]))),"v-411fdbb2":F(()=>y(()=>import("./3.定时任务.html-HLLS9x6l.js"),__vite__mapDeps([]))),"v-0d043462":F(()=>y(()=>import("./4.日志系统.html-rdybAcfJ.js"),__vite__mapDeps([]))),"v-6094ea20":F(()=>y(()=>import("./5.小集群部署.html-6tnyAU-k.js"),__vite__mapDeps([]))),"v-68e11d4e":F(()=>y(()=>import("./6.数据库备份.html-RXzoE_MH.js"),__vite__mapDeps([]))),"v-1f1952ea":F(()=>y(()=>import("./7.那些牛逼的插件.html-553rUa1v.js"),__vite__mapDeps([]))),"v-6dc450d0":F(()=>y(()=>import("./8.基于贝叶斯的情感分析.html-hE6G3Tqn.js"),__vite__mapDeps([]))),"v-44460f42":F(()=>y(()=>import("./9.网站性能优化.html-YAx6WK4Q.js"),__vite__mapDeps([]))),"v-d7d7df80":F(()=>y(()=>import("./kafka.html-p9lSBY-U.js"),__vite__mapDeps([]))),"v-7d9b9318":F(()=>y(()=>import("./zookeeper.html-LJ6qa5Y9.js"),__vite__mapDeps([]))),"v-3706649a":F(()=>y(()=>import("./404.html-F74GSICT.js"),__vite__mapDeps([]))),"v-71b3ae87":F(()=>y(()=>import("./index.html-LxuTaAGt.js"),__vite__mapDeps([]))),"v-14c69af4":F(()=>y(()=>import("./index.html-iUEVv6c6.js"),__vite__mapDeps([]))),"v-14e6315a":F(()=>y(()=>import("./index.html-1sFnb2Lj.js"),__vite__mapDeps([]))),"v-14e6501c":F(()=>y(()=>import("./index.html-VH5_9vnr.js"),__vite__mapDeps([]))),"v-25b47c13":F(()=>y(()=>import("./index.html-cMYV1G54.js"),__vite__mapDeps([]))),"v-5d3e6196":F(()=>y(()=>import("./index.html-m97a0bAY.js"),__vite__mapDeps([]))),"v-3e13af88":F(()=>y(()=>import("./index.html-W7NDSfQJ.js"),__vite__mapDeps([]))),"v-60fc7530":F(()=>y(()=>import("./index.html-99A78MjC.js"),__vite__mapDeps([]))),"v-02bc92be":F(()=>y(()=>import("./index.html-r9GuP2yb.js"),__vite__mapDeps([]))),"v-380c630d":F(()=>y(()=>import("./index.html-Wy8VVR2w.js"),__vite__mapDeps([]))),"v-21ba2ec8":F(()=>y(()=>import("./index.html-ge6-rWX_.js"),__vite__mapDeps([]))),"v-2921a50f":F(()=>y(()=>import("./index.html-EL40ihRZ.js"),__vite__mapDeps([]))),"v-862c4448":F(()=>y(()=>import("./index.html-TQjoPWRe.js"),__vite__mapDeps([]))),"v-0b6dfb7c":F(()=>y(()=>import("./index.html-eHm_BaZP.js"),__vite__mapDeps([]))),"v-a32329e6":F(()=>y(()=>import("./index.html-_qUKpQt2.js"),__vite__mapDeps([]))),"v-4d194044":F(()=>y(()=>import("./index.html-w8XwDCrF.js"),__vite__mapDeps([]))),"v-6e21a4b2":F(()=>y(()=>import("./index.html-XRBVnkdY.js"),__vite__mapDeps([]))),"v-5bc93818":F(()=>y(()=>import("./index.html-90zxtr19.js"),__vite__mapDeps([]))),"v-744d024e":F(()=>y(()=>import("./index.html-1trTdh4U.js"),__vite__mapDeps([]))),"v-e52c881c":F(()=>y(()=>import("./index.html-5mbY1w6w.js"),__vite__mapDeps([]))),"v-154dc4c4":F(()=>y(()=>import("./index.html-Rmp6Dnhx.js"),__vite__mapDeps([]))),"v-01560935":F(()=>y(()=>import("./index.html-NrD26gEP.js"),__vite__mapDeps([])))};var If=Symbol(""),Ms=Symbol(""),Pf=Xt({key:"",path:"",title:"",lang:"",frontmatter:{},headers:[]}),ie=()=>{const e=he(Ms);if(!e)throw new Error("pageData() is called without provider.");return e},Fs=Symbol(""),_e=()=>{const e=he(Fs);if(!e)throw new Error("usePageFrontmatter() is called without provider.");return e},Vs=Symbol(""),Of=()=>{const e=he(Vs);if(!e)throw new Error("usePageHead() is called without provider.");return e},Df=Symbol(""),$s=Symbol(""),Pl=()=>{const e=he($s);if(!e)throw new Error("usePageLang() is called without provider.");return e},js=Symbol(""),Rf=()=>{const e=he(js);if(!e)throw new Error("usePageLayout() is called without provider.");return e},Mf=X(Af),Ol=Symbol(""),ct=()=>{const e=he(Ol);if(!e)throw new Error("useRouteLocale() is called without provider.");return e},cn=X(Lf),Ns=()=>cn,zs=Symbol(""),rr=()=>{const e=he(zs);if(!e)throw new Error("useSiteLocaleData() is called without provider.");return e},Ff=Symbol(""),Vf="Layout",$f="NotFound",yt=Qn({resolveLayouts:e=>e.reduce((t,n)=>({...t,...n.layouts}),{}),resolvePageData:async e=>{const t=Mf.value[e];return await(t==null?void 0:t())??Pf},resolvePageFrontmatter:e=>e.frontmatter,resolvePageHead:(e,t,n)=>{const r=oe(t.description)?t.description:n.description,a=[...Q(t.head)?t.head:[],...n.head,["title",{},e],["meta",{name:"description",content:r}]];return Sf(a)},resolvePageHeadTitle:(e,t)=>[e.title,t.title].filter(n=>!!n).join(" | "),resolvePageLang:(e,t)=>e.lang||t.lang||"en-US",resolvePageLayout:(e,t)=>{let n;if(e.path){const r=e.frontmatter.layout;oe(r)?n=r:n=Vf}else n=$f;return t[n]},resolveRouteLocale:(e,t)=>Cf(e,t),resolveSiteLocaleData:(e,t)=>({...e,...e.locales[t]})}),oa=V({name:"ClientOnly",setup(e,t){const n=X(!1);return Ee(()=>{n.value=!0}),()=>{var r,a;return n.value?(a=(r=t.slots).default)==null?void 0:a.call(r):null}}}),Hs=V({name:"Content",props:{pageKey:{type:String,required:!1,default:""}},setup(e){const t=ie(),n=E(()=>Rs[e.pageKey||t.value.key]);return()=>n.value?i(n.value):i("div","404 Not Found")}}),Ye=(e={})=>e,Le=e=>xn(e)?e:`/${Ds(e)}`;const jf={};function Nf(e,t,n){var r,a,l;t===void 0&&(t=50),n===void 0&&(n={});var o=(r=n.isImmediate)!=null&&r,s=(a=n.callback)!=null&&a,c=n.maxWait,u=Date.now(),d=[];function f(){if(c!==void 0){var h=Date.now()-u;if(h+t>=c)return c-h}return t}var p=function(){var h=[].slice.call(arguments),g=this;return new Promise(function(w,k){var b=o&&l===void 0;if(l!==void 0&&clearTimeout(l),l=setTimeout(function(){if(l=void 0,u=Date.now(),!o){var _=e.apply(g,h);s&&s(_),d.forEach(function(S){return(0,S.resolve)(_)}),d=[]}},f()),b){var x=e.apply(g,h);return s&&s(x),w(x)}d.push({resolve:w,reject:k})})};return p.cancel=function(h){l!==void 0&&clearTimeout(l),d.forEach(function(g){return(0,g.reject)(h)}),d=[]},p}/*!
+ * vue-router v4.2.5
+ * (c) 2023 Eduardo San Martin Morote
+ * @license MIT
+ */const on=typeof window<"u";function zf(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const me=Object.assign;function Sa(e,t){const n={};for(const r in t){const a=t[r];n[r]=st(a)?a.map(e):e(a)}return n}const Nn=()=>{},st=Array.isArray,Hf=/\/$/,qf=e=>e.replace(Hf,"");function Ta(e,t,n="/"){let r,a={},l="",o="";const s=t.indexOf("#");let c=t.indexOf("?");return s=0&&(c=-1),c>-1&&(r=t.slice(0,c),l=t.slice(c+1,s>-1?s:t.length),a=e(l)),s>-1&&(r=r||t.slice(0,s),o=t.slice(s,t.length)),r=Wf(r??t,n),{fullPath:r+(l&&"?")+l+o,path:r,query:a,hash:o}}function Gf(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function qo(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Uf(e,t,n){const r=t.matched.length-1,a=n.matched.length-1;return r>-1&&r===a&&bn(t.matched[r],n.matched[a])&&qs(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function bn(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function qs(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!Kf(e[n],t[n]))return!1;return!0}function Kf(e,t){return st(e)?Go(e,t):st(t)?Go(t,e):e===t}function Go(e,t){return st(t)?e.length===t.length&&e.every((n,r)=>n===t[r]):e.length===1&&e[0]===t}function Wf(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),a=r[r.length-1];(a===".."||a===".")&&r.push("");let l=n.length-1,o,s;for(o=0;o1&&l--;else break;return n.slice(0,l).join("/")+"/"+r.slice(o-(o===r.length?1:0)).join("/")}var Jn;(function(e){e.pop="pop",e.push="push"})(Jn||(Jn={}));var zn;(function(e){e.back="back",e.forward="forward",e.unknown=""})(zn||(zn={}));function Jf(e){if(!e)if(on){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),qf(e)}const Yf=/^[^#]+#/;function Zf(e,t){return e.replace(Yf,"#")+t}function Qf(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const ia=()=>({left:window.pageXOffset,top:window.pageYOffset});function Xf(e){let t;if("el"in e){const n=e.el,r=typeof n=="string"&&n.startsWith("#"),a=typeof n=="string"?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!a)return;t=Qf(a,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.pageXOffset,t.top!=null?t.top:window.pageYOffset)}function Uo(e,t){return(history.state?history.state.position-t:-1)+e}const Ya=new Map;function ep(e,t){Ya.set(e,t)}function tp(e){const t=Ya.get(e);return Ya.delete(e),t}let np=()=>location.protocol+"//"+location.host;function Gs(e,t){const{pathname:n,search:r,hash:a}=t,l=e.indexOf("#");if(l>-1){let s=a.includes(e.slice(l))?e.slice(l).length:1,c=a.slice(s);return c[0]!=="/"&&(c="/"+c),qo(c,"")}return qo(n,e)+r+a}function rp(e,t,n,r){let a=[],l=[],o=null;const s=({state:p})=>{const h=Gs(e,location),g=n.value,w=t.value;let k=0;if(p){if(n.value=h,t.value=p,o&&o===g){o=null;return}k=w?p.position-w.position:0}else r(h);a.forEach(b=>{b(n.value,g,{delta:k,type:Jn.pop,direction:k?k>0?zn.forward:zn.back:zn.unknown})})};function c(){o=n.value}function u(p){a.push(p);const h=()=>{const g=a.indexOf(p);g>-1&&a.splice(g,1)};return l.push(h),h}function d(){const{history:p}=window;p.state&&p.replaceState(me({},p.state,{scroll:ia()}),"")}function f(){for(const p of l)p();l=[],window.removeEventListener("popstate",s),window.removeEventListener("beforeunload",d)}return window.addEventListener("popstate",s),window.addEventListener("beforeunload",d,{passive:!0}),{pauseListeners:c,listen:u,destroy:f}}function Ko(e,t,n,r=!1,a=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:a?ia():null}}function ap(e){const{history:t,location:n}=window,r={value:Gs(e,n)},a={value:t.state};a.value||l(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function l(c,u,d){const f=e.indexOf("#"),p=f>-1?(n.host&&document.querySelector("base")?e:e.slice(f))+c:np()+e+c;try{t[d?"replaceState":"pushState"](u,"",p),a.value=u}catch(h){console.error(h),n[d?"replace":"assign"](p)}}function o(c,u){const d=me({},t.state,Ko(a.value.back,c,a.value.forward,!0),u,{position:a.value.position});l(c,d,!0),r.value=c}function s(c,u){const d=me({},a.value,t.state,{forward:c,scroll:ia()});l(d.current,d,!0);const f=me({},Ko(r.value,c,null),{position:d.position+1},u);l(c,f,!1),r.value=c}return{location:r,state:a,push:s,replace:o}}function lp(e){e=Jf(e);const t=ap(e),n=rp(e,t.state,t.location,t.replace);function r(l,o=!0){o||n.pauseListeners(),history.go(l)}const a=me({location:"",base:e,go:r,createHref:Zf.bind(null,e)},t,n);return Object.defineProperty(a,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(a,"state",{enumerable:!0,get:()=>t.state.value}),a}function op(e){return typeof e=="string"||e&&typeof e=="object"}function Us(e){return typeof e=="string"||typeof e=="symbol"}const Et={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0},Ks=Symbol("");var Wo;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(Wo||(Wo={}));function _n(e,t){return me(new Error,{type:e,[Ks]:!0},t)}function bt(e,t){return e instanceof Error&&Ks in e&&(t==null||!!(e.type&t))}const Jo="[^/]+?",ip={sensitive:!1,strict:!1,start:!0,end:!0},sp=/[.+*?^${}()[\]/\\]/g;function cp(e,t){const n=me({},ip,t),r=[];let a=n.start?"^":"";const l=[];for(const u of e){const d=u.length?[]:[90];n.strict&&!u.length&&(a+="/");for(let f=0;ft.length?t.length===1&&t[0]===80?1:-1:0}function dp(e,t){let n=0;const r=e.score,a=t.score;for(;n0&&t[t.length-1]<0}const fp={type:0,value:""},pp=/[a-zA-Z0-9_]/;function hp(e){if(!e)return[[]];if(e==="/")return[[fp]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(h){throw new Error(`ERR (${n})/"${u}": ${h}`)}let n=0,r=n;const a=[];let l;function o(){l&&a.push(l),l=[]}let s=0,c,u="",d="";function f(){u&&(n===0?l.push({type:0,value:u}):n===1||n===2||n===3?(l.length>1&&(c==="*"||c==="+")&&t(`A repeatable param (${u}) must be alone in its segment. eg: '/:ids+.`),l.push({type:1,value:u,regexp:d,repeatable:c==="*"||c==="+",optional:c==="*"||c==="?"})):t("Invalid state to consume buffer"),u="")}function p(){u+=c}for(;s{o(x)}:Nn}function o(d){if(Us(d)){const f=r.get(d);f&&(r.delete(d),n.splice(n.indexOf(f),1),f.children.forEach(o),f.alias.forEach(o))}else{const f=n.indexOf(d);f>-1&&(n.splice(f,1),d.record.name&&r.delete(d.record.name),d.children.forEach(o),d.alias.forEach(o))}}function s(){return n}function c(d){let f=0;for(;f=0&&(d.record.path!==n[f].record.path||!Ws(d,n[f]));)f++;n.splice(f,0,d),d.record.name&&!Qo(d)&&r.set(d.record.name,d)}function u(d,f){let p,h={},g,w;if("name"in d&&d.name){if(p=r.get(d.name),!p)throw _n(1,{location:d});w=p.record.name,h=me(Zo(f.params,p.keys.filter(x=>!x.optional).map(x=>x.name)),d.params&&Zo(d.params,p.keys.map(x=>x.name))),g=p.stringify(h)}else if("path"in d)g=d.path,p=n.find(x=>x.re.test(g)),p&&(h=p.parse(g),w=p.record.name);else{if(p=f.name?r.get(f.name):n.find(x=>x.re.test(f.path)),!p)throw _n(1,{location:d,currentLocation:f});w=p.record.name,h=me({},f.params,d.params),g=p.stringify(h)}const k=[];let b=p;for(;b;)k.unshift(b.record),b=b.parent;return{name:w,path:g,params:h,matched:k,meta:_p(k)}}return e.forEach(d=>l(d)),{addRoute:l,resolve:u,removeRoute:o,getRoutes:s,getRecordMatcher:a}}function Zo(e,t){const n={};for(const r of t)r in e&&(n[r]=e[r]);return n}function gp(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:bp(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}}}function bp(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const r in e.components)t[r]=typeof n=="object"?n[r]:n;return t}function Qo(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function _p(e){return e.reduce((t,n)=>me(t,n.meta),{})}function Xo(e,t){const n={};for(const r in e)n[r]=r in t?t[r]:e[r];return n}function Ws(e,t){return t.children.some(n=>n===e||Ws(e,n))}const Js=/#/g,yp=/&/g,Ep=/\//g,kp=/=/g,wp=/\?/g,Ys=/\+/g,Ap=/%5B/g,Lp=/%5D/g,Zs=/%5E/g,xp=/%60/g,Qs=/%7B/g,Sp=/%7C/g,Xs=/%7D/g,Tp=/%20/g;function Dl(e){return encodeURI(""+e).replace(Sp,"|").replace(Ap,"[").replace(Lp,"]")}function Bp(e){return Dl(e).replace(Qs,"{").replace(Xs,"}").replace(Zs,"^")}function Za(e){return Dl(e).replace(Ys,"%2B").replace(Tp,"+").replace(Js,"%23").replace(yp,"%26").replace(xp,"`").replace(Qs,"{").replace(Xs,"}").replace(Zs,"^")}function Cp(e){return Za(e).replace(kp,"%3D")}function Ip(e){return Dl(e).replace(Js,"%23").replace(wp,"%3F")}function Pp(e){return e==null?"":Ip(e).replace(Ep,"%2F")}function Gr(e){try{return decodeURIComponent(""+e)}catch{}return""+e}function Op(e){const t={};if(e===""||e==="?")return t;const r=(e[0]==="?"?e.slice(1):e).split("&");for(let a=0;al&&Za(l)):[r&&Za(r)]).forEach(l=>{l!==void 0&&(t+=(t.length?"&":"")+n,l!=null&&(t+="="+l))})}return t}function Dp(e){const t={};for(const n in e){const r=e[n];r!==void 0&&(t[n]=st(r)?r.map(a=>a==null?null:""+a):r==null?r:""+r)}return t}const Rp=Symbol(""),ti=Symbol(""),sa=Symbol(""),Rl=Symbol(""),Qa=Symbol("");function In(){let e=[];function t(r){return e.push(r),()=>{const a=e.indexOf(r);a>-1&&e.splice(a,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function Dt(e,t,n,r,a){const l=r&&(r.enterCallbacks[a]=r.enterCallbacks[a]||[]);return()=>new Promise((o,s)=>{const c=f=>{f===!1?s(_n(4,{from:n,to:t})):f instanceof Error?s(f):op(f)?s(_n(2,{from:t,to:f})):(l&&r.enterCallbacks[a]===l&&typeof f=="function"&&l.push(f),o())},u=e.call(r&&r.instances[a],t,n,c);let d=Promise.resolve(u);e.length<3&&(d=d.then(c)),d.catch(f=>s(f))})}function Ba(e,t,n,r){const a=[];for(const l of e)for(const o in l.components){let s=l.components[o];if(!(t!=="beforeRouteEnter"&&!l.instances[o]))if(Mp(s)){const u=(s.__vccOpts||s)[t];u&&a.push(Dt(u,n,r,l,o))}else{let c=s();a.push(()=>c.then(u=>{if(!u)return Promise.reject(new Error(`Couldn't resolve component "${o}" at "${l.path}"`));const d=zf(u)?u.default:u;l.components[o]=d;const p=(d.__vccOpts||d)[t];return p&&Dt(p,n,r,l,o)()}))}}return a}function Mp(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function Xa(e){const t=he(sa),n=he(Rl),r=E(()=>t.resolve(Wt(e.to))),a=E(()=>{const{matched:c}=r.value,{length:u}=c,d=c[u-1],f=n.matched;if(!d||!f.length)return-1;const p=f.findIndex(bn.bind(null,d));if(p>-1)return p;const h=ni(c[u-2]);return u>1&&ni(d)===h&&f[f.length-1].path!==h?f.findIndex(bn.bind(null,c[u-2])):p}),l=E(()=>a.value>-1&&jp(n.params,r.value.params)),o=E(()=>a.value>-1&&a.value===n.matched.length-1&&qs(n.params,r.value.params));function s(c={}){return $p(c)?t[Wt(e.replace)?"replace":"push"](Wt(e.to)).catch(Nn):Promise.resolve()}return{route:r,href:E(()=>r.value.href),isActive:l,isExactActive:o,navigate:s}}const Fp=V({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:Xa,setup(e,{slots:t}){const n=Qn(Xa(e)),{options:r}=he(sa),a=E(()=>({[ri(e.activeClass,r.linkActiveClass,"router-link-active")]:n.isActive,[ri(e.exactActiveClass,r.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const l=t.default&&t.default(n);return e.custom?l:i("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:a.value},l)}}}),Vp=Fp;function $p(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function jp(e,t){for(const n in t){const r=t[n],a=e[n];if(typeof r=="string"){if(r!==a)return!1}else if(!st(a)||a.length!==r.length||r.some((l,o)=>l!==a[o]))return!1}return!0}function ni(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const ri=(e,t,n)=>e??t??n,Np=V({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const r=he(Qa),a=E(()=>e.route||r.value),l=he(ti,0),o=E(()=>{let u=Wt(l);const{matched:d}=a.value;let f;for(;(f=d[u])&&!f.components;)u++;return u}),s=E(()=>a.value.matched[o.value]);it(ti,E(()=>o.value+1)),it(Rp,s),it(Qa,a);const c=X();return ye(()=>[c.value,s.value,e.name],([u,d,f],[p,h,g])=>{d&&(d.instances[f]=u,h&&h!==d&&u&&u===p&&(d.leaveGuards.size||(d.leaveGuards=h.leaveGuards),d.updateGuards.size||(d.updateGuards=h.updateGuards))),u&&d&&(!h||!bn(d,h)||!p)&&(d.enterCallbacks[f]||[]).forEach(w=>w(u))},{flush:"post"}),()=>{const u=a.value,d=e.name,f=s.value,p=f&&f.components[d];if(!p)return ai(n.default,{Component:p,route:u});const h=f.props[d],g=h?h===!0?u.params:typeof h=="function"?h(u):h:null,k=i(p,me({},g,t,{onVnodeUnmounted:b=>{b.component.isUnmounted&&(f.instances[d]=null)},ref:c}));return ai(n.default,{Component:k,route:u})||k}}});function ai(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const ec=Np;function zp(e){const t=mp(e.routes,e),n=e.parseQuery||Op,r=e.stringifyQuery||ei,a=e.history,l=In(),o=In(),s=In(),c=mt(Et);let u=Et;on&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const d=Sa.bind(null,B=>""+B),f=Sa.bind(null,Pp),p=Sa.bind(null,Gr);function h(B,q){let z,K;return Us(B)?(z=t.getRecordMatcher(B),K=q):K=B,t.addRoute(K,z)}function g(B){const q=t.getRecordMatcher(B);q&&t.removeRoute(q)}function w(){return t.getRoutes().map(B=>B.record)}function k(B){return!!t.getRecordMatcher(B)}function b(B,q){if(q=me({},q||c.value),typeof B=="string"){const m=Ta(n,B,q.path),A=t.resolve({path:m.path},q),C=a.createHref(m.fullPath);return me(m,A,{params:p(A.params),hash:Gr(m.hash),redirectedFrom:void 0,href:C})}let z;if("path"in B)z=me({},B,{path:Ta(n,B.path,q.path).path});else{const m=me({},B.params);for(const A in m)m[A]==null&&delete m[A];z=me({},B,{params:f(m)}),q.params=f(q.params)}const K=t.resolve(z,q),ve=B.hash||"";K.params=d(p(K.params));const ke=Gf(r,me({},B,{hash:Bp(ve),path:K.path})),v=a.createHref(ke);return me({fullPath:ke,hash:ve,query:r===ei?Dp(B.query):B.query||{}},K,{redirectedFrom:void 0,href:v})}function x(B){return typeof B=="string"?Ta(n,B,c.value.path):me({},B)}function _(B,q){if(u!==B)return _n(8,{from:q,to:B})}function S(B){return U(B)}function D(B){return S(me(x(B),{replace:!0}))}function L(B){const q=B.matched[B.matched.length-1];if(q&&q.redirect){const{redirect:z}=q;let K=typeof z=="function"?z(B):z;return typeof K=="string"&&(K=K.includes("?")||K.includes("#")?K=x(K):{path:K},K.params={}),me({query:B.query,hash:B.hash,params:"path"in K?{}:B.params},K)}}function U(B,q){const z=u=b(B),K=c.value,ve=B.state,ke=B.force,v=B.replace===!0,m=L(z);if(m)return U(me(x(m),{state:typeof m=="object"?me({},ve,m.state):ve,force:ke,replace:v}),q||z);const A=z;A.redirectedFrom=q;let C;return!ke&&Uf(r,K,z)&&(C=_n(16,{to:A,from:K}),ut(K,K,!0,!1)),(C?Promise.resolve(C):j(A,K)).catch(T=>bt(T)?bt(T,2)?T:Lt(T):W(T,A,K)).then(T=>{if(T){if(bt(T,2))return U(me({replace:v},x(T.to),{state:typeof T.to=="object"?me({},ve,T.to.state):ve,force:ke}),q||A)}else T=N(A,K,!0,v,ve);return ne(A,K,T),T})}function $(B,q){const z=_(B,q);return z?Promise.reject(z):Promise.resolve()}function R(B){const q=an.values().next().value;return q&&typeof q.runWithContext=="function"?q.runWithContext(B):B()}function j(B,q){let z;const[K,ve,ke]=Hp(B,q);z=Ba(K.reverse(),"beforeRouteLeave",B,q);for(const m of K)m.leaveGuards.forEach(A=>{z.push(Dt(A,B,q))});const v=$.bind(null,B,q);return z.push(v),Me(z).then(()=>{z=[];for(const m of l.list())z.push(Dt(m,B,q));return z.push(v),Me(z)}).then(()=>{z=Ba(ve,"beforeRouteUpdate",B,q);for(const m of ve)m.updateGuards.forEach(A=>{z.push(Dt(A,B,q))});return z.push(v),Me(z)}).then(()=>{z=[];for(const m of ke)if(m.beforeEnter)if(st(m.beforeEnter))for(const A of m.beforeEnter)z.push(Dt(A,B,q));else z.push(Dt(m.beforeEnter,B,q));return z.push(v),Me(z)}).then(()=>(B.matched.forEach(m=>m.enterCallbacks={}),z=Ba(ke,"beforeRouteEnter",B,q),z.push(v),Me(z))).then(()=>{z=[];for(const m of o.list())z.push(Dt(m,B,q));return z.push(v),Me(z)}).catch(m=>bt(m,8)?m:Promise.reject(m))}function ne(B,q,z){s.list().forEach(K=>R(()=>K(B,q,z)))}function N(B,q,z,K,ve){const ke=_(B,q);if(ke)return ke;const v=q===Et,m=on?history.state:{};z&&(K||v?a.replace(B.fullPath,me({scroll:v&&m&&m.scroll},ve)):a.push(B.fullPath,ve)),c.value=B,ut(B,q,z,v),Lt()}let ee;function Se(){ee||(ee=a.listen((B,q,z)=>{if(!mr.listening)return;const K=b(B),ve=L(K);if(ve){U(me(ve,{replace:!0}),K).catch(Nn);return}u=K;const ke=c.value;on&&ep(Uo(ke.fullPath,z.delta),ia()),j(K,ke).catch(v=>bt(v,12)?v:bt(v,2)?(U(v.to,K).then(m=>{bt(m,20)&&!z.delta&&z.type===Jn.pop&&a.go(-1,!1)}).catch(Nn),Promise.reject()):(z.delta&&a.go(-z.delta,!1),W(v,K,ke))).then(v=>{v=v||N(K,ke,!1),v&&(z.delta&&!bt(v,8)?a.go(-z.delta,!1):z.type===Jn.pop&&bt(v,20)&&a.go(-1,!1)),ne(K,ke,v)}).catch(Nn)}))}let Te=In(),J=In(),ae;function W(B,q,z){Lt(B);const K=J.list();return K.length?K.forEach(ve=>ve(B,q,z)):console.error(B),Promise.reject(B)}function rt(){return ae&&c.value!==Et?Promise.resolve():new Promise((B,q)=>{Te.add([B,q])})}function Lt(B){return ae||(ae=!B,Se(),Te.list().forEach(([q,z])=>B?z(B):q()),Te.reset()),B}function ut(B,q,z,K){const{scrollBehavior:ve}=e;if(!on||!ve)return Promise.resolve();const ke=!z&&tp(Uo(B.fullPath,0))||(K||!z)&&history.state&&history.state.scroll||null;return en().then(()=>ve(B,q,ke)).then(v=>v&&Xf(v)).catch(v=>W(v,B,q))}const Ne=B=>a.go(B);let rn;const an=new Set,mr={currentRoute:c,listening:!0,addRoute:h,removeRoute:g,hasRoute:k,getRoutes:w,resolve:b,options:e,push:S,replace:D,go:Ne,back:()=>Ne(-1),forward:()=>Ne(1),beforeEach:l.add,beforeResolve:o.add,afterEach:s.add,onError:J.add,isReady:rt,install(B){const q=this;B.component("RouterLink",Vp),B.component("RouterView",ec),B.config.globalProperties.$router=q,Object.defineProperty(B.config.globalProperties,"$route",{enumerable:!0,get:()=>Wt(c)}),on&&!rn&&c.value===Et&&(rn=!0,S(a.location).catch(ve=>{}));const z={};for(const ve in Et)Object.defineProperty(z,ve,{get:()=>c.value[ve],enumerable:!0});B.provide(sa,q),B.provide(Rl,qi(z)),B.provide(Qa,c);const K=B.unmount;an.add(B),B.unmount=function(){an.delete(B),an.size<1&&(u=Et,ee&&ee(),ee=null,c.value=Et,rn=!1,ae=!1),K()}}};function Me(B){return B.reduce((q,z)=>q.then(()=>R(z)),Promise.resolve())}return mr}function Hp(e,t){const n=[],r=[],a=[],l=Math.max(t.matched.length,e.matched.length);for(let o=0;obn(u,s))?r.push(s):n.push(s));const c=e.matched[o];c&&(t.matched.find(u=>bn(u,c))||a.push(c))}return[n,r,a]}function Ve(){return he(sa)}function gt(){return he(Rl)}const qp=({headerLinkSelector:e,headerAnchorSelector:t,delay:n,offset:r=5})=>{const a=Ve(),o=Nf(()=>{var w,k;const s=Math.max(window.scrollY,document.documentElement.scrollTop,document.body.scrollTop);if(Math.abs(s-0)p.some(x=>x.hash===b.hash));for(let b=0;b=(((w=x.parentElement)==null?void 0:w.offsetTop)??0)-r,D=!_||s<(((k=_.parentElement)==null?void 0:k.offsetTop)??0)-r;if(!(S&&D))continue;const U=decodeURIComponent(a.currentRoute.value.hash),$=decodeURIComponent(x.hash);if(U===$)return;if(f){for(let R=b+1;R{window.addEventListener("scroll",o)}),na(()=>{window.removeEventListener("scroll",o)})},li=async(e,t)=>{const{scrollBehavior:n}=e.options;e.options.scrollBehavior=void 0,await e.replace({query:e.currentRoute.value.query,hash:t}).finally(()=>e.options.scrollBehavior=n)},Gp=".vp-sidebar-link, .toc-link",Up=".header-anchor",Kp=200,Wp=5,Jp=Ye({setup(){qp({headerLinkSelector:Gp,headerAnchorSelector:Up,delay:Kp,offset:Wp})}}),pe=({name:e="",color:t="currentColor"},{slots:n})=>{var r;return i("svg",{xmlns:"http://www.w3.org/2000/svg",class:["icon",`${e}-icon`],viewBox:"0 0 1024 1024",fill:t,"aria-label":`${e} icon`},(r=n.default)==null?void 0:r.call(n))};pe.displayName="IconBase";const tc=({size:e=48,stroke:t=4,wrapper:n=!0,height:r=2*e})=>{const a=i("svg",{xmlns:"http://www.w3.org/2000/svg",width:e,height:e,preserveAspectRatio:"xMidYMid",viewBox:"25 25 50 50"},[i("animateTransform",{attributeName:"transform",type:"rotate",dur:"2s",keyTimes:"0;1",repeatCount:"indefinite",values:"0;360"}),i("circle",{cx:"50",cy:"50",r:"20",fill:"none",stroke:"currentColor","stroke-width":t,"stroke-linecap":"round"},[i("animate",{attributeName:"stroke-dasharray",dur:"1.5s",keyTimes:"0;0.5;1",repeatCount:"indefinite",values:"1,200;90,200;1,200"}),i("animate",{attributeName:"stroke-dashoffset",dur:"1.5s",keyTimes:"0;0.5;1",repeatCount:"indefinite",values:"0;-35px;-125px"})])]);return n?i("div",{class:"loading-icon-wrapper",style:`display:flex;align-items:center;justify-content:center;height:${r}px`},a):a};tc.displayName="LoadingIcon";const nc=(e,{slots:t})=>{var n;return(n=t.default)==null?void 0:n.call(t)},Ml=(e="")=>{if(e){if(typeof e=="number")return new Date(e);const t=Date.parse(e.toString());if(!Number.isNaN(t))return new Date(t)}return null},ca=(e,t)=>{let n=1;for(let r=0;r>6;return n+=n<<3,n^=n>>11,n%t},rc=Array.isArray,Yp=e=>typeof e=="function",Zp=e=>typeof e=="string";var ua=e=>/^(https?:)?\/\//.test(e),Qp=/.md((\?|#).*)?$/,Xp=(e,t="/")=>!!(ua(e)||e.startsWith("/")&&!e.startsWith(t)&&!Qp.test(e)),Fl=e=>Object.prototype.toString.call(e)==="[object Object]",eh=e=>e[e.length-1]==="/"?e.slice(0,-1):e;function th(){const e=X(!1);return tn()&&Ee(()=>{e.value=!0}),e}function nh(e){return th(),E(()=>!!e())}const Ca=e=>typeof e=="number",vt=e=>typeof e=="string",yn=(e,t)=>vt(e)&&e.startsWith(t),xr=(e,t)=>vt(e)&&e.endsWith(t),Sn=Object.entries,rh=Object.fromEntries,wt=Object.keys,ah=e=>(e.endsWith(".md")&&(e=`${e.slice(0,-3)}.html`),!e.endsWith("/")&&!e.endsWith(".html")&&(e=`${e}.html`),e=e.replace(/(^|\/)(?:README|index).html$/i,"$1"),e),ac=e=>{const[t,n=""]=e.split("#");return t?`${ah(t)}${n?`#${n}`:""}`:e},oi=e=>Fl(e)&&vt(e.name),Yn=(e,t=!1)=>e?rc(e)?e.map(n=>vt(n)?{name:n}:oi(n)?n:null).filter(n=>n!==null):vt(e)?[{name:e}]:oi(e)?[e]:(console.error(`Expect "author" to be \`AuthorInfo[] | AuthorInfo | string[] | string ${t?"":"| false"} | undefined\`, but got`,e),[]):[],lc=(e,t)=>{if(e){if(rc(e)&&e.every(vt))return e;if(vt(e))return[e];console.error(`Expect ${t||"value"} to be \`string[] | string | undefined\`, but got`,e)}return[]},oc=e=>lc(e,"category"),ic=e=>lc(e,"tag"),da=e=>yn(e,"/");class lh{constructor(){this.messageElements={};const t="message-container",n=document.getElementById(t);n?this.containerElement=n:(this.containerElement=document.createElement("div"),this.containerElement.id=t,document.body.appendChild(this.containerElement))}pop(t,n=2e3){const r=document.createElement("div"),a=Date.now();return r.className="message move-in",r.innerHTML=t,this.containerElement.appendChild(r),this.messageElements[a]=r,n>0&&setTimeout(()=>{this.close(a)},n),a}close(t){if(t){const n=this.messageElements[t];n.classList.remove("move-in"),n.classList.add("move-out"),n.addEventListener("animationend",()=>{n.remove(),delete this.messageElements[t]})}else wt(this.messageElements).forEach(n=>this.close(Number(n)))}destroy(){document.body.removeChild(this.containerElement)}}const sc=/#.*$/u,oh=e=>{const t=sc.exec(e);return t?t[0]:""},ii=e=>decodeURI(e).replace(sc,"").replace(/(index)?\.html$/i,"").replace(/(README|index)?\.md$/i,""),cc=(e,t)=>{if(t===void 0)return!1;const n=ii(e.path),r=ii(t),a=oh(t);return a?a===e.hash&&(!r||n===r):n===r},ih=e=>ua(e)?e:`https://github.com/${e}`,uc=e=>!ua(e)||/github\.com/.test(e)?"GitHub":/bitbucket\.org/.test(e)?"Bitbucket":/gitlab\.com/.test(e)?"GitLab":/gitee\.com/.test(e)?"Gitee":null,En=(e,...t)=>{const n=e.resolve(...t),r=n.matched[n.matched.length-1];if(!(r!=null&&r.redirect))return n;const{redirect:a}=r,l=Yp(a)?a(n):a,o=Zp(l)?{path:l}:l;return En(e,{hash:n.hash,query:n.query,params:n.params,...o})},sh=e=>{var t;if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)&&!(e.currentTarget&&((t=e.currentTarget.getAttribute("target"))!=null&&t.match(/\b_blank\b/i))))return e.preventDefault(),!0},Ce=({to:e="",class:t="",...n},{slots:r})=>{var s;const a=Ve(),l=ac(e),o=(c={})=>sh(c)?a.push(e).catch():Promise.resolve();return i("a",{...n,class:["vp-link",t],href:yn(l,"/")?Le(l):l,onClick:o},(s=r.default)==null?void 0:s.call(r))};Ce.displayName="VPLink";const dc=()=>i(pe,{name:"github"},()=>i("path",{d:"M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"}));dc.displayName="GitHubIcon";const fc=()=>i(pe,{name:"gitlab"},()=>i("path",{d:"M229.333 78.688C223.52 62 199.895 62 193.895 78.688L87.958 406.438h247.5c-.188 0-106.125-327.75-106.125-327.75zM33.77 571.438c-4.875 15 .563 31.687 13.313 41.25l464.812 345L87.77 406.438zm301.5-165 176.813 551.25 176.812-551.25zm655.125 165-54-165-424.312 551.25 464.812-345c12.938-9.563 18.188-26.25 13.5-41.25zM830.27 78.688c-5.812-16.688-29.437-16.688-35.437 0l-106.125 327.75h247.5z"}));fc.displayName="GitLabIcon";const pc=()=>i(pe,{name:"gitee"},()=>i("path",{d:"M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm242.97-533.34H482.39a23.7 23.7 0 0 0-23.7 23.7l-.03 59.28c0 13.08 10.59 23.7 23.7 23.7h165.96a23.7 23.7 0 0 1 23.7 23.7v11.85a71.1 71.1 0 0 1-71.1 71.1H375.71a23.7 23.7 0 0 1-23.7-23.7V423.11a71.1 71.1 0 0 1 71.1-71.1h331.8a23.7 23.7 0 0 0 23.7-23.7l.06-59.25a23.73 23.73 0 0 0-23.7-23.73H423.11a177.78 177.78 0 0 0-177.78 177.75v331.83c0 13.08 10.62 23.7 23.7 23.7h349.62a159.99 159.99 0 0 0 159.99-159.99V482.33a23.7 23.7 0 0 0-23.7-23.7z"}));pc.displayName="GiteeIcon";const hc=()=>i(pe,{name:"bitbucket"},()=>i("path",{d:"M575.256 490.862c6.29 47.981-52.005 85.723-92.563 61.147-45.714-20.004-45.714-92.562-1.133-113.152 38.29-23.442 93.696 7.424 93.696 52.005zm63.451-11.996c-10.276-81.152-102.29-134.839-177.152-101.156-47.433 21.138-79.433 71.424-77.129 124.562 2.853 69.705 69.157 126.866 138.862 120.576S647.3 548.571 638.708 478.83zm136.558-309.723c-25.161-33.134-67.986-38.839-105.728-45.13-106.862-17.151-216.576-17.7-323.438 1.134-35.438 5.706-75.447 11.996-97.719 43.996 36.572 34.304 88.576 39.424 135.424 45.129 84.553 10.862 171.447 11.447 256 .585 47.433-5.705 99.987-10.276 135.424-45.714zm32.585 591.433c-16.018 55.99-6.839 131.438-66.304 163.986-102.29 56.576-226.304 62.867-338.87 42.862-59.43-10.862-129.135-29.696-161.72-85.723-14.3-54.858-23.442-110.848-32.585-166.84l3.438-9.142 10.276-5.157c170.277 112.567 408.576 112.567 579.438 0 26.844 8.01 6.84 40.558 6.29 60.014zm103.424-549.157c-19.42 125.148-41.728 249.71-63.415 374.272-6.29 36.572-41.728 57.162-71.424 72.558-106.862 53.724-231.424 62.866-348.562 50.286-79.433-8.558-160.585-29.696-225.134-79.433-30.28-23.443-30.28-63.415-35.986-97.134-20.005-117.138-42.862-234.277-57.161-352.585 6.839-51.42 64.585-73.728 107.447-89.71 57.16-21.138 118.272-30.866 178.87-36.571 129.134-12.58 261.157-8.01 386.304 28.562 44.581 13.13 92.563 31.415 122.844 69.705 13.714 17.7 9.143 40.01 6.29 60.014z"}));hc.displayName="BitbucketIcon";const vc=()=>i(pe,{name:"source"},()=>i("path",{d:"M601.92 475.2c0 76.428-8.91 83.754-28.512 99.594-14.652 11.88-43.956 14.058-78.012 16.434-18.81 1.386-40.392 2.97-62.172 6.534-18.612 2.97-36.432 9.306-53.064 17.424V299.772c37.818-21.978 63.36-62.766 63.36-109.692 0-69.894-56.826-126.72-126.72-126.72S190.08 120.186 190.08 190.08c0 46.926 25.542 87.714 63.36 109.692v414.216c-37.818 21.978-63.36 62.766-63.36 109.692 0 69.894 56.826 126.72 126.72 126.72s126.72-56.826 126.72-126.72c0-31.086-11.286-59.598-29.7-81.576 13.266-9.504 27.522-17.226 39.996-19.206 16.038-2.574 32.868-3.762 50.688-5.148 48.312-3.366 103.158-7.326 148.896-44.55 61.182-49.698 74.25-103.158 75.24-187.902V475.2h-126.72zM316.8 126.72c34.848 0 63.36 28.512 63.36 63.36s-28.512 63.36-63.36 63.36-63.36-28.512-63.36-63.36 28.512-63.36 63.36-63.36zm0 760.32c-34.848 0-63.36-28.512-63.36-63.36s28.512-63.36 63.36-63.36 63.36 28.512 63.36 63.36-28.512 63.36-63.36 63.36zM823.68 158.4h-95.04V63.36h-126.72v95.04h-95.04v126.72h95.04v95.04h126.72v-95.04h95.04z"}));vc.displayName="SourceIcon";const Jt=(e,t)=>{var r;const n=(r=(t==null?void 0:t._instance)||tn())==null?void 0:r.appContext.components;return n?e in n||Ge(e)in n||An(Ge(e))in n:!1},ch=()=>nh(()=>typeof window<"u"&&window.navigator&&"userAgent"in window.navigator),uh=()=>{const e=ch();return E(()=>e.value&&/\b(?:Android|iPhone)/i.test(navigator.userAgent))},ar=e=>{const t=ct();return E(()=>e[t.value])};let mc=e=>oe(e.title)?{title:e.title}:null;const gc=Symbol(""),dh=e=>{mc=e},fh=()=>he(gc),ph=e=>{e.provide(gc,mc)};var hh={"/":{title:"目录",empty:"暂无目录"}},vh=V({name:"AutoCatalog",props:{base:{type:String,default:""},level:{type:Number,default:3},index:Boolean,hideHeading:Boolean},setup(e){const t=fh(),n=ar(hh),r=ie(),a=Ve(),l=Ns(),o=X(a.getRoutes().map(({meta:u,path:d})=>{const f=t(u);if(!f)return null;const p=d.split("/").length;return{level:xr(d,"/")?p-2:p-1,base:d.replace(/\/[^/]+\/?$/,"/"),path:d,...f}}).filter(u=>Fl(u)&&oe(u.title))),s=()=>{const u=e.base?Tf(Ps(e.base)):r.value.path.replace(/\/[^/]+$/,"/"),d=u.split("/").length-2,f=[];return o.value.filter(({level:p,path:h})=>{if(!yn(h,u)||h===u)return!1;if(u==="/"){const g=wt(l.value.locales).filter(w=>w!=="/");if(h==="/404.html"||g.some(w=>yn(h,w)))return!1}return p-d<=e.level&&(xr(h,".html")&&!xr(h,"/index.html")||xr(h,"/"))}).sort(({title:p,level:h,order:g},{title:w,level:k,order:b})=>h-k||(Ca(g)?Ca(b)?g>0?b>0?g-b:-1:b<0?g-b:1:g:Ca(b)?b:p.localeCompare(w))).forEach(p=>{var w;const{base:h,level:g}=p;switch(g-d){case 1:f.push(p);break;case 2:{const k=f.find(b=>b.path===h);k&&(k.children??(k.children=[])).push(p);break}default:{const k=f.find(b=>b.path===h.replace(/\/[^/]+\/$/,"/"));if(k){const b=(w=k.children)==null?void 0:w.find(x=>x.path===h);b&&(b.children??(b.children=[])).push(p)}}}}),f},c=E(()=>s());return()=>{const u=c.value.some(d=>d.children);return i("div",{class:["vp-catalog-wrapper",{index:e.index}]},[e.hideHeading?null:i("h2",{class:"vp-catalog-main-title"},n.value.title),c.value.length?i(e.index?"ol":"ul",{class:["vp-catalogs",{deep:u}]},c.value.map(({children:d=[],title:f,path:p,content:h})=>{const g=i(Ce,{class:"vp-catalog-title",to:p},()=>h?i(h):f);return i("li",{class:"vp-catalog"},u?[i("h3",{id:f,class:["vp-catalog-child-title",{"has-children":d.length}]},[i("a",{href:`#${f}`,class:"header-anchor","aria-hidden":!0},"#"),g]),d.length?i(e.index?"ol":"ul",{class:"vp-child-catalogs"},d.map(({children:w=[],content:k,path:b,title:x})=>i("li",{class:"vp-child-catalog"},[i("div",{class:["vp-catalog-sub-title",{"has-children":w.length}]},[i("a",{href:`#${x}`,class:"header-anchor"},"#"),i(Ce,{class:"vp-catalog-title",to:b},()=>k?i(k):x)]),w.length?i(e.index?"ol":"div",{class:e.index?"vp-sub-catalogs":"vp-sub-catalogs-wrapper"},w.map(({content:_,path:S,title:D})=>e.index?i("li",{class:"vp-sub-catalog"},i(Ce,{to:S},()=>_?i(_):D)):i(Ce,{class:"vp-sub-catalog-link",to:S},()=>_?i(_):D))):null]))):null]:i("div",{class:"vp-catalog-child-title"},g))})):i("p",{class:"vp-empty-catalog"},n.value.empty)])}}}),mh=Ye({enhance:({app:e})=>{ph(e),Jt("AutoCatalog",e)||e.component("AutoCatalog",vh)}});const gh=i("svg",{class:"external-link-icon",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"},[i("path",{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}),i("polygon",{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"})]),bc=V({name:"ExternalLinkIcon",props:{locales:{type:Object,required:!1,default:()=>({})}},setup(e){const t=ct(),n=E(()=>e.locales[t.value]??{openInNewWindow:"open in new window"});return()=>i("span",[gh,i("span",{class:"external-link-icon-sr-only"},n.value.openInNewWindow)])}});var bh={};const _h=bh,yh=Ye({enhance({app:e}){e.component("ExternalLinkIcon",i(bc,{locales:_h}))}});/**
+ * NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
+ * @license MIT
+ */const ue={settings:{minimum:.08,easing:"ease",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,barSelector:'[role="bar"]',parent:"body",template:'
'},status:null,set:e=>{const t=ue.isStarted();e=Ia(e,ue.settings.minimum,1),ue.status=e===1?null:e;const n=ue.render(!t),r=n.querySelector(ue.settings.barSelector),a=ue.settings.speed,l=ue.settings.easing;return n.offsetWidth,Eh(o=>{Sr(r,{transform:"translate3d("+si(e)+"%,0,0)",transition:"all "+a+"ms "+l}),e===1?(Sr(n,{transition:"none",opacity:"1"}),n.offsetWidth,setTimeout(function(){Sr(n,{transition:"all "+a+"ms linear",opacity:"0"}),setTimeout(function(){ue.remove(),o()},a)},a)):setTimeout(()=>o(),a)}),ue},isStarted:()=>typeof ue.status=="number",start:()=>{ue.status||ue.set(0);const e=()=>{setTimeout(()=>{ue.status&&(ue.trickle(),e())},ue.settings.trickleSpeed)};return ue.settings.trickle&&e(),ue},done:e=>!e&&!ue.status?ue:ue.inc(.3+.5*Math.random()).set(1),inc:e=>{let t=ue.status;return t?(typeof e!="number"&&(e=(1-t)*Ia(Math.random()*t,.1,.95)),t=Ia(t+e,0,.994),ue.set(t)):ue.start()},trickle:()=>ue.inc(Math.random()*ue.settings.trickleRate),render:e=>{if(ue.isRendered())return document.getElementById("nprogress");ci(document.documentElement,"nprogress-busy");const t=document.createElement("div");t.id="nprogress",t.innerHTML=ue.settings.template;const n=t.querySelector(ue.settings.barSelector),r=e?"-100":si(ue.status||0),a=document.querySelector(ue.settings.parent);return Sr(n,{transition:"all 0 linear",transform:"translate3d("+r+"%,0,0)"}),a!==document.body&&ci(a,"nprogress-custom-parent"),a==null||a.appendChild(t),t},remove:()=>{ui(document.documentElement,"nprogress-busy"),ui(document.querySelector(ue.settings.parent),"nprogress-custom-parent");const e=document.getElementById("nprogress");e&&kh(e)},isRendered:()=>!!document.getElementById("nprogress")},Ia=(e,t,n)=>en?n:e,si=e=>(-1+e)*100,Eh=function(){const e=[];function t(){const n=e.shift();n&&n(t)}return function(n){e.push(n),e.length===1&&t()}}(),Sr=function(){const e=["Webkit","O","Moz","ms"],t={};function n(o){return o.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(s,c){return c.toUpperCase()})}function r(o){const s=document.body.style;if(o in s)return o;let c=e.length;const u=o.charAt(0).toUpperCase()+o.slice(1);let d;for(;c--;)if(d=e[c]+u,d in s)return d;return o}function a(o){return o=n(o),t[o]??(t[o]=r(o))}function l(o,s,c){s=a(s),o.style[s]=c}return function(o,s){for(const c in s){const u=s[c];u!==void 0&&Object.prototype.hasOwnProperty.call(s,c)&&l(o,c,u)}}}(),_c=(e,t)=>(typeof e=="string"?e:Vl(e)).indexOf(" "+t+" ")>=0,ci=(e,t)=>{const n=Vl(e),r=n+t;_c(n,t)||(e.className=r.substring(1))},ui=(e,t)=>{const n=Vl(e);if(!_c(e,t))return;const r=n.replace(" "+t+" "," ");e.className=r.substring(1,r.length-1)},Vl=e=>(" "+(e.className||"")+" ").replace(/\s+/gi," "),kh=e=>{e&&e.parentNode&&e.parentNode.removeChild(e)},wh=()=>{Ee(()=>{const e=Ve(),t=new Set;t.add(e.currentRoute.value.path),e.beforeEach(n=>{t.has(n.path)||ue.start()}),e.afterEach(n=>{t.add(n.path),ue.done()})})},Ah=Ye({setup(){wh()}}),Lh=JSON.parse('{"encrypt":{},"logo":"https://github-images.wenzhihuai.com/images/logo.png","author":{"name":"Zephery","url":"https://wenzhihuai.com/article/"},"repo":"https://github.com/Zephery/MyWebsite","docsDir":"docs","pure":true,"breadcrumb":false,"footer":"粤ICP备17092242号-1 ","displayFooter":true,"pageInfo":["Author","Category","Tag","Original","Word","ReadingTime"],"blog":{"intro":"/about-the-author/","sidebarDisplay":"mobile","medias":{"Zhihu":"https://www.zhihu.com/people/javaZephery","Github":"https://github.com/Zephery","Gitee":"https://gitee.com/zephery.com.cn"}},"locales":{"/":{"lang":"zh-CN","navbarLocales":{"langName":"简体中文","selectLangAriaLabel":"选择语言"},"metaLocales":{"author":"作者","date":"写作日期","origin":"原创","views":"访问量","category":"分类","tag":"标签","readingTime":"阅读时间","words":"字数","toc":"此页内容","prev":"上一页","next":"下一页","lastUpdated":"上次编辑于","contributors":"贡献者","editLink":"编辑此页","print":"打印"},"blogLocales":{"article":"文章","articleList":"文章列表","category":"分类","tag":"标签","timeline":"时间轴","timelineTitle":"昨日不在","all":"全部","intro":"个人介绍","star":"星标","empty":"$text 为空"},"paginationLocales":{"prev":"上一页","next":"下一页","navigate":"跳转到","action":"前往","errorText":"请输入 1 到 $page 之前的页码!"},"outlookLocales":{"themeColor":"主题色","darkmode":"外观","fullscreen":"全屏"},"routeLocales":{"skipToContent":"跳至主要內容","notFoundTitle":"页面不存在","notFoundMsg":["这里什么也没有","我们是怎么来到这儿的?","这 是 四 零 四 !","看起来你访问了一个失效的链接"],"back":"返回上一页","home":"带我回家","openInNewWindow":"Open in new window"},"navbar":[{"text":"Java","icon":"java","link":"/index"},{"text":"中间件","icon":"middleware","link":"/middleware/"},{"text":"数据库","icon":"database","link":"/database/"},{"text":"大数据","icon":"bigdata","link":"/bigdata/"},{"text":"Kubernetes","icon":"Kubernetes","link":"/kubernetes/"},{"text":"好玩的","icon":"others","link":"/others/"},{"text":"捐赠","icon":"donate","link":"/donate/"},{"text":"网站相关","icon":"about","children":[{"text":"关于作者","icon":"zuozhe","link":"/about-the-author/personal-life/wewe.md"},{"text":"友链","icon":"link","link":"/link/main.md"}]}],"sidebar":{"/database/":[{"text":"MySQL","prefix":"mysql/","icon":"mysql","collapsible":false,"children":"structure"},{"text":"Redis","prefix":"redis/","icon":"redis","collapsible":false,"children":"structure"},{"text":"Elasticsearch","prefix":"elasticsearch/","icon":"elasticsearch","collapsible":false,"children":"structure"},{"text":"MongoDB","prefix":"mongodb/","icon":"mongodb","collapsible":false,"children":"structure"}],"/link/":[{"text":"友链","icon":"link","link":"main","collapsible":false}],"/bigdata/":[{"text":"Spark","prefix":"spark/","icon":"bigdata","collapsible":false,"children":"structure"}],"/middleware/":[{"text":"Kafka","prefix":"kafka/","icon":"kafka","collapsible":false,"children":"structure"},{"text":"Zookeeper","prefix":"zookeeper/","icon":"zookeeper","collapsible":false,"children":"structure"}],"/kubernetes/":[{"text":"Kubernetes","icon":"kubernetes","collapsible":false,"children":["spark on k8s operator.md"]}],"/books/":[{"text":"计算机基础","link":"cs-basics","icon":"computer"},{"text":"数据库","link":"database","icon":"database"},{"text":"搜索引擎","link":"search-engine","icon":"search"},{"text":"Java","link":"java","icon":"java"},{"text":"软件质量","link":"software-quality","icon":"highavailable"},{"text":"分布式","link":"distributed-system","icon":"distributed-network"}],"/donate/":[{"text":"微信支付","link":"README","icon":"README"}],"/life/":[{"text":"生活","icon":"life","collapsible":false,"children":"structure"}],"/others/":[{"text":"其他","collapsible":false,"children":"structure"}],"/about-the-author/":[{"text":"个人生活","icon":"experience","prefix":"personal-life/","collapsible":false,"children":"structure"},{"text":"作品","icon":"works","prefix":"works/","collapsible":false,"children":"structure"},{"text":"杂谈","icon":"chat","prefix":"talking/","collapsible":false,"children":"structure"}],"/high-quality-technical-articles/":[{"text":"练级攻略","icon":"et-performance","prefix":"advanced-programmer/","collapsible":false,"children":["programmer-quickly-learn-new-technology","the-growth-strategy-of-the-technological-giant","ten-years-of-dachang-growth-road","meituan-three-year-summary-lesson-10","seven-tips-for-becoming-an-advanced-programmer","20-bad-habits-of-bad-programmers","thinking-about-technology-and-business-after-five-years-of-work"]},{"text":"个人经历","icon":"experience","prefix":"personal-experience/","collapsible":false,"children":["four-year-work-in-tencent-summary","two-years-of-back-end-develop--experience-in-didi-and-toutiao","8-years-programmer-work-summary","huawei-od-275-days"]},{"text":"程序员","icon":"code","prefix":"programmer/","collapsible":false,"children":["how-do-programmers-publish-a-technical-book","efficient-book-publishing-and-practice-Zephery"]},{"text":"面试","icon":"interview","prefix":"interview/","collapsible":true,"children":["the-experience-of-get-offer-from-over-20-big-companies","the-experience-and-thinking-of-an-interview-experienced-by-an-older-programmer","technical-preliminary-preparation","screen-candidates-for-packaging","summary-of-spring-recruitment","my-personal-experience-in-2021","how-to-examine-the-technical-ability-of-programmers-in-the-first-test-of-technology","some-secrets-about-alibaba-interview"]},{"text":"工作","icon":"work","prefix":"work/","collapsible":true,"children":["get-into-work-mode-quickly-when-you-join-a-company","32-tips-improving-career","employee-performance"]}],"/zhuanlan/":["java-mian-shi-zhi-bei","back-end-interview-high-frequency-system-design-and-scenario-questions","handwritten-rpc-framework","source-code-reading"],"/":[{"text":"Java","icon":"java","collapsible":false,"prefix":"java/","children":"structure"}]}}}}'),xh=X(Lh),yc=()=>xh,Ec=Symbol(""),Sh=()=>{const e=he(Ec);if(!e)throw new Error("useThemeLocaleData() is called without provider.");return e},Th=(e,t)=>{const{locales:n,...r}=e;return{...r,...n==null?void 0:n[t]}},Bh=Ye({enhance({app:e}){const t=yc(),n=e._context.provides[Ol],r=E(()=>Th(t.value,n.value));e.provide(Ec,r),Object.defineProperties(e.config.globalProperties,{$theme:{get(){return t.value}},$themeLocale:{get(){return r.value}}})}});function di(e,t){var n;const r=mt();return wl(()=>{r.value=e()},{...t,flush:(n=t==null?void 0:t.flush)!=null?n:"sync"}),Xt(r)}function $l(e,t){let n,r,a;const l=X(!0),o=()=>{l.value=!0,a()};ye(e,o,{flush:"sync"});const s=typeof t=="function"?t:t.get,c=typeof t=="function"?void 0:t.set,u=Yi((d,f)=>(r=d,a=f,{get(){return l.value&&(n=s(),l.value=!1),r(),n},set(p){c==null||c(p)}}));return Object.isExtensible(u)&&(u.trigger=o),u}function lr(e){return Ii()?(nd(e),!0):!1}function nt(e){return typeof e=="function"?e():Wt(e)}const or=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Ch=Object.prototype.toString,Ih=e=>Ch.call(e)==="[object Object]",Ur=()=>{},fi=Ph();function Ph(){var e,t;return or&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&(/iP(ad|hone|od)/.test(window.navigator.userAgent)||((t=window==null?void 0:window.navigator)==null?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test(window==null?void 0:window.navigator.userAgent))}function kc(e,t){function n(...r){return new Promise((a,l)=>{Promise.resolve(e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})).then(a).catch(l)})}return n}const wc=e=>e();function Oh(e,t=!0,n=!0,r=!1){let a=0,l,o=!0,s=Ur,c;const u=()=>{l&&(clearTimeout(l),l=void 0,s(),s=Ur)};return f=>{const p=nt(e),h=Date.now()-a,g=()=>c=f();return u(),p<=0?(a=Date.now(),g()):(h>p&&(n||!o)?(a=Date.now(),g()):t&&(c=new Promise((w,k)=>{s=r?k:w,l=setTimeout(()=>{a=Date.now(),o=!0,w(g()),u()},Math.max(0,p-h))})),!n&&!l&&(l=setTimeout(()=>o=!0,p)),o=!1,c)}}function Dh(e=wc){const t=X(!0);function n(){t.value=!1}function r(){t.value=!0}const a=(...l)=>{t.value&&e(...l)};return{isActive:Xt(t),pause:n,resume:r,eventFilter:a}}function Rh(e){let t;function n(){return t||(t=e()),t}return n.reset=async()=>{const r=t;t=void 0,r&&await r},n}function Mh(e){return e||tn()}function Fh(...e){if(e.length!==1)return Ln(...e);const t=e[0];return typeof t=="function"?Xt(Yi(()=>({get:t,set:Ur}))):X(t)}function Vh(e,t=200,n=!1,r=!0,a=!1){return kc(Oh(t,n,r,a),e)}function $h(e,t,n={}){const{eventFilter:r=wc,...a}=n;return ye(e,kc(r,t),a)}function jh(e,t,n={}){const{eventFilter:r,...a}=n,{eventFilter:l,pause:o,resume:s,isActive:c}=Dh(r);return{stop:$h(e,t,{...a,eventFilter:l}),pause:o,resume:s,isActive:c}}function Nh(e,t=!0,n){Mh()?Ee(e,n):t?e():en(e)}function zh(e,t,n={}){const{immediate:r=!0}=n,a=X(!1);let l=null;function o(){l&&(clearTimeout(l),l=null)}function s(){a.value=!1,o()}function c(...u){o(),a.value=!0,l=setTimeout(()=>{a.value=!1,l=null,e(...u)},nt(t))}return r&&(a.value=!0,or&&c()),lr(s),{isPending:Xt(a),start:c,stop:s}}function pi(e=!1,t={}){const{truthyValue:n=!0,falsyValue:r=!1}=t,a=De(e),l=X(e);function o(s){if(arguments.length)return l.value=s,l.value;{const c=nt(n);return l.value=l.value===c?nt(r):c,l.value}}return a?o:[l,o]}function el(e){var t;const n=nt(e);return(t=n==null?void 0:n.$el)!=null?t:n}const Kr=or?window:void 0,Hh=or?window.document:void 0,Ac=or?window.navigator:void 0;function je(...e){let t,n,r,a;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,r,a]=e,t=Kr):[t,n,r,a]=e,!t)return Ur;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const l=[],o=()=>{l.forEach(d=>d()),l.length=0},s=(d,f,p,h)=>(d.addEventListener(f,p,h),()=>d.removeEventListener(f,p,h)),c=ye(()=>[el(t),nt(a)],([d,f])=>{if(o(),!d)return;const p=Ih(f)?{...f}:f;l.push(...n.flatMap(h=>r.map(g=>s(d,h,g,p))))},{immediate:!0,flush:"post"}),u=()=>{c(),o()};return lr(u),u}function qh(){const e=X(!1);return tn()&&Ee(()=>{e.value=!0}),e}function fa(e){const t=qh();return E(()=>(t.value,!!e()))}function Gh(e,t={}){const{window:n=Kr}=t,r=fa(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let a;const l=X(!1),o=u=>{l.value=u.matches},s=()=>{a&&("removeEventListener"in a?a.removeEventListener("change",o):a.removeListener(o))},c=wl(()=>{r.value&&(s(),a=n.matchMedia(nt(e)),"addEventListener"in a?a.addEventListener("change",o):a.addListener(o),l.value=a.matches)});return lr(()=>{c(),s(),a=void 0}),l}function hi(e,t={}){const{controls:n=!1,navigator:r=Ac}=t,a=fa(()=>r&&"permissions"in r);let l;const o=typeof e=="string"?{name:e}:e,s=X(),c=()=>{l&&(s.value=l.state)},u=Rh(async()=>{if(a.value){if(!l)try{l=await r.permissions.query(o),je(l,"change",c),c()}catch{s.value="prompt"}return l}});return u(),n?{state:s,isSupported:a,query:u}:s}function Uh(e={}){const{navigator:t=Ac,read:n=!1,source:r,copiedDuring:a=1500,legacy:l=!1}=e,o=fa(()=>t&&"clipboard"in t),s=hi("clipboard-read"),c=hi("clipboard-write"),u=E(()=>o.value||l),d=X(""),f=X(!1),p=zh(()=>f.value=!1,a);function h(){o.value&&s.value!=="denied"?t.clipboard.readText().then(b=>{d.value=b}):d.value=k()}u.value&&n&&je(["copy","cut"],h);async function g(b=nt(r)){u.value&&b!=null&&(o.value&&c.value!=="denied"?await t.clipboard.writeText(b):w(b),d.value=b,f.value=!0,p.start())}function w(b){const x=document.createElement("textarea");x.value=b??"",x.style.position="absolute",x.style.opacity="0",document.body.appendChild(x),x.select(),document.execCommand("copy"),x.remove()}function k(){var b,x,_;return(_=(x=(b=document==null?void 0:document.getSelection)==null?void 0:b.call(document))==null?void 0:x.toString())!=null?_:""}return{isSupported:u,text:d,copied:f,copy:g}}const Tr=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Br="__vueuse_ssr_handlers__",Kh=Wh();function Wh(){return Br in Tr||(Tr[Br]=Tr[Br]||{}),Tr[Br]}function Jh(e,t){return Kh[e]||t}function Yh(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const Zh={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},vi="vueuse-storage";function Lc(e,t,n,r={}){var a;const{flush:l="pre",deep:o=!0,listenToStorageChanges:s=!0,writeDefaults:c=!0,mergeDefaults:u=!1,shallow:d,window:f=Kr,eventFilter:p,onError:h=R=>{console.error(R)},initOnMounted:g}=r,w=(d?mt:X)(typeof t=="function"?t():t);if(!n)try{n=Jh("getDefaultStorage",()=>{var R;return(R=Kr)==null?void 0:R.localStorage})()}catch(R){h(R)}if(!n)return w;const k=nt(t),b=Yh(k),x=(a=r.serializer)!=null?a:Zh[b],{pause:_,resume:S}=jh(w,()=>D(w.value),{flush:l,deep:o,eventFilter:p});return f&&s&&Nh(()=>{je(f,"storage",$),je(f,vi,U),g&&$()}),g||$(),w;function D(R){try{if(R==null)n.removeItem(e);else{const j=x.write(R),ne=n.getItem(e);ne!==j&&(n.setItem(e,j),f&&f.dispatchEvent(new CustomEvent(vi,{detail:{key:e,oldValue:ne,newValue:j,storageArea:n}})))}}catch(j){h(j)}}function L(R){const j=R?R.newValue:n.getItem(e);if(j==null)return c&&k!=null&&n.setItem(e,x.write(k)),k;if(!R&&u){const ne=x.read(j);return typeof u=="function"?u(ne,k):b==="object"&&!Array.isArray(ne)?{...k,...ne}:ne}else return typeof j!="string"?j:x.read(j)}function U(R){$(R.detail)}function $(R){if(!(R&&R.storageArea!==n)){if(R&&R.key==null){w.value=k;return}if(!(R&&R.key!==e)){_();try{(R==null?void 0:R.newValue)!==x.write(w.value)&&(w.value=L(R))}catch(j){h(j)}finally{R?en(S):S()}}}}}function Qh(e){return Gh("(prefers-color-scheme: dark)",e)}const mi=["fullscreenchange","webkitfullscreenchange","webkitendfullscreen","mozfullscreenchange","MSFullscreenChange"];function jl(e,t={}){const{document:n=Hh,autoExit:r=!1}=t,a=E(()=>{var b;return(b=el(e))!=null?b:n==null?void 0:n.querySelector("html")}),l=X(!1),o=E(()=>["requestFullscreen","webkitRequestFullscreen","webkitEnterFullscreen","webkitEnterFullScreen","webkitRequestFullScreen","mozRequestFullScreen","msRequestFullscreen"].find(b=>n&&b in n||a.value&&b in a.value)),s=E(()=>["exitFullscreen","webkitExitFullscreen","webkitExitFullScreen","webkitCancelFullScreen","mozCancelFullScreen","msExitFullscreen"].find(b=>n&&b in n||a.value&&b in a.value)),c=E(()=>["fullScreen","webkitIsFullScreen","webkitDisplayingFullscreen","mozFullScreen","msFullscreenElement"].find(b=>n&&b in n||a.value&&b in a.value)),u=["fullscreenElement","webkitFullscreenElement","mozFullScreenElement","msFullscreenElement"].find(b=>n&&b in n),d=fa(()=>a.value&&n&&o.value!==void 0&&s.value!==void 0&&c.value!==void 0),f=()=>u?(n==null?void 0:n[u])===a.value:!1,p=()=>{if(c.value){if(n&&n[c.value]!=null)return n[c.value];{const b=a.value;if((b==null?void 0:b[c.value])!=null)return!!b[c.value]}}return!1};async function h(){if(!(!d.value||!l.value)){if(s.value)if((n==null?void 0:n[s.value])!=null)await n[s.value]();else{const b=a.value;(b==null?void 0:b[s.value])!=null&&await b[s.value]()}l.value=!1}}async function g(){if(!d.value||l.value)return;p()&&await h();const b=a.value;o.value&&(b==null?void 0:b[o.value])!=null&&(await b[o.value](),l.value=!0)}async function w(){await(l.value?h():g())}const k=()=>{const b=p();(!b||b&&f())&&(l.value=b)};return je(n,mi,k,!1),je(()=>el(a),mi,k,!1),r&&lr(h),{isSupported:d,isFullscreen:l,enter:g,exit:h,toggle:w}}function Pa(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function xc(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const Cr=new WeakMap;function Sc(e,t=!1){const n=X(t);let r=null,a;ye(Fh(e),s=>{const c=Pa(nt(s));if(c){const u=c;Cr.get(u)||Cr.set(u,a),n.value&&(u.style.overflow="hidden")}},{immediate:!0});const l=()=>{const s=Pa(nt(e));!s||n.value||(fi&&(r=je(s,"touchmove",c=>{Xh(c)},{passive:!1})),s.style.overflow="hidden",n.value=!0)},o=()=>{var s;const c=Pa(nt(e));!c||!n.value||(fi&&(r==null||r()),c.style.overflow=(s=Cr.get(c))!=null?s:"",Cr.delete(c),n.value=!1)};return lr(o),E({get(){return n.value},set(s){s?l():o()}})}var e0={"/":{copy:"复制代码",copied:"已复制",hint:"复制成功"}},t0=['.theme-hope-content div[class*="language-"] pre'];const n0=800,r0=2e3,a0=e0,l0=t0,gi=!1,Oa=new Map,o0=()=>{const{copy:e}=Uh({legacy:!0}),t=ar(a0),n=ie(),r=uh(),a=s=>{if(!s.hasAttribute("copy-code-registered")){const c=document.createElement("button");c.type="button",c.classList.add("copy-code-button"),c.innerHTML='
',c.setAttribute("aria-label",t.value.copy),c.setAttribute("data-copied",t.value.copied),s.parentElement&&s.parentElement.insertBefore(c,s),s.setAttribute("copy-code-registered","")}},l=()=>en().then(()=>new Promise(s=>{setTimeout(()=>{l0.forEach(c=>{document.querySelectorAll(c).forEach(a)}),s()},n0)})),o=(s,c,u)=>{let{innerText:d=""}=c;/language-(shellscript|shell|bash|sh|zsh)/.test(s.classList.toString())&&(d=d.replace(/^ *(\$|>) /gm,"")),e(d).then(()=>{u.classList.add("copied"),clearTimeout(Oa.get(u));const f=setTimeout(()=>{u.classList.remove("copied"),u.blur(),Oa.delete(u)},r0);Oa.set(u,f)})};Ee(()=>{(!r.value||gi)&&l(),je("click",s=>{const c=s.target;if(c.matches('div[class*="language-"] > button.copy')){const u=c.parentElement,d=c.nextElementSibling;d&&o(u,d,c)}else if(c.matches('div[class*="language-"] div.copy-icon')){const u=c.parentElement,d=u.parentElement,f=u.nextElementSibling;f&&o(d,f,u)}}),ye(()=>n.value.path,()=>{(!r.value||gi)&&l()})})};var i0=Ye({setup:()=>{o0()}}),s0={"/":{author:"著作权归:author所有",license:"基于:license协议",link:"原文链接::link"}};const Da="https://wenzhihuai.com/",c0=()=>{const e=_e(),t=ar(s0),n=ie(),r=E(()=>!!e.value.copy||e.value.copy!==!1&&!0),a=E(()=>Fl(e.value.copy)?e.value.copy:null),l=E(()=>{var h;return((h=a.value)==null?void 0:h.disableCopy)??!1}),o=E(()=>{var h;return r.value?((h=a.value)==null?void 0:h.disableSelection)??!1:!1}),s=E(()=>{var h;return r.value?((h=a.value)==null?void 0:h.maxLength)??700:0}),c=E(()=>{var h;return((h=a.value)==null?void 0:h.triggerLength)??100}),u=()=>`${eh(ua(Da)?Da:`https://${Da}`)}${n.value.path}`,d=(h,g)=>{const{author:w,license:k,link:b}=t.value;return[h?w.replace(":author",h):"",g?k.replace(":license",g):"",b.replace(":link",u())].filter(x=>x).join(`
+`)},f=()=>{if(vt(n.value.copyright))return n.value.copyright.replace(":link",u());const{author:h,license:g}=n.value.copyright||{};return d(h??"wenzhihuai.com",g??"MIT")},p=h=>{const g=getSelection();if(g){const w=g.getRangeAt(0);if(r.value){const k=w.toString().length;if(l.value||s.value&&k>s.value)return h.preventDefault();if(k>=c.value){h.preventDefault();const b=f(),x=document.createElement("div");x.appendChild(g.getRangeAt(0).cloneContents()),h.clipboardData&&(h.clipboardData.setData("text/html",`${x.innerHTML}${b.replace(/\\n/g," ")}
`),h.clipboardData.setData("text/plain",`${g.getRangeAt(0).cloneContents().textContent||""}
+------
+${b}`))}}}};Ee(()=>{const h=document.querySelector("#app");je(h,"copy",p),wl(()=>{h.style.userSelect=o.value?"none":"auto"})})};var u0=Ye({setup:()=>{c0()}});const Ir=Lc("VUEPRESS_CODE_TAB_STORE",{});var d0=V({name:"CodeTabs",props:{active:{type:Number,default:0},data:{type:Array,required:!0},id:{type:String,required:!0},tabId:{type:String,default:""}},slots:Object,setup(e,{slots:t}){const n=X(e.active),r=mt([]),a=()=>{e.tabId&&(Ir.value[e.tabId]=e.data[n.value].id)},l=(u=n.value)=>{n.value=u{n.value=u>0?u-1:r.value.length-1,r.value[n.value].focus()},s=(u,d)=>{u.key===" "||u.key==="Enter"?(u.preventDefault(),n.value=d):u.key==="ArrowRight"?(u.preventDefault(),l()):u.key==="ArrowLeft"&&(u.preventDefault(),o()),e.tabId&&(Ir.value[e.tabId]=e.data[n.value].id)},c=()=>{if(e.tabId){const u=e.data.findIndex(({id:d})=>Ir.value[e.tabId]===d);if(u!==-1)return u}return e.active};return Ee(()=>{n.value=c(),ye(()=>Ir.value[e.tabId],(u,d)=>{if(e.tabId&&u!==d){const f=e.data.findIndex(({id:p})=>p===u);f!==-1&&(n.value=f)}})}),()=>e.data.length?i("div",{class:"vp-code-tabs"},[i("div",{class:"vp-code-tabs-nav",role:"tablist"},e.data.map(({id:u},d)=>{const f=d===n.value;return i("button",{type:"button",ref:p=>{p&&(r.value[d]=p)},class:["vp-code-tab-nav",{active:f}],role:"tab","aria-controls":`codetab-${e.id}-${d}`,"aria-selected":f,onClick:()=>{n.value=d,a()},onKeydown:p=>s(p,d)},t[`title${d}`]({value:u,isActive:f}))})),e.data.map(({id:u},d)=>{const f=d===n.value;return i("div",{class:["vp-code-tab",{active:f}],id:`codetab-${e.id}-${d}`,role:"tabpanel","aria-expanded":f},[i("div",{class:"vp-code-tab-title"},t[`title${d}`]({value:u,isActive:f})),t[`tab${d}`]({value:u,isActive:f})])})]):null}});const f0=()=>{je("beforeprint",()=>{document.querySelectorAll("details").forEach(e=>{e.open=!0})})},p0=Ye({enhance:({app:e})=>{e.component("CodeTabs",d0)},setup:()=>{f0()}});let h0={};const Tc=Symbol(""),v0=()=>he(Tc),m0=e=>{e.provide(Tc,h0)};var g0={"/":{closeTitle:"关闭",downloadTitle:"下载图片",fullscreenTitle:"切换全屏",zoomTitle:"缩放",arrowPrevTitle:"上一个 (左箭头)",arrowNextTitle:"下一个 (右箭头)"}};const b0=".theme-hope-content :not(a) > img:not([no-view])",_0=g0,y0=800,E0='',k0=e=>oe(e)?Array.from(document.querySelectorAll(e)):e.map(t=>Array.from(document.querySelectorAll(t))).flat(),Bc=e=>new Promise((t,n)=>{e.complete?t({type:"image",element:e,src:e.src,width:e.naturalWidth,height:e.naturalHeight,alt:e.alt,msrc:e.src}):(e.onload=()=>t(Bc(e)),e.onerror=r=>n(r))}),w0=()=>{const e=ar(_0),t=_e(),n=ie(),{isSupported:r,toggle:a}=jl(),l=v0();let o;const s=E(()=>t.value.photoSwipe===!1?!1:t.value.photoSwipe||b0),c=d=>{d.on("uiRegister",()=>{r&&d.ui.registerElement({name:"fullscreen",order:7,isButton:!0,html:' ',onClick:()=>{a()}}),d.ui.registerElement({name:"download",order:8,isButton:!0,tagName:"a",html:{isCustomSVG:!0,inner:' ',outlineID:"pswp__icn-download"},onInit:(f,p)=>{f.setAttribute("download",""),f.setAttribute("target","_blank"),f.setAttribute("rel","noopener"),p.on("change",()=>{f.setAttribute("href",p.currSlide.data.src)})}}),d.ui.registerElement({name:"bulletsIndicator",className:"photo-swipe-bullets-indicator",appendTo:"wrapper",onInit:(f,p)=>{const h=[];let g=-1;for(let w=0;w{p.goTo(h.indexOf(b.target))},h.push(k),f.appendChild(k)}p.on("change",()=>{g>=0&&h[g].classList.remove("active"),h[p.currIndex].classList.add("active"),g=p.currIndex})}})})},u=async()=>{if(s.value)return Promise.all([y(()=>import("./photoswipe.esm-08_zHRDQ.js"),__vite__mapDeps([])),en().then(()=>new Promise(d=>setTimeout(d,y0)).then(()=>k0(s.value)))]).then(([{default:d},f])=>{const p=f.map(h=>({html:E0,element:h,msrc:h.src}));f.forEach((h,g)=>{const w=()=>{o=new d({preloaderDelay:0,showHideAnimationType:"zoom",...e.value,...l,dataSource:p,index:g,closeOnVerticalDrag:!0,wheelToZoom:!1}),c(o),o.addFilter("thumbEl",()=>h),o.addFilter("placeholderSrc",()=>h.src),o.init()};h.style.cursor="zoom-in",h.addEventListener("click",()=>{w()}),h.addEventListener("keypress",({key:k})=>{k==="Enter"&&w()})}),f.forEach((h,g)=>{Bc(h).then(w=>{p.splice(g,1,w),o==null||o.refreshSlideContent(g)})})})};Ee(()=>{je("wheel",()=>{o==null||o.close()}),ye(()=>n.value.path,u,{immediate:!0})})};var A0=Ye({enhance:({app:e})=>{m0(e)},setup:()=>{w0()}});const L0=e=>e instanceof Element?document.activeElement===e&&(["TEXTAREA","SELECT","INPUT"].includes(e.tagName)||e.hasAttribute("contenteditable")):!1,x0=(e,t)=>t.some(n=>{if(oe(n))return n===e.key;const{key:r,ctrl:a=!1,shift:l=!1,alt:o=!1}=n;return r===e.key&&a===e.ctrlKey&&l===e.shiftKey&&o===e.altKey}),S0=/[^\x00-\x7F]/,T0=e=>e.split(/\s+/g).map(t=>t.trim()).filter(t=>!!t),bi=e=>e.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),_i=(e,t)=>{const n=t.join(" "),r=T0(e);if(S0.test(e))return r.some(o=>n.toLowerCase().indexOf(o)>-1);const a=e.endsWith(" ");return new RegExp(r.map((o,s)=>r.length===s+1&&!a?`(?=.*\\b${bi(o)})`:`(?=.*\\b${bi(o)}\\b)`).join("")+".+","gi").test(n)},B0=({input:e,hotKeys:t})=>{if(t.value.length===0)return;const n=r=>{e.value&&x0(r,t.value)&&!L0(r.target)&&(r.preventDefault(),e.value.focus())};Ee(()=>{document.addEventListener("keydown",n)}),na(()=>{document.removeEventListener("keydown",n)})},C0=[{title:"关于我",headers:[],path:"/about-the-author/",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/cloudnative/",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/database/",pathLocale:"/",extraFields:[]},{title:"三、DevOps",headers:[],path:"/devops/",pathLocale:"/",extraFields:[]},{title:"3.1 DevOps平台.md",headers:[{level:2,title:"一、自由风格的软件项目",slug:"一、自由风格的软件项目",link:"#一、自由风格的软件项目",children:[]},{level:2,title:"二、优化之后的CICD",slug:"二、优化之后的cicd",link:"#二、优化之后的cicd",children:[]},{level:2,title:"三、调研期",slug:"三、调研期",link:"#三、调研期",children:[]},{level:2,title:"四、产品化后的DevOps平台",slug:"四、产品化后的devops平台",link:"#四、产品化后的devops平台",children:[{level:3,title:"4.1 Java代码扫描",slug:"_4-1-java代码扫描",link:"#_4-1-java代码扫描",children:[]},{level:3,title:"4.2 Java单元测试",slug:"_4-2-java单元测试",link:"#_4-2-java单元测试",children:[]},{level:3,title:"4.3 Java构建并上传镜像",slug:"_4-3-java构建并上传镜像",link:"#_4-3-java构建并上传镜像",children:[]},{level:3,title:"4.4 部署到阿里云k8s",slug:"_4-4-部署到阿里云k8s",link:"#_4-4-部署到阿里云k8s",children:[]},{level:3,title:"4.5 整体流程",slug:"_4-5-整体流程",link:"#_4-5-整体流程",children:[]},{level:3,title:"4.4 日志",slug:"_4-4-日志",link:"#_4-4-日志",children:[]},{level:3,title:"4.5 定时触发",slug:"_4-5-定时触发",link:"#_4-5-定时触发",children:[]}]},{level:2,title:"五、其他",slug:"五、其他",link:"#五、其他",children:[{level:3,title:"5.1 Gitlab触发",slug:"_5-1-gitlab触发",link:"#_5-1-gitlab触发",children:[]}]},{level:2,title:"六、总结",slug:"六、总结",link:"#六、总结",children:[]}],path:"/devops/devops-ping-tai.html",pathLocale:"/",extraFields:[]},{title:"Git",headers:[],path:"/devops/gitlab-ci.html",pathLocale:"/",extraFields:[]},{title:"jenkins-x",headers:[],path:"/devops/jenkins-x.html",pathLocale:"/",extraFields:[]},{title:"tekton",headers:[],path:"/devops/tekton.html",pathLocale:"/",extraFields:[]},{title:"微信支付",headers:[],path:"/donate/",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/interview/tiktok2023.html",pathLocale:"/",extraFields:[]},{title:"JVM调优参数",headers:[{level:2,title:"一、堆大小设置",slug:"一、堆大小设置",link:"#一、堆大小设置",children:[{level:3,title:"典型设置:",slug:"典型设置",link:"#典型设置",children:[]}]},{level:2,title:"二、回收器选择",slug:"二、回收器选择",link:"#二、回收器选择",children:[{level:3,title:"2.1 吞吐量优先的并行收集器",slug:"_2-1-吞吐量优先的并行收集器",link:"#_2-1-吞吐量优先的并行收集器",children:[]},{level:3,title:"2.2 响应时间优先的并发收集器",slug:"_2-2-响应时间优先的并发收集器",link:"#_2-2-响应时间优先的并发收集器",children:[]}]},{level:2,title:"三、辅助信息",slug:"三、辅助信息",link:"#三、辅助信息",children:[{level:3,title:"3.1 堆设置",slug:"_3-1-堆设置",link:"#_3-1-堆设置",children:[]},{level:3,title:"3.2 收集器设置",slug:"_3-2-收集器设置",link:"#_3-2-收集器设置",children:[]},{level:3,title:"3.3 垃圾回收统计信息",slug:"_3-3-垃圾回收统计信息",link:"#_3-3-垃圾回收统计信息",children:[]},{level:3,title:"3.4 并行收集器设置",slug:"_3-4-并行收集器设置",link:"#_3-4-并行收集器设置",children:[]},{level:3,title:"3.5 并发收集器设置",slug:"_3-5-并发收集器设置",link:"#_3-5-并发收集器设置",children:[]}]},{level:2,title:"四、调优总结",slug:"四、调优总结",link:"#四、调优总结",children:[{level:3,title:"4.1 年轻代大小选择",slug:"_4-1-年轻代大小选择",link:"#_4-1-年轻代大小选择",children:[]},{level:3,title:"4.2 年老代大小选择",slug:"_4-2-年老代大小选择",link:"#_4-2-年老代大小选择",children:[]},{level:3,title:"4.3 较小堆引起的碎片问题",slug:"_4-3-较小堆引起的碎片问题",link:"#_4-3-较小堆引起的碎片问题",children:[]}]}],path:"/java/JVM%E8%B0%83%E4%BC%98%E5%8F%82%E6%95%B0.html",pathLocale:"/",extraFields:[]},{title:"被挖矿攻击",headers:[],path:"/java/serverlog.html",pathLocale:"/",extraFields:[]},{title:"一次jvm调优过程",headers:[{level:2,title:"1. 启用jmx和远程debug模式",slug:"_1-启用jmx和远程debug模式",link:"#_1-启用jmx和远程debug模式",children:[]},{level:2,title:"2. memory analyzer、jprofiler进行堆内存分析",slug:"_2-memory-analyzer、jprofiler进行堆内存分析",link:"#_2-memory-analyzer、jprofiler进行堆内存分析",children:[]},{level:2,title:"3. netty的方面的考虑",slug:"_3-netty的方面的考虑",link:"#_3-netty的方面的考虑",children:[]},{level:2,title:"4. 直接内存排查",slug:"_4-直接内存排查",link:"#_4-直接内存排查",children:[]},{level:2,title:"5. 推荐的直接内存排查方法",slug:"_5-推荐的直接内存排查方法",link:"#_5-推荐的直接内存排查方法",children:[]},{level:2,title:"6. 意外的结果",slug:"_6-意外的结果",link:"#_6-意外的结果",children:[]},{level:2,title:"总结",slug:"总结",link:"#总结",children:[]}],path:"/java/%E4%B8%80%E6%AC%A1jvm%E8%B0%83%E4%BC%98%E8%BF%87%E7%A8%8B.html",pathLocale:"/",extraFields:[]},{title:"内存屏障",headers:[],path:"/java/%E5%86%85%E5%AD%98%E5%B1%8F%E9%9A%9C.html",pathLocale:"/",extraFields:[]},{title:"在 Spring 6 中使用虚拟线程",headers:[{level:2,title:"一、简介",slug:"一、简介",link:"#一、简介",children:[]},{level:2,title:"二、 虚拟线程与平台线程",slug:"二、-虚拟线程与平台线程",link:"#二、-虚拟线程与平台线程",children:[]},{level:2,title:"三、在Spring 6中使用虚拟线程",slug:"三、在spring-6中使用虚拟线程",link:"#三、在spring-6中使用虚拟线程",children:[]},{level:2,title:"四、性能比较",slug:"四、性能比较",link:"#四、性能比较",children:[]}],path:"/java/%E5%9C%A8%20Spring%206%20%E4%B8%AD%E4%BD%BF%E7%94%A8%E8%99%9A%E6%8B%9F%E7%BA%BF%E7%A8%8B.html",pathLocale:"/",extraFields:[]},{title:"基于kubernetes的分布式限流",headers:[{level:2,title:"一、概念",slug:"一、概念",link:"#一、概念",children:[{level:3,title:"1.1 使用场景",slug:"_1-1-使用场景",link:"#_1-1-使用场景",children:[]},{level:3,title:"1.2 维度",slug:"_1-2-维度",link:"#_1-2-维度",children:[]},{level:3,title:"1.3 分布式限流",slug:"_1-3-分布式限流",link:"#_1-3-分布式限流",children:[]}]},{level:2,title:"二、分布式限流常用方案",slug:"二、分布式限流常用方案",link:"#二、分布式限流常用方案",children:[]},{level:2,title:"三、基于kubernetes的分布式限流",slug:"三、基于kubernetes的分布式限流",link:"#三、基于kubernetes的分布式限流",children:[{level:3,title:"3.1 kubernetes中的副本数",slug:"_3-1-kubernetes中的副本数",link:"#_3-1-kubernetes中的副本数",children:[]},{level:3,title:"3.2 rateLimiter的创建",slug:"_3-2-ratelimiter的创建",link:"#_3-2-ratelimiter的创建",children:[]},{level:3,title:"3.3 rateLimiter的获取",slug:"_3-3-ratelimiter的获取",link:"#_3-3-ratelimiter的获取",children:[]},{level:3,title:"3.4 filter里的判断",slug:"_3-4-filter里的判断",link:"#_3-4-filter里的判断",children:[]}]},{level:2,title:"四、性能压测",slug:"四、性能压测",link:"#四、性能压测",children:[]},{level:2,title:"五、其他问题",slug:"五、其他问题",link:"#五、其他问题",children:[]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/java/%E5%9F%BA%E4%BA%8Ekubernetes%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E9%99%90%E6%B5%81.html",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/kubernetes/",pathLocale:"/",extraFields:[]},{title:"spark on k8s operator",headers:[],path:"/kubernetes/spark%20on%20k8s%20operator.html",pathLocale:"/",extraFields:[]},{title:"2017",headers:[],path:"/life/2017.html",pathLocale:"/",extraFields:[]},{title:"2018",headers:[{level:2,title:"心惊胆战的裸辞经历",slug:"心惊胆战的裸辞经历",link:"#心惊胆战的裸辞经历",children:[]},{level:2,title:"工作工作",slug:"工作工作",link:"#工作工作",children:[]},{level:2,title:"跑步跑步",slug:"跑步跑步",link:"#跑步跑步",children:[]},{level:2,title:"Others",slug:"others",link:"#others",children:[]},{level:2,title:"2019",slug:"_2019",link:"#_2019",children:[]}],path:"/life/2018.html",pathLocale:"/",extraFields:[]},{title:"2019",headers:[{level:2,title:"工作",slug:"工作",link:"#工作",children:[]},{level:2,title:"学习",slug:"学习",link:"#学习",children:[]},{level:2,title:"感情",slug:"感情",link:"#感情",children:[]},{level:2,title:"运动",slug:"运动",link:"#运动",children:[]},{level:2,title:"其他",slug:"其他",link:"#其他",children:[]},{level:2,title:"2020展望",slug:"_2020展望",link:"#_2020展望",children:[]}],path:"/life/2019.html",pathLocale:"/",extraFields:[]},{title:"友链地址",headers:[],path:"/link/main.html",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/open-source-project/",pathLocale:"/",extraFields:[]},{title:"微信公众号-chatgpt智能客服搭建",headers:[{level:2,title:"一、ChatGPT注册",slug:"一、chatgpt注册",link:"#一、chatgpt注册",children:[{level:3,title:"1.1 短信手机号申请",slug:"_1-1-短信手机号申请",link:"#_1-1-短信手机号申请",children:[]},{level:3,title:"1.2 云服务器申请",slug:"_1-2-云服务器申请",link:"#_1-2-云服务器申请",children:[]},{level:3,title:"1.3 ChatGPT注册",slug:"_1-3-chatgpt注册",link:"#_1-3-chatgpt注册",children:[]}]},{level:2,title:"二、搭建nginx服务器",slug:"二、搭建nginx服务器",link:"#二、搭建nginx服务器",children:[]},{level:2,title:"三、公众号开发",slug:"三、公众号开发",link:"#三、公众号开发",children:[{level:3,title:"3.1 微信云托管",slug:"_3-1-微信云托管",link:"#_3-1-微信云托管",children:[]},{level:3,title:"3.2 一个简单ChatGPT简单回复",slug:"_3-2-一个简单chatgpt简单回复",link:"#_3-2-一个简单chatgpt简单回复",children:[]},{level:3,title:"3.3 服务部署",slug:"_3-3-服务部署",link:"#_3-3-服务部署",children:[]}]},{level:2,title:"四、没有回复(超时回复问题)",slug:"四、没有回复-超时回复问题",link:"#四、没有回复-超时回复问题",children:[]},{level:2,title:"五、会话保存",slug:"五、会话保存",link:"#五、会话保存",children:[]},{level:2,title:"六、其他问题",slug:"六、其他问题",link:"#六、其他问题",children:[{level:3,title:"6.1 限频",slug:"_6-1-限频",link:"#_6-1-限频",children:[]},{level:3,title:"6.2 秘钥key被更新",slug:"_6-2-秘钥key被更新",link:"#_6-2-秘钥key被更新",children:[]},{level:3,title:"6.3 为啥和官网的回复不一样",slug:"_6-3-为啥和官网的回复不一样",link:"#_6-3-为啥和官网的回复不一样",children:[]},{level:3,title:"6.4 玄学挂掉",slug:"_6-4-玄学挂掉",link:"#_6-4-玄学挂掉",children:[]}]},{level:2,title:"最后",slug:"最后",link:"#最后",children:[]}],path:"/others/chatgpt.html",pathLocale:"/",extraFields:[]},{title:"StarCraft Ⅱ 人工智能教程",headers:[],path:"/others/starcraft-ai.html",pathLocale:"/",extraFields:[]},{title:"Tesla api",headers:[{level:2,title:"一、特斯拉应用申请",slug:"一、特斯拉应用申请",link:"#一、特斯拉应用申请",children:[{level:3,title:"1.1 创建 Tesla 账户",slug:"_1-1-创建-tesla-账户",link:"#_1-1-创建-tesla-账户",children:[]},{level:3,title:"1.2 提交访问请求",slug:"_1-2-提交访问请求",link:"#_1-2-提交访问请求",children:[]},{level:3,title:"1.3 访问应用程序凭据",slug:"_1-3-访问应用程序凭据",link:"#_1-3-访问应用程序凭据",children:[]},{level:3,title:"1.4 开始 API 集成",slug:"_1-4-开始-api-集成",link:"#_1-4-开始-api-集成",children:[]},{level:3,title:"2.1 认识token",slug:"_2-1-认识token",link:"#_2-1-认识token",children:[]},{level:3,title:"2.2 获取第三方应用token",slug:"_2-2-获取第三方应用token",link:"#_2-2-获取第三方应用token",children:[]},{level:3,title:"2.3 验证域名归属",slug:"_2-3-验证域名归属",link:"#_2-3-验证域名归属",children:[]}]}],path:"/others/tesla.html",pathLocale:"/",extraFields:[]},{title:"广州图书馆借阅抓取",headers:[{level:3,title:"1.页面跳转过程",slug:"_1-页面跳转过程",link:"#_1-页面跳转过程",children:[]},{level:3,title:"2.处理方法",slug:"_2-处理方法",link:"#_2-处理方法",children:[]},{level:3,title:"3.代码",slug:"_3-代码",link:"#_3-代码",children:[]},{level:2,title:"总结",slug:"总结",link:"#总结",children:[]}],path:"/others/%E5%B9%BF%E5%B7%9E%E5%9B%BE%E4%B9%A6%E9%A6%86%E5%80%9F%E9%98%85%E6%8A%93%E5%8F%96.html",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/redis/",pathLocale:"/",extraFields:[]},{title:"一、概述",headers:[{level:2,title:"1.1 缓存介绍",slug:"_1-1-缓存介绍",link:"#_1-1-缓存介绍",children:[]},{level:2,title:"1.2 本站缓存架构",slug:"_1-2-本站缓存架构",link:"#_1-2-本站缓存架构",children:[]},{level:2,title:"2.1 mybatis一级缓存",slug:"_2-1-mybatis一级缓存",link:"#_2-1-mybatis一级缓存",children:[]},{level:2,title:"2.2 mybatis二级缓存",slug:"_2-2-mybatis二级缓存",link:"#_2-2-mybatis二级缓存",children:[{level:3,title:"2.2.1 MyBatis二级缓存的划分",slug:"_2-2-1-mybatis二级缓存的划分",link:"#_2-2-1-mybatis二级缓存的划分",children:[]},{level:3,title:"2.2.2 二级缓存的开启",slug:"_2-2-2-二级缓存的开启",link:"#_2-2-2-二级缓存的开启",children:[]},{level:3,title:"2.2.3 使用第三方支持的二级缓存的实现",slug:"_2-2-3-使用第三方支持的二级缓存的实现",link:"#_2-2-3-使用第三方支持的二级缓存的实现",children:[]}]},{level:2,title:"2.3 Mybatis在分布式环境下脏读问题",slug:"_2-3-mybatis在分布式环境下脏读问题",link:"#_2-3-mybatis在分布式环境下脏读问题",children:[]},{level:2,title:"3.1 Spring Cache",slug:"_3-1-spring-cache",link:"#_3-1-spring-cache",children:[]},{level:2,title:"3.2 引入包",slug:"_3-2-引入包",link:"#_3-2-引入包",children:[]},{level:2,title:"3.3 ApplicationContext.xml",slug:"_3-3-applicationcontext-xml",link:"#_3-3-applicationcontext-xml",children:[]},{level:2,title:"3.5 自定义KeyGenerator",slug:"_3-5-自定义keygenerator",link:"#_3-5-自定义keygenerator",children:[]},{level:2,title:"3.4 添加注解",slug:"_3-4-添加注解",link:"#_3-4-添加注解",children:[]},{level:2,title:"3.5 测试",slug:"_3-5-测试",link:"#_3-5-测试",children:[]},{level:2,title:"3.6 实验结果",slug:"_3-6-实验结果",link:"#_3-6-实验结果",children:[]},{level:2,title:"3.7 分页的数据怎么办",slug:"_3-7-分页的数据怎么办",link:"#_3-7-分页的数据怎么办",children:[]}],path:"/redis/redis%E7%BC%93%E5%AD%98.html",pathLocale:"/",extraFields:[]},{title:"自我介绍",headers:[],path:"/about-the-author/personal-life/wewe.html",pathLocale:"/",extraFields:[]},{title:"小程序",headers:[],path:"/about-the-author/works/%E4%B8%AA%E4%BA%BA%E4%BD%9C%E5%93%81.html",pathLocale:"/",extraFields:[]},{title:"elastic spark",headers:[{level:2,title:"一、原生RDD支持",slug:"一、原生rdd支持",link:"#一、原生rdd支持",children:[{level:3,title:"1.1 基础配置",slug:"_1-1-基础配置",link:"#_1-1-基础配置",children:[]},{level:3,title:"1.2 读取es数据",slug:"_1-2-读取es数据",link:"#_1-2-读取es数据",children:[]},{level:3,title:"1.3 写数据",slug:"_1-3-写数据",link:"#_1-3-写数据",children:[]}]},{level:2,title:"二、Spark Streaming",slug:"二、spark-streaming",link:"#二、spark-streaming",children:[]},{level:2,title:"三、Spark SQL",slug:"三、spark-sql",link:"#三、spark-sql",children:[]},{level:2,title:"四、Spark Structure Streaming",slug:"四、spark-structure-streaming",link:"#四、spark-structure-streaming",children:[]},{level:2,title:"五、Spark on kubernetes Operator",slug:"五、spark-on-kubernetes-operator",link:"#五、spark-on-kubernetes-operator",children:[]}],path:"/bigdata/spark/elastic-spark.html",pathLocale:"/",extraFields:[]},{title:"【elasticsearch】源码debug",headers:[],path:"/database/elasticsearch/elasticsearch%E6%BA%90%E7%A0%81debug.html",pathLocale:"/",extraFields:[]},{title:"【elasticsearch】搜索过程详解",headers:[{level:3,title:"SearchType",slug:"searchtype",link:"#searchtype",children:[]},{level:2,title:"搜索入口:",slug:"搜索入口",link:"#搜索入口",children:[]},{level:2,title:"3.1 query阶段",slug:"_3-1-query阶段",link:"#_3-1-query阶段",children:[]},{level:2,title:"3.2 Fetch阶段",slug:"_3-2-fetch阶段",link:"#_3-2-fetch阶段",children:[{level:3,title:"3.2.1 FetchSearchPhase(对应上面的1)",slug:"_3-2-1-fetchsearchphase-对应上面的1",link:"#_3-2-1-fetchsearchphase-对应上面的1",children:[]},{level:3,title:"3.2.2 ExpandSearchPhase(对应上图的2)",slug:"_3-2-2-expandsearchphase-对应上图的2",link:"#_3-2-2-expandsearchphase-对应上图的2",children:[]}]},{level:2,title:"4.1 执行query、fetch流程",slug:"_4-1-执行query、fetch流程",link:"#_4-1-执行query、fetch流程",children:[]}],path:"/database/elasticsearch/%E3%80%90elasticsearch%E3%80%91%E6%90%9C%E7%B4%A2%E8%BF%87%E7%A8%8B%E8%AF%A6%E8%A7%A3.html",pathLocale:"/",extraFields:[]},{title:"mysql",headers:[],path:"/database/mysql/1mysql.html",pathLocale:"/",extraFields:[]},{title:"数据库缓存",headers:[],path:"/database/mysql/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%BC%93%E5%AD%98.html",pathLocale:"/",extraFields:[]},{title:"redis缓存",headers:[{level:2,title:"一、概述",slug:"一、概述",link:"#一、概述",children:[{level:3,title:"1.1 缓存介绍",slug:"_1-1-缓存介绍",link:"#_1-1-缓存介绍",children:[]},{level:3,title:"1.2 本站缓存架构",slug:"_1-2-本站缓存架构",link:"#_1-2-本站缓存架构",children:[]}]},{level:2,title:"二、Mybatis缓存",slug:"二、mybatis缓存",link:"#二、mybatis缓存",children:[{level:3,title:"2.1 mybatis一级缓存",slug:"_2-1-mybatis一级缓存",link:"#_2-1-mybatis一级缓存",children:[]},{level:3,title:"2.2 mybatis二级缓存",slug:"_2-2-mybatis二级缓存",link:"#_2-2-mybatis二级缓存",children:[]},{level:3,title:"2.3 Mybatis在分布式环境下脏读问题",slug:"_2-3-mybatis在分布式环境下脏读问题",link:"#_2-3-mybatis在分布式环境下脏读问题",children:[]}]},{level:2,title:"三、Redis缓存",slug:"三、redis缓存",link:"#三、redis缓存",children:[{level:3,title:"3.1 Spring Cache",slug:"_3-1-spring-cache",link:"#_3-1-spring-cache",children:[]},{level:3,title:"3.2 引入包",slug:"_3-2-引入包",link:"#_3-2-引入包",children:[]},{level:3,title:"3.3 ApplicationContext.xml",slug:"_3-3-applicationcontext-xml",link:"#_3-3-applicationcontext-xml",children:[]},{level:3,title:"3.5 自定义KeyGenerator",slug:"_3-5-自定义keygenerator",link:"#_3-5-自定义keygenerator",children:[]},{level:3,title:"3.4 添加注解",slug:"_3-4-添加注解",link:"#_3-4-添加注解",children:[]},{level:3,title:"3.5 测试",slug:"_3-5-测试",link:"#_3-5-测试",children:[]},{level:3,title:"3.6 实验结果",slug:"_3-6-实验结果",link:"#_3-6-实验结果",children:[]},{level:3,title:"3.7 分页的数据怎么办",slug:"_3-7-分页的数据怎么办",link:"#_3-7-分页的数据怎么办",children:[]}]},{level:2,title:"四、如何解决脏读?",slug:"四、如何解决脏读",link:"#四、如何解决脏读",children:[]},{level:2,title:"五、题外话",slug:"五、题外话",link:"#五、题外话",children:[]}],path:"/database/redis/redis%E7%BC%93%E5%AD%98.html",pathLocale:"/",extraFields:[]},{title:"Spring Boot Prometheus使用",headers:[{level:2,title:"(1)引入库",slug:"_1-引入库",link:"#_1-引入库",children:[]},{level:2,title:"(2)修改配置文件",slug:"_2-修改配置文件",link:"#_2-修改配置文件",children:[]},{level:2,title:"(3)抓包看一下metrics(可跳过)",slug:"_3-抓包看一下metrics-可跳过",link:"#_3-抓包看一下metrics-可跳过",children:[]}],path:"/java/SpringBoot/Spring%20Boot%20Prometheus%E4%BD%BF%E7%94%A8.html",pathLocale:"/",extraFields:[]},{title:"AOP",headers:[{level:2,title:"一、概述",slug:"一、概述",link:"#一、概述",children:[{level:3,title:"1.1 特点",slug:"_1-1-特点",link:"#_1-1-特点",children:[]},{level:3,title:"1.2 AOP概述",slug:"_1-2-aop概述",link:"#_1-2-aop概述",children:[]}]},{level:2,title:"二、Spring中的AOP",slug:"二、spring中的aop",link:"#二、spring中的aop",children:[{level:3,title:"2.1 AspectJ支持5种类型的通知注解:",slug:"_2-1-aspectj支持5种类型的通知注解",link:"#_2-1-aspectj支持5种类型的通知注解",children:[]},{level:3,title:"2.2 Spring提供了4种实现AOP的方式:",slug:"_2-2-spring提供了4种实现aop的方式",link:"#_2-2-spring提供了4种实现aop的方式",children:[]}]},{level:2,title:"三、原理概述",slug:"三、原理概述",link:"#三、原理概述",children:[]},{level:2,title:"四、使用",slug:"四、使用",link:"#四、使用",children:[]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/java/SpringBoot/aop.html",pathLocale:"/",extraFields:[]},{title:"Webflux",headers:[{level:3,title:"1.Servlet 3.1就已经支持异步非阻塞,为什么要用webflux?",slug:"_1-servlet-3-1就已经支持异步非阻塞-为什么要用webflux",link:"#_1-servlet-3-1就已经支持异步非阻塞-为什么要用webflux",children:[]},{level:3,title:"webflux和springboot虚拟线程对比",slug:"webflux和springboot虚拟线程对比",link:"#webflux和springboot虚拟线程对比",children:[]}],path:"/java/SpringBoot/webflux.html",pathLocale:"/",extraFields:[]},{title:"1.历史与架构",headers:[{level:2,title:"1.建站故事与网站架构",slug:"_1-建站故事与网站架构",link:"#_1-建站故事与网站架构",children:[{level:3,title:"1.1建站过程",slug:"_1-1建站过程",link:"#_1-1建站过程",children:[]},{level:3,title:"1.2 网站整体技术架构",slug:"_1-2-网站整体技术架构",link:"#_1-2-网站整体技术架构",children:[]},{level:3,title:"1.3 日志系统",slug:"_1-3-日志系统",link:"#_1-3-日志系统",children:[]},{level:3,title:"1.4 【有点意思】自然语言处理",slug:"_1-4-【有点意思】自然语言处理",link:"#_1-4-【有点意思】自然语言处理",children:[]}]},{level:2,title:"总结",slug:"总结",link:"#总结",children:[]}],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html",pathLocale:"/",extraFields:[]},{title:"10.历时8年最终改版",headers:[{level:2,title:"一、博客的安装",slug:"一、博客的安装",link:"#一、博客的安装",children:[]},{level:2,title:"二、配置",slug:"二、配置",link:"#二、配置",children:[]},{level:2,title:"三、为文章增加评论",slug:"三、为文章增加评论",link:"#三、为文章增加评论",children:[]},{level:2,title:"四、博客的部署",slug:"四、博客的部署",link:"#四、博客的部署",children:[]},{level:2,title:"五、Github pages自定义域名",slug:"五、github-pages自定义域名",link:"#五、github-pages自定义域名",children:[]},{level:2,title:"六、Typora图床",slug:"六、typora图床",link:"#六、typora图床",children:[]},{level:2,title:"七、为自己的内容增加收入",slug:"七、为自己的内容增加收入",link:"#七、为自己的内容增加收入",children:[]},{level:2,title:"常见问题",slug:"常见问题",link:"#常见问题",children:[]}],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/10.%E5%8E%86%E6%97%B68%E5%B9%B4%E6%9C%80%E7%BB%88%E6%94%B9%E7%89%88.html",pathLocale:"/",extraFields:[]},{title:"2.Lucene的使用",headers:[{level:3,title:"Lucene的整体架构",slug:"lucene的整体架构",link:"#lucene的整体架构",children:[]},{level:3,title:"搜索引擎的几个重要概念:",slug:"搜索引擎的几个重要概念",link:"#搜索引擎的几个重要概念",children:[]},{level:3,title:"Lucene中的几个概念",slug:"lucene中的几个概念",link:"#lucene中的几个概念",children:[]},{level:3,title:"lucene在本网站的使用:",slug:"lucene在本网站的使用",link:"#lucene在本网站的使用",children:[]},{level:2,title:"一、搜索",slug:"一、搜索",link:"#一、搜索",children:[]},{level:2,title:"二、lucene自动补全",slug:"二、lucene自动补全",link:"#二、lucene自动补全",children:[]}],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html",pathLocale:"/",extraFields:[]},{title:"3.定时任务",headers:[{level:3,title:"一.特点:",slug:"一-特点",link:"#一-特点",children:[]},{level:3,title:"二.主要组成部分",slug:"二-主要组成部分",link:"#二-主要组成部分",children:[]},{level:3,title:"三、Quartz设计",slug:"三、quartz设计",link:"#三、quartz设计",children:[]},{level:3,title:"四、使用",slug:"四、使用",link:"#四、使用",children:[]},{level:2,title:"Spring的高级特性之定时任务",slug:"spring的高级特性之定时任务",link:"#spring的高级特性之定时任务",children:[]}],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html",pathLocale:"/",extraFields:[]},{title:"4.日志系统.md",headers:[{level:2,title:"1.网站代码安装",slug:"_1-网站代码安装",link:"#_1-网站代码安装",children:[]},{level:2,title:"2.根据API获取数据",slug:"_2-根据api获取数据",link:"#_2-根据api获取数据",children:[]},{level:2,title:"3.构建请求",slug:"_3-构建请求",link:"#_3-构建请求",children:[]},{level:2,title:"4.实际运用",slug:"_4-实际运用",link:"#_4-实际运用",children:[]},{level:2,title:"5.基本代码",slug:"_5-基本代码",link:"#_5-基本代码",children:[]},{level:2,title:"6.展示数据",slug:"_6-展示数据",link:"#_6-展示数据",children:[]}],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html",pathLocale:"/",extraFields:[]},{title:"5.小集群部署.md",headers:[{level:2,title:"1.1 Nginx的安装",slug:"_1-1-nginx的安装",link:"#_1-1-nginx的安装",children:[]},{level:2,title:"1.2 Nginx的配置",slug:"_1-2-nginx的配置",link:"#_1-2-nginx的配置",children:[]},{level:2,title:"测试:",slug:"测试",link:"#测试",children:[]}],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html",pathLocale:"/",extraFields:[]},{title:"6.数据库备份",headers:[{level:3,title:"2.1 创建所用的复制账号",slug:"_2-1-创建所用的复制账号",link:"#_2-1-创建所用的复制账号",children:[]},{level:3,title:"2.2 配置master",slug:"_2-2-配置master",link:"#_2-2-配置master",children:[]},{level:3,title:"2.3 配置slave",slug:"_2-3-配置slave",link:"#_2-3-配置slave",children:[]}],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html",pathLocale:"/",extraFields:[]},{title:"7.那些牛逼的插件",headers:[{level:2,title:"wowslider",slug:"wowslider",link:"#wowslider",children:[]},{level:2,title:"畅言",slug:"畅言",link:"#畅言",children:[]},{level:2,title:"Editor.md",slug:"editor-md",link:"#editor-md",children:[]},{level:2,title:"图表",slug:"图表",link:"#图表",children:[]},{level:2,title:"百度分享",slug:"百度分享",link:"#百度分享",children:[]},{level:2,title:"瀑布流",slug:"瀑布流",link:"#瀑布流",children:[]},{level:2,title:"天气插件",slug:"天气插件",link:"#天气插件",children:[]},{level:2,title:"标签云",slug:"标签云",link:"#标签云",children:[]}],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html",pathLocale:"/",extraFields:[]},{title:"8.基于贝叶斯的情感分析",headers:[],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/8.%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%9A%84%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90.html",pathLocale:"/",extraFields:[]},{title:"9.网站性能优化",headers:[],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html",pathLocale:"/",extraFields:[]},{title:"kafka面试题",headers:[],path:"/middleware/kafka/kafka.html",pathLocale:"/",extraFields:[]},{title:"Zookeeper",headers:[],path:"/middleware/zookeeper/zookeeper.html",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/404.html",pathLocale:"/",extraFields:[]},{title:"Interview",headers:[],path:"/interview/",pathLocale:"/",extraFields:[]},{title:"Java",headers:[],path:"/java/",pathLocale:"/",extraFields:[]},{title:"Life",headers:[],path:"/life/",pathLocale:"/",extraFields:[]},{title:"Link",headers:[],path:"/link/",pathLocale:"/",extraFields:[]},{title:"Others",headers:[],path:"/others/",pathLocale:"/",extraFields:[]},{title:"Personal Life",headers:[],path:"/about-the-author/personal-life/",pathLocale:"/",extraFields:[]},{title:"Works",headers:[],path:"/about-the-author/works/",pathLocale:"/",extraFields:[]},{title:"Spark",headers:[],path:"/bigdata/spark/",pathLocale:"/",extraFields:[]},{title:"Bigdata",headers:[],path:"/bigdata/",pathLocale:"/",extraFields:[]},{title:"Elasticsearch",headers:[],path:"/database/elasticsearch/",pathLocale:"/",extraFields:[]},{title:"Mysql",headers:[],path:"/database/mysql/",pathLocale:"/",extraFields:[]},{title:"Redis",headers:[],path:"/database/redis/",pathLocale:"/",extraFields:[]},{title:"Spring Boot",headers:[],path:"/java/SpringBoot/",pathLocale:"/",extraFields:[]},{title:"个人网站",headers:[],path:"/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/",pathLocale:"/",extraFields:[]},{title:"Kafka",headers:[],path:"/middleware/kafka/",pathLocale:"/",extraFields:[]},{title:"Middleware",headers:[],path:"/middleware/",pathLocale:"/",extraFields:[]},{title:"Zookeeper",headers:[],path:"/middleware/zookeeper/",pathLocale:"/",extraFields:[]},{title:"分类",headers:[],path:"/category/",pathLocale:"/",extraFields:[]},{title:"标签",headers:[],path:"/tag/",pathLocale:"/",extraFields:[]},{title:"文章",headers:[],path:"/article/",pathLocale:"/",extraFields:[]},{title:"星标",headers:[],path:"/star/",pathLocale:"/",extraFields:[]},{title:"时间轴",headers:[],path:"/timeline/",pathLocale:"/",extraFields:[]}],I0=X(C0),P0=()=>I0,O0=({searchIndex:e,routeLocale:t,query:n,maxSuggestions:r})=>{const a=E(()=>e.value.filter(l=>l.pathLocale===t.value));return E(()=>{const l=n.value.trim().toLowerCase();if(!l)return[];const o=[],s=(c,u)=>{_i(l,[u.title])&&o.push({link:`${c.path}#${u.slug}`,title:c.title,header:u.title});for(const d of u.children){if(o.length>=r.value)return;s(c,d)}};for(const c of a.value){if(o.length>=r.value)break;if(_i(l,[c.title,...c.extraFields])){o.push({link:c.path,title:c.title});continue}for(const u of c.headers){if(o.length>=r.value)break;s(c,u)}}return o})},D0=e=>{const t=X(0);return{focusIndex:t,focusNext:()=>{t.value{t.value>0?t.value-=1:t.value=e.value.length-1}}},R0=V({name:"SearchBox",props:{locales:{type:Object,required:!1,default:()=>({})},hotKeys:{type:Array,required:!1,default:()=>[]},maxSuggestions:{type:Number,required:!1,default:5}},setup(e){const{locales:t,hotKeys:n,maxSuggestions:r}=Sd(e),a=Ve(),l=ct(),o=P0(),s=X(null),c=X(!1),u=X(""),d=E(()=>t.value[l.value]??{}),f=O0({searchIndex:o,routeLocale:l,query:u,maxSuggestions:r}),{focusIndex:p,focusNext:h,focusPrev:g}=D0(f);B0({input:s,hotKeys:n});const w=E(()=>c.value&&!!f.value.length),k=()=>{w.value&&g()},b=()=>{w.value&&h()},x=_=>{if(!w.value)return;const S=f.value[_];S&&a.push(S.link).then(()=>{u.value="",p.value=0})};return()=>i("form",{class:"search-box",role:"search"},[i("input",{ref:s,type:"search",placeholder:d.value.placeholder,autocomplete:"off",spellcheck:!1,value:u.value,onFocus:()=>c.value=!0,onBlur:()=>c.value=!1,onInput:_=>u.value=_.target.value,onKeydown:_=>{switch(_.key){case"ArrowUp":{k();break}case"ArrowDown":{b();break}case"Enter":{_.preventDefault(),x(p.value);break}}}}),w.value&&i("ul",{class:"suggestions",onMouseleave:()=>p.value=-1},f.value.map(({link:_,title:S,header:D},L)=>i("li",{class:["suggestion",{focus:p.value===L}],onMouseenter:()=>p.value=L,onMousedown:()=>x(L)},i("a",{href:_,onClick:U=>U.preventDefault()},[i("span",{class:"page-title"},S),D&&i("span",{class:"page-header"},`> ${D}`)]))))])}});var M0=["s","/"],F0={"/":{placeholder:"搜索"}};const V0=F0,$0=M0,j0=10,N0=Ye({enhance({app:e}){e.component("SearchBox",t=>i(R0,{locales:V0,hotKeys:$0,maxSuggestions:j0,...t}))}}),Re=e=>{const{icon:t="",color:n,size:r}=e,a={};return n&&(a.color=n),r&&(a.height=Number.isNaN(Number(r))?r:`${r}px`),xn(t)?i("img",{class:"icon",src:t,"no-view":"",style:a}):da(t)?i("img",{class:"icon",src:Le(t),"aria-hidden":"","no-view":"",style:a}):i(He("FontIcon"),e)};Re.displayName="HopeIcon";const ir=()=>{const e=Ve(),t=gt();return n=>{if(n)if(da(n))t.path!==n&&e.push(n);else if(Os(n))window&&window.open(n);else{const r=t.path.slice(0,t.path.lastIndexOf("/"));e.push(`${r}/${encodeURI(n)}`)}}};var yi={"/":{word:"约 $word 字",less1Minute:"小于 1 分钟",time:"大约 $time 分钟"}};const Cc=()=>{const e=ie();return E(()=>e.value.readingTime??null)},tl=typeof yi>"u"?null:yi,Ic=(e,t)=>{const{minutes:n,words:r}=e,{less1Minute:a,word:l,time:o}=t;return{time:n<1?a:o.replace("$time",Math.round(n).toString()),words:l.replace("$word",r.toString())}},Ei={words:"",time:""},Pc=()=>tl?ar(tl):E(()=>null),z0=()=>{if(typeof tl>"u")return E(()=>Ei);const e=Cc(),t=Pc();return E(()=>e.value&&t.value?Ic(e.value,t.value):Ei)},$t=()=>yc(),se=()=>Sh(),nn=()=>E(()=>!!$t().value.pure),Oc=()=>{const e=se(),t=_e();return E(()=>{const{author:n}=t.value;return n?Yn(n):n===!1?[]:Yn(e.value.author,!1)})},H0=()=>{const e=_e();return E(()=>oc(e.value.category).map(t=>{var n,r;return{name:t,path:((r=(n=he(Symbol.for("categoryMap")))==null?void 0:n.value.map[t])==null?void 0:r.path)||""}}))},q0=()=>{const e=_e();return E(()=>ic(e.value.tag).map(t=>{var n,r;return{name:t,path:((r=(n=he(Symbol.for("tagMap")))==null?void 0:n.value.map[t])==null?void 0:r.path)||""}}))},G0=()=>{const e=_e(),t=ie();return E(()=>{const n=Ml(e.value.date);if(n)return n;const{createdTime:r}=t.value.git||{};return r?new Date(r):null})},U0=()=>{const e=se(),t=ie(),n=_e(),r=Oc(),a=H0(),l=q0(),o=G0(),s=Cc(),c=z0(),u=E(()=>({author:r.value,category:a.value,date:o.value,localizedDate:t.value.localizedDate,tag:l.value,isOriginal:n.value.isOriginal||!1,readingTime:s.value,readingTimeLocale:c.value,pageview:"pageview"in n.value?n.value.pageview:!0})),d=E(()=>"pageInfo"in n.value?n.value.pageInfo:"pageInfo"in e.value?e.value.pageInfo:null);return{info:u,items:d}};let Ra=null,Pn=null;const K0={wait:()=>Ra,pending:()=>{Ra=new Promise(e=>Pn=e)},resolve:()=>{Pn==null||Pn(),Ra=null,Pn=null}},Dc=()=>K0,W0="719px",J0="1440px",Y0="true",Nl={mobileBreakPoint:W0,pcBreakPoint:J0,enableThemeColor:Y0,"theme-1":"#2196f3","theme-2":"#f26d6d","theme-3":"#3eaf7c","theme-4":"#fb9b5f"},{mobileBreakPoint:Z0,pcBreakPoint:Q0}=Nl,ki=e=>e.endsWith("px")?Number(e.slice(0,-2)):null,sr=()=>{const e=X(!1),t=X(!1),n=()=>{e.value=window.innerWidth<=(ki(Z0)??719),t.value=window.innerWidth>=(ki(Q0)??1440)};return Ee(()=>{n(),je("resize",n,!1),je("orientationchange",n,!1)}),{isMobile:e,isPC:t}},Rc=Symbol(""),cr=()=>{const e=he(Rc);if(!e)throw new Error("useDarkmode() is called without provider.");return e},X0=e=>{const t=$t(),n=Qh(),r=Lc("vuepress-theme-hope-scheme","auto"),a=E(()=>t.value.darkmode||"switch"),l=E(()=>{const s=a.value;return s==="disable"?!1:s==="enable"?!0:s==="auto"?n.value:s==="toggle"?r.value==="dark":r.value==="dark"||r.value==="auto"&&n.value}),o=E(()=>{const s=a.value;return s==="switch"||s==="toggle"});e.provide(Rc,{canToggle:o,config:a,isDarkmode:l,status:r}),Object.defineProperties(e.config.globalProperties,{$isDarkmode:{get:()=>l.value}})},e2=()=>{const{isDarkmode:e}=cr(),t=(n=e.value)=>document.documentElement.setAttribute("data-theme",n?"dark":"light");Ee(()=>{ye(e,t,{immediate:!0})})},qe=V({name:"AutoLink",inheritAttrs:!1,props:{config:{type:Object,required:!0},exact:Boolean,noExternalLinkIcon:Boolean},emits:["focusout"],slots:Object,setup(e,{attrs:t,emit:n,slots:r}){const a=gt(),l=Ns(),o=Ln(e,"config"),s=E(()=>xn(o.value.link)),c=E(()=>!s.value&&Os(o.value.link)),u=E(()=>o.value.target||(s.value?"_blank":void 0)),d=E(()=>u.value==="_blank"),f=E(()=>!s.value&&!c.value&&!d.value),p=E(()=>o.value.rel||(d.value?"noopener noreferrer":void 0)),h=E(()=>o.value.ariaLabel||o.value.text),g=E(()=>{if(e.exact)return!1;const k=wt(l.value.locales);return k.length?k.every(b=>b!==o.value.link):o.value.link!=="/"}),w=E(()=>f.value?o.value.activeMatch?new RegExp(o.value.activeMatch).test(a.path):g.value?yn(a.path,o.value.link):a.path===o.value.link:!1);return()=>{const{before:k,after:b,default:x}=r,{text:_,icon:S,link:D}=o.value;return f.value?i(Ce,{to:D,"aria-label":h.value,...t,class:["nav-link",{active:w.value},t.class],onFocusout:()=>n("focusout")},()=>x?x():[k?k():i(Re,{icon:S}),_,b==null?void 0:b()]):i("a",{href:D,rel:p.value,target:u.value,"aria-label":h.value,...t,class:["nav-link",t.class],onFocusout:()=>n("focusout")},x?x():[k?k():i(Re,{icon:S}),_,e.noExternalLinkIcon?null:i(bc),b==null?void 0:b()])}}}),kn=(e,t,n=!1)=>"activeMatch"in t?new RegExp(t.activeMatch).test(e.path):cc(e,t.link)?!0:t.children&&!n?t.children.some(r=>kn(e,r)):!1,Mc=(e,t)=>t.type==="group"?t.children.some(n=>n.type==="group"?Mc(e,n):n.type==="page"&&kn(e,n,!0))||"prefix"in t&&cc(e,t.prefix):!1,Fc=(e,t)=>oe(e.link)?i(qe,{...t,config:e}):i("p",t,[i(Re,{icon:e.icon}),e.text]),Vc=e=>{const t=gt();return e?i("ul",{class:"vp-sidebar-sub-headers"},e.map(n=>i("li",{class:"vp-sidebar-sub-header"},[Fc(n,{class:["vp-sidebar-link","vp-heading",{active:kn(t,n,!0)}]}),Vc(n.children)]))):null},zl={"/database/mysql/":["1mysql","数据库缓存"],"/database/redis/":["redis缓存"],"/database/elasticsearch/":["【elasticsearch】搜索过程详解","elasticsearch源码debug"],"/database/mongodb/":[],"/bigdata/spark/":["elastic-spark"],"/middleware/kafka/":["kafka"],"/middleware/zookeeper/":["zookeeper"],"/life/":["2017","2018","2019"],"/others/":["starcraft-ai","tesla","广州图书馆借阅抓取","chatgpt"],"/about-the-author/personal-life/":["wewe"],"/about-the-author/works/":["个人作品"],"/about-the-author/talking/":[],"/java/":["JVM调优参数",{text:"Spring Boot",prefix:"SpringBoot/",collapsible:!0,children:["aop","Spring Boot Prometheus使用","webflux"]},"一次jvm调优过程",{text:"个人网站",prefix:"个人网站/",collapsible:!0,children:["1.历史与架构","2.Lucene的使用","3.定时任务","4.日志系统","5.小集群部署","6.数据库备份","7.那些牛逼的插件","8.基于贝叶斯的情感分析","9.网站性能优化","10.历时8年最终改版"]},"内存屏障","在 Spring 6 中使用虚拟线程","基于kubernetes的分布式限流","serverlog"]},t2=(e,t)=>{const n=e.replace(t,"/").split("/"),r=[];let a=Il(t);return n.forEach((l,o)=>{o!==n.length-1?(a+=`${l}/`,r.push({link:a,name:l||"Home"})):l!==""&&(a+=l,r.push({link:a,name:l}))}),r};var ge;(function(e){e.type="y",e.title="t",e.shortTitle="s",e.icon="i",e.author="a",e.date="d",e.localizedDate="l",e.category="c",e.tag="g",e.isEncrypted="n",e.isOriginal="o",e.readingTime="r",e.excerpt="e",e.sticky="u",e.cover="v",e.index="I",e.order="O"})(ge||(ge={}));var nl;(function(e){e.article="a",e.home="h",e.slide="s",e.page="p"})(nl||(nl={}));const Gt=(e="",t="")=>da(t)?t:`${Ps(e)}${t}`,pn=(e,t,n=!1)=>{let r=En(e,ac(encodeURI(t)));r.name==="404"&&(r=En(e,t));const{fullPath:a,meta:l,name:o}=r;return{text:!n&&l[ge.shortTitle]?l[ge.shortTitle]:l[ge.title]||t,link:o==="404"?t:a,...l[ge.icon]?{icon:l[ge.icon]}:{}}},n2=(e,t)=>{const n=ie();return{type:"heading",text:e.title,link:`${n.value.path}#${e.slug}`,children:Hl(e.children,t)}},Hl=(e,t)=>t>0?e.map(n=>n2(n,t-1)):[],$c=e=>{const t=ie();return Hl(t.value.headers,e)},rl=(e,t,n="")=>{const r=Ve(),a=ie(),l=(o,s=n)=>{var u;const c=oe(o)?pn(r,Gt(s,o)):o.link?{...o,...qr(o.link)?{}:{link:pn(r,Gt(s,o.link)).link}}:o;if("children"in c){const d=Gt(s,c.prefix),f=c.children==="structure"?zl[d]:c.children;return{type:"group",...c,prefix:d,children:f.map(p=>l(p,d))}}return{type:"page",...c,children:c.link===a.value.path?Hl(((u=a.value.headers[0])==null?void 0:u.level)===1?a.value.headers[0].children:a.value.headers,t):[]}};return e.map(o=>l(o))},r2=(e,t)=>{const n=ie(),r=wt(e).sort((a,l)=>l.length-a.length);for(const a of r)if(yn(decodeURI(n.value.path),a)){const l=e[a];return l?rl(l==="structure"?zl[a]:l==="heading"?$c(t):l,t,a):[]}return console.warn(`${n.value.path} is missing sidebar config.`),[]},a2=(e,t)=>{const n=ct();return e===!1?[]:e==="heading"?$c(t):e==="structure"?rl(zl[n.value],t,n.value):Q(e)?rl(e,t):Cl(e)?r2(e,t):[]},jc=Symbol(""),l2=()=>{const e=_e(),t=se(),n=ie(),r=E(()=>e.value.home?!1:e.value.sidebar??t.value.sidebar??"structure"),a=E(()=>e.value.headerDepth??t.value.headerDepth??2),l=$l(()=>[r.value,a.value,n.value.path,null],()=>a2(r.value,a.value));it(jc,l)},ql=()=>{const e=he(jc);if(!e)throw new Error("useSidebarItems() is called without provider.");return e},o2=V({name:"PageFooter",setup(){const e=$t(),t=se(),n=_e(),r=Oc(),a=E(()=>{const{copyright:u,footer:d}=n.value;return d!==!1&&!!(u||d||t.value.displayFooter)}),l=E(()=>{const{footer:u}=n.value;return u===!1?!1:oe(u)?u:t.value.footer||""}),o=E(()=>r.value.map(({name:u})=>u).join(", ")),s=u=>`Copyright © ${new Date().getFullYear()} ${o.value} ${u?`${u} Licensed`:""}`,c=E(()=>{const{copyright:u,license:d=""}=n.value,{license:f}=e.value,{copyright:p}=t.value;return u??(d?s(d):oe(p)?p:o.value||f?s(f):!1)});return()=>a.value?i("footer",{class:"vp-footer-wrapper"},[l.value?i("div",{class:"vp-footer",innerHTML:l.value}):null,c.value?i("div",{class:"vp-copyright",innerHTML:c.value}):null]):null}});var Ma=V({name:"EmptyComponent",setup:()=>()=>null});const i2=V({name:"NavbarDropdownLink",props:{config:{type:Object,required:!0}},slots:Object,setup(e,{slots:t}){const n=ie(),r=Ln(e,"config"),a=E(()=>r.value.ariaLabel||r.value.text),l=X(!1);ye(()=>n.value.path,()=>{l.value=!1});const o=s=>{s.detail===0&&(l.value=!l.value)};return()=>{var s;return i("div",{class:["dropdown-wrapper",{open:l.value}]},[i("button",{type:"button",class:"dropdown-title","aria-label":a.value,onClick:o},[((s=t.title)==null?void 0:s.call(t))||i("span",{class:"title"},[i(Re,{icon:r.value.icon}),e.config.text]),i("span",{class:"arrow"}),i("ul",{class:"nav-dropdown"},r.value.children.map((c,u)=>{const d=u===r.value.children.length-1;return i("li",{class:"dropdown-item"},"children"in c?[i("h4",{class:"dropdown-subtitle"},c.link?i(qe,{config:c,onFocusout:()=>{c.children.length===0&&d&&(l.value=!1)}}):i("span",c.text)),i("ul",{class:"dropdown-subitem-wrapper"},c.children.map((f,p)=>i("li",{class:"dropdown-subitem"},i(qe,{config:f,onFocusout:()=>{p===c.children.length-1&&d&&(l.value=!1)}}))))]:i(qe,{config:c,onFocusout:()=>{d&&(l.value=!1)}}))}))])])}}}),Nc=(e,t,n="")=>oe(t)?pn(e,Gt(n,t)):"children"in t?{...t,...t.link&&!qr(t.link)?pn(e,Gt(n,t.link)):{},children:t.children.map(r=>Nc(e,r,Gt(n,t.prefix)))}:{...t,link:qr(t.link)?t.link:pn(e,Gt(n,t.link)).link},zc=()=>{const e=se(),t=Ve(),n=()=>(e.value.navbar||[]).map(a=>Nc(t,a));return $l(()=>e.value.navbar,()=>n())},s2=()=>{const e=se(),t=E(()=>e.value.repo||null),n=E(()=>t.value?ih(t.value):null),r=E(()=>t.value?uc(t.value):null),a=E(()=>n.value?e.value.repoLabel??(r.value===null?"Source":r.value):null);return E(()=>!n.value||!a.value||e.value.repoDisplay===!1?null:{type:r.value||"Source",label:a.value,link:n.value})},c2=V({name:"NavScreenDropdown",props:{config:{type:Object,required:!0}},setup(e){const t=ie(),n=Ln(e,"config"),r=E(()=>n.value.ariaLabel||n.value.text),a=X(!1);ye(()=>t.value.path,()=>{a.value=!1});const l=(o,s)=>s[s.length-1]===o;return()=>[i("button",{type:"button",class:["nav-screen-dropdown-title",{active:a.value}],"aria-label":r.value,onClick:()=>{a.value=!a.value}},[i("span",{class:"title"},[i(Re,{icon:n.value.icon}),e.config.text]),i("span",{class:["arrow",a.value?"down":"end"]})]),i("ul",{class:["nav-screen-dropdown",{hide:!a.value}]},n.value.children.map(o=>i("li",{class:"dropdown-item"},"children"in o?[i("h4",{class:"dropdown-subtitle"},o.link?i(qe,{config:o,onFocusout:()=>{l(o,n.value.children)&&o.children.length===0&&(a.value=!1)}}):i("span",o.text)),i("ul",{class:"dropdown-subitem-wrapper"},o.children.map(s=>i("li",{class:"dropdown-subitem"},i(qe,{config:s,onFocusout:()=>{l(s,o.children)&&l(o,n.value.children)&&(a.value=!1)}}))))]:i(qe,{config:o,onFocusout:()=>{l(o,n.value.children)&&(a.value=!1)}}))))]}}),u2=V({name:"NavScreenLinks",setup(){const e=zc();return()=>e.value.length?i("nav",{class:"nav-screen-links"},e.value.map(t=>i("div",{class:"navbar-links-item"},"children"in t?i(c2,{config:t}):i(qe,{config:t})))):null}}),Hc=()=>i(pe,{name:"dark"},()=>i("path",{d:"M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"}));Hc.displayName="DarkIcon";const qc=()=>i(pe,{name:"light"},()=>i("path",{d:"M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"}));qc.displayName="LightIcon";const Gc=()=>i(pe,{name:"auto"},()=>i("path",{d:"M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"}));Gc.displayName="AutoIcon";const Uc=()=>i(pe,{name:"enter-fullscreen"},()=>i("path",{d:"M762.773 90.24h-497.28c-96.106 0-174.4 78.293-174.4 174.4v497.28c0 96.107 78.294 174.4 174.4 174.4h497.28c96.107 0 175.04-78.293 174.4-174.4V264.64c0-96.213-78.186-174.4-174.4-174.4zm-387.2 761.173H215.04c-21.867 0-40.427-17.92-41.067-41.066V649.92c0-22.507 17.92-40.427 40.427-40.427 11.307 0 21.227 4.694 28.48 11.947 7.253 7.253 11.947 17.92 11.947 28.48v62.293l145.28-145.28c15.893-15.893 41.813-15.893 57.706 0 15.894 15.894 15.894 41.814 0 57.707l-145.28 145.28h62.294c22.506 0 40.426 17.92 40.426 40.427s-17.173 41.066-39.68 41.066zM650.24 165.76h160.427c21.866 0 40.426 17.92 41.066 41.067v160.426c0 22.507-17.92 40.427-40.426 40.427-11.307 0-21.227-4.693-28.48-11.947-7.254-7.253-11.947-17.92-11.947-28.48v-62.186L625.6 450.347c-15.893 15.893-41.813 15.893-57.707 0-15.893-15.894-15.893-41.814 0-57.707l145.28-145.28H650.88c-22.507 0-40.427-17.92-40.427-40.427s17.174-41.173 39.787-41.173z"}));Uc.displayName="EnterFullScreenIcon";const Kc=()=>i(pe,{name:"cancel-fullscreen"},()=>i("path",{d:"M778.468 78.62H247.922c-102.514 0-186.027 83.513-186.027 186.027V795.08c0 102.514 83.513 186.027 186.027 186.027h530.432c102.514 0 186.71-83.513 186.026-186.027V264.647C964.494 162.02 880.981 78.62 778.468 78.62zM250.88 574.35h171.122c23.324 0 43.122 19.115 43.804 43.805v171.121c0 24.008-19.114 43.122-43.122 43.122-12.06 0-22.641-5.006-30.378-12.743s-12.743-19.115-12.743-30.379V722.83L224.597 877.91c-16.953 16.952-44.6 16.952-61.553 0-16.953-16.954-16.953-44.602 0-61.554L318.009 661.39h-66.446c-24.007 0-43.122-19.114-43.122-43.122 0-24.12 18.432-43.918 42.439-43.918zm521.899-98.873H601.657c-23.325 0-43.122-19.114-43.805-43.804V260.55c0-24.007 19.115-43.122 43.122-43.122 12.06 0 22.642 5.007 30.379 12.743s12.743 19.115 12.743 30.38v66.445l154.965-154.965c16.953-16.953 44.601-16.953 61.554 0 16.953 16.953 16.953 44.6 0 61.554L705.536 388.55h66.446c24.007 0 43.122 19.115 43.122 43.122.114 24.007-18.318 43.804-42.325 43.804z"}));Kc.displayName="CancelFullScreenIcon";const Wc=()=>i(pe,{name:"outlook"},()=>[i("path",{d:"M224 800c0 9.6 3.2 44.8 6.4 54.4 6.4 48-48 76.8-48 76.8s80 41.6 147.2 0 134.4-134.4 38.4-195.2c-22.4-12.8-41.6-19.2-57.6-19.2C259.2 716.8 227.2 761.6 224 800zM560 675.2l-32 51.2c-51.2 51.2-83.2 32-83.2 32 25.6 67.2 0 112-12.8 128 25.6 6.4 51.2 9.6 80 9.6 54.4 0 102.4-9.6 150.4-32l0 0c3.2 0 3.2-3.2 3.2-3.2 22.4-16 12.8-35.2 6.4-44.8-9.6-12.8-12.8-25.6-12.8-41.6 0-54.4 60.8-99.2 137.6-99.2 6.4 0 12.8 0 22.4 0 12.8 0 38.4 9.6 48-25.6 0-3.2 0-3.2 3.2-6.4 0-3.2 3.2-6.4 3.2-6.4 6.4-16 6.4-16 6.4-19.2 9.6-35.2 16-73.6 16-115.2 0-105.6-41.6-198.4-108.8-268.8C704 396.8 560 675.2 560 675.2zM224 419.2c0-28.8 22.4-51.2 51.2-51.2 28.8 0 51.2 22.4 51.2 51.2 0 28.8-22.4 51.2-51.2 51.2C246.4 470.4 224 448 224 419.2zM320 284.8c0-22.4 19.2-41.6 41.6-41.6 22.4 0 41.6 19.2 41.6 41.6 0 22.4-19.2 41.6-41.6 41.6C339.2 326.4 320 307.2 320 284.8zM457.6 208c0-12.8 12.8-25.6 25.6-25.6 12.8 0 25.6 12.8 25.6 25.6 0 12.8-12.8 25.6-25.6 25.6C470.4 233.6 457.6 220.8 457.6 208zM128 505.6C128 592 153.6 672 201.6 736c28.8-60.8 112-60.8 124.8-60.8-16-51.2 16-99.2 16-99.2l316.8-422.4c-48-19.2-99.2-32-150.4-32C297.6 118.4 128 291.2 128 505.6zM764.8 86.4c-22.4 19.2-390.4 518.4-390.4 518.4-22.4 28.8-12.8 76.8 22.4 99.2l9.6 6.4c35.2 22.4 80 12.8 99.2-25.6 0 0 6.4-12.8 9.6-19.2 54.4-105.6 275.2-524.8 288-553.6 6.4-19.2-3.2-32-19.2-32C777.6 76.8 771.2 80 764.8 86.4z"})]);Wc.displayName="OutlookIcon";const Jc=V({name:"AppearanceSwitch",setup(){const{config:e,isDarkmode:t,status:n}=cr(),r=nn(),a=()=>{e.value==="switch"?n.value={light:"dark",dark:"auto",auto:"light"}[n.value]:n.value=n.value==="light"?"dark":"light"},l=async o=>{if(!(document.startViewTransition&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches&&!r.value)||!o){a();return}const c=o.clientX,u=o.clientY,d=Math.hypot(Math.max(c,innerWidth-c),Math.max(u,innerHeight-u)),f=t.value;await document.startViewTransition(async()=>{a(),await en()}).ready,t.value!==f&&document.documentElement.animate({clipPath:t.value?[`circle(${d}px at ${c}px ${u}px)`,`circle(0px at ${c}px ${u}px)`]:[`circle(0px at ${c}px ${u}px)`,`circle(${d}px at ${c}px ${u}px)`]},{duration:400,pseudoElement:t.value?"::view-transition-old(root)":"::view-transition-new(root)"})};return()=>i("button",{type:"button",id:"appearance-switch",onClick:l},[i(Gc,{style:{display:n.value==="auto"?"block":"none"}}),i(Hc,{style:{display:n.value==="dark"?"block":"none"}}),i(qc,{style:{display:n.value==="light"?"block":"none"}})])}}),d2=V({name:"AppearanceMode",setup(){const e=se(),{canToggle:t}=cr(),n=E(()=>e.value.outlookLocales.darkmode);return()=>t.value?i("div",{class:"appearance-wrapper"},[i("label",{class:"appearance-title",for:"appearance-switch"},n.value),i(Jc)]):null}}),Fa="VUEPRESS_THEME_COLOR",f2=V({name:"ThemeColorPicker",props:{themeColor:{type:Object,required:!0}},setup(e){const t=(n="")=>{const r=document.documentElement.classList,a=wt(e.themeColor);if(!n){localStorage.removeItem(Fa),r.remove(...a);return}r.remove(...a.filter(l=>l!==n)),r.add(n),localStorage.setItem(Fa,n)};return Ee(()=>{const n=localStorage.getItem(Fa);n&&t(n)}),()=>i("ul",{id:"theme-color-picker"},[i("li",i("span",{class:"theme-color",onClick:()=>t()})),Sn(e.themeColor).map(([n,r])=>i("li",i("span",{style:{background:r},onClick:()=>t(n)})))])}}),hn=Nl.enableThemeColor==="true",p2=hn?rh(Sn(Nl).filter(([e])=>e.startsWith("theme-"))):{},h2=V({name:"ThemeColor",setup(){const e=se(),t=E(()=>e.value.outlookLocales.themeColor);return()=>hn?i("div",{class:"theme-color-wrapper"},[i("label",{class:"theme-color-title",for:"theme-color-picker"},t.value),i(f2,{themeColor:p2})]):null}}),Yc=V({name:"ToggleFullScreenButton",setup(){const e=se(),{isSupported:t,isFullscreen:n,toggle:r}=jl(),a=E(()=>e.value.outlookLocales.fullscreen);return()=>t?i("div",{class:"full-screen-wrapper"},[i("label",{class:"full-screen-title",for:"full-screen-switch"},a.value),i("button",{type:"button",id:"full-screen-switch",class:"full-screen",ariaPressed:n.value,onClick:()=>r()},n.value?i(Kc):i(Uc))]):null}}),Zc=V({name:"OutlookSettings",setup(){const e=$t(),t=nn(),n=E(()=>!t.value&&e.value.fullscreen);return()=>i(oa,()=>[hn?i(h2):null,i(d2),n.value?i(Yc):null])}}),v2=V({name:"NavScreen",props:{show:Boolean},emits:["close"],slots:Object,setup(e,{emit:t,slots:n}){const r=ie(),{isMobile:a}=sr(),l=mt(),o=Sc(l);return Ee(()=>{l.value=document.body,ye(a,s=>{!s&&e.show&&(o.value=!1,t("close"))}),ye(()=>r.value.path,()=>{o.value=!1,t("close")})}),ra(()=>{o.value=!1}),()=>i(Yt,{name:"fade",onEnter:()=>{o.value=!0},onAfterLeave:()=>{o.value=!1}},()=>{var s,c;return e.show?i("div",{id:"nav-screen"},i("div",{class:"vp-nav-screen-container"},[(s=n.before)==null?void 0:s.call(n),i(u2),i("div",{class:"vp-outlook-wrapper"},i(Zc)),(c=n.after)==null?void 0:c.call(n)])):null})}}),m2=V({name:"NavbarBrand",setup(){const e=ct(),t=rr(),n=se(),r=E(()=>n.value.home||e.value),a=E(()=>t.value.title),l=E(()=>n.value.navTitle??a.value),o=E(()=>n.value.logo?Le(n.value.logo):null),s=E(()=>n.value.logoDark?Le(n.value.logoDark):null);return()=>i(Ce,{to:r.value,class:"vp-brand"},()=>[o.value?i("img",{class:["vp-nav-logo",{light:!!s.value}],src:o.value,alt:""}):null,s.value?i("img",{class:["vp-nav-logo dark"],src:s.value,alt:""}):null,l.value?i("span",{class:["vp-site-name",{"hide-in-pad":o.value&&n.value.hideSiteNameOnMobile!==!1}]},l.value):null])}}),g2=V({name:"NavbarLinks",setup(){const e=zc();return()=>e.value.length?i("nav",{class:"vp-nav-links"},e.value.map(t=>i("div",{class:"nav-item hide-in-mobile"},"children"in t?i(i2,{config:t}):i(qe,{config:t})))):null}}),b2=V({name:"RepoLink",components:{BitbucketIcon:hc,GiteeIcon:pc,GitHubIcon:dc,GitLabIcon:fc,SourceIcon:vc},setup(){const e=s2();return()=>e.value?i("div",{class:"nav-item vp-repo"},i("a",{class:"vp-repo-link",href:e.value.link,target:"_blank",rel:"noopener noreferrer","aria-label":e.value.label},i(He(`${e.value.type}Icon`),{style:{width:"1.25rem",height:"1.25rem",verticalAlign:"middle"}}))):null}}),Qc=({active:e=!1},{emit:t})=>i("button",{type:"button",class:["vp-toggle-navbar-button",{"is-active":e}],"aria-label":"Toggle Navbar","aria-expanded":e,"aria-controls":"nav-screen",onClick:()=>t("toggle")},i("span",[i("span",{class:"vp-top"}),i("span",{class:"vp-middle"}),i("span",{class:"vp-bottom"})]));Qc.displayName="ToggleNavbarButton";const Gl=(e,{emit:t})=>i("button",{type:"button",class:"vp-toggle-sidebar-button",title:"Toggle Sidebar",onClick:()=>t("toggle")},i("span",{class:"icon"}));Gl.displayName="ToggleSidebarButton";Gl.emits=["toggle"];const _2=V({name:"OutlookButton",setup(){const{isSupported:e}=jl(),t=$t(),n=nn(),r=ie(),{canToggle:a}=cr(),l=X(!1),o=E(()=>!n.value&&t.value.fullscreen&&e);return ye(()=>r.value.path,()=>{l.value=!1}),()=>a.value||o.value||hn?i("div",{class:"nav-item hide-in-mobile"},a.value&&!o.value&&!hn?i(Jc):o.value&&!a.value&&!hn?i(Yc):i("button",{type:"button",class:["outlook-button",{open:l.value}],tabindex:"-1","aria-hidden":!0},[i(Wc),i("div",{class:"outlook-dropdown"},i(Zc))])):null}}),y2=V({name:"NavBar",emits:["toggleSidebar"],slots:Object,setup(e,{emit:t,slots:n}){const r=se(),{isMobile:a}=sr(),l=X(!1),o=E(()=>{const{navbarAutoHide:d="mobile"}=r.value;return d!=="none"&&(d==="always"||a.value)}),s=E(()=>r.value.navbarLayout||{start:["Brand"],center:["Links"],end:["Language","Repo","Outlook","Search"]}),c={Brand:m2,Language:Ma,Links:g2,Repo:b2,Outlook:_2,Search:Jt("Docsearch")?He("Docsearch"):Jt("SearchBox")?He("SearchBox"):Ma},u=d=>c[d]??(Jt(d)?He(d):Ma);return()=>{var d,f,p,h,g,w;return[i("header",{id:"navbar",class:["vp-navbar",{"auto-hide":o.value,"hide-icon":r.value.navbarIcon===!1}]},[i("div",{class:"vp-navbar-start"},[i(Gl,{onToggle:()=>{l.value&&(l.value=!1),t("toggleSidebar")}}),(d=n.startBefore)==null?void 0:d.call(n),(s.value.start||[]).map(k=>i(u(k))),(f=n.startAfter)==null?void 0:f.call(n)]),i("div",{class:"vp-navbar-center"},[(p=n.centerBefore)==null?void 0:p.call(n),(s.value.center||[]).map(k=>i(u(k))),(h=n.centerAfter)==null?void 0:h.call(n)]),i("div",{class:"vp-navbar-end"},[(g=n.endBefore)==null?void 0:g.call(n),(s.value.end||[]).map(k=>i(u(k))),(w=n.endAfter)==null?void 0:w.call(n),i(Qc,{active:l.value,onToggle:()=>{l.value=!l.value}})])]),i(v2,{show:l.value,onClose:()=>{l.value=!1}},{before:()=>{var k;return(k=n.screenTop)==null?void 0:k.call(n)},after:()=>{var k;return(k=n.screenBottom)==null?void 0:k.call(n)}})]}}}),E2=V({name:"SidebarChild",props:{config:{type:Object,required:!0}},setup(e){const t=gt();return()=>[Fc(e.config,{class:["vp-sidebar-link",`vp-sidebar-${e.config.type}`,{active:kn(t,e.config,!0)}],exact:!0}),Vc(e.config.children)]}}),k2=V({name:"SidebarGroup",props:{config:{type:Object,required:!0},open:{type:Boolean,required:!0}},emits:["toggle"],setup(e,{emit:t}){const n=gt(),r=E(()=>kn(n,e.config)),a=E(()=>kn(n,e.config,!0));return()=>{const{collapsible:l,children:o=[],icon:s,prefix:c,link:u,text:d}=e.config;return i("section",{class:"vp-sidebar-group"},[i(l?"button":"p",{class:["vp-sidebar-heading",{clickable:l||u,exact:a.value,active:r.value}],...l?{type:"button",onClick:()=>t("toggle"),onKeydown:f=>{f.key==="Enter"&&t("toggle")}}:{}},[i(Re,{icon:s}),u?i(qe,{class:"vp-sidebar-title",config:{text:d,link:u},noExternalLinkIcon:!0}):i("span",{class:"vp-sidebar-title"},d),l?i("span",{class:["vp-arrow",e.open?"down":"end"]}):null]),e.open||!l?i(Xc,{key:c,config:o}):null])}}}),Xc=V({name:"SidebarLinks",props:{config:{type:Array,required:!0}},setup(e){const t=gt(),n=X(-1),r=a=>{n.value=a===n.value?-1:a};return ye(()=>t.path,()=>{const a=e.config.findIndex(l=>Mc(t,l));n.value=a},{immediate:!0,flush:"post"}),()=>i("ul",{class:"vp-sidebar-links"},e.config.map((a,l)=>i("li",a.type==="group"?i(k2,{config:a,open:l===n.value,onToggle:()=>r(l)}):i(E2,{config:a}))))}}),w2=V({name:"SideBar",slots:Object,setup(e,{slots:t}){const n=gt(),r=se(),a=ql(),l=mt();return Ee(()=>{ye(()=>n.hash,o=>{const s=document.querySelector(`.vp-sidebar a.vp-sidebar-link[href="${n.path}${o}"]`);if(!s)return;const{top:c,height:u}=l.value.getBoundingClientRect(),{top:d,height:f}=s.getBoundingClientRect();dc+u&&s.scrollIntoView(!1)},{immediate:!0})}),()=>{var o,s,c;return i("aside",{ref:l,id:"sidebar",class:["vp-sidebar",{"hide-icon":r.value.sidebarIcon===!1}]},[(o=t.top)==null?void 0:o.call(t),((s=t.default)==null?void 0:s.call(t))||i(Xc,{config:a.value}),(c=t.bottom)==null?void 0:c.call(t)])}}}),Ul=V({name:"CommonWrapper",props:{containerClass:{type:String,default:""},noNavbar:Boolean,noSidebar:Boolean,noToc:Boolean},slots:Object,setup(e,{slots:t}){const n=Ve(),r=ie(),a=_e(),l=se(),{isMobile:o,isPC:s}=sr(),[c,u]=pi(!1),[d,f]=pi(!1),p=ql(),h=X(!1),g=E(()=>e.noNavbar||a.value.navbar===!1||l.value.navbar===!1?!1:!!(r.value.title||l.value.logo||l.value.repo||l.value.navbar)),w=E(()=>e.noSidebar?!1:a.value.sidebar!==!1&&p.value.length!==0&&!a.value.home),k=E(()=>e.noToc||a.value.home?!1:a.value.toc||l.value.toc!==!1&&a.value.toc!==!1),b={x:0,y:0},x=L=>{b.x=L.changedTouches[0].clientX,b.y=L.changedTouches[0].clientY},_=L=>{const U=L.changedTouches[0].clientX-b.x,$=L.changedTouches[0].clientY-b.y;Math.abs(U)>Math.abs($)*1.5&&Math.abs(U)>40&&(U>0&&b.x<=80?u(!0):u(!1))},S=()=>window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;let D=0;return je("scroll",Vh(()=>{const L=S();L<=58||L{L||u(!1)}),Ee(()=>{const L=Sc(document.body);ye(c,$=>{L.value=$});const U=n.afterEach(()=>{u(!1)});ra(()=>{L.value=!1,U()})}),()=>i(Jt("GlobalEncrypt")?He("GlobalEncrypt"):nc,()=>i("div",{class:["theme-container",{"no-navbar":!g.value,"no-sidebar":!w.value&&!(t.sidebar||t.sidebarTop||t.sidebarBottom),"has-toc":k.value,"hide-navbar":h.value,"sidebar-collapsed":!o.value&&!s.value&&d.value,"sidebar-open":o.value&&c.value},e.containerClass,a.value.containerClass||""],onTouchStart:x,onTouchEnd:_},[g.value?i(y2,{onToggleSidebar:()=>u()},{startBefore:()=>{var L;return(L=t.navbarStartBefore)==null?void 0:L.call(t)},startAfter:()=>{var L;return(L=t.navbarStartAfter)==null?void 0:L.call(t)},centerBefore:()=>{var L;return(L=t.navbarCenterBefore)==null?void 0:L.call(t)},centerAfter:()=>{var L;return(L=t.navbarCenterAfter)==null?void 0:L.call(t)},endBefore:()=>{var L;return(L=t.navbarEndBefore)==null?void 0:L.call(t)},endAfter:()=>{var L;return(L=t.navbarEndAfter)==null?void 0:L.call(t)},screenTop:()=>{var L;return(L=t.navScreenTop)==null?void 0:L.call(t)},screenBottom:()=>{var L;return(L=t.navScreenBottom)==null?void 0:L.call(t)}}):null,i(Yt,{name:"fade"},()=>c.value?i("div",{class:"vp-sidebar-mask",onClick:()=>u(!1)}):null),i(Yt,{name:"fade"},()=>o.value?null:i("div",{class:"toggle-sidebar-wrapper",onClick:()=>f()},i("span",{class:["arrow",d.value?"end":"start"]}))),i(w2,{},{...t.sidebar?{default:()=>t.sidebar()}:{},top:()=>{var L;return(L=t.sidebarTop)==null?void 0:L.call(t)},bottom:()=>{var L;return(L=t.sidebarBottom)==null?void 0:L.call(t)}}),t.default(),i(o2)]))}}),al=(e,{slots:t})=>{var f,p;const{bgImage:n,bgImageDark:r,bgImageStyle:a,color:l,description:o,image:s,imageDark:c,header:u,features:d=[]}=e;return i("div",{class:"vp-feature-wrapper"},[n?i("div",{class:["vp-feature-bg",{light:r}],style:[{"background-image":`url(${n})`},a]}):null,r?i("div",{class:"vp-feature-bg dark",style:[{"background-image":`url(${r})`},a]}):null,i("div",{class:"vp-feature",style:l?{color:l}:{}},[((f=t.image)==null?void 0:f.call(t,e))||[s?i("img",{class:["vp-feature-image",{light:c}],src:Le(s),alt:""}):null,c?i("img",{class:"vp-feature-image dark",src:Le(c),alt:""}):null],((p=t.info)==null?void 0:p.call(t,e))||[u?i("h2",{class:"vp-feature-header"},u):null,o?i("p",{class:"vp-feature-description",innerHTML:o}):null],d.length?i("div",{class:"vp-features"},d.map(({icon:h,title:g,details:w,link:k})=>{const b=[i("h3",{class:"vp-feature-title"},[i(Re,{icon:h}),i("span",{innerHTML:g})]),i("p",{class:"vp-feature-details",innerHTML:w})];return k?qr(k)?i("a",{class:"vp-feature-item link",href:k,"aria-label":g,target:"_blank"},b):i(Ce,{class:"vp-feature-item link",to:k,"aria-label":g},()=>b):i("div",{class:"vp-feature-item"},b)})):null])])};al.displayName="FeaturePanel";const fe=V({name:"DropTransition",props:{type:{type:String,default:"single"},delay:{type:Number,default:0},duration:{type:Number,default:.25},appear:Boolean},slots:Object,setup(e,{slots:t}){const n=a=>{a.style.transition=`transform ${e.duration}s ease-in-out ${e.delay}s, opacity ${e.duration}s ease-in-out ${e.delay}s`,a.style.transform="translateY(-20px)",a.style.opacity="0"},r=a=>{a.style.transform="translateY(0)",a.style.opacity="1"};return()=>i(e.type==="single"?Yt:ff,{name:"drop",appear:e.appear,onAppear:n,onAfterAppear:r,onEnter:n,onAfterEnter:r,onBeforeLeave:n},()=>t.default())}}),A2=V({name:"HeroInfo",slots:Object,setup(e,{slots:t}){const n=_e(),r=rr(),a=E(()=>n.value.heroFullScreen??!1),l=E(()=>{const{heroText:u,tagline:d}=n.value;return{text:u??r.value.title??"Hello",tagline:d??r.value.description??"",isFullScreen:a.value}}),o=E(()=>{const{heroText:u,heroImage:d,heroImageDark:f,heroAlt:p,heroImageStyle:h}=n.value;return{image:d?Le(d):null,imageDark:f?Le(f):null,heroStyle:h,alt:p||u||"",isFullScreen:a.value}}),s=E(()=>{const{bgImage:u,bgImageDark:d,bgImageStyle:f}=n.value;return{image:vt(u)?Le(u):null,imageDark:vt(d)?Le(d):null,bgStyle:f,isFullScreen:a.value}}),c=E(()=>n.value.actions??[]);return()=>{var u,d,f;return i("header",{class:["vp-hero-info-wrapper",{fullscreen:a.value}]},[((u=t.heroBg)==null?void 0:u.call(t,s.value))||[s.value.image?i("div",{class:["vp-hero-mask",{light:s.value.imageDark}],style:[{"background-image":`url(${s.value.image})`},s.value.bgStyle]}):null,s.value.imageDark?i("div",{class:"vp-hero-mask dark",style:[{"background-image":`url(${s.value.imageDark})`},s.value.bgStyle]}):null],i("div",{class:"vp-hero-info"},[((d=t.heroImage)==null?void 0:d.call(t,o.value))||i(fe,{appear:!0,type:"group"},()=>[o.value.image?i("img",{key:"light",class:["vp-hero-image",{light:o.value.imageDark}],style:o.value.heroStyle,src:o.value.image,alt:o.value.alt}):null,o.value.imageDark?i("img",{key:"dark",class:"vp-hero-image dark",style:o.value.heroStyle,src:o.value.imageDark,alt:o.value.alt}):null]),((f=t.heroInfo)==null?void 0:f.call(t,l.value))??i("div",{class:"vp-hero-infos"},[l.value.text?i(fe,{appear:!0,delay:.04},()=>i("h1",{id:"main-title"},l.value.text)):null,l.value.tagline?i(fe,{appear:!0,delay:.08},()=>i("p",{id:"main-description",innerHTML:l.value.tagline})):null,c.value.length?i(fe,{appear:!0,delay:.12},()=>i("p",{class:"vp-hero-actions"},c.value.map(p=>i(qe,{class:["vp-hero-action",p.type||"default"],config:p,noExternalLinkIcon:!0},p.icon?{before:()=>i(Re,{icon:p.icon})}:{})))):null])])])}}}),eu=(e,{slots:t})=>{var p,h,g;const{bgImage:n,bgImageDark:r,bgImageStyle:a,color:l,description:o,image:s,imageDark:c,header:u,highlights:d=[],type:f="un-order"}=e;return i("div",{class:"vp-highlight-wrapper",style:l?{color:l}:{}},[n?i("div",{class:["vp-highlight-bg",{light:r}],style:[{"background-image":`url(${n})`},a]}):null,r?i("div",{class:"vp-highlight-bg dark",style:[{"background-image":`url(${r})`},a]}):null,i("div",{class:"vp-highlight"},[((p=t.image)==null?void 0:p.call(t,e))||[s?i("img",{class:["vp-highlight-image",{light:c}],src:Le(s),alt:""}):null,c?i("img",{class:"vp-highlight-image dark",src:Le(c),alt:""}):null],((h=t.info)==null?void 0:h.call(t,e))||[i("div",{class:"vp-highlight-info-wrapper"},i("div",{class:"vp-highlight-info"},[u?i("h2",{class:"vp-highlight-header",innerHTML:u}):null,o?i("p",{class:"vp-highlight-description",innerHTML:o}):null,((g=t.highlights)==null?void 0:g.call(t,d))||i(f==="order"?"ol":f==="no-order"?"dl":"ul",{class:"vp-highlights"},d.map(({icon:w,title:k,details:b,link:x})=>{const _=[i(f==="no-order"?"dt":"h3",{class:"vp-highlight-title"},[w?i(Re,{class:"vp-highlight-icon",icon:w}):null,i("span",{innerHTML:k})]),b?i(f==="no-order"?"dd":"p",{class:"vp-highlight-details",innerHTML:b}):null];return i(f==="no-order"?"div":"li",{class:["vp-highlight-item-wrapper",{link:x}]},x?Xp(x)?i("a",{class:"vp-highlight-item link",href:x,"aria-label":k,target:"_blank"},_):i(Ce,{class:"vp-highlight-item link",to:x,"aria-label":k},()=>_):i("div",{class:"vp-highlight-item"},_))}))]))]])])};eu.displayName="HighlightPanel";const ur=({custom:e})=>i(Hs,{class:["theme-hope-content",{custom:e}]});ur.displayName="MarkdownContent";ur.props={custom:Boolean};const L2=V({name:"HomePage",slots:Object,setup(e,{slots:t}){const n=nn(),r=_e(),a=E(()=>{const{features:o}=r.value;return Q(o)?o:null}),l=E(()=>{const{highlights:o}=r.value;return Q(o)?o:null});return()=>{var o,s,c,u;return i("main",{id:"main-content",class:["vp-project-home ",{pure:n.value}],"aria-labelledby":r.value.heroText===null?"":"main-title"},[(o=t.top)==null?void 0:o.call(t),i(A2),((s=l.value)==null?void 0:s.map(d=>"features"in d?i(al,d):i(eu,d)))||(a.value?i(fe,{appear:!0,delay:.24},()=>i(al,{features:a.value})):null),(c=t.center)==null?void 0:c.call(t),i(fe,{appear:!0,delay:.32},()=>i(ur)),(u=t.bottom)==null?void 0:u.call(t)])}}}),x2=V({name:"BreadCrumb",setup(){const e=Ve(),t=ie(),n=ct(),r=_e(),a=se(),l=mt([]),o=E(()=>(r.value.breadcrumb||r.value.breadcrumb!==!1&&a.value.breadcrumb!==!1)&&l.value.length>1),s=E(()=>r.value.breadcrumbIcon||r.value.breadcrumbIcon!==!1&&a.value.breadcrumbIcon!==!1),c=()=>{const u=e.getRoutes(),d=t2(t.value.path,n.value).map(({link:f,name:p})=>{const h=u.find(g=>g.path===f);if(h){const{meta:g,path:w}=En(e,h.path);return{title:g[ge.shortTitle]||g[ge.title]||p,icon:g[ge.icon],path:w}}return null}).filter(f=>f!==null);d.length>1&&(l.value=d)};return Ee(()=>{ye(()=>t.value.path,c,{immediate:!0})}),()=>i("nav",{class:["vp-breadcrumb",{disable:!o.value}]},o.value?i("ol",{vocab:"https://schema.org/",typeof:"BreadcrumbList"},l.value.map((u,d)=>i("li",{class:{"is-active":l.value.length-1===d},property:"itemListElement",typeof:"ListItem"},[i(Ce,{to:u.path,property:"item",typeof:"WebPage"},()=>[s.value?i(Re,{icon:u.icon}):null,i("span",{property:"name"},u.title||"Unknown")]),i("meta",{property:"position",content:d+1})]))):[])}}),wi=e=>{const t=Ve();return e===!1?!1:oe(e)?pn(t,e,!0):Cl(e)?e:null},ll=(e,t,n)=>{const r=e.findIndex(a=>a.link===t);if(r!==-1){const a=e[r+n];return a!=null&&a.link?a:null}for(const a of e)if(a.children){const l=ll(a.children,t,n);if(l)return l}return null},S2=V({name:"PageNav",setup(){const e=se(),t=_e(),n=ql(),r=ie(),a=ir(),l=E(()=>{const s=wi(t.value.prev);return s===!1?null:s||(e.value.prevLink===!1?null:ll(n.value,r.value.path,-1))}),o=E(()=>{const s=wi(t.value.next);return s===!1?null:s||(e.value.nextLink===!1?null:ll(n.value,r.value.path,1))});return je("keydown",s=>{s.altKey&&(s.key==="ArrowRight"?o.value&&(a(o.value.link),s.preventDefault()):s.key==="ArrowLeft"&&l.value&&(a(l.value.link),s.preventDefault()))}),()=>l.value||o.value?i("nav",{class:"vp-page-nav"},[l.value?i(qe,{class:"prev",config:l.value},()=>{var s,c;return[i("div",{class:"hint"},[i("span",{class:"arrow start"}),e.value.metaLocales.prev]),i("div",{class:"link"},[i(Re,{icon:(s=l.value)==null?void 0:s.icon}),(c=l.value)==null?void 0:c.text])]}):null,o.value?i(qe,{class:"next",config:o.value},()=>{var s,c;return[i("div",{class:"hint"},[e.value.metaLocales.next,i("span",{class:"arrow end"})]),i("div",{class:"link"},[(s=o.value)==null?void 0:s.text,i(Re,{icon:(c=o.value)==null?void 0:c.icon})])]}):null]):null}}),tu=()=>i(pe,{name:"author"},()=>i("path",{d:"M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z"}));tu.displayName="AuthorIcon";const nu=()=>i(pe,{name:"calendar"},()=>i("path",{d:"M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 01-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 01-33.473-33.473V143.657H180.6A134.314 134.314 0 0046.66 277.595v535.756A134.314 134.314 0 00180.6 947.289h669.74a134.36 134.36 0 00133.94-133.938V277.595a134.314 134.314 0 00-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 01-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 01-33.472 33.473z"}));nu.displayName="CalendarIcon";const ru=()=>i(pe,{name:"category"},()=>i("path",{d:"M148.41 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H148.41c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.311-40.31zM147.556 553.478H429.73c22.263 0 40.311 18.048 40.311 40.31v282.176c0 22.263-18.048 40.312-40.31 40.312H147.555c-22.263 0-40.311-18.049-40.311-40.312V593.79c0-22.263 18.048-40.311 40.31-40.311zM593.927 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H593.927c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.31-40.31zM730.22 920.502H623.926c-40.925 0-74.22-33.388-74.22-74.425V623.992c0-41.038 33.387-74.424 74.425-74.424h222.085c41.038 0 74.424 33.226 74.424 74.067v114.233c0 10.244-8.304 18.548-18.547 18.548s-18.548-8.304-18.548-18.548V623.635c0-20.388-16.746-36.974-37.33-36.974H624.13c-20.585 0-37.331 16.747-37.331 37.33v222.086c0 20.585 16.654 37.331 37.126 37.331H730.22c10.243 0 18.547 8.304 18.547 18.547 0 10.244-8.304 18.547-18.547 18.547z"}));ru.displayName="CategoryIcon";const au=()=>i(pe,{name:"print"},()=>i("path",{d:"M819.2 364.8h-44.8V128c0-17.067-14.933-32-32-32H281.6c-17.067 0-32 14.933-32 32v236.8h-44.8C145.067 364.8 96 413.867 96 473.6v192c0 59.733 49.067 108.8 108.8 108.8h44.8V896c0 17.067 14.933 32 32 32h460.8c17.067 0 32-14.933 32-32V774.4h44.8c59.733 0 108.8-49.067 108.8-108.8v-192c0-59.733-49.067-108.8-108.8-108.8zM313.6 160h396.8v204.8H313.6V160zm396.8 704H313.6V620.8h396.8V864zM864 665.6c0 25.6-19.2 44.8-44.8 44.8h-44.8V588.8c0-17.067-14.933-32-32-32H281.6c-17.067 0-32 14.933-32 32v121.6h-44.8c-25.6 0-44.8-19.2-44.8-44.8v-192c0-25.6 19.2-44.8 44.8-44.8h614.4c25.6 0 44.8 19.2 44.8 44.8v192z"}));au.displayName="PrintIcon";const lu=()=>i(pe,{name:"tag"},()=>i("path",{d:"M939.902 458.563L910.17 144.567c-1.507-16.272-14.465-29.13-30.737-30.737L565.438 84.098h-.402c-3.215 0-5.726 1.005-7.634 2.913l-470.39 470.39a10.004 10.004 0 000 14.164l365.423 365.424c1.909 1.908 4.42 2.913 7.132 2.913s5.223-1.005 7.132-2.913l470.39-470.39c2.01-2.11 3.014-5.023 2.813-8.036zm-240.067-72.121c-35.458 0-64.286-28.828-64.286-64.286s28.828-64.285 64.286-64.285 64.286 28.828 64.286 64.285-28.829 64.286-64.286 64.286z"}));lu.displayName="TagIcon";const ou=()=>i(pe,{name:"timer"},()=>i("path",{d:"M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"}));ou.displayName="TimerIcon";const iu=()=>i(pe,{name:"word"},()=>[i("path",{d:"M518.217 432.64V73.143A73.143 73.143 0 01603.43 1.097a512 512 0 01419.474 419.474 73.143 73.143 0 01-72.046 85.212H591.36a73.143 73.143 0 01-73.143-73.143z"}),i("path",{d:"M493.714 566.857h340.297a73.143 73.143 0 0173.143 85.577A457.143 457.143 0 11371.566 117.76a73.143 73.143 0 0185.577 73.143v339.383a36.571 36.571 0 0036.571 36.571z"})]);iu.displayName="WordIcon";const jt=()=>{const e=se();return E(()=>e.value.metaLocales)},T2={GitHub:":repo/edit/:branch/:path",GitLab:":repo/-/edit/:branch/:path",Gitee:":repo/edit/:branch/:path",Bitbucket:":repo/src/:branch/:path?mode=edit&spa=0&at=:branch&fileviewer=file-view-default"},B2=({docsRepo:e,docsBranch:t,docsDir:n,filePathRelative:r,editLinkPattern:a})=>{if(!r)return null;const l=uc(e);let o;return a?o=a:l!==null&&(o=T2[l]),o?o.replace(/:repo/,xn(e)?e:`https://github.com/${e}`).replace(/:branch/,t).replace(/:path/,Ds(`${Il(n)}/${r}`)):null},C2=()=>{const e=se(),t=ie(),n=_e();return E(()=>{const{repo:r,docsRepo:a=r,docsBranch:l="main",docsDir:o="",editLink:s,editLinkPattern:c=""}=e.value;if(!(n.value.editLink??s??!0)||!a)return null;const d=B2({docsRepo:a,docsBranch:l,docsDir:o,editLinkPattern:c,filePathRelative:t.value.filePathRelative});return d?{text:e.value.metaLocales.editLink,link:d}:null})},I2=()=>{const e=rr(),t=se(),n=ie(),r=_e();return E(()=>{var o,s;return!(r.value.lastUpdated??t.value.lastUpdated??!0)||!((o=n.value.git)!=null&&o.updatedTime)?null:new Date((s=n.value.git)==null?void 0:s.updatedTime).toLocaleString(e.value.lang)})},P2=()=>{const e=se(),t=ie(),n=_e();return E(()=>{var a;return n.value.contributors??e.value.contributors??!0?((a=t.value.git)==null?void 0:a.contributors)??null:null})},O2=V({name:"AuthorInfo",inheritAttrs:!1,props:{author:{type:Array,required:!0},pure:Boolean},setup(e){const t=jt();return()=>e.author.length?i("span",{class:"page-author-info","aria-label":`${t.value.author}${e.pure?"":"🖊"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[i(tu),i("span",e.author.map(n=>n.url?i("a",{class:"page-author-item",href:n.url,target:"_blank",rel:"noopener noreferrer"},n.name):i("span",{class:"page-author-item"},n.name))),i("span",{property:"author",content:e.author.map(n=>n.name).join(", ")})]):null}}),D2=V({name:"CategoryInfo",inheritAttrs:!1,props:{category:{type:Array,required:!0},pure:Boolean},setup(e){const t=Ve(),n=ie(),r=jt(),a=(l,o="")=>{o&&n.value.path!==o&&(l.preventDefault(),t.push(o))};return()=>e.category.length?i("span",{class:"page-category-info","aria-label":`${r.value.category}${e.pure?"":"🌈"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[i(ru),e.category.map(({name:l,path:o})=>i("span",{class:["page-category-item",{[`category${ca(l,9)}`]:!e.pure,clickable:o}],role:o?"navigation":"",onClick:s=>a(s,o)},l)),i("meta",{property:"articleSection",content:e.category.map(({name:l})=>l).join(",")})]):null}}),R2=V({name:"DateInfo",inheritAttrs:!1,props:{date:{type:Object,default:null},localizedDate:{type:String,default:""},pure:Boolean},setup(e){const t=Pl(),n=jt();return()=>e.date?i("span",{class:"page-date-info","aria-label":`${n.value.date}${e.pure?"":"📅"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[i(nu),i("span",i(oa,()=>e.localizedDate||e.date.toLocaleDateString(t.value))),i("meta",{property:"datePublished",content:e.date.toISOString()||""})]):null}}),M2=V({name:"OriginalInfo",inheritAttrs:!1,props:{isOriginal:Boolean},setup(e){const t=jt();return()=>e.isOriginal?i("span",{class:"page-original-info"},t.value.origin):null}}),F2=V({name:"ReadingTimeInfo",inheritAttrs:!1,props:{readingTime:{type:Object,default:()=>null},readingTimeLocale:{type:Object,default:()=>null},pure:Boolean},setup(e){const t=jt(),n=E(()=>{if(!e.readingTime)return null;const{minutes:r}=e.readingTime;return r<1?"PT1M":`PT${Math.round(r)}M`});return()=>{var r,a;return(r=e.readingTimeLocale)!=null&&r.time?i("span",{class:"page-reading-time-info","aria-label":`${t.value.readingTime}${e.pure?"":"⌛"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[i(ou),i("span",(a=e.readingTimeLocale)==null?void 0:a.time),i("meta",{property:"timeRequired",content:n.value})]):null}}}),V2=V({name:"TagInfo",inheritAttrs:!1,props:{tag:{type:Array,default:()=>[]},pure:Boolean},setup(e){const t=Ve(),n=ie(),r=jt(),a=(l,o="")=>{o&&n.value.path!==o&&(l.preventDefault(),t.push(o))};return()=>e.tag.length?i("span",{class:"page-tag-info","aria-label":`${r.value.tag}${e.pure?"":"🏷"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[i(lu),e.tag.map(({name:l,path:o})=>i("span",{class:["page-tag-item",{[`tag${ca(l,9)}`]:!e.pure,clickable:o}],role:o?"navigation":"",onClick:s=>a(s,o)},l)),i("meta",{property:"keywords",content:e.tag.map(({name:l})=>l).join(",")})]):null}}),$2=V({name:"ReadTimeInfo",inheritAttrs:!1,props:{readingTime:{type:Object,default:()=>null},readingTimeLocale:{type:Object,default:()=>null},pure:Boolean},setup(e){const t=jt();return()=>{var n,r,a;return(n=e.readingTimeLocale)!=null&&n.words?i("span",{class:"page-word-info","aria-label":`${t.value.words}${e.pure?"":"🔠"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[i(iu),i("span",(r=e.readingTimeLocale)==null?void 0:r.words),i("meta",{property:"wordCount",content:(a=e.readingTime)==null?void 0:a.words})]):null}}}),su=V({name:"PageInfo",components:{AuthorInfo:O2,CategoryInfo:D2,DateInfo:R2,OriginalInfo:M2,PageViewInfo:()=>null,ReadingTimeInfo:F2,TagInfo:V2,WordInfo:$2},props:{items:{type:[Array,Boolean],default:()=>["Author","Original","Date","PageView","ReadingTime","Category","Tag"]},info:{type:Object,required:!0}},setup(e){const t=nn();return()=>e.items?i("div",{class:"page-info"},e.items.map(n=>i(He(`${n}Info`),{...e.info,pure:t.value}))):null}}),j2=V({name:"PageTitle",setup(){const e=ie(),t=_e(),n=se(),{info:r,items:a}=U0();return()=>i("div",{class:"vp-page-title"},[i("h1",[n.value.titleIcon===!1?null:i(Re,{icon:t.value.icon}),e.value.title]),i(su,{info:r.value,...a.value===null?{}:{items:a.value}}),i("hr")])}}),cu=()=>i(pe,{name:"edit"},()=>[i("path",{d:"M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"}),i("path",{d:"M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"})]);cu.displayName="EditIcon";const N2=V({name:"PageMeta",setup(){const e=se(),t=C2(),n=I2(),r=P2();return()=>{const{metaLocales:a}=e.value;return i("footer",{class:"page-meta"},[t.value?i("div",{class:"meta-item edit-link"},i(qe,{class:"label",config:t.value},{before:()=>i(cu)})):null,i("div",{class:"meta-item git-info"},[n.value?i("div",{class:"update-time"},[i("span",{class:"label"},`${a.lastUpdated}: `),i(oa,()=>i("span",{class:"info"},n.value))]):null,r.value&&r.value.length?i("div",{class:"contributors"},[i("span",{class:"label"},`${a.contributors}: `),r.value.map(({email:l,name:o},s)=>[i("span",{class:"contributor",title:`email: ${l}`},o),s!==r.value.length-1?",":""])]):null])])}}}),z2=V({name:"PrintButton",setup(){const e=$t(),t=se();return()=>e.value.print===!1?null:i("button",{type:"button",class:"print-button",title:t.value.metaLocales.print,onClick:()=>{window.print()}},i(au))}}),H2=({title:e,level:t,slug:n})=>i(Ce,{to:`#${n}`,class:["toc-link",`level${t}`]},()=>e),ol=(e,t)=>{const n=gt();return e.length&&t>0?i("ul",{class:"toc-list"},e.map(r=>{const a=ol(r.children,t-1);return[i("li",{class:["toc-item",{active:n.hash===`#${r.slug}`}]},H2(r)),a?i("li",a):null]})):null},uu=V({name:"TOC",props:{items:{type:Array,default:()=>[]},headerDepth:{type:Number,default:2}},slots:Object,setup(e,{slots:t}){const n=gt(),r=ie(),a=jt(),l=mt(),o=X("-1.7rem"),s=u=>{var d;(d=l.value)==null||d.scrollTo({top:u,behavior:"smooth"})},c=()=>{if(l.value){const u=document.querySelector(".toc-item.active");u?o.value=`${u.getBoundingClientRect().top-l.value.getBoundingClientRect().top+l.value.scrollTop}px`:o.value="-1.7rem"}else o.value="-1.7rem"};return Ee(()=>{ye(()=>n.hash,u=>{if(l.value){const d=document.querySelector(`#toc a.toc-link[href$="${u}"]`);if(!d)return;const{top:f,height:p}=l.value.getBoundingClientRect(),{top:h,height:g}=d.getBoundingClientRect();hf+p&&s(l.value.scrollTop+h+g-f-p)}}),ye(()=>n.fullPath,c,{flush:"post",immediate:!0})}),()=>{var d,f;const u=e.items.length?ol(e.items,e.headerDepth):r.value.headers?ol(r.value.headers,e.headerDepth):null;return u?i("div",{class:"toc-place-holder"},[i("aside",{id:"toc"},[(d=t.before)==null?void 0:d.call(t),i("div",{class:"toc-header"},[a.value.toc,i(z2)]),i("div",{class:"toc-wrapper",ref:l},[u,i("div",{class:"toc-marker",style:{top:o.value}})]),(f=t.after)==null?void 0:f.call(t)])]):null}}}),q2=V({name:"NormalPage",slots:Object,setup(e,{slots:t}){const n=_e(),{isDarkmode:r}=cr(),a=se(),l=E(()=>n.value.toc||n.value.toc!==!1&&a.value.toc!==!1);return()=>i("main",{id:"main-content",class:"vp-page"},i(Jt("LocalEncrypt")?He("LocalEncrypt"):nc,()=>{var o,s,c,u;return[(o=t.top)==null?void 0:o.call(t),n.value.cover?i("div",{class:"page-cover"},i("img",{src:Le(n.value.cover),alt:"","no-view":""})):null,i(x2),i(j2),l.value?i(uu,{headerDepth:n.value.headerDepth??a.value.headerDepth??2},{before:()=>{var d;return(d=t.tocBefore)==null?void 0:d.call(t)},after:()=>{var d;return(d=t.tocAfter)==null?void 0:d.call(t)}}):null,(s=t.contentBefore)==null?void 0:s.call(t),i(ur),(c=t.contentAfter)==null?void 0:c.call(t),i(N2),i(S2),Jt("CommentService")?i(He("CommentService"),{darkmode:r.value}):null,(u=t.bottom)==null?void 0:u.call(t)]}))}}),G2=(e,t)=>{const n=e.__vccOpts||e;for(const[r,a]of t)n[r]=a;return n},U2={name:"adsense-inline",components:{"normal-page":q2},mounted(){this.adsenseAddLoad(),this.loadBaiduAdAsync()},methods:{adsenseAddLoad(){let e=document.createElement("script");e.type="text/javascript",e.text="(adsbygoogle = window.adsbygoogle || []).push({});",document.getElementsByTagName("body")[0].appendChild(e)},loadBaiduAdAsync(){(window.slotbydup=window.slotbydup||[]).push({id:"u6953633",container:"_vyps37o7ou",async:!0})}}},du=e=>(Md("data-v-1ae3d011"),e=e(),Fd(),e),K2=du(()=>la("ins",{class:"adsbygoogle",style:{display:"block","text-align":"center",width:"90%",margin:"0 auto"},"data-ad-layout":"in-article","data-ad-format":"fluid","data-ad-client":"ca-pub-9037099208128116","data-ad-slot":"8206550629"},null,-1)),W2=du(()=>la("div",{class:"_vyps37o7ou",style:{display:"block","text-align":"center",width:"90%",margin:"0 auto"}},null,-1));function J2(e,t,n,r,a,l){const o=He("normal-page",!0);return L1(),S1(o,null,{contentBefore:za(()=>[K2]),contentAfter:za(()=>[W2]),_:1})}const Y2=G2(U2,[["render",J2],["__scopeId","data-v-1ae3d011"],["__file","NormalPage.vue"]]),Kl=V({name:"SkipLink",props:{content:{type:String,default:"main-content"}},setup(e){const t=ie(),n=se(),r=mt(),a=({target:l})=>{const o=document.querySelector(l.hash);if(o){const s=()=>{o.removeAttribute("tabindex"),o.removeEventListener("blur",s)};o.setAttribute("tabindex","-1"),o.addEventListener("blur",s),o.focus(),window.scrollTo(0,0)}};return Ee(()=>{ye(()=>t.value.path,()=>r.value.focus())}),()=>[i("span",{ref:r,tabindex:"-1"}),i("a",{href:`#${e.content}`,class:"vp-skip-link sr-only",onClick:a},n.value.routeLocales.skipToContent)]}}),Z2=V({name:"FadeSlideY",slots:Object,setup(e,{slots:t}){const{resolve:n,pending:r}=Dc();return()=>i(Yt,{name:"fade-slide-y",mode:"out-in",onBeforeEnter:n,onBeforeLeave:r},()=>{var a;return(a=t.default)==null?void 0:a.call(t)})}}),Q2=V({name:"Layout",slots:Object,setup(e,{slots:t}){const n=$t(),r=se(),a=ie(),l=_e(),{isMobile:o}=sr(),s=E(()=>{var c,u;return((c=r.value.blog)==null?void 0:c.sidebarDisplay)||((u=n.value.blog)==null?void 0:u.sidebarDisplay)||"mobile"});return()=>[i(Kl),i(Ul,{},{default:()=>{var c;return((c=t.default)==null?void 0:c.call(t))||(l.value.home?i(L2):i(Z2,()=>i(Y2,{key:a.value.path},{top:()=>{var u;return(u=t.top)==null?void 0:u.call(t)},bottom:()=>{var u;return(u=t.bottom)==null?void 0:u.call(t)},contentBefore:()=>{var u;return(u=t.contentBefore)==null?void 0:u.call(t)},contentAfter:()=>{var u;return(u=t.contentAfter)==null?void 0:u.call(t)},tocBefore:()=>{var u;return(u=t.tocBefore)==null?void 0:u.call(t)},tocAfter:()=>{var u;return(u=t.tocAfter)==null?void 0:u.call(t)}})))},...s.value!=="none"?{navScreenBottom:()=>i(He("BloggerInfo"))}:{},...!o.value&&s.value==="always"?{sidebar:()=>i(He("BloggerInfo"))}:{}})]}}),X2=V({name:"NotFoundHint",setup(){const e=se(),t=()=>{const n=e.value.routeLocales.notFoundMsg;return n[Math.floor(Math.random()*n.length)]};return()=>i("div",{class:"not-found-hint"},[i("p",{class:"error-code"},"404"),i("h1",{class:"error-title"},e.value.routeLocales.notFoundTitle),i("p",{class:"error-hint"},t())])}}),e3=V({name:"NotFound",slots:Object,setup(e,{slots:t}){const n=ct(),r=se(),{navigate:a}=Xa({to:r.value.home??n.value});return()=>[i(Kl),i(Ul,{noSidebar:!0},()=>{var l;return i("main",{id:"main-content",class:"vp-page not-found"},((l=t.default)==null?void 0:l.call(t))||[i(X2),i("div",{class:"actions"},[i("button",{type:"button",class:"action-button",onClick:()=>{window.history.go(-1)}},r.value.routeLocales.back),i("button",{type:"button",class:"action-button",onClick:()=>a()},r.value.routeLocales.home)])])})]}}),t3={Zhihu:' ',Github:' ',Gitee:' '},n3={category:{"/":{path:"/category/",map:{}}},tag:{"/":{path:"/tag/",map:{}}}},r3={article:{"/":{path:"/article/",keys:["v-59449ba0","v-2626dfde","v-058e4a4b","v-411fdbb2","v-0d043462","v-6094ea20","v-68e11d4e","v-1f1952ea","v-6dc450d0","v-44460f42","v-b0e413b8","v-90e5bb66","v-137d5dcc","v-5089f9f3","v-16aa42ca","v-33bd146f","v-7586af98","v-68e0ce3f","v-43e9e6b0","v-728c3a8f","v-d7d7df80","v-7d9b9318","v-90f2343c","v-510415f9","v-3c114a75","v-d73a9aee","v-3f2a15ee","v-2e25198a","v-50cb12f2","v-04e32b44","v-258f309e","v-aa93dec0","v-0a0b7a54","v-8daa1a0e","v-cfe8b6c8","v-71fde78e","v-580db9be","v-06d5cd4c","v-132efcd1","v-1a2ca7a7","v-091223ce","v-0a27b598","v-60eda44c","v-399e07b6","v-660266c1","v-0b5d4df0","v-21e54510","v-57ae83ac","v-22e4234a","v-1f7a720c","v-1c10c0ce","v-dc384366","v-70796e0a"]}},star:{"/":{path:"/star/",keys:[]}},timeline:{"/":{path:"/timeline/",keys:["v-59449ba0","v-2626dfde","v-058e4a4b","v-411fdbb2","v-0d043462","v-6094ea20","v-68e11d4e","v-1f1952ea","v-6dc450d0","v-44460f42","v-b0e413b8","v-90e5bb66","v-137d5dcc","v-5089f9f3","v-16aa42ca","v-33bd146f","v-7586af98","v-68e0ce3f","v-43e9e6b0","v-728c3a8f","v-d7d7df80","v-7d9b9318","v-90f2343c","v-510415f9","v-3c114a75","v-d73a9aee","v-3f2a15ee","v-2e25198a","v-50cb12f2","v-04e32b44","v-258f309e","v-aa93dec0","v-0a0b7a54","v-8daa1a0e","v-cfe8b6c8","v-71fde78e","v-580db9be","v-06d5cd4c","v-132efcd1","v-1a2ca7a7","v-091223ce","v-0a27b598","v-60eda44c","v-399e07b6","v-660266c1","v-0b5d4df0","v-21e54510","v-57ae83ac","v-22e4234a","v-1f7a720c","v-1c10c0ce","v-dc384366","v-70796e0a"]}}},Ai=X(n3),fu=(e="")=>{const t=ie(),n=Ve(),r=ct();return E(()=>{var c;const a=e||((c=_e().value.blog)==null?void 0:c.key)||"";if(!a)return console.warn("useBlogCategory: key not found"),{path:"/",map:{}};const l=n.getRoutes();if(!Ai.value[a])throw new Error(`useBlogCategory: key ${a} is invalid`);const o=Ai.value[a][r.value],s={path:o.path,map:{}};for(const u in o.map){const d=o.map[u];s.map[u]={path:d.path,items:[]};for(const f of d.keys){const p=l.find(({name:h})=>h===f);if(p){const h=En(n,p.path);s.map[u].items.push({path:h.path,info:h.meta})}}t.value.path===d.path&&(s.currentItems=s.map[u].items)}return s})},Li=X(r3),pa=(e="")=>{const t=Ve(),n=ct();return E(()=>{var s;const r=e||((s=_e().value.blog)==null?void 0:s.key)||"";if(!r)return console.warn("useBlogType: key not found"),{path:"/",items:[]};if(!Li.value[r])throw new Error(`useBlogType: key ${e} is invalid`);const a=t.getRoutes(),l=Li.value[r][n.value],o={path:l.path,items:[]};for(const c of l.keys){const u=a.find(({name:d})=>d===c);if(u){const d=En(t,u.path);o.items.push({path:d.path,info:d.meta})}}return o})},pu=Symbol.for("categoryMap"),dr=()=>{const e=he(pu);if(!e)throw new Error("useCategoryMap() is called without provider.");return e},a3=()=>{const e=fu("category");it(pu,e)},fr=()=>{const e=$t(),t=se();return E(()=>({...e.value.blog,...t.value.blog}))},hu=Symbol.for("tagMap"),pr=()=>{const e=he(hu);if(!e)throw new Error("useTagMap() is called without provider.");return e},l3=()=>{const e=fu("tag");it(hu,e)},o3=e=>{const t=se();return E(()=>{const{[ge.author]:n}=e.value;return n?Yn(n):n===!1?[]:Yn(t.value.author,!1)})},i3=e=>{const t=dr();return E(()=>oc(e.value[ge.category]).map(n=>({name:n,path:t.value.map[n].path})))},s3=e=>{const t=pr();return E(()=>ic(e.value[ge.tag]).map(n=>({name:n,path:t.value.map[n].path})))},c3=e=>E(()=>{const{[ge.date]:t}=e.value;return Ml(t)}),u3=e=>{const t=Ln(e,"info"),n=fr(),r=o3(t),a=i3(t),l=s3(t),o=c3(t),s=Pc(),c=E(()=>({author:r.value,category:a.value,date:o.value,localizedDate:t.value[ge.localizedDate]||"",tag:l.value,isOriginal:t.value[ge.isOriginal]||!1,readingTime:t.value[ge.readingTime]||null,readingTimeLocale:t.value[ge.readingTime]&&s.value?Ic(t.value[ge.readingTime],s.value):null,pageview:e.path})),u=E(()=>n.value.articleInfo);return{info:c,items:u}},vu=Symbol(""),hr=()=>{const e=he(vu);if(!e)throw new Error("useArticles() is called without provider.");return e},d3=()=>{const e=pa("article");it(vu,e)},mu=Symbol(""),Wl=()=>{const e=he(mu);if(!e)throw new Error("useStars() is called without provider.");return e},f3=()=>{const e=pa("star");it(mu,e)},gu=Symbol(""),Jl=()=>{const e=he(gu);if(!e)throw new Error("useTimelines() is called without provider.");return e},p3=()=>{const e=pa("timeline"),t=E(()=>{const n=[];return e.value.items.forEach(({info:r,path:a})=>{const l=Ml(r[ge.date]),o=l==null?void 0:l.getFullYear(),s=l?l.getMonth()+1:null,c=l==null?void 0:l.getDate();o&&s&&c&&((!n[0]||n[0].year!==o)&&n.unshift({year:o,items:[]}),n[0].items.push({date:`${s}/${c}`,info:r,path:a}))}),{...e.value,config:n.reverse()}});it(gu,t)},h3=()=>{d3(),a3(),f3(),l3(),p3()},v3=V({name:"SocialMedia",setup(){const e=fr(),t=nn(),n=E(()=>{const r=e.value.medias;return r?Sn(r).map(([a,l])=>({name:a,icon:t3[a],url:l})):[]});return()=>n.value.length?i("div",{class:"vp-social-medias"},n.value.map(({name:r,icon:a,url:l})=>i("a",{class:"vp-social-media",href:l,rel:"noopener noreferrer",target:"_blank","aria-label":r,...t.value?{}:{"data-balloon-pos":"up"},innerHTML:a}))):null}}),Yl=V({name:"BloggerInfo",setup(){const e=fr(),t=rr(),n=se(),r=hr(),a=dr(),l=pr(),o=Jl(),s=ir(),c=E(()=>{var p;return e.value.name||((p=Yn(n.value.author)[0])==null?void 0:p.name)||t.value.title}),u=E(()=>e.value.avatar||n.value.logo),d=E(()=>n.value.blogLocales),f=E(()=>e.value.intro);return()=>{const{article:p,category:h,tag:g,timeline:w}=d.value,k=[[r.value.path,r.value.items.length,p],[a.value.path,wt(a.value.map).length,h],[l.value.path,wt(l.value.map).length,g],[o.value.path,o.value.items.length,w]];return i("div",{class:"vp-blogger-info",vocab:"https://schema.org/",typeof:"Person"},[i("div",{class:"vp-blogger",...f.value?{style:{cursor:"pointer"},"aria-label":d.value.intro,"data-balloon-pos":"down",role:"link",onClick:()=>s(f.value)}:{}},[u.value?i("img",{class:["vp-blogger-avatar",{round:e.value.roundAvatar}],src:Le(u.value),property:"image",alt:"Blogger Avatar",loading:"lazy"}):null,c.value?i("div",{class:"vp-blogger-name",property:"name"},c.value):null,e.value.description?i("div",{class:"vp-blogger-description",innerHTML:e.value.description}):null,f.value?i("meta",{property:"url",content:Le(f.value)}):null]),i("div",{class:"vp-blog-counts"},k.map(([b,x,_])=>i(Ce,{class:"vp-blog-count",to:b},()=>[i("div",{class:"count"},x),i("div",_)]))),i(v3)])}}}),Zl=()=>i(pe,{name:"category"},()=>i("path",{d:"M148.41 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H148.41c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.311-40.31zM147.556 553.478H429.73c22.263 0 40.311 18.048 40.311 40.31v282.176c0 22.263-18.048 40.312-40.31 40.312H147.555c-22.263 0-40.311-18.049-40.311-40.312V593.79c0-22.263 18.048-40.311 40.31-40.311zM593.927 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H593.927c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.31-40.31zM730.22 920.502H623.926c-40.925 0-74.22-33.388-74.22-74.425V623.992c0-41.038 33.387-74.424 74.425-74.424h222.085c41.038 0 74.424 33.226 74.424 74.067v114.233c0 10.244-8.304 18.548-18.547 18.548s-18.548-8.304-18.548-18.548V623.635c0-20.388-16.746-36.974-37.33-36.974H624.13c-20.585 0-37.331 16.747-37.331 37.33v222.086c0 20.585 16.654 37.331 37.126 37.331H730.22c10.243 0 18.547 8.304 18.547 18.547 0 10.244-8.304 18.547-18.547 18.547z"}));Zl.displayName="CategoryIcon";const Ql=()=>i(pe,{name:"tag"},()=>i("path",{d:"M939.902 458.563L910.17 144.567c-1.507-16.272-14.465-29.13-30.737-30.737L565.438 84.098h-.402c-3.215 0-5.726 1.005-7.634 2.913l-470.39 470.39a10.004 10.004 0 000 14.164l365.423 365.424c1.909 1.908 4.42 2.913 7.132 2.913s5.223-1.005 7.132-2.913l470.39-470.39c2.01-2.11 3.014-5.023 2.813-8.036zm-240.067-72.121c-35.458 0-64.286-28.828-64.286-64.286s28.828-64.285 64.286-64.285 64.286 28.828 64.286 64.285-28.829 64.286-64.286 64.286z"}));Ql.displayName="TagIcon";const Xl=()=>i(pe,{name:"timeline"},()=>i("path",{d:"M511.997 70.568c-243.797 0-441.429 197.633-441.429 441.435 0 243.797 197.632 441.429 441.43 441.429S953.431 755.8 953.431 512.002c0-243.796-197.637-441.434-441.435-441.434zm150.158 609.093-15.605 15.61c-8.621 8.615-22.596 8.615-31.215 0L472.197 552.126c-4.95-4.944-4.34-14.888-4.34-24.677V247.14c0-12.19 9.882-22.07 22.07-22.07h22.07c12.19 0 22.07 9.882 22.07 22.07v273.218l128.088 128.088c8.62 8.62 8.62 22.595 0 31.215zm0 0"}));Xl.displayName="TimelineIcon";const bu=()=>i(pe,{name:"slides"},()=>i("path",{d:"M896 170.667v426.666a85.333 85.333 0 0 1-85.333 85.334h-256v61.184l192.597 115.584-43.861 73.13-148.736-89.173v95.275h-85.334v-95.318l-148.736 89.216-43.861-73.13 192.597-115.627v-61.141h-256A85.333 85.333 0 0 1 128 597.333V170.667H85.333V85.333h853.334v85.334H896zm-682.667 0v426.666h597.334V170.667H213.333zM426.667 512h-85.334V341.333h85.334V512zm128 0h-85.334V256h85.334v256zm128 0h-85.334V384h85.334v128z"}));bu.displayName="SlideIcon";const _u=()=>i(pe,{name:"sticky"},()=>[i("path",{d:"m381.3 733.8l-161.9 118c-5.9 4.5-13.2 6.6-20.1 6.6-8.7 0-17.7-3.4-24.3-10-12.2-12.2-13.9-31.3-3.5-45.2l144.5-195.5-113.6-112.9c-11.1-11.1-13.2-28.4-5.5-42 5.5-8.7 52.1-76.4 155.5-51 1.8 0.3 3.5 0.3 5.6 0.7 4.2 0.3 9 0.7 14.2 1.7 21.9 3.5 60.8-13.9 94.5-42.7 32.3-27.5 53.1-59.4 53.1-81.6 0-5.2 0-10.8-0.3-16-0.7-20.8-2.1-52.8 21.5-76.4 28.1-28.1 72.9-30.6 103.9-5.2 0.6 0.3 1 1 1.7 1.7 16.7 16.3 187.5 187.2 189.3 188.9 14.5 14.6 22.9 34.4 22.9 55.3 0 20.8-8 40.2-22.9 54.8-23.7 23.6-56 22.6-77.1 21.6-4.9 0-10.5-0.4-15.7-0.4-20.8 0-45.8 14.6-70.5 41.3-34.3 37.5-55.5 85.8-53.8 107.7 0.7 6.9 2.1 19.1 2.4 20.8 25 101.4-42.7 147.6-50.7 152.8-13.9 8.4-31.6 6.3-42.7-4.8l-112.1-112.2z"})]);_u.displayName="StickyIcon";const ha=()=>i(pe,{name:"article"},()=>i("path",{d:"M853.333 938.667H170.667A42.667 42.667 0 0 1 128 896V128a42.667 42.667 0 0 1 42.667-42.667h682.666A42.667 42.667 0 0 1 896 128v768a42.667 42.667 0 0 1-42.667 42.667zm-42.666-85.334V170.667H213.333v682.666h597.334zM298.667 256h170.666v170.667H298.667V256zm0 256h426.666v85.333H298.667V512zm0 170.667h426.666V768H298.667v-85.333zm256-384h170.666V384H554.667v-85.333z"}));ha.displayName="ArticleIcon";const yu=()=>i(pe,{name:"book"},()=>i("path",{d:"M256 853.333h426.667A85.333 85.333 0 0 0 768 768V256a85.333 85.333 0 0 0-85.333-85.333H469.333a42.667 42.667 0 0 1 0-85.334h213.334A170.667 170.667 0 0 1 853.333 256v512a170.667 170.667 0 0 1-170.666 170.667H213.333A42.667 42.667 0 0 1 170.667 896V128a42.667 42.667 0 0 1 42.666-42.667h128A42.667 42.667 0 0 1 384 128v304.256l61.653-41.088a42.667 42.667 0 0 1 47.36 0l61.654 41.045V256A42.667 42.667 0 0 1 640 256v256a42.667 42.667 0 0 1-66.347 35.499l-104.32-69.547-104.32 69.547A42.667 42.667 0 0 1 298.667 512V170.667H256v682.666z"}));yu.displayName="BookIcon";const Eu=()=>i(pe,{name:"link"},()=>i("path",{d:"M460.8 584.533c17.067 17.067 17.067 42.667 0 59.734-17.067 17.066-42.667 17.066-59.733 0-85.334-85.334-85.334-217.6 0-302.934L554.667 192C640 110.933 776.533 110.933 857.6 196.267c81.067 81.066 81.067 213.333 0 294.4l-68.267 64c0-34.134-4.266-68.267-17.066-102.4l21.333-21.334c51.2-46.933 55.467-128 4.267-179.2s-128-55.466-179.2-4.266c-4.267 0-4.267 4.266-4.267 4.266L465.067 401.067c-51.2 51.2-51.2 132.266-4.267 183.466m123.733-183.466C601.6 384 627.2 384 644.267 401.067c85.333 85.333 85.333 217.6 0 302.933l-153.6 149.333C405.333 934.4 268.8 934.4 187.733 849.067c-81.066-81.067-81.066-213.334 0-294.4l68.267-64c0 34.133 4.267 72.533 17.067 102.4L251.733 614.4C204.8 665.6 204.8 746.667 256 793.6c51.2 46.933 123.733 46.933 174.933 0l149.334-149.333c51.2-51.2 51.2-128 0-179.2-12.8-17.067-17.067-46.934 4.266-64z"}));Eu.displayName="LinkIcon";const ku=()=>i(pe,{name:"project"},()=>i("path",{d:"M987.456 425.152H864V295.296a36.48 36.48 0 0 0-36.544-36.544h-360l-134.08-128.256A9.344 9.344 0 0 0 327.04 128H36.48A36.48 36.48 0 0 0 0 164.544v676.608a36.48 36.48 0 0 0 36.544 36.544h797.76a36.672 36.672 0 0 0 33.92-22.848L1021.44 475.52a36.48 36.48 0 0 0-33.92-50.304zM82.304 210.304h215.424l136.64 130.752h347.328v84.096H198.848A36.672 36.672 0 0 0 164.928 448L82.304 652.8V210.304zM808.32 795.456H108.544l118.08-292.608h699.904L808.32 795.52z"}));ku.displayName="ProjectIcon";const wu=()=>i(pe,{name:"friend"},()=>i("path",{d:"M860.16 213.333A268.373 268.373 0 0 0 512 186.027a267.52 267.52 0 0 0-348.16 404.48L428.8 855.893a118.613 118.613 0 0 0 166.4 0l264.96-265.386a267.52 267.52 0 0 0 0-377.174zM800 531.627l-264.96 264.96a32.427 32.427 0 0 1-46.08 0L224 530.347a183.04 183.04 0 0 1 0-256 182.187 182.187 0 0 1 256 0 42.667 42.667 0 0 0 60.587 0 182.187 182.187 0 0 1 256 0 183.04 183.04 0 0 1 3.413 256z"}));wu.displayName="FriendIcon";const il=()=>i(pe,{name:"slide-down"},()=>i("path",{d:"M108.775 312.23c13.553 0 27.106 3.734 39.153 11.806l375.205 250.338 363.641-252.808c32.587-21.624 76.499-12.83 98.123 19.757 21.685 32.467 12.95 76.56-19.576 98.184l-402.854 278.89c-23.733 15.901-54.694 15.962-78.547.12L69.501 442.097c-32.647-21.685-41.441-65.777-19.817-98.304 13.734-20.54 36.201-31.563 59.09-31.563Z"}));il.displayName="SlideDownIcon";const Au=()=>i("svg",{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",class:"empty-icon",viewBox:"0 0 1024 1024",innerHTML:' '});Au.displayName="EmptyIcon";const Lu=()=>i(pe,{name:"lock"},()=>i("path",{d:"M787.168 952.268H236.832c-30.395 0-55.033-24.638-55.033-55.033V429.45c0-30.395 24.638-55.034 55.033-55.034h82.55V264.35c0-106.38 86.238-192.618 192.618-192.618S704.618 157.97 704.618 264.35v110.066h82.55c30.395 0 55.033 24.639 55.033 55.034v467.785c0 30.395-24.639 55.033-55.033 55.033zM484.483 672.046v115.122h55.034V672.046c31.99-11.373 55.033-41.605 55.033-77.496 0-45.592-36.958-82.55-82.55-82.55s-82.55 36.958-82.55 82.55c0 35.89 23.042 66.123 55.033 77.496zM622.067 264.35c0-60.788-49.28-110.067-110.067-110.067s-110.067 49.28-110.067 110.067v110.066h220.135V264.35z"}));Lu.displayName="LockIcon";const m3=V({name:"ArticleItem",props:{info:{type:Object,required:!0},path:{type:String,required:!0}},slots:Object,setup(e,{slots:t}){const n=Ln(e,"info"),{info:r,items:a}=u3(e);return()=>{var p,h,g;const{[ge.title]:l,[ge.type]:o,[ge.isEncrypted]:s=!1,[ge.cover]:c,[ge.excerpt]:u,[ge.sticky]:d}=n.value,f=r.value;return i("div",{class:"vp-article-wrapper"},i("article",{class:"vp-article-item",vocab:"https://schema.org/",typeof:"Article"},[((p=t.cover)==null?void 0:p.call(t,{cover:c}))||(c?[i("img",{class:"vp-article-cover",src:Le(c),loading:"lazy"}),i("meta",{property:"image",content:Le(c)})]:[]),d?i(_u):null,i(Ce,{to:e.path},()=>{var w;return((w=t.title)==null?void 0:w.call(t,{title:l,isEncrypted:s,type:o}))||i("header",{class:"vp-article-title"},[s?i(Lu):null,o===nl.slide?i(bu):null,i("span",{property:"headline"},l)])}),((h=t.excerpt)==null?void 0:h.call(t,{excerpt:u}))||(u?i("div",{class:"vp-article-excerpt",innerHTML:u}):null),i("hr",{class:"vp-article-hr"}),((g=t.info)==null?void 0:g.call(t,{info:f}))||i(su,{info:f,...a.value?{items:a.value}:{}})]))}}}),g3=V({name:"Pagination",props:{total:{type:Number,default:10},perPage:{type:Number,default:10},current:{type:Number,default:1}},emits:["updateCurrentPage"],setup(e,{emit:t}){let n;const r=se(),a=X(""),l=E(()=>r.value.paginationLocales),o=E(()=>Math.ceil(e.total/e.perPage)),s=E(()=>!!o.value&&o.value!==1),c=E(()=>o.value<7?!1:e.current>4),u=E(()=>o.value<7?!1:e.current{const{current:h}=e;let g=1,w=o.value;const k=[];o.value>=7&&(h<=4&&h4&&h>=o.value-3?(w=o.value,g=o.value-4):o.value>7&&(g=h-2,w=h+2));for(let b=g;b<=w;b++)k.push(b);return k}),f=h=>t("updateCurrentPage",h),p=h=>{const g=parseInt(h);g<=o.value&&g>0?f(g):n.pop(` ${l.value.errorText.replace(/\$page/g,o.value.toString())}`)};return Ee(()=>{n=new lh}),()=>i("div",{class:"vp-pagination"},s.value?i("nav",{class:"vp-pagination-list"},[i("div",{class:"vp-pagination-number "},[e.current>1?i("div",{class:"prev",role:"navigation",unselectable:"on",onClick:()=>f(e.current-1)},l.value.prev):null,c.value?[i("div",{role:"navigation",onClick:()=>f(1)},1),i("div",{class:"ellipsis"},"...")]:null,d.value.map(h=>i("div",{key:h,class:{active:e.current===h},role:"navigation",onClick:()=>f(h)},h)),u.value?[i("div",{class:"ellipsis"},"..."),i("div",{role:"navigation",onClick:()=>f(o.value)},o.value)]:null,e.currentf(e.current+1)},l.value.next):null]),i("div",{class:"vp-pagination-nav"},[i("label",{for:"navigation-text"},`${l.value.navigate}: `),i("input",{id:"navigation-text",value:a.value,onInput:({target:h})=>{a.value=h.value},onKeydown:h=>{h.key==="Enter"&&(h.preventDefault(),p(a.value))}}),i("button",{class:"vp-pagination-button",role:"navigation",title:l.value.action,onClick:()=>p(a.value)},l.value.action)])]):[])}}),eo=V({name:"ArticleList",props:{items:{type:Array,default:()=>[]}},setup(e){const t=gt(),n=Ve(),r=fr(),a=X(1),l=E(()=>r.value.articlePerPage||10),o=E(()=>e.items.slice((a.value-1)*l.value,a.value*l.value)),s=async c=>{a.value=c;const u={...t.query};!(u.page===c.toString()||c===1&&!u.page)&&(c===1?delete u.page:u.page=c.toString(),await n.push({path:t.path,query:u}))};return Ee(()=>{const{page:c}=t.query;console.log("mounted"),s(c?Number(c):1),ye(a,()=>{const u=document.querySelector("#article-list").getBoundingClientRect().top+window.scrollY;setTimeout(()=>{window.scrollTo(0,u)},100)})}),()=>i("div",{id:"article-list",class:"vp-article-list",role:"feed"},o.value.length?[...o.value.map(({info:c,path:u},d)=>i(fe,{appear:!0,delay:d*.04},()=>i(m3,{key:u,info:c,path:u}))),i(g3,{current:a.value,perPage:l.value,total:e.items.length,onUpdateCurrentPage:s})]:i(Au))}}),xu=V({name:"CategoryList",setup(){const e=ie(),t=dr();return()=>i("ul",{class:"vp-category-list"},Sn(t.value.map).sort(([,n],[,r])=>r.items.length-n.items.length).map(([n,{path:r,items:a}])=>i("li",{class:["vp-category",`vp-category${ca(n,9)}`,{active:r===e.value.path}]},i(Ce,{to:r},()=>[n,i("span",{class:"count"},a.length)]))))}}),Su=V({name:"TagList",setup(){const e=_e(),t=pr(),n=r=>{var a;return r===((a=e.value.blog)==null?void 0:a.name)};return()=>i("ul",{class:"tag-list-wrapper"},Sn(t.value.map).sort(([,r],[,a])=>a.items.length-r.items.length).map(([r,{path:a,items:l}])=>i("li",{class:["tag",`tag${ca(r,9)}`,{active:n(r)}]},i(Ce,{to:a},()=>[r,i("span",{class:"tag-num"},l.length)]))))}}),b3=V({name:"TimelineList",setup(){const e=se(),t=Jl(),n=ir(),r=E(()=>e.value.blogLocales.timeline);return()=>i("div",{class:"timeline-list-wrapper"},[i("div",{class:"timeline-list-title",onClick:()=>n(t.value.path)},[i(Xl),i("span",{class:"num"},t.value.items.length),r.value]),i("hr"),i("div",{class:"timeline-content"},i("ul",{class:"timeline-list"},t.value.config.map(({year:a,items:l},o)=>i(fe,{appear:!0,delay:.08*(o+1)},()=>i("li",[i("h3",{class:"timeline-year"},a),i("ul",{class:"timeline-year-wrapper"},l.map(({date:s,info:c,path:u})=>i("li",{class:"timeline-item"},[i("span",{class:"timeline-date"},s),i(Ce,{class:"timeline-title",to:u},()=>c[ge.title])])))])))))])}}),_3={article:ha,category:Zl,tag:Ql,timeline:Xl},Tu=V({name:"InfoList",setup(){const e=se(),t=hr(),n=dr(),r=E(()=>wt(n.value.map).length),a=Wl(),l=pr(),o=E(()=>wt(l.value.map).length),s=ir(),c=X("article"),u=E(()=>e.value.blogLocales);return()=>i("div",{class:"vp-blog-infos"},[i("div",{class:"vp-blog-type-switcher"},Sn(_3).map(([d,f])=>i("button",{type:"button",class:"vp-blog-type-button",onClick:()=>{c.value=d}},i("div",{class:["icon-wrapper",{active:c.value===d}],"aria-label":u.value[d],"data-balloon-pos":"up"},i(f))))),i(fe,()=>c.value==="article"?i("div",{class:"vp-star-article-wrapper"},[i("div",{class:"title",onClick:()=>s(t.value.path)},[i(ha),i("span",{class:"num"},t.value.items.length),u.value.article]),i("hr"),a.value.items.length?i("ul",{class:"vp-star-articles"},a.value.items.map(({info:d,path:f},p)=>i(fe,{appear:!0,delay:.08*(p+1)},()=>i("li",{class:"vp-star-article"},i(Ce,{to:f},()=>d[ge.title]))))):i("div",{class:"vp-star-article-empty"},u.value.empty.replace("$text",u.value.star))]):c.value==="category"?i("div",{class:"vp-category-wrapper"},[r.value?[i("div",{class:"title",onClick:()=>s(n.value.path)},[i(Zl),i("span",{class:"num"},r.value),u.value.category]),i("hr"),i(fe,{delay:.04},()=>i(xu))]:i("div",{class:"vp-category-empty"},u.value.empty.replace("$text",u.value.category))]):c.value==="tag"?i("div",{class:"vp-tag-wrapper"},[o.value?[i("div",{class:"title",onClick:()=>s(l.value.path)},[i(Ql),i("span",{class:"num"},o.value),u.value.tag]),i("hr"),i(fe,{delay:.04},()=>i(Su))]:i("div",{class:"vp-tag-empty"},u.value.empty.replace("$text",u.value.tag))]):i(fe,()=>i(b3)))])}}),va=V({name:"BlogWrapper",slots:Object,setup(e,{slots:t}){const{isMobile:n}=sr();return()=>[i(Kl),i(Ul,{noSidebar:!0,noToc:!0},{default:()=>t.default(),navScreenBottom:()=>i(Yl),...n.value?{sidebar:()=>i(Tu)}:{}})]}}),vr=()=>i("aside",{class:"vp-blog-info-wrapper"},[i(fe,()=>i(Yl)),i(fe,{delay:.04},()=>i(Tu))]);vr.displayName="InfoPanel";const y3=V({name:"BlogPage",setup(){const e=ie(),t=_e(),n=dr(),r=pr();return()=>{const{key:a="",name:l=""}=t.value.blog||{},o=l?a==="category"?n.value.map[l].items:a==="tag"?r.value.map[l].items:[]:[];return i(va,()=>i("div",{class:"vp-page vp-blog"},i("div",{class:"blog-page-wrapper"},[i("main",{id:"main-content",class:"vp-blog-main"},[i(fe,()=>a==="category"?i(xu):a==="tag"?i(Su):null),l?i(fe,{appear:!0,delay:.24},()=>i(eo,{key:e.value.path,items:o})):null]),i(fe,{delay:.16},()=>i(vr,{key:"blog"}))])))}}}),E3="//theme-hope-assets.vuejs.press/hero/default.jpg",k3=V({name:"BlogHero",slots:Object,setup(e,{slots:t}){const n=_e(),r=rr(),a=mt(),l=E(()=>n.value.heroFullScreen??!1),o=E(()=>{const{heroText:c,heroImage:u,heroImageDark:d,heroAlt:f,heroImageStyle:p,tagline:h}=n.value;return{text:c??r.value.title??"Hello",image:u?Le(u):null,imageDark:d?Le(d):null,heroStyle:p,alt:f||c||"",tagline:h??"",isFullScreen:l.value}}),s=E(()=>{const{bgImage:c,bgImageDark:u,bgImageStyle:d}=n.value;return{image:oe(c)?Le(c):c===!1?null:E3,imageDark:oe(u)?Le(u):null,bgStyle:d,isFullScreen:l.value}});return()=>{var c,u;return n.value.hero===!1?null:i("div",{ref:a,class:["vp-blog-hero",{fullscreen:l.value,"no-bg":!s.value.image}]},[((c=t.heroBg)==null?void 0:c.call(t,s.value))||[s.value.image?i("div",{class:["vp-blog-mask",{light:s.value.imageDark}],style:[{background:`url(${s.value.image}) center/cover no-repeat`},s.value.bgStyle]}):null,s.value.imageDark?i("div",{class:"vp-blog-mask dark",style:[{background:`url(${s.value.imageDark}) center/cover no-repeat`},s.value.bgStyle]}):null],((u=t.heroInfo)==null?void 0:u.call(t,o.value))||[i(fe,{appear:!0,type:"group",delay:.04},()=>[o.value.image?i("img",{key:"light",class:["vp-blog-hero-image",{light:o.value.imageDark}],style:o.value.heroStyle,src:o.value.image,alt:o.value.alt}):null,o.value.imageDark?i("img",{key:"dark",class:"vp-blog-hero-image dark",style:o.value.heroStyle,src:o.value.imageDark,alt:o.value.alt}):null]),i(fe,{appear:!0,delay:.08},()=>o.value.text?i("h1",{class:"vp-blog-hero-title"},o.value.text):null),i(fe,{appear:!0,delay:.12},()=>o.value.tagline?i("p",{class:"vp-blog-hero-description",innerHTML:o.value.tagline}):null)],o.value.isFullScreen?i("button",{type:"button",class:"slide-down-button",onClick:()=>{window.scrollTo({top:a.value.clientHeight,behavior:"smooth"})}},[i(il),i(il)]):null])}}}),w3=["link","article","book","project","friend"],A3=V({name:"ProjectPanel",components:{ArticleIcon:ha,BookIcon:yu,FriendIcon:wu,LinkIcon:Eu,ProjectIcon:ku},props:{items:{type:Array,required:!0}},setup(e){const t=nn(),n=ir(),r=(a="",l="icon")=>w3.includes(a)?i(He(`${a}-icon`)):xn(a)?i("img",{class:"vp-project-image",src:a,alt:l}):da(a)?i("img",{class:"vp-project-image",src:Le(a),alt:l}):i(Re,{icon:a});return()=>i("div",{class:"vp-project-panel"},e.items.map(({icon:a,link:l,name:o,desc:s},c)=>i("div",{class:["vp-project-card",{[`project${c%9}`]:!t.value}],onClick:()=>n(l)},[r(a,o),i("div",{class:"vp-project-name"},o),i("div",{class:"vp-project-desc"},s)])))}}),L3=V({name:"BlogHome",setup(){const e=hr(),t=_e(),n=E(()=>t.value.projects??[]);return()=>i("div",{class:"vp-page vp-blog"},[i(k3),i("div",{class:"blog-page-wrapper"},[i("main",{id:"main-content",class:"vp-blog-main"},[n.value.length?i(fe,{appear:!0,delay:.16},()=>i(A3,{items:n.value})):null,i(fe,{appear:!0,delay:.24},()=>i(eo,{items:e.value.items}))]),i(fe,{appear:!0,delay:.16},()=>i(vr,{key:"blog"}))]),i(fe,{appear:!0,delay:.28},()=>i(ur))])}}),Bu=()=>i(va,()=>i(L3));Bu.displayName="BlogHomeLayout";var x3=[];const S3=V({name:"ArticleType",setup(){const e=ie(),t=ct(),n=se(),r=hr(),a=Wl(),l=E(()=>{const o=n.value.blogLocales;return[{text:o.all,path:r.value.path},{text:o.star,path:a.value.path},...x3.map(({key:s,path:c})=>({text:o[s],path:c.replace(/^\//,t.value)}))]});return()=>i("ul",{class:"vp-article-type-wrapper"},l.value.map(o=>i("li",{class:["vp-article-type",{active:o.path===e.value.path}]},i(Ce,{to:o.path},()=>o.text))))}}),T3=V({name:"BlogPage",setup(){const e=pa(),t=_e(),n=ie(),r=hr(),a=Wl(),l=E(()=>{const{key:o="",type:s}=t.value.blog||{};return o==="star"?a.value.items:s==="type"&&o?e.value.items:r.value.items});return()=>i(va,()=>i("div",{class:"vp-page vp-blog"},i("div",{class:"blog-page-wrapper"},[i("main",{id:"main-content",class:"vp-blog-main"},[i(fe,()=>i(S3)),i(fe,{appear:!0,delay:.24},()=>i(eo,{key:n.value.path,items:l.value}))]),i(fe,{delay:.16},()=>i(vr,{key:"blog"}))])))}}),B3=V({name:"TimelineItems",setup(){const e=fr(),t=se(),n=Jl(),r=E(()=>e.value.timeline||t.value.blogLocales.timelineTitle),a=E(()=>n.value.config.map(({year:l})=>({title:l.toString(),level:2,slug:l.toString(),children:[]})));return()=>i("div",{class:"timeline-wrapper"},i("ul",{class:"timeline-content"},[i(fe,()=>i("li",{class:"motto"},r.value)),i(uu,{items:a.value}),n.value.config.map(({year:l,items:o},s)=>i(fe,{appear:!0,delay:.08*(s+1),type:"group"},()=>[i("h3",{key:"title",id:l,class:"timeline-year-title"},i("span",l)),i("li",{key:"content",class:"timeline-year-list"},[i("ul",{class:"timeline-year-wrapper"},o.map(({date:c,info:u,path:d})=>i("li",{class:"timeline-item"},[i("span",{class:"timeline-date"},c),i(Ce,{class:"timeline-title",to:d},()=>u[ge.title])])))])]))]))}}),Cu=()=>i(va,()=>i("div",{class:"vp-page vp-blog"},i("div",{class:"blog-page-wrapper"},[i("main",{id:"main-content",class:"vp-blog-main"},[i(fe,{appear:!0,delay:.24},()=>i(B3))]),i(fe,{delay:.16},()=>i(vr,{key:"blog"}))])));Cu.displayName="Timeline";dh(e=>{const t=e.t,n=e.I!==!1,r=e.i;return n?{title:t,content:r?()=>[i(Re,{icon:r}),t]:null,order:e.O,index:e.I}:null});const C3=Ye({enhance:({app:e,router:t})=>{const{scrollBehavior:n}=t.options;t.options.scrollBehavior=async(...r)=>(await Dc().wait(),n(...r)),X0(e),e.component("HopeIcon",Re),e.component("VPLink",Ce),e.component("BloggerInfo",Yl)},setup:()=>{e2(),l2(),h3()},layouts:{Layout:Q2,NotFound:e3,BlogCategory:y3,BlogHome:Bu,BlogType:T3,Timeline:Cu}});var I3={provider:"Giscus",comment:!0,repo:"Zephery/MyWebsite",repoId:"MDEwOlJlcG9zaXRvcnkyMDM2MDIyMDQ=",category:"General",categoryId:"DIC_kwDODCK5HM4Ccp32"};const P3=I3;let O3=P3;const Iu=Symbol(""),Pu=()=>he(Iu),D3=Pu,R3=e=>{e.provide(Iu,O3)},xi=["ar","ca","de","en","eo","es","fa","fr","he","id","it","ja","ko","nl","pl","pt","ro","ru","th","tr","uk","vi","zh-CN","zh-TW"];var M3=V({name:"GiscusComment",props:{identifier:{type:String,required:!0},darkmode:Boolean},setup(e){const t=D3(),n=!!(t.repo&&t.repoId&&t.category&&t.categoryId),{repo:r,repoId:a,category:l,categoryId:o}=t,s=X(!1),c=E(()=>{const d=Pl().value;if(xi.includes(d))return d;const f=d.split("-")[0];return xi.includes(f)?f:"en"}),u=E(()=>({repo:r,repoId:a,category:l,categoryId:o,lang:c.value,theme:e.darkmode?t.darkTheme||"dark":t.lightTheme||"light",mapping:t.mapping||"pathname",term:e.identifier,inputPosition:t.inputPosition||"top",reactionsEnabled:t.reactionsEnabled===!1?"0":"1",strict:t.strict===!1?"0":"1",loading:t.lazyLoading===!1?"eager":"lazy",emitMetadata:"0"}));return Ee(async()=>{await y(()=>import("./giscus-hHrgKA30.js"),__vite__mapDeps([])),s.value=!0}),()=>n?i("div",{id:"comment",class:["giscus-wrapper",{"input-top":t.inputPosition!=="bottom"}]},s.value?i("giscus-widget",u.value):i(tc)):null}}),F3=V({name:"CommentService",props:{darkmode:Boolean},setup(e){const t=Pu(),n=ie(),r=_e(),a=t.comment!==!1,l=E(()=>r.value.comment||a&&r.value.comment!==!1);return()=>i(M3,{identifier:r.value.commentID||n.value.path,darkmode:e.darkmode,style:{display:l.value?"block":"none"}})}}),V3=Ye({enhance:({app:e})=>{R3(e),e.component("CommentService",F3)}});const Tn=({name:e="",color:t="currentColor"},{slots:n})=>{var r;return i("svg",{xmlns:"http://www.w3.org/2000/svg",class:["icon",`${e}-icon`],viewBox:"0 0 1024 1024",fill:t,"aria-label":`${e} icon`},(r=n.default)==null?void 0:r.call(n))};Tn.displayName="IconBase";var $3=e=>/^(https?:)?\/\//.test(e),j3=e=>Object.prototype.toString.call(e)==="[object Object]";const N3=e=>!$3(e)||/github\.com/.test(e)?"GitHub":/bitbucket\.org/.test(e)?"Bitbucket":/gitlab\.com/.test(e)?"GitLab":/gitee\.com/.test(e)?"Gitee":null,Ou=()=>i(Tn,{name:"github"},()=>i("path",{d:"M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"}));Ou.displayName="GitHubIcon";const Du=()=>i(Tn,{name:"gitlab"},()=>i("path",{d:"M229.333 78.688C223.52 62 199.895 62 193.895 78.688L87.958 406.438h247.5c-.188 0-106.125-327.75-106.125-327.75zM33.77 571.438c-4.875 15 .563 31.687 13.313 41.25l464.812 345L87.77 406.438zm301.5-165 176.813 551.25 176.812-551.25zm655.125 165-54-165-424.312 551.25 464.812-345c12.938-9.563 18.188-26.25 13.5-41.25zM830.27 78.688c-5.812-16.688-29.437-16.688-35.437 0l-106.125 327.75h247.5z"}));Du.displayName="GitLabIcon";const Ru=()=>i(Tn,{name:"gitee"},()=>i("path",{d:"M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm242.97-533.34H482.39a23.7 23.7 0 0 0-23.7 23.7l-.03 59.28c0 13.08 10.59 23.7 23.7 23.7h165.96a23.7 23.7 0 0 1 23.7 23.7v11.85a71.1 71.1 0 0 1-71.1 71.1H375.71a23.7 23.7 0 0 1-23.7-23.7V423.11a71.1 71.1 0 0 1 71.1-71.1h331.8a23.7 23.7 0 0 0 23.7-23.7l.06-59.25a23.73 23.73 0 0 0-23.7-23.73H423.11a177.78 177.78 0 0 0-177.78 177.75v331.83c0 13.08 10.62 23.7 23.7 23.7h349.62a159.99 159.99 0 0 0 159.99-159.99V482.33a23.7 23.7 0 0 0-23.7-23.7z"}));Ru.displayName="GiteeIcon";const Mu=()=>i(Tn,{name:"bitbucket"},()=>i("path",{d:"M575.256 490.862c6.29 47.981-52.005 85.723-92.563 61.147-45.714-20.004-45.714-92.562-1.133-113.152 38.29-23.442 93.696 7.424 93.696 52.005zm63.451-11.996c-10.276-81.152-102.29-134.839-177.152-101.156-47.433 21.138-79.433 71.424-77.129 124.562 2.853 69.705 69.157 126.866 138.862 120.576S647.3 548.571 638.708 478.83zm136.558-309.723c-25.161-33.134-67.986-38.839-105.728-45.13-106.862-17.151-216.576-17.7-323.438 1.134-35.438 5.706-75.447 11.996-97.719 43.996 36.572 34.304 88.576 39.424 135.424 45.129 84.553 10.862 171.447 11.447 256 .585 47.433-5.705 99.987-10.276 135.424-45.714zm32.585 591.433c-16.018 55.99-6.839 131.438-66.304 163.986-102.29 56.576-226.304 62.867-338.87 42.862-59.43-10.862-129.135-29.696-161.72-85.723-14.3-54.858-23.442-110.848-32.585-166.84l3.438-9.142 10.276-5.157c170.277 112.567 408.576 112.567 579.438 0 26.844 8.01 6.84 40.558 6.29 60.014zm103.424-549.157c-19.42 125.148-41.728 249.71-63.415 374.272-6.29 36.572-41.728 57.162-71.424 72.558-106.862 53.724-231.424 62.866-348.562 50.286-79.433-8.558-160.585-29.696-225.134-79.433-30.28-23.443-30.28-63.415-35.986-97.134-20.005-117.138-42.862-234.277-57.161-352.585 6.839-51.42 64.585-73.728 107.447-89.71 57.16-21.138 118.272-30.866 178.87-36.571 129.134-12.58 261.157-8.01 386.304 28.562 44.581 13.13 92.563 31.415 122.844 69.705 13.714 17.7 9.143 40.01 6.29 60.014z"}));Mu.displayName="BitbucketIcon";const Fu=()=>i(Tn,{name:"source"},()=>i("path",{d:"M601.92 475.2c0 76.428-8.91 83.754-28.512 99.594-14.652 11.88-43.956 14.058-78.012 16.434-18.81 1.386-40.392 2.97-62.172 6.534-18.612 2.97-36.432 9.306-53.064 17.424V299.772c37.818-21.978 63.36-62.766 63.36-109.692 0-69.894-56.826-126.72-126.72-126.72S190.08 120.186 190.08 190.08c0 46.926 25.542 87.714 63.36 109.692v414.216c-37.818 21.978-63.36 62.766-63.36 109.692 0 69.894 56.826 126.72 126.72 126.72s126.72-56.826 126.72-126.72c0-31.086-11.286-59.598-29.7-81.576 13.266-9.504 27.522-17.226 39.996-19.206 16.038-2.574 32.868-3.762 50.688-5.148 48.312-3.366 103.158-7.326 148.896-44.55 61.182-49.698 74.25-103.158 75.24-187.902V475.2h-126.72zM316.8 126.72c34.848 0 63.36 28.512 63.36 63.36s-28.512 63.36-63.36 63.36-63.36-28.512-63.36-63.36 28.512-63.36 63.36-63.36zm0 760.32c-34.848 0-63.36-28.512-63.36-63.36s28.512-63.36 63.36-63.36 63.36 28.512 63.36 63.36-28.512 63.36-63.36 63.36zM823.68 158.4h-95.04V63.36h-126.72v95.04h-95.04v126.72h95.04v95.04h126.72v-95.04h95.04z"}));Fu.displayName="SourceIcon";const z3=(e,t)=>{const n=t?t._instance:tn();return j3(n==null?void 0:n.appContext.components)&&(e in n.appContext.components||Ge(e)in n.appContext.components||An(Ge(e))in n.appContext.components)},H3=e=>{const t=ct();return E(()=>e[t.value])};var q3={"/":{source:"源代码"}},G3=V({name:"SiteInfo",components:{BitbucketIcon:Mu,GiteeIcon:Ru,GitHubIcon:Ou,GitLabIcon:Du,SourceIcon:Fu},props:{name:{type:String,required:!0},desc:{type:String,default:""},logo:{type:String,default:""},url:{type:String,required:!0},preview:{type:String,required:!0},repo:{type:String,default:""}},setup(e){const t=H3(q3),n=E(()=>e.repo?N3(e.repo):null);return()=>i("div",{class:"vp-site-info"},[i("a",{class:"vp-site-info-navigator",title:e.name,href:e.url,target:"_blank"}),i("div",{class:"vp-site-info-preview",style:{background:`url(${Le(e.preview)}) center/cover no-repeat`}}),i("div",{class:"vp-site-info-detail"},[e.logo?i("img",{class:"vp-site-info-logo",src:e.logo,alt:e.name,loading:"lazy","no-view":""}):null,i("div",{class:"vp-site-info-name"},e.name),i("div",{class:"vp-site-info-desc"},e.desc)]),e.repo?i("div",{class:"vp-site-info-source-wrapper"},i("a",{class:"vp-site-info-source",href:e.repo,"aria-label":t.value.source,"data-balloon-pos":"left",title:t.value.source,target:"_blank"},i(He(`${n.value}Icon`)))):null])}});const U3=Ye({enhance:({app:e})=>{z3("SiteInfo")||e.component("SiteInfo",G3)},setup:()=>{},rootComponents:[]}),Pr=[jf,Jp,mh,yh,Ah,Bh,i0,u0,p0,A0,N0,C3,V3,U3],K3=[["v-8daa1a0e","/",{d:1706066758e3,e:`
+`,r:{minutes:.32,words:97},y:"a",t:""},["/README.md"]],["v-728c3a8f","/about-the-author/",{d:1706204085e3,e:` 关于我
+留空
+`,r:{minutes:.02,words:5},y:"a",t:"关于我"},["/about-the-author/README.md"]],["v-cfe8b6c8","/cloudnative/",{d:1706066758e3,y:"a",t:""},["/cloudnative/README.md"]],["v-2e25198a","/database/",{d:1706182936e3,e:`
+`,r:{minutes:.05,words:15},y:"a",t:""},["/database/README.md"]],["v-71fde78e","/devops/",{d:1706066758e3,e:` 三、DevOps
+`,r:{minutes:.08,words:24},y:"a",t:"三、DevOps"},["/devops/README.md"]],["v-580db9be","/devops/devops-ping-tai.html",{d:1706066758e3,e:`
+DevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
+公司技术部目前几百人左右吧,但是整个技术栈还是比较落后的,尤其是DevOps、容器这一块,需要将全线打通,当时进来也主要是负责DevOps这一块的工作,应该说也是没怎么做好,其中也走了不少弯路,下面主要是自己踩过的坑吧。
`,r:{minutes:11.93,words:3580},y:"a",t:"3.1 DevOps平台.md"},[":md"]],["v-06d5cd4c","/devops/gitlab-ci.html",{d:1706066758e3,e:` Git
+`,r:{minutes:0,words:1},y:"a",t:"Git"},[":md"]],["v-132efcd1","/devops/jenkins-x.html",{d:1706066758e3,e:` jenkins-x
+`,r:{minutes:.01,words:2},y:"a",t:"jenkins-x"},[":md"]],["v-1a2ca7a7","/devops/tekton.html",{d:1706066758e3,e:` tekton
+`,r:{minutes:0,words:1},y:"a",t:"tekton"},[":md"]],["v-50cb12f2","/donate/",{d:1706182936e3,e:` 微信支付
+微信支付
+`,r:{minutes:.04,words:12},y:"a",t:"微信支付"},["/donate/README.md"]],["v-091223ce","/interview/tiktok2023.html",{d:1706066758e3,e:`tt一面:
+1.全程项目
+2.lc3,最长无重复子串,滑动窗口解决
+tt二面:
+全程基础,一直追问
+1.java内存模型介绍一下
+2.volatile原理
+3.内存屏障,使用场景?(我提了在gc中有使用)
+4.gc中具体是怎么使用内存屏障的,详细介绍
+5.cms和g1介绍一下,g1能取代cms吗?g1和cms各自的使用场景是什么
+6.线程内存分配方式,tlab相关
+7.happens-before介绍一下
+8.总线风暴是什么,怎么解决
+9.网络相关,time_wait,close_wait产生原因,带来的影响,怎么解决
+10.算法题,给你一个数字n,求用这个n的各位上的数字组合出最大的小于n的数字m,注意边界case,如2222
+11.场景题,设计一个微信朋友圈,功能包含feed流拉取,评论,转发,点赞等操作
`,r:{minutes:1.15,words:344},y:"a",t:""},[":md"]],["v-0a27b598","/java/JVM%E8%B0%83%E4%BC%98%E5%8F%82%E6%95%B0.html",{d:1706066758e3,e:` JVM调优参数
+ 一、堆大小设置
+JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
+ 典型设置:
+java -Xmx3550m -Xms3550m -Xmn2g -Xss128k
+
`,r:{minutes:9.13,words:2739},y:"a",t:"JVM调优参数"},["/java/JVM调优参数.html","/java/JVM调优参数.md",":md"]],["v-60eda44c","/java/serverlog.html",{d:1706066758e3,e:` 被挖矿攻击
+服务器被黑,进程占用率高达99%,查看了一下,是/usr/sbin/bashd的原因,怎么删也删不掉,使用ps查看:
+
+stratum+tcp://get.bi-chi.com:3333 -u 47EAoaBc5TWDZKVaAYvQ7Y4ZfoJMFathAR882gabJ43wHEfxEp81vfJ3J3j6FQGJxJNQTAwvmJYS2Ei8dbkKcwfPFst8FhG
`,r:{minutes:.57,words:172},y:"a",t:"被挖矿攻击"},[":md"]],["v-399e07b6","/java/%E4%B8%80%E6%AC%A1jvm%E8%B0%83%E4%BC%98%E8%BF%87%E7%A8%8B.html",{d:1706066758e3,e:` 一次jvm调优过程
+前端时间把公司的一个分布式定时调度的系统弄上了容器云,部署在kubernetes,在容器运行的动不动就出现问题,特别容易jvm溢出,导致程序不可用,终端无法进入,日志一直在刷错误,kubernetes也没有将该容器自动重启。业务方基本每天都在反馈task不稳定,后续就协助接手看了下,先主要讲下该程序的架构吧。
+该程序task主要分为三个模块:
+console进行一些cron的配置(表达式、任务名称、任务组等);
+schedule主要从数据库中读取配置然后装载到quartz再然后进行命令下发;
+client接收任务执行,然后向schedule返回运行的信息(成功、失败原因等)。
+整体架构跟github上开源的xxl-job类似,也可以参考一下。
`,r:{minutes:6.28,words:1884},y:"a",t:"一次jvm调优过程"},["/java/一次jvm调优过程.html","/java/一次jvm调优过程.md",":md"]],["v-660266c1","/java/%E5%86%85%E5%AD%98%E5%B1%8F%E9%9A%9C.html",{d:1706066758e3,e:` 内存屏障
+四个内存屏障指令:LoadLoad,
StoreStore,
LoadStore,
StoreLoad
+在每个volatile写操作前插入StoreStore屏障,这样就能让其他线程修改A变量后,把修改的值对当前线程可见,在写操作后插入StoreLoad屏障,这样就能让其他线程获取A变量的时候,能够获取到已经被当前线程修改的值
+在每个volatile读操作前插入LoadLoad屏障,这样就能让当前线程获取A变量的时候,保证其他线程也都能获取到相同的值,这样所有的线程读取的数据就一样了,在读操作后插入LoadStore屏障;这样就能让当前线程在其他线程修改A变量的值之前,获取到主内存里面A变量的的值。
`,r:{minutes:.69,words:208},y:"a",t:"内存屏障"},["/java/内存屏障.html","/java/内存屏障.md",":md"]],["v-90f2343c","/java/%E5%9C%A8%20Spring%206%20%E4%B8%AD%E4%BD%BF%E7%94%A8%E8%99%9A%E6%8B%9F%E7%BA%BF%E7%A8%8B.html",{d:1706186538e3,e:` 在 Spring 6 中使用虚拟线程
+ 一、简介
+在这个简短的教程中,我们将了解如何在 Spring Boot 应用程序中利用虚拟线程的强大功能。
+虚拟线程是Java 19 的预览功能 ,这意味着它们将在未来 12 个月内包含在官方 JDK 版本中。Spring 6 版本 最初由 Project Loom 引入,为开发人员提供了开始尝试这一出色功能的选项。
`,r:{minutes:4.83,words:1448},y:"a",t:"在 Spring 6 中使用虚拟线程"},["/java/在 Spring 6 中使用虚拟线程.html","/java/在 Spring 6 中使用虚拟线程.md",":md"]],["v-0b5d4df0","/java/%E5%9F%BA%E4%BA%8Ekubernetes%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E9%99%90%E6%B5%81.html",{d:1706066758e3,e:` 基于kubernetes的分布式限流
+做为一个数据上报系统,随着接入量越来越大,由于 API 接口无法控制调用方的行为,因此当遇到瞬时请求量激增时,会导致接口占用过多服务器资源,使得其他请求响应速度降低或是超时,更有甚者可能导致服务器宕机。
+ 一、概念
+限流(Ratelimiting)指对应用服务的请求进行限制,例如某一接口的请求限制为 100 个每秒,对超过限制的请求则进行快速失败或丢弃。
+ 1.1 使用场景
+限流可以应对:
+
+热点业务带来的突发请求;
+调用方 bug 导致的突发请求;
+恶意攻击请求。
+ `,r:{minutes:7.18,words:2155},y:"a",t:"基于kubernetes的分布式限流"},["/java/基于kubernetes的分布式限流.html","/java/基于kubernetes的分布式限流.md",":md"]],["v-21e54510","/kubernetes/",{d:1706066758e3,y:"a",t:""},["/kubernetes/README.md"]],["v-57ae83ac","/kubernetes/spark%20on%20k8s%20operator.html",{d:1706066758e3,e:` spark on k8s operator
+Spark operator是一个管理Kubernetes上的Apache Spark应用程序生命周期的operator,旨在像在Kubernetes上运行其他工作负载一样简单的指定和运行spark应用程序。
+使用Spark Operator管理Spark应用,能更好的利用Kubernetes原生能力控制和管理Spark应用的生命周期,包括应用状态监控、日志获取、应用运行控制等,弥补Spark on Kubernetes方案在集成Kubernetes上与其他类型的负载之间存在的差距。
+Spark Operator包括如下几个组件:
`,r:{minutes:3.51,words:1054},y:"a",t:"spark on k8s operator"},["/kubernetes/spark on k8s operator.html","/kubernetes/spark on k8s operator.md",":md"]],["v-22e4234a","/life/2017.html",{d:1706066758e3,e:` 2017
+2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。
+17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?
+ `,r:{minutes:11.22,words:3366},y:"a",t:"2017"},[":md"]],["v-1f7a720c","/life/2018.html",{d:1706066758e3,e:` 2018
+年底老姐结婚,跑回家去了,忙着一直没写,本来想回深圳的时候空余的时候写写,没想到一直加班,嗯,9点半下班那种,偶尔也趁着间隙的时间,一段一段的凑着吧。
+想着17年12月31号写的那篇文章https://www.cnblogs.com/w1570631036/p/8158284.html ,感叹18年还算恢复了点。
+ 心惊胆战的裸辞经历 `,r:{minutes:4.35,words:1306},y:"a",t:"2018"},[":md"]],["v-1c10c0ce","/life/2019.html",{d:1706066758e3,e:` 2019
+2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。
+19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。
+ 工作
+从18年底开始吧,大概就知道领导对容器云这么快的完全架构设计错误,就是一个完完全全错误的产品,其他人也觉得有点很有问题,但老板就是固执不听,结果一个跑路,一个被压得懒得反抗,然后我一个人跟老板和项目经理怼了前前后后半年,真是惨啊,还要被骂,各种拉到小黑屋里批斗,一直在对他们强调:没有这么做的!!!然后被以年轻人,不懂事,不要抱怨,长大了以后就领会了怼回来,当时气得真是无语。。。。。自己调研的阿里云、腾讯云、青云,还有其他小公司的容器,发现真的只有我们这么设计,完全错误的方向,,,,直到老板走了之后,才开始决定重构,走上正轨。
`,r:{minutes:4.43,words:1329},y:"a",t:"2019"},[":md"]],["v-b0e413b8","/link/main.html",{d:1706846339e3,e:` 友链地址
+`,r:{minutes:.16,words:49},y:"a",t:"友链地址"},[":md"]],["v-258f309e","/open-source-project/",{d:1706092222e3,e:`jfaowejfoewj
+`,r:{minutes:0,words:1},y:"a",t:""},["/open-source-project/README.md"]],["v-510415f9","/others/chatgpt.html",{d:1706186538e3,e:` 微信公众号-chatgpt智能客服搭建
+想体验的可以去微信上搜索【旅行的树】公众号。
+ 一、ChatGPT注册
+ 1.1 短信手机号申请
+openai提供服务的区域,美国最好,这个解决办法是搞个翻墙,或者买一台美国的服务器更好。
+国外邮箱,hotmail或者google最好,qq邮箱可能会对这些平台进行邮件过滤。
+国外手机号,没有的话也可以去https://sms-activate.org ,费用大概需要1美元,这个网站记得也用国外邮箱注册,需要先充值,使用支付宝支付。
`,r:{minutes:9.96,words:2987},y:"a",t:"微信公众号-chatgpt智能客服搭建"},[":md"]],["v-68e0ce3f","/others/starcraft-ai.html",{d:1706288023e3,e:` StarCraft Ⅱ 人工智能教程
+非深度学习人士,仅仅是兴趣驱动,可能有很多不对的地方,也欢迎大家指正。这里主要讲解如何将AI运行起来、机器人对战、人机对战、天梯上分等等,希望能对大家的人工智能工程道路上有所帮助。
+ 一、其他的太抽象了,先讲人机对战吧
+sc2的wiki 资料很全,可以从这里下载并运行,目前人机对战只能在win下运行,这边特别强调一下的就是,需要以管理员身份运行,下面详细过程,翻译自 ProBots 2021 Season 1 - Human vs Bot 。
`,r:{minutes:2.72,words:817},y:"a",t:"StarCraft Ⅱ 人工智能教程"},[":md"]],["v-3c114a75","/others/tesla.html",{d:1706186538e3,e:` Tesla api
+ 一、特斯拉应用申请
+ 1.1 创建 Tesla 账户
+如果您还没有 Tesla 账户,请创建账户。验证您的电子邮件并设置多重身份验证。
+正常创建用户就好,然后需要开启多重身份认证,这边常用的是mircrosoft的Authenticator.
+
+ `,r:{minutes:4.5,words:1351},y:"a",t:"Tesla api"},[":md"]],["v-90e5bb66","/others/%E5%B9%BF%E5%B7%9E%E5%9B%BE%E4%B9%A6%E9%A6%86%E5%80%9F%E9%98%85%E6%8A%93%E5%8F%96.html",{d:1706596625e3,e:` 广州图书馆借阅抓取
+欢迎访问我的个人网站 ,要是能在GitHub上对网站源码 给个star就更好了。
+搭建自己的网站的时候,想把自己读过借过的书都想记录一下,大学也做过自己学校的借书记录的爬取,但是数据库删掉了==,只保留一张截图。所以还是要好好珍惜自己阅读的日子吧,记录自己的借书记录——广州图书馆 ,现在代码已经放在服务器上定时运行,结果查看我的网站(关于我)页面 。整个代码采用HttpClient,存储放在MySql,定时使用Spring自带的Schedule,下面是抓取的过程。
`,r:{minutes:6.83,words:2049},y:"a",t:"广州图书馆借阅抓取"},["/others/广州图书馆借阅抓取.html","/others/广州图书馆借阅抓取.md",":md"]],["v-dc384366","/redis/",{d:1706066758e3,y:"a",t:""},["/redis/README.md"]],["v-70796e0a","/redis/redis%E7%BC%93%E5%AD%98.html",{d:1706066758e3,e:` 一、概述
+ 1.1 缓存介绍
+系统的性能指标一般包括响应时间、延迟时间、吞吐量,并发用户数和资源利用率等。在应用运行过程中,我们有可能在一次数据库会话中,执行多次查询条件完全相同的SQL,MyBatis提供了一级缓存的方案优化这部分场景,如果是相同的SQL语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能。
+缓存常用语:
+数据不一致性、缓存更新机制、缓存可用性、缓存服务降级、缓存预热、缓存穿透
+可查看Redis实战(一) 使用缓存合理性
`,r:{minutes:11.96,words:3588},y:"a",t:"一、概述"},["/redis/redis缓存.html","/redis/redis缓存.md",":md"]],["v-43e9e6b0","/about-the-author/personal-life/wewe.html",{d:1706244827e3,e:` 自我介绍
+普通人
+`,r:{minutes:.02,words:7},y:"a",t:"自我介绍"},[":md"]],["v-33bd146f","/about-the-author/works/%E4%B8%AA%E4%BA%BA%E4%BD%9C%E5%93%81.html",{d:1706349103e3,e:` 小程序
+助眠风扇
+MyTesMate `,r:{minutes:.05,words:14},y:"a",t:"小程序"},["/about-the-author/works/个人作品.html","/about-the-author/works/个人作品.md",":md"]],["v-04e32b44","/bigdata/spark/elastic-spark.html",{d:1706182936e3,e:` elastic spark
+Hadoop允许Elasticsearch在Spark中以两种方式使用:通过自2.1以来的原生RDD支持,或者通过自2.0以来的Map/Reduce桥接器。从5.0版本开始,elasticsearch-hadoop就支持Spark 2.0。目前spark支持的数据源有:
+(1)文件系统:LocalFS、HDFS、Hive、text、parquet、orc、json、csv
+(2)数据RDBMS:mysql、oracle、mssql
+(3)NOSQL数据库:HBase、ES、Redis
+(4)消息对象:Redis
`,r:{minutes:1.71,words:514},y:"a",t:"elastic spark"},[":md"]],["v-d73a9aee","/database/elasticsearch/elasticsearch%E6%BA%90%E7%A0%81debug.html",{d:1706186538e3,e:` 【elasticsearch】源码debug
+ 一、下载源代码
+直接用idea下载代码https://github.com/elastic/elasticsearch.git
+
`,r:{minutes:.52,words:157},y:"a",t:"【elasticsearch】源码debug"},["/database/elasticsearch/elasticsearch源码debug.html","/database/elasticsearch/elasticsearch源码debug.md",":md"]],["v-3f2a15ee","/database/elasticsearch/%E3%80%90elasticsearch%E3%80%91%E6%90%9C%E7%B4%A2%E8%BF%87%E7%A8%8B%E8%AF%A6%E8%A7%A3.html",{d:1706183164e3,e:` 【elasticsearch】搜索过程详解
+本文基于elasticsearch8.1。在es搜索中,经常会使用索引+星号,采用时间戳来进行搜索,比如aaaa-*在es中是怎么处理这类请求的呢?是对匹配的进行搜索呢还是仅仅根据时间找出索引,然后才遍历索引进行搜索。在了解其原理前先了解一些基本知识。
+ SearchType
+QUERY_THEN_FETCH(默认):第一步,先向所有的shard发出请求,各分片只返回排序和排名相关的信息(注意,不包括文档document),然后按照各分片返回的分数进行重新排序和排名,取前size个文档。然后进行第二步,去相关的shard取document。这种方式返回的document与用户要求的size是相等的。
+DFS_QUERY_THEN_FETCH:比第1种方式多了一个初始化散发(initial scatter)步骤。
`,r:{minutes:8.92,words:2676},y:"a",t:"【elasticsearch】搜索过程详解"},["/database/elasticsearch/【elasticsearch】搜索过程详解.html","/database/elasticsearch/【elasticsearch】搜索过程详解.md",":md"]],["v-aa93dec0","/database/mysql/1mysql.html",{d:1706092222e3,e:` mysql
+img
+`,r:{minutes:.02,words:5},y:"a",t:"mysql"},[":md"]],["v-0a0b7a54","/database/mysql/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%BC%93%E5%AD%98.html",{d:1706092222e3,e:` 数据库缓存
+在MySQL 5.6开始,就已经默认禁用查询缓存了。在MySQL 8.0,就已经删除查询缓存功能了。
+将select语句和语句的结果做hash 映射关系后保存在一定的内存区域内。
+禁用原因:
+1.命中率低
+2.写时所有都失效
+禁用了:https://mp.weixin.qq.com/s/_EXXmciNdgXswSVzKyO4xg。
`,r:{minutes:.34,words:101},y:"a",t:"数据库缓存"},["/database/mysql/数据库缓存.html","/database/mysql/数据库缓存.md",":md"]],["v-137d5dcc","/database/redis/redis%E7%BC%93%E5%AD%98.html",{d:1706596625e3,e:` redis缓存
+ 一、概述
+ 1.1 缓存介绍
+系统的性能指标一般包括响应时间、延迟时间、吞吐量,并发用户数和资源利用率等。在应用运行过程中,我们有可能在一次数据库会话中,执行多次查询条件完全相同的SQL,MyBatis提供了一级缓存的方案优化这部分场景,如果是相同的SQL语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能。
+缓存常用语:
+数据不一致性、缓存更新机制、缓存可用性、缓存服务降级、缓存预热、缓存穿透
+可查看Redis实战(一) 使用缓存合理性
`,r:{minutes:12.08,words:3623},y:"a",t:"redis缓存"},["/database/redis/redis缓存.html","/database/redis/redis缓存.md",":md"]],["v-16aa42ca","/java/SpringBoot/Spring%20Boot%20Prometheus%E4%BD%BF%E7%94%A8.html",{d:1706363521e3,e:` Spring Boot Prometheus使用
+ 一、基本原理
+Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。
`,r:{minutes:3.49,words:1046},y:"a",t:"Spring Boot Prometheus使用"},["/java/SpringBoot/Spring Boot Prometheus使用.html","/java/SpringBoot/Spring Boot Prometheus使用.md",":md"]],["v-5089f9f3","/java/SpringBoot/aop.html",{d:1706596625e3,e:` AOP
+ 一、概述
+在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了。AOP关注的是横向的,而OOP的是纵向。
+ `,r:{minutes:7.17,words:2150},y:"a",t:"AOP"},[":md"]],["v-7586af98","/java/SpringBoot/webflux.html",{d:1706349103e3,e:` Webflux
+ 1.Servlet 3.1就已经支持异步非阻塞,为什么要用webflux?
+ChatGpt:
+Servlet 3.1 和 WebFlux 虽然底层都使用了 Java 的 NIO(非阻塞 IO),但是他们的编程模型和如何使用 NIO 是不同的,这也是导致他们性能差异的原因。
+Servlet 3.1:虽然 Servlet 3.1 支持非阻塞 IO,但是它的 API 设计仍然是基于传统的阻塞模型,这意味着每个请求通常会在一个单独的线程中处理,直到请求处理完成并返回响应。这种模型在并发请求数量较少的情况下工作得很好,但是在高并发的情况下,可能会因为线程数量过多而导致资源消耗过大,性能下降。
`,r:{minutes:3.07,words:921},y:"a",t:"Webflux"},[":md"]],["v-59449ba0","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html",{d:1706849761e3,e:` 1.历史与架构
+各位大佬瞄一眼我的个人网站 呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。
+大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。
`,r:{minutes:6.79,words:2038},y:"a",t:"1.历史与架构"},["/java/个人网站/1.历史与架构.html","/java/个人网站/1.历史与架构.md",":md"]],["v-2626dfde","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/10.%E5%8E%86%E6%97%B68%E5%B9%B4%E6%9C%80%E7%BB%88%E6%94%B9%E7%89%88.html",{d:1706849761e3,e:` 10.历时8年最终改版
+不知不觉,自建站https://www.wenzhihuai.com 已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。有时候因为要用服务器搞一些别的东西,直接没有备份数据库就重装,导致不少文章丢失,虽然别的平台可能零散分布。
`,r:{minutes:5.78,words:1733},y:"a",t:"10.历时8年最终改版"},["/java/个人网站/10.历时8年最终改版.html","/java/个人网站/10.历时8年最终改版.md",":md"]],["v-058e4a4b","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html",{d:1706849761e3,e:` 2.Lucene的使用
+首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。
`,r:{minutes:6.82,words:2046},y:"a",t:"2.Lucene的使用"},["/java/个人网站/2.Lucene的使用.html","/java/个人网站/2.Lucene的使用.md",":md"]],["v-411fdbb2","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html",{d:1706849761e3,e:` 3.定时任务
+先看一下Quartz的架构图:
+
+ 一.特点:
+
+强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;
+灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;
+分布式和集群能力。
+ `,r:{minutes:3.55,words:1064},y:"a",t:"3.定时任务"},["/java/个人网站/3.定时任务.html","/java/个人网站/3.定时任务.md",":md"]],["v-0d043462","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html",{d:1706849761e3,e:`
+欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
`,r:{minutes:9.64,words:2891},y:"a",t:"4.日志系统.md"},["/java/个人网站/4.日志系统.html","/java/个人网站/4.日志系统.md",":md"]],["v-6094ea20","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html",{d:1706849761e3,e:`
+欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com ,个人网站代码地址:https://github.com/Zephery/newblog 。
+洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。
`,r:{minutes:9.5,words:2849},y:"a",t:"5.小集群部署.md"},["/java/个人网站/5.小集群部署.html","/java/个人网站/5.小集群部署.md",":md"]],["v-68e11d4e","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html",{d:1706849761e3,e:` 6.数据库备份
+先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地:
+
+由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下:
`,r:{minutes:5.77,words:1732},y:"a",t:"6.数据库备份"},["/java/个人网站/6.数据库备份.html","/java/个人网站/6.数据库备份.md",":md"]],["v-1f1952ea","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html",{d:1706849761e3,e:` 7.那些牛逼的插件
+欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
+建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Java的程序员,前端的东西一碰脑子就有“我又不是前端,浪费时间在这合适么?”这种想法,捣鼓来捣鼓去,做出的东西实在是没法看,我就觉得,如果自己的“产品”连自己都看不下去了,那还好意思给别人看?特别是留言板那块,初版的页面简直low的要死。所以,还是踏踏实实的“站在巨人的肩膀上”吧,改用别人的插件。但不要纯粹的使用别人的博客模板了,如hexo,wordpress这些,就算是自己拼凑过来的也比这些强。下面是本博客中所用到的插件,给大家介绍介绍,共同学习学习。
+本站主要用到的插件有:
+1.wowslider
+2.畅言
+3.Editor.md
+4.highchart、echart
+5.百度分享
+6.waterfall.js
+7.心知天气
+8.标签云
`,r:{minutes:7.24,words:2173},y:"a",t:"7.那些牛逼的插件"},["/java/个人网站/7.那些牛逼的插件.html","/java/个人网站/7.那些牛逼的插件.md",":md"]],["v-6dc450d0","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/8.%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%9A%84%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90.html",{d:1706849761e3,e:` 8.基于贝叶斯的情感分析
+`,r:{minutes:.04,words:11},y:"a",t:"8.基于贝叶斯的情感分析"},["/java/个人网站/8.基于贝叶斯的情感分析.html","/java/个人网站/8.基于贝叶斯的情感分析.md",":md"]],["v-44460f42","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html",{d:1706849761e3,e:` 9.网站性能优化
+`,r:{minutes:.02,words:7},y:"a",t:"9.网站性能优化"},["/java/个人网站/9.网站性能优化.html","/java/个人网站/9.网站性能优化.md",":md"]],["v-d7d7df80","/middleware/kafka/kafka.html",{d:1706204085e3,e:` kafka面试题
+1、请说明什么是Apache Kafka?
+Apache Kafka是由Apache开发的一种发布订阅消息系统,它是一个分布式的、分区的和可复制的提交日志服务。
+2、说说Kafka的使用场景?
+①异步处理
+②应用解耦
+③流量削峰
+④日志处理
+⑤消息通讯等。
+3、使用Kafka有什么优点和缺点?
+优点:
+①支持跨数据中心的消息复制;
+②单机吞吐量:十万级,最大的优点,就是吞吐量高;
+③topic数量都吞吐量的影响:topic从几十个到几百个的时候,吞吐量会大幅度下降。所以在同等机器下,kafka尽量保证topic数量不要过多。如果要支撑大规模topic,需要增加更多的机器资源;
+④时效性:ms级;
+⑤可用性:非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用;
+⑥消息可靠性:经过参数优化配置,消息可以做到0丢失;
+⑦功能支持:功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用。
`,r:{minutes:17.01,words:5103},y:"a",t:"kafka面试题"},[":md"]],["v-7d9b9318","/middleware/zookeeper/zookeeper.html",{d:1706204085e3,e:` Zookeeper
+留空
+`,r:{minutes:.01,words:3},y:"a",t:"Zookeeper"},[":md"]],["v-3706649a","/404.html",{y:"p",t:""},[]],["v-71b3ae87","/interview/",{y:"p",t:"Interview"},[]],["v-14c69af4","/java/",{y:"p",t:"Java"},[]],["v-14e6315a","/life/",{y:"p",t:"Life"},[]],["v-14e6501c","/link/",{y:"p",t:"Link"},[]],["v-25b47c13","/others/",{y:"p",t:"Others"},[]],["v-5d3e6196","/about-the-author/personal-life/",{y:"p",t:"Personal Life"},[]],["v-3e13af88","/about-the-author/works/",{y:"p",t:"Works"},[]],["v-60fc7530","/bigdata/spark/",{y:"p",t:"Spark"},[]],["v-02bc92be","/bigdata/",{y:"p",t:"Bigdata"},[]],["v-380c630d","/database/elasticsearch/",{y:"p",t:"Elasticsearch"},[]],["v-21ba2ec8","/database/mysql/",{y:"p",t:"Mysql"},[]],["v-2921a50f","/database/redis/",{y:"p",t:"Redis"},[]],["v-862c4448","/java/SpringBoot/",{y:"p",t:"Spring Boot"},[]],["v-0b6dfb7c","/java/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/",{y:"p",t:"个人网站"},["/java/个人网站/"]],["v-a32329e6","/middleware/kafka/",{y:"p",t:"Kafka"},[]],["v-4d194044","/middleware/",{y:"p",t:"Middleware"},[]],["v-6e21a4b2","/middleware/zookeeper/",{y:"p",t:"Zookeeper"},[]],["v-5bc93818","/category/",{y:"p",t:"分类",I:!1},[]],["v-744d024e","/tag/",{y:"p",t:"标签",I:!1},[]],["v-e52c881c","/article/",{y:"p",t:"文章",I:!1},[]],["v-154dc4c4","/star/",{y:"p",t:"星标",I:!1},[]],["v-01560935","/timeline/",{y:"p",t:"时间轴",I:!1},[]]];var Si=V({name:"Vuepress",setup(){const e=Rf();return()=>i(e.value)}}),W3=()=>K3.reduce((e,[t,n,r,a])=>(e.push({name:t,path:n,component:Si,meta:r},{path:n.endsWith("/")?n+"index.html":n.substring(0,n.length-5),redirect:n},...a.map(l=>({path:l===":md"?n.substring(0,n.length-5)+".md":l,redirect:n}))),e),[{name:"404",path:"/:catchAll(.*)",component:Si}]),J3=lp,Y3=()=>{const e=zp({history:J3(Il("/")),routes:W3(),scrollBehavior:(t,n,r)=>r||(t.hash?{el:t.hash}:{top:0})});return e.beforeResolve(async(t,n)=>{var r;(t.path!==n.path||n===Et)&&([t.meta._data]=await Promise.all([yt.resolvePageData(t.name),(r=Rs[t.name])==null?void 0:r.__asyncLoader()]))}),e},Z3=e=>{e.component("ClientOnly",oa),e.component("Content",Hs)},Q3=(e,t,n)=>{const r=di(()=>t.currentRoute.value.path),a=di(()=>yt.resolveRouteLocale(cn.value.locales,r.value)),l=$l(r,()=>t.currentRoute.value.meta._data),o=E(()=>yt.resolveLayouts(n)),s=E(()=>yt.resolveSiteLocaleData(cn.value,a.value)),c=E(()=>yt.resolvePageFrontmatter(l.value)),u=E(()=>yt.resolvePageHeadTitle(l.value,s.value)),d=E(()=>yt.resolvePageHead(u.value,c.value,s.value)),f=E(()=>yt.resolvePageLang(l.value,s.value)),p=E(()=>yt.resolvePageLayout(l.value,o.value));return e.provide(If,o),e.provide(Ms,l),e.provide(Fs,c),e.provide(Df,u),e.provide(Vs,d),e.provide($s,f),e.provide(js,p),e.provide(Ol,a),e.provide(zs,s),Object.defineProperties(e.config.globalProperties,{$frontmatter:{get:()=>c.value},$head:{get:()=>d.value},$headTitle:{get:()=>u.value},$lang:{get:()=>f.value},$page:{get:()=>l.value},$routeLocale:{get:()=>a.value},$site:{get:()=>cn.value},$siteLocale:{get:()=>s.value},$withBase:{get:()=>Le}}),{layouts:o,pageData:l,pageFrontmatter:c,pageHead:d,pageHeadTitle:u,pageLang:f,pageLayout:p,routeLocale:a,siteData:cn,siteLocaleData:s}},X3=()=>{const e=Of(),t=Pl(),n=X([]),r=()=>{e.value.forEach(l=>{const o=ev(l);o&&n.value.push(o)})},a=()=>{document.documentElement.lang=t.value,n.value.forEach(l=>{l.parentNode===document.head&&document.head.removeChild(l)}),n.value.splice(0,n.value.length),e.value.forEach(l=>{const o=tv(l);o!==null&&(document.head.appendChild(o),n.value.push(o))})};it(Ff,a),Ee(()=>{r(),a(),ye(()=>e.value,a)})},ev=([e,t,n=""])=>{const r=Object.entries(t).map(([s,c])=>oe(c)?`[${s}=${JSON.stringify(c)}]`:c===!0?`[${s}]`:"").join(""),a=`head > ${e}${r}`;return Array.from(document.querySelectorAll(a)).find(s=>s.innerText===n)||null},tv=([e,t,n])=>{if(!oe(e))return null;const r=document.createElement(e);return Cl(t)&&Object.entries(t).forEach(([a,l])=>{oe(l)?r.setAttribute(a,l):l===!0&&r.setAttribute(a,"")}),oe(n)&&r.appendChild(document.createTextNode(n)),r},nv=_f,rv=async()=>{var n;const e=nv({name:"VuepressApp",setup(){var r;X3();for(const a of Pr)(r=a.setup)==null||r.call(a);return()=>[i(ec),...Pr.flatMap(({rootComponents:a=[]})=>a.map(l=>i(l)))]}}),t=Y3();Z3(e),Q3(e,t,Pr);for(const r of Pr)await((n=r.enhance)==null?void 0:n.call(r,{app:e,router:t,siteData:cn}));return e.use(t),{app:e,router:t}};rv().then(({app:e,router:t})=>{t.isReady().then(()=>{e.mount("#app")})});export{G2 as _,la as a,Be as b,av as c,rv as createVueApp,ks as d,lv as e,L1 as o,He as r,za as w};
+function __vite__mapDeps(indexes) {
+ if (!__vite__mapDeps.viteFileDeps) {
+ __vite__mapDeps.viteFileDeps = []
+ }
+ return indexes.map((i) => __vite__mapDeps.viteFileDeps[i])
+}
diff --git a/assets/chatgpt.html-soLgBokY.js b/assets/chatgpt.html-soLgBokY.js
new file mode 100644
index 00000000..6bcaf260
--- /dev/null
+++ b/assets/chatgpt.html-soLgBokY.js
@@ -0,0 +1 @@
+const t=JSON.parse('{"key":"v-510415f9","path":"/others/chatgpt.html","title":"微信公众号-chatgpt智能客服搭建","lang":"zh-CN","frontmatter":{"description":"微信公众号-chatgpt智能客服搭建 想体验的可以去微信上搜索【旅行的树】公众号。 一、ChatGPT注册 1.1 短信手机号申请 openai提供服务的区域,美国最好,这个解决办法是搞个翻墙,或者买一台美国的服务器更好。 国外邮箱,hotmail或者google最好,qq邮箱可能会对这些平台进行邮件过滤。 国外手机号,没有的话也可以去https://sms-activate.org,费用大概需要1美元,这个网站记得也用国外邮箱注册,需要先充值,使用支付宝支付。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/others/chatgpt.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"微信公众号-chatgpt智能客服搭建"}],["meta",{"property":"og:description","content":"微信公众号-chatgpt智能客服搭建 想体验的可以去微信上搜索【旅行的树】公众号。 一、ChatGPT注册 1.1 短信手机号申请 openai提供服务的区域,美国最好,这个解决办法是搞个翻墙,或者买一台美国的服务器更好。 国外邮箱,hotmail或者google最好,qq邮箱可能会对这些平台进行邮件过滤。 国外手机号,没有的话也可以去https://sms-activate.org,费用大概需要1美元,这个网站记得也用国外邮箱注册,需要先充值,使用支付宝支付。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-26T03:58:56.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-26T03:58:56.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"微信公众号-chatgpt智能客服搭建\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-26T03:58:56.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、ChatGPT注册","slug":"一、chatgpt注册","link":"#一、chatgpt注册","children":[{"level":3,"title":"1.1 短信手机号申请","slug":"_1-1-短信手机号申请","link":"#_1-1-短信手机号申请","children":[]},{"level":3,"title":"1.2 云服务器申请","slug":"_1-2-云服务器申请","link":"#_1-2-云服务器申请","children":[]},{"level":3,"title":"1.3 ChatGPT注册","slug":"_1-3-chatgpt注册","link":"#_1-3-chatgpt注册","children":[]}]},{"level":2,"title":"二、搭建nginx服务器","slug":"二、搭建nginx服务器","link":"#二、搭建nginx服务器","children":[]},{"level":2,"title":"三、公众号开发","slug":"三、公众号开发","link":"#三、公众号开发","children":[{"level":3,"title":"3.1 微信云托管","slug":"_3-1-微信云托管","link":"#_3-1-微信云托管","children":[]},{"level":3,"title":"3.2 一个简单ChatGPT简单回复","slug":"_3-2-一个简单chatgpt简单回复","link":"#_3-2-一个简单chatgpt简单回复","children":[]},{"level":3,"title":"3.3 服务部署","slug":"_3-3-服务部署","link":"#_3-3-服务部署","children":[]}]},{"level":2,"title":"四、没有回复(超时回复问题)","slug":"四、没有回复-超时回复问题","link":"#四、没有回复-超时回复问题","children":[]},{"level":2,"title":"五、会话保存","slug":"五、会话保存","link":"#五、会话保存","children":[]},{"level":2,"title":"六、其他问题","slug":"六、其他问题","link":"#六、其他问题","children":[{"level":3,"title":"6.1 限频","slug":"_6-1-限频","link":"#_6-1-限频","children":[]},{"level":3,"title":"6.2 秘钥key被更新","slug":"_6-2-秘钥key被更新","link":"#_6-2-秘钥key被更新","children":[]},{"level":3,"title":"6.3 为啥和官网的回复不一样","slug":"_6-3-为啥和官网的回复不一样","link":"#_6-3-为啥和官网的回复不一样","children":[]},{"level":3,"title":"6.4 玄学挂掉","slug":"_6-4-玄学挂掉","link":"#_6-4-玄学挂掉","children":[]}]},{"level":2,"title":"最后","slug":"最后","link":"#最后","children":[]}],"git":{"createdTime":1706186538000,"updatedTime":1706241536000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":5}]},"readingTime":{"minutes":9.96,"words":2987},"filePathRelative":"others/chatgpt.md","localizedDate":"2024年1月25日","excerpt":" 微信公众号-chatgpt智能客服搭建 \\n想体验的可以去微信上搜索【旅行的树】公众号。
\\n 一、ChatGPT注册 \\n 1.1 短信手机号申请 \\nopenai提供服务的区域,美国最好,这个解决办法是搞个翻墙,或者买一台美国的服务器更好。
\\n国外邮箱,hotmail或者google最好,qq邮箱可能会对这些平台进行邮件过滤。
\\n国外手机号,没有的话也可以去https://sms-activate.org ,费用大概需要1美元,这个网站记得也用国外邮箱注册,需要先充值,使用支付宝支付。
","autoDesc":true}');export{t as data};
diff --git a/assets/chatgpt.html-tmuTnMCN.js b/assets/chatgpt.html-tmuTnMCN.js
new file mode 100644
index 00000000..0ac235f6
--- /dev/null
+++ b/assets/chatgpt.html-tmuTnMCN.js
@@ -0,0 +1,110 @@
+import{_ as p,r as o,o as i,c,a as n,d as s,b as e,e as t}from"./app-BDpQ7oW_.js";const l={},r=t(' 微信公众号-chatgpt智能客服搭建 想体验的可以去微信上搜索【旅行的树】公众号。
一、ChatGPT注册 1.1 短信手机号申请 openai提供服务的区域,美国最好,这个解决办法是搞个翻墙,或者买一台美国的服务器更好。
国外邮箱,hotmail或者google最好,qq邮箱可能会对这些平台进行邮件过滤。
',6),u={href:"https://sms-activate.org",target:"_blank",rel:"noopener noreferrer"},d=t('之后再搜索框填openai进行下单购买即可。
1.2 云服务器申请 openai在国内不提供服务的,而且也通过ip识别是不是在国内,解决办法用vpn也行,或者,自己去买一台国外的服务器也行。我这里使用的是腾讯云轻量服务器,最低配置54元/月,选择windows的主要原因毕竟需要注册openai,需要看页面,同时也可以搭建nginx,当然,用ubuntu如果能自己搞界面也行。
1.3 ChatGPT注册 ',7),k={href:"https://platform.openai.com/signup%E5%AE%98%E7%BD%91%E9%87%8C%E6%B3%A8%E5%86%8C%EF%BC%8C%E6%B3%A8%E5%86%8C%E8%BF%87%E7%A8%8B%E5%85%B7%E4%BD%93%E5%B0%B1%E4%B8%8D%E8%AE%B2%E4%BA%86%EF%BC%8C%E8%AE%B2%E4%B8%8B%E6%A0%B8%E5%BF%83%E9%97%AE%E9%A2%98%E2%80%94%E2%80%94%E7%9F%AD%E4%BF%A1%E9%AA%8C%E8%AF%81%E7%A0%81",target:"_blank",rel:"noopener noreferrer"},m=t(`然后回sms查看验证码。
注册成功之后就可以在chatgpt里聊天啦,能够识别各种语言,发起多轮会话的时候,可能回出现访问超过限制什么的。
通过chatgpt聊天不是我们最终想要的,我们需要的是在微信公众号也提供智能客服的聊天回复,所以我们需要在通过openai的api来进行调用。
二、搭建nginx服务器 跟页面一样,OpenAI的调用也是不能再国内访问的,这里,我们使用同一台服务器来搭建nginx,还是保留使用windows吧,主要还是得注意下面这段话,如果API key被泄露了,OpenAI可能会自动重新更新你的API key,这个规则似乎是API key如果被多个ip使用,就会触发这个规则,调试阶段还是尽量使用windows的服务器吧,万一被更新了,还能去页面上重新找到。
Do not share your API key with others, or expose it in the browser or other client-side code. In order to protect the security of your account, OpenAI may also automatically rotate any API key that we've found has leaked publicly.
+
windows的安装过程参考网上的来,我们只需要添加下面这个配置即可,原理主要是将调用OpenAI的接口全部往官网转发。
location /v1/completions {
+ proxy_pass https://api.openai.com/v1/completions;
+ }
+
然后使用下面的方法进行调试即可:
POST http://YOUR IP/v1/completions
+
+
+
+{
+ "model" : "text-davinci-003" ,
+ "prompt" : "Say this is a test" ,
+ "max_tokens" : 7 ,
+ "temperature" : 0
+}
+
三、公众号开发 网上有很多关于微信通过chatgpt回复的文章,有些使用自己微信号直接做为载体,因为要扫码网页登陆,而且是网页端在国外,很容易被封;有些是使用公众号,相对来说,公众号被封也不至于导致个人微信号出问题。
3.1 微信云托管 微信公众平台提供了微信云托管,无需鉴权,比其他方式都方便不少,可以免费试用3个月,继续薅羊毛,当然,如果自己开发能力足够,也可以自己从0开始开发。
提供了各种语言的模版,方便快速开发,OpenAI官方提供的sdk是node和python,这里我们选择express(node)。
3.2 一个简单ChatGPT简单回复 `,22),v={href:"https://github.com/WeixinCloud/wxcloudrun-express%EF%BC%8C%E6%88%91%E4%BB%AC%E7%9B%B4%E6%8E%A5fork%E4%B8%80%E4%BB%BD%E8%87%AA%E5%B7%B1%E6%9D%A5%E5%BC%80%E5%8F%91%E3%80%82",target:"_blank",rel:"noopener noreferrer"},h=t(`一个简单的消息回复功能(无db),直接在我们的index.js里添加如下代码。
const configuration = new Configuration ( {
+ apiKey : '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' ,
+ basePath : 'http://43.153.15.174/v1'
+} ) ;
+const openai = new OpenAIApi ( configuration) ;
+
+async function simpleResponse ( prompt ) {
+ const completion = await openai. createCompletion ( {
+ model : 'text-davinci-003' ,
+ prompt,
+ max_tokens : 1024 ,
+ temperature : 0.1 ,
+ } ) ;
+ const response = ( completion?. data?. choices?. [ 0 ] . text || 'AI 挂了' ) . trim ( ) ;
+ return strip ( response, [ '\\n' , 'A: ' ] ) ;
+}
+
+app. post ( "/message/simple" , async ( req, res ) => {
+ console. log ( '消息推送' , req. body)
+
+ const appid = req. headers[ 'x-wx-from-appid' ] || ''
+ const { ToUserName, FromUserName, MsgType, Content, CreateTime} = req. body
+ console. log ( '推送接收的账号' , ToUserName, '创建时间' , CreateTime)
+ if ( MsgType === 'text' ) {
+ message = await simpleResponse ( Content)
+ res. send ( {
+ ToUserName : FromUserName,
+ FromUserName : ToUserName,
+ CreateTime : CreateTime,
+ MsgType : 'text' ,
+ Content : message,
+ } )
+ } else {
+ res. send ( 'success' )
+ }
+} )
+
本地可以直接使用http请求测试,成功调用之后直接提交发布即可,在微信云托管上需要先授权代码库,即可使用云托管的流水线,一键发布。注意,api_base和api_key可以填写在服务设置-基础信息那里,一个是OPENAI_API_BASE,一个是OPENAI_API_KEY,服务会自动从环境变量里取。
3.3 服务部署 提交代码只github或者gitee都可以,值得注意的是,OpenAI判断key泄露的规则,不知道是不是判断调用的ip地址不一样,还是github的提交记录里含有这块,有点玄学,同样的key本地调用一次,然后在云托管也调用的话,OpenAI就很容易把key给重新更新。
部署完之后,云托管也提供了云端调试功能,相当于在服务里发送了http请求。这一步很重要,如果没有调用成功,则无法进行云托管消息推送。
这里填上你自己的url,我们这里配置的是/meesage/simple,如果没有成功,需要进行下面步骤进行排查:
(1)服务有没有正常启动,看日志
(2)端口有没有设置错误,这个很多次没有注意到
保存成功之后,就可以在微信公众号里测试了。
体验还可以
四、没有回复(超时回复问题) 很多OpenAI的回答都要几十秒,有的甚至更久,比如对chatgpt问“写一篇1000字关于深圳的文章”,就需要几十秒,而微信的主动回复接口,是需要我们3s内返回给用户。
订阅号的消息推送分几种:
被动消息回复 :指用户给公众号发一条消息,系统接收到后,可以回复一条消息。主动回复/客服消息 :可以脱离被动消息的5秒超时权限,在48小时内可以主动回复。但需要公众号完成微信认证。 `,19),g={href:"https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Explanation_of_interface_privileges.html",target:"_blank",rel:"noopener noreferrer"},b=t(`对于有微信认证的订阅号或者服务号,可以调用微信官方的/cgi-bin/message/custom/send接口来实现主动回复,但是对于个人的公众号,没有权限调用,只能尝试别的办法。想来想去,只能在3s内返回让用户重新复制发送的信息,同时后台里保存记录异步调用,用户重新发送的时候再从数据库里提取回复。
1.先往数据库存一条 回复记录,把用户的提问存下来,以便后续查询。设置回复的内容为空,设置状态为 回复中(thinking)。
+ await Message. create ( {
+ fromUser : FromUserName,
+ response : '' ,
+ request : Content,
+ aiType : AI_TYPE_TEXT ,
+ } ) ;
+
2.抽象一个 chatGPT 请求方法 getAIMessage
,函数内部得到 GPT 响应后,会更新之前那条记录(通过用户id & 用户提问 查询),把状态更新为 已回答(answered),并把回复内容更新上。
+ await Message. update (
+ {
+ response : response,
+ status : MESSAGE_STATUS_ANSWERED ,
+ } ,
+ {
+ where : {
+ fromUser : FromUserName,
+ request : Content,
+ } ,
+ } ,
+ ) ;
+
3.前置增加一些判断,当用户在请求时,如果 AI 还没完成响应,直接回复用户 AI 还在响应,让用户过一会儿再重试。如果 AI 此时已响应完成,则直接把 内容返回给用户。
+ const message = await Message. findOne ( {
+ where : {
+ fromUser : FromUserName,
+ request : Content,
+ } ,
+ } ) ;
+
+
+ if ( message?. status === MESSAGE_STATUS_ANSWERED ) {
+ return \` [GPT]: \${ message?. response} \` ;
+ }
+
+
+ if ( message?. status === MESSAGE_STATUS_THINKING ) {
+ return AI_THINKING_MESSAGE ;
+ }
+
4.最后就是一个 Promise.race
const message = await Promise. race ( [
+
+ sleep ( 2900 ) . then ( ( ) => AI_THINKING_MESSAGE ) ,
+ getAIMessage ( { Content, FromUserName } ) ,
+ ] ) ;
+
这样子大概就能实现超时之前返回了。
五、会话保存 掉接口是一次性的,一次接口调用完之后怎么做到下一次通话的时候,还能继续保持会话,是不是应该类似客户端与服务端那种有个session这种,但是实际上在openai里是没有session这种东西的,令人震惊的是,chatgpt里是通过前几次会话拼接起来一起发送给chatgpt里的,需要通过回车符来拼接。
async function buildCtxPrompt ( { FromUserName } ) {
+
+ const messages = await Message. findAll ( {
+ where : {
+ fromUser : FromUserName,
+ aiType : AI_TYPE_TEXT ,
+ } ,
+ limit : 10 ,
+ order : [ [ 'updatedAt' , 'ASC' ] ] ,
+ } ) ;
+
+ return messages. length === 1
+ ? messages[ 0 ] . request
+ : messages
+ . map ( ( { response, request } ) => \` Q: \${ request} \\n A: \${ response} \` )
+ . join ( '\\n' ) ;
+}
+
之后就可以实现会话之间的保存通信了。
六、其他问题 6.1 限频 chatgpt毕竟也是新上线的,火热是肯定的,聊天窗口只能开几个,api调用的话,也是有限频的,但是规则具体没有找到,只是在调用次数过多的时候会报429的错误,出现之后就需要等待一个小时左右。
对于这个的解决办法只能是多开几个账号,一旦429就只能换个账号重试了。
6.2 秘钥key被更新 没有找到详细的规则,凭个人经验的话,可能github提交的代码会被扫描,可能ip调用的来源不一样,最好还是开发一个秘钥,生产一个秘钥吧。
6.3 为啥和官网的回复不一样 `,23),y={href:"https://platform.openai.com/docs/models/overview%EF%BC%8C%E4%B9%9F%E7%AE%97%E6%98%AF%E4%B8%80%E4%B8%AA%E6%AF%94%E8%BE%83%E8%80%81%E7%9A%84%E6%A0%B7%E6%9C%AC%E4%BA%86%E5%90%A7",target:"_blank",rel:"noopener noreferrer"},_=n("img",{src:"https://github-images.wenzhihuai.com/images/qh4efq.png",alt:"image-20230221192417900",style:{zoom:"50%"}},null,-1),f=n("code",null,"text-davinci-003",-1),E={href:"https://link.juejin.cn/?target=https%3A%2F%2Fplatform.openai.com%2Fdocs%2Fguides%2Ffine-tuning",target:"_blank",rel:"noopener noreferrer"},w=n("h3",{id:"_6-4-玄学挂掉",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_6-4-玄学挂掉","aria-hidden":"true"},"#"),s(" 6.4 玄学挂掉")],-1),A=n("p",null,"有时候消息没有回复,真的不是我们的问题,chatgpt毕竟太火了,官网的这个能力都经常挂掉,也可以订阅官网修复的通知,一旦修复则会发邮件告知你。",-1),x=n("img",{src:"https://github-images.wenzhihuai.com/images/4hod0s.png",alt:"image-20230221175150025",style:{zoom:"50%"}},null,-1),B={href:"https://juejin.cn/post/7200769439335546935",target:"_blank",rel:"noopener noreferrer"},I=n("h2",{id:"最后",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#最后","aria-hidden":"true"},"#"),s(" 最后")],-1),z=n("br",null,null,-1),C={href:"https://github.com/Zephery/wechat-gpt",target:"_blank",rel:"noopener noreferrer"};function T(q,j){const a=o("ExternalLinkIcon");return i(),c("div",null,[r,n("p",null,[s("国外手机号,没有的话也可以去"),n("a",u,[s("https://sms-activate.org"),e(a)]),s(",费用大概需要1美元,这个网站记得也用国外邮箱注册,需要先充值,使用支付宝支付。")]),d,n("p",null,[s("购买完之后,就可以直接打开openai的官网了,然后去"),n("a",k,[s("https://platform.openai.com/signup官网里注册,注册过程具体就不讲了,讲下核心问题——短信验证码"),e(a)])]),m,n("p",null,[s("微信官方的源码在这,"),n("a",v,[s("https://github.com/WeixinCloud/wxcloudrun-express,我们直接fork一份自己来开发。"),e(a)])]),h,n("p",null,[s("根据微信官方文档,没有认证的公众号是没有调用主动回复接口权限的,"),n("a",g,[s("https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Explanation_of_interface_privileges.html"),e(a)])]),b,n("p",null,[s("我们这里用的模型算法是text-davinci-003,具体可以参考:"),n("a",y,[s("https://platform.openai.com/docs/models/overview,也算是一个比较老的样本了吧"),e(a)])]),_,n("p",null,[s("从官方文档来看,官方服务版的 ChatGPT 的模型并非基础版的"),f,s(",而是经过了「微调:fine-tunes」。文档地址在这:"),n("a",E,[s("platform.openai.com/docs/guides…"),e(a)])]),w,A,x,n("p",null,[s("参考:"),n("a",B,[s("https://juejin.cn/post/7200769439335546935"),e(a)])]),I,n("p",null,[s("记得去微信关注【旅行的树】公众号体验"),z,s(" 代码地址:"),n("a",C,[s("https://github.com/Zephery/wechat-gpt"),e(a)])])])}const N=p(l,[["render",T],["__file","chatgpt.html.vue"]]);export{N as default};
diff --git a/assets/devops-ping-tai.html-1QswvRRV.js b/assets/devops-ping-tai.html-1QswvRRV.js
new file mode 100644
index 00000000..30828d80
--- /dev/null
+++ b/assets/devops-ping-tai.html-1QswvRRV.js
@@ -0,0 +1,246 @@
+import{_ as i,r as l,o as p,c,a as n,d as s,b as e,e as t}from"./app-BDpQ7oW_.js";const o={},u={id:"_3-1-devops平台-md",tabindex:"-1"},d=n("a",{class:"header-anchor",href:"#_3-1-devops平台-md","aria-hidden":"true"},"#",-1),r={href:"http://xn--DevOps-gc6jn80e.md",target:"_blank",rel:"noopener noreferrer"},v=n("p",null,"DevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。",-1),m=n("p",null,"公司技术部目前几百人左右吧,但是整个技术栈还是比较落后的,尤其是DevOps、容器这一块,需要将全线打通,当时进来也主要是负责DevOps这一块的工作,应该说也是没怎么做好,其中也走了不少弯路,下面主要是自己踩过的坑吧。",-1),g=n("h2",{id:"一、自由风格的软件项目",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#一、自由风格的软件项目","aria-hidden":"true"},"#"),s(" 一、自由风格的软件项目")],-1),k={href:"https://www.cnblogs.com/w1570631036/p/9861473.html",target:"_blank",rel:"noopener noreferrer"},b=t(`完成了以上的东西,不过由于太过于简单,导致只能进行单条线的CICD,而且CI仅仅实现了打包,没有将CD的过程一同串行起来。简单来说就是,用户点击了构建只是能够打出一个镜像,但是如果要部署到kubernetes,还是需要在应用里手动更换一下镜像版本。总体而言,这个版本的jenkins我们使用的还是单点的,不足以支撑构建量比较大的情况,甚至如果当前服务挂了,断网了,整一块的构建功能都不能用。
< project>
+ < actions/>
+ < description> xxx</ description>
+ < properties>
+ < hudson.model.ParametersDefinitionProperty>
+ < parameterDefinitions>
+ < hudson.model.TextParameterDefinition>
+ < name> buildParam</ name>
+ < defaultValue> v1</ defaultValue>
+ </ hudson.model.TextParameterDefinition>
+ < hudson.model.TextParameterDefinition>
+ < name> codeBranch</ name>
+ < defaultValue> master</ defaultValue>
+ </ hudson.model.TextParameterDefinition>
+ </ parameterDefinitions>
+ </ hudson.model.ParametersDefinitionProperty>
+ </ properties>
+ < scm class = " hudson.plugins.git.GitSCM" >
+ < configVersion> 2</ configVersion>
+ < userRemoteConfigs>
+ < hudson.plugins.git.UserRemoteConfig>
+ < url> http://xxxxx.git</ url>
+ < credentialsId> 002367566a4eb4bb016a4eb723550054</ credentialsId>
+ </ hudson.plugins.git.UserRemoteConfig>
+ </ userRemoteConfigs>
+ < branches>
+ < hudson.plugins.git.BranchSpec>
+ < name> \${codeBranch}</ name>
+ </ hudson.plugins.git.BranchSpec>
+ </ branches>
+ < doGenerateSubmoduleConfigurations> false</ doGenerateSubmoduleConfigurations>
+ < extensions/>
+ </ scm>
+ < builders>
+ < hudson.tasks.Shell>
+ < command> ls</ command>
+ </ hudson.tasks.Shell>
+ < hudson.tasks.Maven>
+ < targets> clean package install -Dmaven.test.skip=true</ targets>
+ < mavenName> mvn3.5.4</ mavenName>
+ </ hudson.tasks.Maven>
+ < com.cloudbees.dockerpublish.DockerBuilder>
+ < server>
+ < uri> unix:///var/run/docker.sock</ uri>
+ </ server>
+ < registry>
+ < url> http://xxxx</ url>
+ </ registry>
+ < repoName> xxx/xx</ repoName>
+ < forcePull> true</ forcePull>
+ < dockerfilePath> Dockerfile</ dockerfilePath>
+ < repoTag> \${buildParam}</ repoTag>
+ < skipTagLatest> true</ skipTagLatest>
+ </ com.cloudbees.dockerpublish.DockerBuilder>
+ </ builders>
+ < publishers>
+ < com.xxxx.notifications.Notifier/>
+ </ publishers>
+</ project>
+
二、优化之后的CICD 上面的过程也仍然没有没住DevOps的流程,人工干预的东西依旧很多,由于上级急需产出,所以只能将就着继续下去。我们将构建、部署每个当做一个小块,一个CICD的过程可以选择构建、部署,花了很大的精力,完成了串行化的别样的CICD。 以下图为例,整个流程的底层为:paas平台-jenkins-kakfa-管理平台(选择cicd的下一步)-kafka-cicd组件调用管理平台触发构建-jenkins-kafka-管理平台(选择cicd的下一步)-kafka-cicd组件调用管理平台触发部署。
目前实现了串行化的CICD构建部署,之后考虑实现多个CICD并行,并且一个CICD能够调用另一个CICD,实际运行中,出现了一大堆问题。由于经过的组件太多,一次cicd的运行报错,却很难排查到问题出现的原因,业务方的投诉也开始慢慢多了起来,只能说劝导他们不要用这个功能。
没有CICD,就无法帮助公司上容器云,无法合理的利用容器云的特性,更无法走上云原生的道路。于是,我们决定另谋出路。
三、调研期 由于之前的CICD问题太多,特别是经过的组件太多了,导致出现问题的时候无法正常排查,为了能够更加稳定可靠,还是决定了要更换一下底层。 我们重新审视了下pipeline,觉得这才是正确的做法,可惜不知道如果做成一个产品样子的东西,用户方Dockerfile都不怎么会写,你让他写一个Jenkinsfile?不合理!在此之外,我们看到了serverless jenkins、谷歌的tekton。 GitLab-CICD Gitlab中自带了cicd的工具,需要配置一下runner,然后配置一下.gitlab-ci.yml写一下程序的cicd过程即可,构建镜像的时候我们使用的是kaniko,整个gitlab的cicd在我们公司小项目中大范围使用,但是学习成本过高,尤其是引入了kaniko之后,还是寻找一个产品化的CICD方案。
`,9),h=n("strong",null,"分布式构建jenkins x",-1),x={href:"https://github.com/jenkins-x/jenkins-x-image",target:"_blank",rel:"noopener noreferrer"},f=n("figure",null,[n("img",{src:"http://image.wenzhihuai.com/images/201908170612301464716259.png",alt:"",tabindex:"0"}),n("figcaption")],-1),q=n("p",null,[n("strong",null,"serverless jenkins"),s(" 好像跟谷歌的tekton相关,用了下,没调通,只能用于GitHub。感觉还不如直接使用tekton。")],-1),_=n("p",null,[n("strong",null,"阿里云云效"),s(" 提供了图形化配置DevOps流程,支持定时触发,可惜没有跟gitlab触发结合,如果需要个公司级的DevOps,需要将公司的jira、gitlab、jenkins等集合起来,但是图形化jenkins pipeline是个特别好的参考方向,可以结合阿里云云效来做一个自己的DevOps产品。")],-1),D=n("p",null,[n("strong",null,"微软Pipeline"),s(" 微软也是提供了DevOps解决方案的,也是提供了yaml格式的写法,即:在右边填写完之后会转化成yaml。如果想把DevOps打造成一款产品,这样的设计显然不是最好的。")],-1),j=n("figure",null,[n("img",{src:"http://image.wenzhihuai.com/images/201908100346011648784131.png",alt:"",tabindex:"0"}),n("figcaption")],-1),C=n("strong",null,"谷歌tekton",-1),w={href:"https://www.jianshu.com/p/8871b7ea7d6e",target:"_blank",rel:"noopener noreferrer"},y=t(` 四、产品化后的DevOps平台 在调研DockOne以及各个产商的DevOps产品时,发现,真的只有阿里云的云效才是真正比较完美的DevOps产品,用户不需要知道pipeline的语法,也不需要掌握kubernetes的相关知识,甚至不用写yaml文件,对于开发、测试来说简直就是神一样的存在了。云效对小公司(创业公司)免费,但是有一定的量之后,就要开始收费了。在调研了一番云效的东西之后,发现云效也是基于jenkins x改造的,不过阿里毕竟人多,虽然能约莫看出是pipeline的语法,但是阿里彻底改造成了能够使用yaml来与后台交互。 下面是以阿里云的云效界面以及配合jenkins的pipeline语法来讲解:
4.1 Java代码扫描 PMD是一款可拓展的静态代码分析器它不仅可以对代码分析器,它不仅可以对代码风格进行检查,还可以检查设计、多线程、性能等方面的问题。阿里云的是简单的集成了一下而已,对于我们来说,底层使用了sonar来接入,所有的代码扫描结果都接入了sonar。
stage('Clone') {
+ steps{
+ git branch: 'master', credentialsId: 'xxxx', url: "xxx"
+ }
+}
+stage('check') {
+ steps{
+ container('maven') {
+ echo "mvn pmd:pmd"
+ }
+ }
+}
+
4.2 Java单元测试 Java的单元测试一般用的是Junit,在阿里云中,使用了surefire插件,用来在maven构建生命周期的test phase执行一个应用的单元测试。它会产生两种不同形式的测试结果报告。我这里就简单的过一下,使用"mvn test"命令来代替。
+stage('Clone') {
+ steps{
+ echo "1.Clone Stage"
+ git branch: 'master', credentialsId: 'xxxxx', url: "xxxxxx"
+ }
+}
+stage('test') {
+ steps{
+ container('maven') {
+ sh "mvn test"
+ }
+ }
+}
+
4.3 Java构建并上传镜像 镜像的构建比较想使用kaniko,尝试找了不少方法,到最后还是只能使用dind(docker in docker),挂载宿主机的docker来进行构建,如果能有其他方案,希望能提醒下。目前jenkins x使用的是dind,挂载的时候需要配置一下config.json,然后挂载到容器的/root/.docker目录,才能在容器中使用docker。
为什么不推荐dind:挂载了宿主机的docker,就可以使用docker ps查看正在运行的容器,也就意味着可以使用docker stop、docker rm来控制宿主机的容器,虽然kubernetes会重新调度起来,但是这一段的重启时间极大的影响业务。
+stage('下载代码') {
+ steps{
+ echo "1.Clone Stage"
+ git branch: 'master', credentialsId: 'xxxxx', url: "xxxxxx"
+ script {
+ build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
+ }
+ }
+}
+stage('打包并构建镜像') {
+ steps{
+ container('maven') {
+ echo "3.Build Docker Image Stage"
+ sh "mvn clean install -Dmaven.test.skip=true"
+ sh "docker build -f xxx/Dockerfile -t xxxxxx:\${build_tag} ."
+ sh "docker push xxxxxx:\${build_tag}"
+ }
+ }
+}
+
+
4.4 部署到阿里云k8s CD过程有点困难,由于我们的kubernetes平台是图形化的,类似于阿里云,用户根本不需要自己写deployment,只需要在图形化界面做一下操作即可部署。对于CD过程来说,如果应用存在的话,就可以直接替换掉镜像版本即可,如果没有应用,就提供个简单的界面让用户新建应用。当然,在容器最初推行的时候,对于用户来说,一下子需要接受docker、kubernetes、helm等概念是十分困难的,不能一个一个帮他们写deployment这些yaml文件,只能用helm创建一个通用的spring boot或者其他的模板,然后让业务方修改自己的配置,每次构建的时候只需要替换镜像即可。
def tmp = sh (
+ returnStdout: true,
+ script: "kubectl get deployment -n \${namespace} | grep \${JOB_NAME} | awk '{print \\$1}'"
+)
+//如果是第一次,则使用helm模板创建,创建完后需要去epaas修改pod的配置
+if(tmp.equals('')){
+ sh "helm init --client-only"
+ sh """helm repo add mychartmuseum http://xxxxxx \\
+ --username myuser \\
+ --password=mypass"""
+ sh """helm install --set name=\${JOB_NAME} \\
+ --set namespace=\${namespace} \\
+ --set deployment.image=\${image} \\
+ --set deployment.imagePullSecrets=\${harborProject} \\
+ --name \${namespace}-\${JOB_NAME} \\
+ mychartmuseum/soa-template"""
+}else{
+ println "已经存在,替换镜像"
+ //epaas中一个pod的容器名称需要带上"-0"来区分
+ sh "kubectl set image deployment/\${JOB_NAME} \${JOB_NAME}-0=\${image} -n \${namespace}"
+}
+
+
4.5 整体流程 代码扫描,单元测试,构建镜像三个并行运行,等三个完成之后,在进行部署
pipeline:
pipeline {
+ agent {
+ label "jenkins-maven"
+ }
+ stages{
+ stage('代码扫描,单元测试,镜像构建'){
+ parallel {
+ stage('并行任务一') {
+ agent {
+ label "jenkins-maven"
+ }
+ stages('Java代码扫描') {
+ stage('Clone') {
+ steps{
+ git branch: 'master', credentialsId: 'xxxxxxx', url: "xxxxxxx"
+ }
+ }
+ stage('check') {
+ steps{
+ container('maven') {
+ echo "$BUILD_NUMBER"
+ }
+ }
+ }
+ }
+ }
+ stage('并行任务二') {
+ agent {
+ label "jenkins-maven"
+ }
+ stages('Java单元测试') {
+ stage('Clone') {
+ steps{
+ echo "1.Clone Stage"
+ git branch: 'master', credentialsId: 'xxxxxxx', url: "xxxxxxx"
+ }
+ }
+ stage('test') {
+ steps{
+ container('maven') {
+ echo "3.Build Docker Image Stage"
+ sh "mvn -v"
+ }
+ }
+ }
+ }
+ }
+ stage('并行任务三') {
+ agent {
+ label "jenkins-maven"
+ }
+ stages('java构建镜像') {
+ stage('Clone') {
+ steps{
+ echo "1.Clone Stage"
+ git branch: 'master', credentialsId: 'xxxxxxx', url: "xxxxxxx"
+ script {
+ build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
+ }
+ }
+ }
+ stage('Build') {
+ steps{
+ container('maven') {
+ echo "3.Build Docker Image Stage"
+ sh "mvn clean install -Dmaven.test.skip=true"
+ sh "docker build -f epaas-portal/Dockerfile -t hub.gcloud.lab/rongqiyun/epaas:\${build_tag} ."
+ sh "docker push hub.gcloud.lab/rongqiyun/epaas:\${build_tag}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ stage('部署'){
+ stages('部署到容器云') {
+ stage('check') {
+ steps{
+ container('maven') {
+ script{
+ if (deploy_app == "true"){
+ def tmp = sh (
+ returnStdout: true,
+ script: "kubectl get deployment -n \${namespace} | grep \${JOB_NAME} | awk '{print \\$1}'"
+ )
+ //如果是第一次,则使用helm模板创建,创建完后需要去epaas修改pod的配置
+ if(tmp.equals('')){
+ sh "helm init --client-only"
+ sh """helm repo add mychartmuseum http://xxxxxx \\
+ --username myuser \\
+ --password=mypass"""
+ sh """helm install --set name=\${JOB_NAME} \\
+ --set namespace=\${namespace} \\
+ --set deployment.image=\${image} \\
+ --set deployment.imagePullSecrets=\${harborProject} \\
+ --name \${namespace}-\${JOB_NAME} \\
+ mychartmuseum/soa-template"""
+ }else{
+ println "已经存在,替换镜像"
+ //epaas中一个pod的容器名称需要带上"-0"来区分
+ sh "kubectl set image deployment/\${JOB_NAME} \${JOB_NAME}-0=\${image} -n \${namespace}"
+ }
+ }else{
+ println "用户选择不部署代码"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
在jenkins x中查看:
4.4 日志 jenkins blue ocean步骤日志:
云效中的日志:
4.5 定时触发 triggers {
+ cron('H H * * *') //每天
+ }
+
五、其他 5.1 Gitlab触发 pipeline中除了有对于时间的trigger,还支持了gitlab的触发,需要各种配置,不过如果真的对于gitlab的cicd有要求,直接使用gitlab-ci会更好,我们同时也对gitlab进行了runner的配置来支持gitlab的cicd。gitlab的cicd也提供了构建完后即销毁的过程。
六、总结 功能最强大的过程莫过于自己使用pipeline脚本实现,选取最适合自己的,但是对于一个公司来说,如果要求业务方来掌握这些,特别是IT流动性大的时候,既需要重新培训,同个问题又会被问多遍,所以,只能将DevOps实现成一个图形化的东西,方便,简单,相对来说功能还算强大。
DevOps最难的可能都不是以上这些,关键是让用户接受,容器云最初推行时,公司原本传统的很多发版方式都需要进行改变,有些业务方不愿意改,或者有些代码把持久化的东西存到了代码中而不是分布式存储里,甚至有些用户方都不愿意维护老代码,看都不想看然后想上容器,一个公司在做技术架构的时候,过于混乱到最后填坑要么需要耗费太多精力甚至大换血。
最后,DevOps是云原生的必经之路!!!
`,39),$=n("br",null,null,-1),O={href:"https://www.cnblogs.com/w1570631036/p/11524673.html",target:"_blank",rel:"noopener noreferrer"},I=n("br",null,null,-1),B={href:"http://www.wenzhihuai.com/getblogdetail.html?blogid=663",target:"_blank",rel:"noopener noreferrer"},P=n("br",null,null,-1),S={href:"https://gitbook.wenzhihuai.com/devops/devops-ping-tai",target:"_blank",rel:"noopener noreferrer"};function N(J,E){const a=l("ExternalLinkIcon");return p(),c("div",null,[n("h1",u,[d,s(" 3.1 "),n("a",r,[s("DevOps平台.md"),e(a)])]),v,m,g,n("p",null,[s("主要还是基于jenkins里面构建一个自由风格的软件项目,当时参考的是阿里的codepipeline,就是对jenkins封装一层,包括创建job、立即构建、获取构建进度等都进行封装,并将需要的东西进行存库,没有想到码代码的时候,一堆的坑,比如: 1.连续点击立即构建,jenkins是不按顺序返回的,(分布式锁解决) 2.跨域调用,csrf,这个还好,不过容易把jenkins搞的无法登录(注意配置,具体可以点击"),n("a",k,[s("这里"),e(a)]),s(") 3.创建job的时候只支持xml格式,还要转换一下,超级坑(xstream强行转换) 4.docker构建的时候,需要挂载宿主机的docker(想过用远程的,但效率不高) 5.数据库与jenkins的job一致性问题,任务创建失败,批量删除太慢(目前没想好怎么解决) 6.由于使用了数据库,需要检测job是否构建完成,为了自定义参数,我们自写了个通知插件,将构建状态返回到kafka,然后管理平台在进行消息处理。")]),b,n("p",null,[h,s(" 首先要解决的是多个构建同时运行的问题,很久之前就调研过jenkins x,它必须要使用在kubernetes上,由于当时官方文档不全,而且我们的DevOps项目处于初始期,所有没有使用。jenkins的master slave结构就不多说了。jenkins x应该说是个全家桶,包含了helm仓库、nexus仓库、docker registry等,代码是"),n("a",x,[s("jenkins-x-image"),e(a)]),s("。")]),f,q,_,D,j,n("p",null,[C,s(" kubernetes的官方cicd,目前已用于kubernetes的release发版过程,目前也仅仅是与GitHub相结合,gitlab无法使用,全过程可使用yaml文件来创建,跑起来就是类似kubernetes的job一样,用完即销毁,可惜目前比较新,依旧处于alpha版本,无法用于生产。有兴趣可以参考下:"),n("a",w,[s("Knative 初体验:CICD 极速入门 "),e(a)])]),y,n("p",null,[s("文章同步:"),$,s(" 博客园:"),n("a",O,[s("https://www.cnblogs.com/w1570631036/p/11524673.html"),e(a)]),I,s(" 个人网站:"),n("a",B,[s("http://www.wenzhihuai.com/getblogdetail.html?blogid=663"),e(a)]),P,s(" gitbook:"),n("a",S,[s("https://gitbook.wenzhihuai.com/devops/devops-ping-tai"),e(a)])])])}const z=i(o,[["render",N],["__file","devops-ping-tai.html.vue"]]);export{z as default};
diff --git a/assets/devops-ping-tai.html-kDtCSXpk.js b/assets/devops-ping-tai.html-kDtCSXpk.js
new file mode 100644
index 00000000..3583863a
--- /dev/null
+++ b/assets/devops-ping-tai.html-kDtCSXpk.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-580db9be","path":"/devops/devops-ping-tai.html","title":"3.1 DevOps平台.md","lang":"zh-CN","frontmatter":{"description":"3.1 DevOps平台.md DevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。 公司技术部目前几百人左右吧,但是整个技术栈还是比较落后的,尤其是DevOps、容器这一块,需要将全线打通,当时进来也主要是负责DevOps这一块的工作,应该说也是没怎么做好,其中也走了不少弯路,下面主要是自己踩过的坑吧。","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/devops/devops-ping-tai.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"3.1 DevOps平台.md"}],["meta",{"property":"og:description","content":"3.1 DevOps平台.md DevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。 公司技术部目前几百人左右吧,但是整个技术栈还是比较落后的,尤其是DevOps、容器这一块,需要将全线打通,当时进来也主要是负责DevOps这一块的工作,应该说也是没怎么做好,其中也走了不少弯路,下面主要是自己踩过的坑吧。"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-24T03:25:58.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-24T03:25:58.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.1 DevOps平台.md\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-24T03:25:58.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、自由风格的软件项目","slug":"一、自由风格的软件项目","link":"#一、自由风格的软件项目","children":[]},{"level":2,"title":"二、优化之后的CICD","slug":"二、优化之后的cicd","link":"#二、优化之后的cicd","children":[]},{"level":2,"title":"三、调研期","slug":"三、调研期","link":"#三、调研期","children":[]},{"level":2,"title":"四、产品化后的DevOps平台","slug":"四、产品化后的devops平台","link":"#四、产品化后的devops平台","children":[{"level":3,"title":"4.1 Java代码扫描","slug":"_4-1-java代码扫描","link":"#_4-1-java代码扫描","children":[]},{"level":3,"title":"4.2 Java单元测试","slug":"_4-2-java单元测试","link":"#_4-2-java单元测试","children":[]},{"level":3,"title":"4.3 Java构建并上传镜像","slug":"_4-3-java构建并上传镜像","link":"#_4-3-java构建并上传镜像","children":[]},{"level":3,"title":"4.4 部署到阿里云k8s","slug":"_4-4-部署到阿里云k8s","link":"#_4-4-部署到阿里云k8s","children":[]},{"level":3,"title":"4.5 整体流程","slug":"_4-5-整体流程","link":"#_4-5-整体流程","children":[]},{"level":3,"title":"4.4 日志","slug":"_4-4-日志","link":"#_4-4-日志","children":[]},{"level":3,"title":"4.5 定时触发","slug":"_4-5-定时触发","link":"#_4-5-定时触发","children":[]}]},{"level":2,"title":"五、其他","slug":"五、其他","link":"#五、其他","children":[{"level":3,"title":"5.1 Gitlab触发","slug":"_5-1-gitlab触发","link":"#_5-1-gitlab触发","children":[]}]},{"level":2,"title":"六、总结","slug":"六、总结","link":"#六、总结","children":[]}],"git":{"createdTime":1706066758000,"updatedTime":1706066758000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":11.93,"words":3580},"filePathRelative":"devops/devops-ping-tai.md","localizedDate":"2024年1月24日","excerpt":"\\nDevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
\\n公司技术部目前几百人左右吧,但是整个技术栈还是比较落后的,尤其是DevOps、容器这一块,需要将全线打通,当时进来也主要是负责DevOps这一块的工作,应该说也是没怎么做好,其中也走了不少弯路,下面主要是自己踩过的坑吧。
","autoDesc":true}');export{e as data};
diff --git a/assets/elastic-spark.html-yTkDwYPM.js b/assets/elastic-spark.html-yTkDwYPM.js
new file mode 100644
index 00000000..76503bf4
--- /dev/null
+++ b/assets/elastic-spark.html-yTkDwYPM.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-04e32b44","path":"/bigdata/spark/elastic-spark.html","title":"elastic spark","lang":"zh-CN","frontmatter":{"description":"elastic spark Hadoop允许Elasticsearch在Spark中以两种方式使用:通过自2.1以来的原生RDD支持,或者通过自2.0以来的Map/Reduce桥接器。从5.0版本开始,elasticsearch-hadoop就支持Spark 2.0。目前spark支持的数据源有: (1)文件系统:LocalFS、HDFS、Hive、text、parquet、orc、json、csv (2)数据RDBMS:mysql、oracle、mssql (3)NOSQL数据库:HBase、ES、Redis (4)消息对象:Redis","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/bigdata/spark/elastic-spark.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"elastic spark"}],["meta",{"property":"og:description","content":"elastic spark Hadoop允许Elasticsearch在Spark中以两种方式使用:通过自2.1以来的原生RDD支持,或者通过自2.0以来的Map/Reduce桥接器。从5.0版本开始,elasticsearch-hadoop就支持Spark 2.0。目前spark支持的数据源有: (1)文件系统:LocalFS、HDFS、Hive、text、parquet、orc、json、csv (2)数据RDBMS:mysql、oracle、mssql (3)NOSQL数据库:HBase、ES、Redis (4)消息对象:Redis"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-25T11:42:16.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-25T11:42:16.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"elastic spark\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-25T11:42:16.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、原生RDD支持","slug":"一、原生rdd支持","link":"#一、原生rdd支持","children":[{"level":3,"title":"1.1 基础配置","slug":"_1-1-基础配置","link":"#_1-1-基础配置","children":[]},{"level":3,"title":"1.2 读取es数据","slug":"_1-2-读取es数据","link":"#_1-2-读取es数据","children":[]},{"level":3,"title":"1.3 写数据","slug":"_1-3-写数据","link":"#_1-3-写数据","children":[]}]},{"level":2,"title":"二、Spark Streaming","slug":"二、spark-streaming","link":"#二、spark-streaming","children":[]},{"level":2,"title":"三、Spark SQL","slug":"三、spark-sql","link":"#三、spark-sql","children":[]},{"level":2,"title":"四、Spark Structure Streaming","slug":"四、spark-structure-streaming","link":"#四、spark-structure-streaming","children":[]},{"level":2,"title":"五、Spark on kubernetes Operator","slug":"五、spark-on-kubernetes-operator","link":"#五、spark-on-kubernetes-operator","children":[]}],"git":{"createdTime":1706182936000,"updatedTime":1706182936000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":1.71,"words":514},"filePathRelative":"bigdata/spark/elastic-spark.md","localizedDate":"2024年1月25日","excerpt":" elastic spark \\nHadoop允许Elasticsearch在Spark中以两种方式使用:通过自2.1以来的原生RDD支持,或者通过自2.0以来的Map/Reduce桥接器。从5.0版本开始,elasticsearch-hadoop就支持Spark 2.0。目前spark支持的数据源有: \\n(1)文件系统:LocalFS、HDFS、Hive、text、parquet、orc、json、csv \\n(2)数据RDBMS:mysql、oracle、mssql \\n(3)NOSQL数据库:HBase、ES、Redis \\n(4)消息对象:Redis
","autoDesc":true}');export{e as data};
diff --git a/assets/elastic-spark.html-ys8zTss9.js b/assets/elastic-spark.html-ys8zTss9.js
new file mode 100644
index 00000000..6dbdcf72
--- /dev/null
+++ b/assets/elastic-spark.html-ys8zTss9.js
@@ -0,0 +1,31 @@
+import{_ as p,r as o,o as c,c as l,a,d as n,b as t,e}from"./app-BDpQ7oW_.js";const i={},u=e(` elastic spark Hadoop允许Elasticsearch在Spark中以两种方式使用:通过自2.1以来的原生RDD支持,或者通过自2.0以来的Map/Reduce桥接器。从5.0版本开始,elasticsearch-hadoop就支持Spark 2.0。目前spark支持的数据源有: (1)文件系统:LocalFS、HDFS、Hive、text、parquet、orc、json、csv (2)数据RDBMS:mysql、oracle、mssql (3)NOSQL数据库:HBase、ES、Redis (4)消息对象:Redis
elasticsearch相对hdfs来说,容易搭建、并且有可视化kibana支持,非常方便spark的初学入门,本文主要讲解用elasticsearch-spark的入门。
Spark - Apache Spark 一、原生RDD支持 1.1 基础配置 相关库引入:
< dependency>
+ < groupId> org.elasticsearch</ groupId>
+ < artifactId> elasticsearch-spark-30_2.13</ artifactId>
+ < version> 8.1.3</ version>
+ </ dependency>
+
`,8),r={href:"https://www.elastic.co/Zephery/en/elasticsearch/hadoop/current/configuration.html",target:"_blank",rel:"noopener noreferrer"},k={href:"https://github.com/elastic/elasticsearch-hadoop/blob/master/mr/src/main/java/org/elasticsearch/hadoop/cfg/ConfigurationOptions.java",target:"_blank",rel:"noopener noreferrer"},d=e(`public static SparkConf getSparkConf ( ) {
+ SparkConf sparkConf = new SparkConf ( ) . setAppName ( "elasticsearch-spark-demo" ) ;
+ sparkConf. set ( "es.nodes" , "host" )
+ . set ( "es.port" , "xxxxxx" )
+ . set ( "es.nodes.wan.only" , "true" )
+ . set ( "es.net.http.auth.user" , "elxxxxastic" )
+ . set ( "es.net.http.auth.pass" , "xxxx" )
+ . setMaster ( "local[*]" ) ;
+ return sparkConf;
+}
+
1.2 读取es数据 这里用的是kibana提供的sample data里面的索引kibana_sample_data_ecommerce,也可以替换成自己的索引。
public static void main ( String [ ] args) {
+ SparkConf conf = getSparkConf ( ) ;
+ try ( JavaSparkContext jsc = new JavaSparkContext ( conf) ) {
+
+ JavaPairRDD < String , Map < String , Object > > esRDD =
+ JavaEsSpark . esRDD ( jsc, "kibana_sample_data_ecommerce" ) ;
+ esRDD. collect ( ) . forEach ( System . out:: println ) ;
+ }
+}
+
esRDD同时也支持query语句esRDD(final JavaSparkContext jsc, final String resource, final String query),一般对es的查询都需要根据时间筛选一下,不过相对于es的官方sdk,并没有那么友好的api,只能直接使用原生的dsl语句。
1.3 写数据 支持序列化对象、json,并且能够使用占位符动态索引写入数据(使用较少),不过多介绍了。
public static void jsonWrite ( ) {
+ String json1 = "{\\"reason\\" : \\"business\\",\\"airport\\" : \\"SFO\\"}" ;
+ String json2 = "{\\"participants\\" : 5,\\"airport\\" : \\"OTP\\"}" ;
+ JavaRDD < String > stringRDD = jsc. parallelize ( ImmutableList . of ( json1, json2) ) ;
+ JavaEsSpark . saveJsonToEs ( stringRDD, "spark-json" ) ;
+}
+
比较常用的读写也就这些,更多可以看下官网相关介绍。
二、Spark Streaming spark的实时处理,es5.0的时候开始支持,目前
三、Spark SQL 四、Spark Structure Streaming 五、Spark on kubernetes Operator 参考: `,15),h={href:"https://www.elastic.co/Zephery/en/elasticsearch/hadoop/current/spark.html",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/elastic/elasticsearch-hadoop",target:"_blank",rel:"noopener noreferrer"},v={href:"https://www.jianshu.com/p/996c60f0492a",target:"_blank",rel:"noopener noreferrer"};function g(b,f){const s=o("ExternalLinkIcon");return c(),l("div",null,[u,a("p",null,[n("SparkConf配置,更多详细的请点击"),a("a",r,[n("这里"),t(s)]),n("或者源码"),a("a",k,[n("ConfigurationOptions"),t(s)]),n("。")]),d,a("p",null,[n("1."),a("a",h,[n("Apache Spark support"),t(s)])]),a("p",null,[n("2."),a("a",m,[n("elasticsearch-hadoop"),t(s)])]),a("p",null,[n("3."),a("a",v,[n("使用SparkSQL操作Elasticsearch - Spark入门教程"),t(s)])])])}const S=p(i,[["render",g],["__file","elastic-spark.html.vue"]]);export{S as default};
diff --git "a/assets/elasticsearch\346\272\220\347\240\201debug.html-0y-mDJbS.js" "b/assets/elasticsearch\346\272\220\347\240\201debug.html-0y-mDJbS.js"
new file mode 100644
index 00000000..3d8142d7
--- /dev/null
+++ "b/assets/elasticsearch\346\272\220\347\240\201debug.html-0y-mDJbS.js"
@@ -0,0 +1 @@
+import{_ as s,r,o as i,c,a as e,d as a,b as n,e as h}from"./app-BDpQ7oW_.js";const o={},d=e("h1",{id:"【elasticsearch】源码debug",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#【elasticsearch】源码debug","aria-hidden":"true"},"#"),a(" 【elasticsearch】源码debug")],-1),l=e("h1",{id:"一、下载源代码",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#一、下载源代码","aria-hidden":"true"},"#"),a(" 一、下载源代码")],-1),u={href:"https://github.com/elastic/elasticsearch.git",target:"_blank",rel:"noopener noreferrer"},g=e("br",null,null,-1),p=e("img",{src:"https://github-images.wenzhihuai.com/images/755525-20220124160719006-851383635.png",alt:"image"},null,-1),m=h('切换到特定版本的分支:比如7.17,之后idea会自己加上Run/Debug Elasitcsearch的,配置可以不用改,默认就好
二、修改设置(可选) 为了方便, 在 gradle/run.gradle 中关闭 Auth 认证:
setting 'xpack.security.enabled', 'false'
或者使用其中的用户名密码:
user username: 'elastic-admin', password: 'elastic-password', role: 'superuser'
三、启动 先启动上面的 remote debug, 然后用 gradlew 启动项目:
./gradlew :run --debug-jvm 打开浏览器http://localhost:9200即可看到es相关信息了
',9);function _(b,f){const t=r("ExternalLinkIcon");return i(),c("div",null,[d,l,e("p",null,[a("直接用idea下载代码"),e("a",u,[a("https://github.com/elastic/elasticsearch.git"),n(t)]),g,p]),m])}const w=s(o,[["render",_],["__file","elasticsearch源码debug.html.vue"]]);export{w as default};
diff --git "a/assets/elasticsearch\346\272\220\347\240\201debug.html-MPOlcYKm.js" "b/assets/elasticsearch\346\272\220\347\240\201debug.html-MPOlcYKm.js"
new file mode 100644
index 00000000..4ac0e468
--- /dev/null
+++ "b/assets/elasticsearch\346\272\220\347\240\201debug.html-MPOlcYKm.js"
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-d73a9aee","path":"/database/elasticsearch/elasticsearch%E6%BA%90%E7%A0%81debug.html","title":"【elasticsearch】源码debug","lang":"zh-CN","frontmatter":{"description":"【elasticsearch】源码debug 一、下载源代码 直接用idea下载代码https://github.com/elastic/elasticsearch.git","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/database/elasticsearch/elasticsearch%E6%BA%90%E7%A0%81debug.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"【elasticsearch】源码debug"}],["meta",{"property":"og:description","content":"【elasticsearch】源码debug 一、下载源代码 直接用idea下载代码https://github.com/elastic/elasticsearch.git"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-26T03:58:56.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-26T03:58:56.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"【elasticsearch】源码debug\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-26T03:58:56.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1706186538000,"updatedTime":1706241536000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":4}]},"readingTime":{"minutes":0.52,"words":157},"filePathRelative":"database/elasticsearch/elasticsearch源码debug.md","localizedDate":"2024年1月25日","excerpt":" 【elasticsearch】源码debug \\n 一、下载源代码 \\n直接用idea下载代码https://github.com/elastic/elasticsearch.git \\n
","autoDesc":true}');export{e as data};
diff --git a/assets/giscus-hHrgKA30.js b/assets/giscus-hHrgKA30.js
new file mode 100644
index 00000000..db345b1f
--- /dev/null
+++ b/assets/giscus-hHrgKA30.js
@@ -0,0 +1,66 @@
+/**
+ * @license
+ * Copyright 2019 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const H=globalThis,V=H.ShadowRoot&&(H.ShadyCSS===void 0||H.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,q=Symbol(),J=new WeakMap;let ot=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==q)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(V&&t===void 0){const s=e!==void 0&&e.length===1;s&&(t=J.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),s&&J.set(e,t))}return t}toString(){return this.cssText}};const ut=i=>new ot(typeof i=="string"?i:i+"",void 0,q),$t=(i,...t)=>{const e=i.length===1?i[0]:t.reduce((s,r,o)=>s+(n=>{if(n._$cssResult$===!0)return n.cssText;if(typeof n=="number")return n;throw Error("Value passed to 'css' function must be a 'css' function result: "+n+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(r)+i[o+1],i[0]);return new ot(e,i,q)},_t=(i,t)=>{if(V)i.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const e of t){const s=document.createElement("style"),r=H.litNonce;r!==void 0&&s.setAttribute("nonce",r),s.textContent=e.cssText,i.appendChild(s)}},F=V?i=>i:i=>i instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return ut(e)})(i):i;/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const{is:gt,defineProperty:ft,getOwnPropertyDescriptor:mt,getOwnPropertyNames:At,getOwnPropertySymbols:yt,getPrototypeOf:St}=Object,A=globalThis,Q=A.trustedTypes,vt=Q?Q.emptyScript:"",Y=A.reactiveElementPolyfillSupport,U=(i,t)=>i,L={toAttribute(i,t){switch(t){case Boolean:i=i?vt:null;break;case Object:case Array:i=i==null?i:JSON.stringify(i)}return i},fromAttribute(i,t){let e=i;switch(t){case Boolean:e=i!==null;break;case Number:e=i===null?null:Number(i);break;case Object:case Array:try{e=JSON.parse(i)}catch{e=null}}return e}},K=(i,t)=>!gt(i,t),Z={attribute:!0,type:String,converter:L,reflect:!1,hasChanged:K};Symbol.metadata??(Symbol.metadata=Symbol("metadata")),A.litPropertyMetadata??(A.litPropertyMetadata=new WeakMap);class E extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??(this.l=[])).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=Z){if(e.state&&(e.attribute=!1),this._$Ei(),this.elementProperties.set(t,e),!e.noAccessor){const s=Symbol(),r=this.getPropertyDescriptor(t,s,e);r!==void 0&&ft(this.prototype,t,r)}}static getPropertyDescriptor(t,e,s){const{get:r,set:o}=mt(this.prototype,t)??{get(){return this[e]},set(n){this[e]=n}};return{get(){return r==null?void 0:r.call(this)},set(n){const a=r==null?void 0:r.call(this);o.call(this,n),this.requestUpdate(t,a,s)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??Z}static _$Ei(){if(this.hasOwnProperty(U("elementProperties")))return;const t=St(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(U("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(U("properties"))){const e=this.properties,s=[...At(e),...yt(e)];for(const r of s)this.createProperty(r,e[r])}const t=this[Symbol.metadata];if(t!==null){const e=litPropertyMetadata.get(t);if(e!==void 0)for(const[s,r]of e)this.elementProperties.set(s,r)}this._$Eh=new Map;for(const[e,s]of this.elementProperties){const r=this._$Eu(e,s);r!==void 0&&this._$Eh.set(r,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const s=new Set(t.flat(1/0).reverse());for(const r of s)e.unshift(F(r))}else t!==void 0&&e.push(F(t));return e}static _$Eu(t,e){const s=e.attribute;return s===!1?void 0:typeof s=="string"?s:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){var t;this._$ES=new Promise(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),(t=this.constructor.l)==null||t.forEach(e=>e(this))}addController(t){var e;(this._$EO??(this._$EO=new Set)).add(t),this.renderRoot!==void 0&&this.isConnected&&((e=t.hostConnected)==null||e.call(t))}removeController(t){var e;(e=this._$EO)==null||e.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const s of e.keys())this.hasOwnProperty(s)&&(t.set(s,this[s]),delete this[s]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return _t(t,this.constructor.elementStyles),t}connectedCallback(){var t;this.renderRoot??(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),(t=this._$EO)==null||t.forEach(e=>{var s;return(s=e.hostConnected)==null?void 0:s.call(e)})}enableUpdating(t){}disconnectedCallback(){var t;(t=this._$EO)==null||t.forEach(e=>{var s;return(s=e.hostDisconnected)==null?void 0:s.call(e)})}attributeChangedCallback(t,e,s){this._$AK(t,s)}_$EC(t,e){var o;const s=this.constructor.elementProperties.get(t),r=this.constructor._$Eu(t,s);if(r!==void 0&&s.reflect===!0){const n=(((o=s.converter)==null?void 0:o.toAttribute)!==void 0?s.converter:L).toAttribute(e,s.type);this._$Em=t,n==null?this.removeAttribute(r):this.setAttribute(r,n),this._$Em=null}}_$AK(t,e){var o;const s=this.constructor,r=s._$Eh.get(t);if(r!==void 0&&this._$Em!==r){const n=s.getPropertyOptions(r),a=typeof n.converter=="function"?{fromAttribute:n.converter}:((o=n.converter)==null?void 0:o.fromAttribute)!==void 0?n.converter:L;this._$Em=r,this[r]=a.fromAttribute(e,n.type),this._$Em=null}}requestUpdate(t,e,s){if(t!==void 0){if(s??(s=this.constructor.getPropertyOptions(t)),!(s.hasChanged??K)(this[t],e))return;this.P(t,e,s)}this.isUpdatePending===!1&&(this._$ES=this._$ET())}P(t,e,s){this._$AL.has(t)||this._$AL.set(t,e),s.reflect===!0&&this._$Em!==t&&(this._$Ej??(this._$Ej=new Set)).add(t)}async _$ET(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var s;if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??(this.renderRoot=this.createRenderRoot()),this._$Ep){for(const[o,n]of this._$Ep)this[o]=n;this._$Ep=void 0}const r=this.constructor.elementProperties;if(r.size>0)for(const[o,n]of r)n.wrapped!==!0||this._$AL.has(o)||this[o]===void 0||this.P(o,this[o],n)}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),(s=this._$EO)==null||s.forEach(r=>{var o;return(o=r.hostUpdate)==null?void 0:o.call(r)}),this.update(e)):this._$EU()}catch(r){throw t=!1,this._$EU(),r}t&&this._$AE(e)}willUpdate(t){}_$AE(t){var e;(e=this._$EO)==null||e.forEach(s=>{var r;return(r=s.hostUpdated)==null?void 0:r.call(s)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EU(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Ej&&(this._$Ej=this._$Ej.forEach(e=>this._$EC(e,this[e]))),this._$EU()}updated(t){}firstUpdated(t){}}E.elementStyles=[],E.shadowRootOptions={mode:"open"},E[U("elementProperties")]=new Map,E[U("finalized")]=new Map,Y==null||Y({ReactiveElement:E}),(A.reactiveElementVersions??(A.reactiveElementVersions=[])).push("2.0.4");/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const P=globalThis,k=P.trustedTypes,X=k?k.createPolicy("lit-html",{createHTML:i=>i}):void 0,ht="$lit$",m=`lit$${(Math.random()+"").slice(9)}$`,at="?"+m,Et=`<${at}>`,v=document,N=()=>v.createComment(""),R=i=>i===null||typeof i!="object"&&typeof i!="function",ct=Array.isArray,bt=i=>ct(i)||typeof(i==null?void 0:i[Symbol.iterator])=="function",j=`[
+\f\r]`,w=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,tt=/-->/g,et=/>/g,y=RegExp(`>|${j}(?:([^\\s"'>=/]+)(${j}*=${j}*(?:[^
+\f\r"'\`<>=]|("|')|))|$)`,"g"),st=/'/g,it=/"/g,lt=/^(?:script|style|textarea|title)$/i,Ct=i=>(t,...e)=>({_$litType$:i,strings:t,values:e}),wt=Ct(1),b=Symbol.for("lit-noChange"),l=Symbol.for("lit-nothing"),rt=new WeakMap,S=v.createTreeWalker(v,129);function dt(i,t){if(!Array.isArray(i)||!i.hasOwnProperty("raw"))throw Error("invalid template strings array");return X!==void 0?X.createHTML(t):t}const Ut=(i,t)=>{const e=i.length-1,s=[];let r,o=t===2?"":"",n=w;for(let a=0;a"?(n=r??w,c=-1):u[1]===void 0?c=-2:(c=n.lastIndex-u[2].length,d=u[1],n=u[3]===void 0?y:u[3]==='"'?it:st):n===it||n===st?n=y:n===tt||n===et?n=w:(n=y,r=void 0);const f=n===y&&i[a+1].startsWith("/>")?" ":"";o+=n===w?h+Et:c>=0?(s.push(d),h.slice(0,c)+ht+h.slice(c)+m+f):h+m+(c===-2?a:f)}return[dt(i,o+(i[e]||">")+(t===2?" ":"")),s]};class I{constructor({strings:t,_$litType$:e},s){let r;this.parts=[];let o=0,n=0;const a=t.length-1,h=this.parts,[d,u]=Ut(t,e);if(this.el=I.createElement(d,s),S.currentNode=this.el.content,e===2){const c=this.el.content.firstChild;c.replaceWith(...c.childNodes)}for(;(r=S.nextNode())!==null&&h.length0){r.textContent=k?k.emptyScript:"";for(let f=0;f2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=l}_$AI(t,e=this,s,r){const o=this.strings;let n=!1;if(o===void 0)t=C(this,t,e,0),n=!R(t)||t!==this._$AH&&t!==b,n&&(this._$AH=t);else{const a=t;let h,d;for(t=o[0],h=0;h{const s=(e==null?void 0:e.renderBefore)??t;let r=s._$litPart$;if(r===void 0){const o=(e==null?void 0:e.renderBefore)??null;s._$litPart$=r=new M(t.insertBefore(N(),o),o,void 0,e??{})}return r._$AI(i),r};/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */let T=class extends E{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var e;const t=super.createRenderRoot();return(e=this.renderOptions).renderBefore??(e.renderBefore=t.firstChild),t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=It(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),(t=this._$Do)==null||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),(t=this._$Do)==null||t.setConnected(!1)}render(){return b}};var nt;T._$litElement$=!0,T.finalized=!0,(nt=globalThis.litElementHydrateSupport)==null||nt.call(globalThis,{LitElement:T});const G=globalThis.litElementPolyfillSupport;G==null||G({LitElement:T});(globalThis.litElementVersions??(globalThis.litElementVersions=[])).push("4.0.4");/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const Mt=i=>(t,e)=>{e!==void 0?e.addInitializer(()=>{customElements.define(i,t)}):customElements.define(i,t)};/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const xt={attribute:!0,type:String,converter:L,reflect:!1,hasChanged:K},Ht=(i=xt,t,e)=>{const{kind:s,metadata:r}=e;let o=globalThis.litPropertyMetadata.get(r);if(o===void 0&&globalThis.litPropertyMetadata.set(r,o=new Map),o.set(e.name,i),s==="accessor"){const{name:n}=e;return{set(a){const h=t.get.call(this);t.set.call(this,a),this.requestUpdate(n,h,i)},init(a){return a!==void 0&&this.P(n,void 0,i),a}}}if(s==="setter"){const{name:n}=e;return function(a){const h=this[n];t.call(this,a),this.requestUpdate(n,h,i)}}throw Error("Unsupported decorator location: "+s)};function _(i){return(t,e)=>typeof e=="object"?Ht(i,t,e):((s,r,o)=>{const n=r.hasOwnProperty(o);return r.constructor.createProperty(o,n?{...s,wrapped:!0}:s),n?Object.getOwnPropertyDescriptor(r,o):void 0})(i,t,e)}/**
+ * @license
+ * Copyright 2020 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const Lt=i=>i.strings===void 0;/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const kt={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},Dt=i=>(...t)=>({_$litDirective$:i,values:t});let zt=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,s){this._$Ct=t,this._$AM=e,this._$Ci=s}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const O=(i,t)=>{var s;const e=i._$AN;if(e===void 0)return!1;for(const r of e)(s=r._$AO)==null||s.call(r,t,!1),O(r,t);return!0},D=i=>{let t,e;do{if((t=i._$AM)===void 0)break;e=t._$AN,e.delete(i),i=t}while((e==null?void 0:e.size)===0)},pt=i=>{for(let t;t=i._$AM;i=t){let e=t._$AN;if(e===void 0)t._$AN=e=new Set;else if(e.has(i))break;e.add(i),Bt(t)}};function Yt(i){this._$AN!==void 0?(D(this),this._$AM=i,pt(this)):this._$AM=i}function jt(i,t=!1,e=0){const s=this._$AH,r=this._$AN;if(r!==void 0&&r.size!==0)if(t)if(Array.isArray(s))for(let o=e;o{i.type==kt.CHILD&&(i._$AP??(i._$AP=jt),i._$AQ??(i._$AQ=Yt))};class Gt extends zt{constructor(){super(...arguments),this._$AN=void 0}_$AT(t,e,s){super._$AT(t,e,s),pt(this),this.isConnected=t._$AU}_$AO(t,e=!0){var s,r;t!==this.isConnected&&(this.isConnected=t,t?(s=this.reconnected)==null||s.call(this):(r=this.disconnected)==null||r.call(this)),e&&(O(this,t),D(this))}setValue(t){if(Lt(this._$Ct))this._$Ct._$AI(t,this);else{const e=[...this._$Ct._$AH];e[this._$Ci]=t,this._$Ct._$AI(e,this,0)}}disconnected(){}reconnected(){}}/**
+ * @license
+ * Copyright 2020 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const Wt=()=>new Vt;class Vt{}const W=new WeakMap,qt=Dt(class extends Gt{render(i){return l}update(i,[t]){var s;const e=t!==this.Y;return e&&this.Y!==void 0&&this.rt(void 0),(e||this.lt!==this.ct)&&(this.Y=t,this.ht=(s=i.options)==null?void 0:s.host,this.rt(this.ct=i.element)),l}rt(i){if(typeof this.Y=="function"){const t=this.ht??globalThis;let e=W.get(t);e===void 0&&(e=new WeakMap,W.set(t,e)),e.get(this.Y)!==void 0&&this.Y.call(this.ht,void 0),e.set(this.Y,i),i!==void 0&&this.Y.call(this.ht,i)}else this.Y.value=i}get lt(){var i,t;return typeof this.Y=="function"?(i=W.get(this.ht??globalThis))==null?void 0:i.get(this.Y):(t=this.Y)==null?void 0:t.value}disconnected(){this.lt===this.ct&&this.rt(void 0)}reconnected(){this.rt(this.ct)}});var Kt=Object.defineProperty,Jt=Object.getOwnPropertyDescriptor,$=(i,t,e,s)=>{for(var r=s>1?void 0:s?Jt(t,e):t,o=i.length-1,n;o>=0;o--)(n=i[o])&&(r=(s?n(t,e,r):n(r))||r);return s&&r&&Kt(t,e,r),r};function Ft(i){return customElements.get(i)?t=>t:Mt(i)}let p=class extends T{constructor(){super(),this.GISCUS_SESSION_KEY="giscus-session",this.GISCUS_DEFAULT_HOST="https://giscus.app",this.ERROR_SUGGESTION="Please consider reporting this error at https://github.com/giscus/giscus/issues/new.",this.__session="",this._iframeRef=Wt(),this.messageEventHandler=this.handleMessageEvent.bind(this),this.hasLoaded=!1,this.host=this.GISCUS_DEFAULT_HOST,this.strict="0",this.reactionsEnabled="1",this.emitMetadata="0",this.inputPosition="bottom",this.theme="light",this.lang="en",this.loading="eager",this.setupSession(),window.addEventListener("message",this.messageEventHandler)}get iframeRef(){var i;return(i=this._iframeRef)==null?void 0:i.value}get _host(){try{return new URL(this.host),this.host}catch{return this.GISCUS_DEFAULT_HOST}}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("message",this.messageEventHandler)}_formatError(i){return`[giscus] An error occurred. Error message: "${i}".`}setupSession(){const i=location.href,t=new URL(i),e=localStorage.getItem(this.GISCUS_SESSION_KEY),s=t.searchParams.get("giscus")??"";if(this.__session="",s){localStorage.setItem(this.GISCUS_SESSION_KEY,JSON.stringify(s)),this.__session=s,t.searchParams.delete("giscus"),t.hash="",history.replaceState(void 0,document.title,t.toString());return}if(e)try{this.__session=JSON.parse(e)}catch(r){localStorage.removeItem(this.GISCUS_SESSION_KEY),console.warn(`${this._formatError(r==null?void 0:r.message)} Session has been cleared.`)}}signOut(){localStorage.removeItem(this.GISCUS_SESSION_KEY),this.__session="",this.update(new Map)}handleMessageEvent(i){if(i.origin!==this._host)return;const{data:t}=i;if(!(typeof t=="object"&&t.giscus))return;if(this.iframeRef&&t.giscus.resizeHeight&&(this.iframeRef.style.height=`${t.giscus.resizeHeight}px`),t.giscus.signOut){console.info("[giscus] User has logged out. Session has been cleared."),this.signOut();return}if(!t.giscus.error)return;const e=t.giscus.error;if(e.includes("Bad credentials")||e.includes("Invalid state value")||e.includes("State has expired")){if(localStorage.getItem(this.GISCUS_SESSION_KEY)!==null){console.warn(`${this._formatError(e)} Session has been cleared.`),this.signOut();return}console.error(`${this._formatError(e)} No session is stored initially. ${this.ERROR_SUGGESTION}`)}if(e.includes("Discussion not found")){console.warn(`[giscus] ${e}. A new discussion will be created if a comment/reaction is submitted.`);return}console.error(`${this._formatError(e)} ${this.ERROR_SUGGESTION}`)}sendMessage(i){var t;!((t=this.iframeRef)!=null&&t.contentWindow)||!this.hasLoaded||this.iframeRef.contentWindow.postMessage({giscus:i},this._host)}updateConfig(){const i={setConfig:{repo:this.repo,repoId:this.repoId,category:this.category,categoryId:this.categoryId,term:this.getTerm(),number:+this.getNumber(),strict:this.strict==="1",reactionsEnabled:this.reactionsEnabled==="1",emitMetadata:this.emitMetadata==="1",inputPosition:this.inputPosition,theme:this.theme,lang:this.lang}};this.sendMessage(i)}firstUpdated(){var i;(i=this.iframeRef)==null||i.addEventListener("load",()=>{var t;(t=this.iframeRef)==null||t.classList.remove("loading"),this.hasLoaded=!0,this.updateConfig()})}requestUpdate(i,t,e){if(!this.hasUpdated||i==="host"){super.requestUpdate(i,t,e);return}this.updateConfig()}getMetaContent(i,t=!1){const e=t?`meta[property='og:${i}'],`:"",s=document.querySelector(e+`meta[name='${i}']`);return s?s.content:""}_getCleanedUrl(){const i=new URL(location.href);return i.searchParams.delete("giscus"),i.hash="",i}getTerm(){switch(this.mapping){case"url":return this._getCleanedUrl().toString();case"title":return document.title;case"og:title":return this.getMetaContent("title",!0);case"specific":return this.term??"";case"number":return"";case"pathname":default:return location.pathname.length<2?"index":location.pathname.substring(1).replace(/\.\w+$/,"")}}getNumber(){return this.mapping==="number"?this.term??"":""}getIframeSrc(){const i=this._getCleanedUrl().toString(),t=`${i}${this.id?"#"+this.id:""}`,e=this.getMetaContent("description",!0),s=this.getMetaContent("giscus:backlink")||i,r={origin:t,session:this.__session,repo:this.repo,repoId:this.repoId??"",category:this.category??"",categoryId:this.categoryId??"",term:this.getTerm(),number:this.getNumber(),strict:this.strict,reactionsEnabled:this.reactionsEnabled,emitMetadata:this.emitMetadata,inputPosition:this.inputPosition,theme:this.theme,description:e,backLink:s},o=this._host,n=this.lang?`/${this.lang}`:"",a=new URLSearchParams(r);return`${o}${n}/widget?${a.toString()}`}render(){return wt`
+
+ `}};p.styles=$t`
+ :host,
+ iframe {
+ width: 100%;
+ border: none;
+ min-height: 150px;
+ color-scheme: light dark;
+ }
+
+ iframe.loading {
+ opacity: 0;
+ }
+ `;$([_({reflect:!0})],p.prototype,"host",2);$([_({reflect:!0})],p.prototype,"repo",2);$([_({reflect:!0})],p.prototype,"repoId",2);$([_({reflect:!0})],p.prototype,"category",2);$([_({reflect:!0})],p.prototype,"categoryId",2);$([_({reflect:!0})],p.prototype,"mapping",2);$([_({reflect:!0})],p.prototype,"term",2);$([_({reflect:!0})],p.prototype,"strict",2);$([_({reflect:!0})],p.prototype,"reactionsEnabled",2);$([_({reflect:!0})],p.prototype,"emitMetadata",2);$([_({reflect:!0})],p.prototype,"inputPosition",2);$([_({reflect:!0})],p.prototype,"theme",2);$([_({reflect:!0})],p.prototype,"lang",2);$([_({reflect:!0})],p.prototype,"loading",2);p=$([Ft("giscus-widget")],p);export{p as GiscusWidget};
diff --git a/assets/gitlab-ci.html-HyFv5Ls3.js b/assets/gitlab-ci.html-HyFv5Ls3.js
new file mode 100644
index 00000000..6397a4ab
--- /dev/null
+++ b/assets/gitlab-ci.html-HyFv5Ls3.js
@@ -0,0 +1 @@
+const t=JSON.parse('{"key":"v-06d5cd4c","path":"/devops/gitlab-ci.html","title":"Git","lang":"zh-CN","frontmatter":{"description":"Git","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/devops/gitlab-ci.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"Git"}],["meta",{"property":"og:description","content":"Git"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-24T03:25:58.000Z"}],["meta",{"property":"article:author","content":"Zephery"}],["meta",{"property":"article:modified_time","content":"2024-01-24T03:25:58.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Git\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-24T03:25:58.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1706066758000,"updatedTime":1706066758000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":0,"words":1},"filePathRelative":"devops/gitlab-ci.md","localizedDate":"2024年1月24日","excerpt":" Git \\n","autoDesc":true}');export{t as data};
diff --git a/assets/gitlab-ci.html-dr4MxX4e.js b/assets/gitlab-ci.html-dr4MxX4e.js
new file mode 100644
index 00000000..c6d3ab40
--- /dev/null
+++ b/assets/gitlab-ci.html-dr4MxX4e.js
@@ -0,0 +1 @@
+import{_ as t,o as a,c,a as e,d as i}from"./app-BDpQ7oW_.js";const o={},r=e("h1",{id:"git",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#git","aria-hidden":"true"},"#"),i(" Git")],-1),s=[r];function n(_,d){return a(),c("div",null,s)}const h=t(o,[["render",n],["__file","gitlab-ci.html.vue"]]);export{h as default};
diff --git a/assets/icon/apple-icon-152.png b/assets/icon/apple-icon-152.png
new file mode 100644
index 0000000000000000000000000000000000000000..f53c6c55b049ea917c283acd84bd5a5f62a289c3
GIT binary patch
literal 3086
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
aFZ=--2|INIa
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
literal 0
HcmV?d00001
diff --git a/assets/icon/chrome-mask-192.png b/assets/icon/chrome-mask-192.png
new file mode 100644
index 0000000000000000000000000000000000000000..77c39a2a828560cdfa70eec967cf4e5892ed767d
GIT binary patch
literal 4079
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
literal 0
HcmV?d00001
diff --git a/assets/icon/chrome-mask-512.png b/assets/icon/chrome-mask-512.png
new file mode 100644
index 0000000000000000000000000000000000000000..b8349f4ea1d00b8bdc5a2dc905376803ffaa317c
GIT binary patch
literal 9208
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