广州图书馆借阅抓取
+欢迎访问我的个人网站,要是能在GitHub上对网站源码给个star就更好了。
+搭建自己的网站的时候,想把自己读过借过的书都想记录一下,大学也做过自己学校的借书记录的爬取,但是数据库删掉了==,只保留一张截图。所以还是要好好珍惜自己阅读的日子吧,记录自己的借书记录——广州图书馆,现在代码已经放在服务器上定时运行,结果查看我的网站(关于我)页面。整个代码采用HttpClient,存储放在MySql,定时使用Spring自带的Schedule,下面是抓取的过程。
From 2f37b3b6cffc36cfd37682c70d8a4bdaf3ce8bb4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 12:31:10 +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 | 89 +++++ ...\346\236\266\346\236\204.html-5y0SHOi3.js" | 1 + ...\346\236\266\346\236\204.html-hY3Aapwp.js" | 1 + ...\351\207\215\346\236\204.html-8BbyrcnW.js" | 1 + ...\351\207\215\346\236\204.html-Mp3R-WY2.js" | 1 + assets/1mysql.html-K9WVG0vy.js | 1 + assets/1mysql.html-_FE7EY_e.js | 1 + ...\344\275\277\347\224\250.html-Dotj8RrP.js" | 1 + ...\344\275\277\347\224\250.html-iRWlAkDH.js" | 241 ++++++++++++ assets/2017.html-dyRb1VL5.js | 1 + assets/2017.html-zfvjl-5A.js | 1 + assets/2018.html-ibX-zlXM.js | 1 + assets/2018.html-pd4XfNXB.js | 1 + assets/2019.html-9VeA33Ol.js | 1 + assets/2019.html-QgZCLsLC.js | 1 + ...\344\273\273\345\212\241.html-3ziLr-Ev.js" | 1 + ...\344\273\273\345\212\241.html-YWN_AF8s.js" | 71 ++++ ...\347\263\273\347\273\237.html-Vr6wBNUl.js" | 224 ++++++++++++ ...\347\263\273\347\273\237.html-irQFt6qr.js" | 1 + assets/404.html-WhIsgby4.js | 1 + assets/404.html-bFP867g4.js | 1 + ...\351\203\250\347\275\262.html-3yoX3jO9.js" | 105 ++++++ ...\351\203\250\347\275\262.html-M8m-ZELy.js" | 1 + ...\345\244\207\344\273\275.html-02CCztL7.js" | 1 + ...\345\244\207\344\273\275.html-EACVFara.js" | 65 ++++ ...\346\217\222\344\273\266.html-rNj4FqCC.js" | 14 + ...\346\217\222\344\273\266.html-x2q9y-pD.js" | 1 + ...\345\210\206\346\236\220.html-6PQREPEX.js" | 1 + ...\345\210\206\346\236\220.html-O9J2qs51.js" | 1 + ...\344\274\230\345\214\226.html-dTPlQo4Y.js" | 1 + ...\344\274\230\345\214\226.html-npDz6nv1.js" | 1 + ...\345\217\202\346\225\260.html-RmR4uDpi.js" | 1 + ...\345\217\202\346\225\260.html-h5u7_TmA.js" | 33 ++ ...\344\275\277\347\224\250.html-C4jpqxXi.js" | 1 + ...\344\275\277\347\224\250.html-tEZFyQZb.js" | 54 +++ assets/aop.html-MaOjAA3t.js | 61 ++++ assets/aop.html-rc4rLz6V.js | 1 + assets/app-slTLQ-pc.js | 247 +++++++++++++ assets/chatgpt.html-KMWnqK_m.js | 110 ++++++ assets/chatgpt.html-soLgBokY.js | 1 + assets/devops-ping-tai.html-eRtFukrp.js | 246 +++++++++++++ assets/devops-ping-tai.html-kDtCSXpk.js | 1 + assets/elastic-spark.html-_qX2JCGa.js | 31 ++ assets/elastic-spark.html-yTkDwYPM.js | 1 + ...272\220\347\240\201debug.html-MPOlcYKm.js" | 1 + ...272\220\347\240\201debug.html-ux_5qZGG.js" | 1 + assets/giscus-NkhROb6B.js | 66 ++++ assets/gitlab-ci.html-HyFv5Ls3.js | 1 + assets/gitlab-ci.html-mSez-CGs.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-2NIkjES-.js | 1 + assets/index.html-2xQqwR-V.js | 1 + assets/index.html-3vTjthN3.js | 1 + assets/index.html-48vkkelG.js | 1 + assets/index.html-5KP2soWP.js | 1 + assets/index.html-5Ud_mAI1.js | 1 + assets/index.html-6zSBWJFl.js | 1 + assets/index.html-8MJuJxlA.js | 1 + assets/index.html-ALK8A2OJ.js | 1 + assets/index.html-DLDIhIzm.js | 1 + assets/index.html-FrLYPym2.js | 1 + assets/index.html-G7ri16RO.js | 1 + assets/index.html-GvvIZ3im.js | 1 + assets/index.html-IZIHDPXq.js | 1 + assets/index.html-K0NPFYN4.js | 1 + assets/index.html-KA0_6BkE.js | 1 + assets/index.html-Lbi6MibC.js | 1 + assets/index.html-NPk7ZlMe.js | 1 + assets/index.html-N_67P6-s.js | 1 + assets/index.html-NqrU9ViM.js | 1 + assets/index.html-NupEPZnP.js | 1 + assets/index.html-Og8tRCl2.js | 1 + assets/index.html-OlL-6l44.js | 1 + assets/index.html-P7BZhZZ3.js | 1 + assets/index.html-Prj9iPTA.js | 1 + assets/index.html-QSycEhOj.js | 1 + assets/index.html-SLeyy5iI.js | 1 + assets/index.html-T5wPpx5i.js | 1 + assets/index.html-TuBE6nT4.js | 1 + assets/index.html-VZNNIAqy.js | 1 + assets/index.html-WyFvweeV.js | 1 + assets/index.html-XULjGA2d.js | 1 + assets/index.html-YC-dEbWq.js | 1 + assets/index.html-YeQQJRDb.js | 1 + assets/index.html-YtSVVbX9.js | 1 + assets/index.html-gD7ZdfDI.js | 1 + assets/index.html-h8W5zSaK.js | 1 + assets/index.html-hCmlVboM.js | 1 + assets/index.html-i1cBLBTr.js | 1 + assets/index.html-iMotbL4n.js | 1 + assets/index.html-j3N_gv-O.js | 1 + assets/index.html-k7gT6RRu.js | 1 + assets/index.html-mNLKf94V.js | 1 + assets/index.html-nAXzS96k.js | 1 + assets/index.html-oIxwfSaO.js | 1 + assets/index.html-qzfzgXy9.js | 1 + assets/index.html-raEG4bsB.js | 1 + assets/index.html-sgH7oDMT.js | 1 + assets/index.html-t2KDSwiJ.js | 1 + assets/index.html-tMixJPN7.js | 1 + assets/index.html-uaK_Ufl7.js | 1 + assets/index.html-va_I8g1i.js | 1 + assets/index.html-vgYoWX9F.js | 1 + assets/index.html-wXTpok86.js | 1 + assets/index.html-xgoJibcf.js | 1 + assets/index.html-xrX_JdJz.js | 1 + assets/index.html-yuZKtvix.js | 1 + assets/index.html-zEn3PTqR.js | 1 + assets/index.html-zcQ2zC0z.js | 1 + assets/index.html-zdhpQIq5.js | 1 + assets/jenkins-x.html-gi90zyZ8.js | 1 + assets/jenkins-x.html-zCVNj34k.js | 1 + assets/kafka.html-F6asoFaN.js | 1 + assets/kafka.html-vXPGDb5r.js | 1 + assets/photoswipe.esm-08_zHRDQ.js | 4 + ...\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-rNePPmRD.js" | 96 +++++ ...\347\274\223\345\255\230.html-ypr-mvgs.js" | 93 +++++ assets/serverlog.html-Hm6VMJqE.js | 3 + assets/serverlog.html-ib9svlbN.js | 1 + assets/spark on k8s operator.html-Uq_G4U-U.js | 1 + assets/spark on k8s operator.html-VI4MG2dr.js | 73 ++++ assets/starcraft-ai.html-cchZINBe.js | 1 + assets/starcraft-ai.html-jENBJ0MN.js | 1 + assets/style-izZKCT-g.css | 1 + assets/tekton.html-7q40Qc0_.js | 1 + assets/tekton.html-U0tQ1pPN.js | 1 + assets/tesla.html-2JZEV-fS.js | 30 ++ assets/tesla.html-NVSkMPRC.js | 1 + assets/tiktok2023.html-VVmqvR2f.js | 1 + assets/tiktok2023.html-qCFByo0Z.js | 1 + assets/webflux.html-BMCSAQQq.js | 1 + assets/webflux.html-L1PizKRY.js | 1 + assets/wewe.html-dxhYsqpt.js | 1 + assets/wewe.html-yoLO0ZeB.js | 1 + assets/zookeeper.html-YcPoe8IG.js | 1 + assets/zookeeper.html-t3PHJ53M.js | 1 + ...\350\257\246\350\247\243.html-NGfX8s6C.js" | 1 + ...\350\257\246\350\247\243.html-dRj9fBxw.js" | 300 +++++++++++++++ ...\350\277\207\347\250\213.html-Fez3X8xk.js" | 1 + ...\350\277\207\347\250\213.html-uFoGHpCT.js" | 9 + ...\344\275\234\345\223\201.html-HGTJItSS.js" | 1 + ...\344\275\234\345\223\201.html-Q7C0m6N_.js" | 1 + ...\345\261\217\351\232\234.html-NZo4BJww.js" | 1 + ...\345\261\217\351\232\234.html-YpsEGPcG.js" | 1 + ...\347\272\277\347\250\213.html-HbXCZyjO.js" | 60 +++ ...\347\272\277\347\250\213.html-aSy3Jyqy.js" | 1 + ...\351\231\220\346\265\201.html-HKqWtH4o.js" | 54 +++ ...\351\231\220\346\265\201.html-SsVfGmol.js" | 1 + ...\346\212\223\345\217\226.html--2YXMPa3.js" | 122 +++++++ ...\346\212\223\345\217\226.html-DyyYunsJ.js" | 1 + ...\347\274\223\345\255\230.html-914rF9h2.js" | 1 + ...\347\274\223\345\255\230.html-D5OE_lZE.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 +++ ...\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 +++ 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 +++++++++ ...\344\270\216\346\236\266\346\236\204.html" | 46 +++ ...\347\253\231\351\207\215\346\236\204.html" | 46 +++ ...\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 +++ personalWebsite/index.html | 46 +++ 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 +++ 243 files changed, 8323 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-5y0SHOi3.js" create mode 100644 "assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-hY3Aapwp.js" create mode 100644 "assets/10.\347\275\221\347\253\231\351\207\215\346\236\204.html-8BbyrcnW.js" create mode 100644 "assets/10.\347\275\221\347\253\231\351\207\215\346\236\204.html-Mp3R-WY2.js" create mode 100644 assets/1mysql.html-K9WVG0vy.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-Dotj8RrP.js" create mode 100644 "assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-iRWlAkDH.js" create mode 100644 assets/2017.html-dyRb1VL5.js create mode 100644 assets/2017.html-zfvjl-5A.js create mode 100644 assets/2018.html-ibX-zlXM.js create mode 100644 assets/2018.html-pd4XfNXB.js create mode 100644 assets/2019.html-9VeA33Ol.js create mode 100644 assets/2019.html-QgZCLsLC.js create mode 100644 "assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-3ziLr-Ev.js" create mode 100644 "assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-YWN_AF8s.js" create mode 100644 "assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-Vr6wBNUl.js" create mode 100644 "assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-irQFt6qr.js" create mode 100644 assets/404.html-WhIsgby4.js create mode 100644 assets/404.html-bFP867g4.js create mode 100644 "assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-3yoX3jO9.js" create mode 100644 "assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-M8m-ZELy.js" create mode 100644 "assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-02CCztL7.js" create mode 100644 "assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-EACVFara.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-rNj4FqCC.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-x2q9y-pD.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-6PQREPEX.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-O9J2qs51.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-dTPlQo4Y.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-npDz6nv1.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-h5u7_TmA.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-tEZFyQZb.js" create mode 100644 assets/aop.html-MaOjAA3t.js create mode 100644 assets/aop.html-rc4rLz6V.js create mode 100644 assets/app-slTLQ-pc.js create mode 100644 assets/chatgpt.html-KMWnqK_m.js create mode 100644 assets/chatgpt.html-soLgBokY.js create mode 100644 assets/devops-ping-tai.html-eRtFukrp.js create mode 100644 assets/devops-ping-tai.html-kDtCSXpk.js create mode 100644 assets/elastic-spark.html-_qX2JCGa.js create mode 100644 assets/elastic-spark.html-yTkDwYPM.js create mode 100644 "assets/elasticsearch\346\272\220\347\240\201debug.html-MPOlcYKm.js" create mode 100644 "assets/elasticsearch\346\272\220\347\240\201debug.html-ux_5qZGG.js" create mode 100644 assets/giscus-NkhROb6B.js create mode 100644 assets/gitlab-ci.html-HyFv5Ls3.js create mode 100644 assets/gitlab-ci.html-mSez-CGs.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-2NIkjES-.js create mode 100644 assets/index.html-2xQqwR-V.js create mode 100644 assets/index.html-3vTjthN3.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-6zSBWJFl.js create mode 100644 assets/index.html-8MJuJxlA.js create mode 100644 assets/index.html-ALK8A2OJ.js create mode 100644 assets/index.html-DLDIhIzm.js create mode 100644 assets/index.html-FrLYPym2.js create mode 100644 assets/index.html-G7ri16RO.js create mode 100644 assets/index.html-GvvIZ3im.js create mode 100644 assets/index.html-IZIHDPXq.js create mode 100644 assets/index.html-K0NPFYN4.js create mode 100644 assets/index.html-KA0_6BkE.js create mode 100644 assets/index.html-Lbi6MibC.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-NqrU9ViM.js create mode 100644 assets/index.html-NupEPZnP.js create mode 100644 assets/index.html-Og8tRCl2.js create mode 100644 assets/index.html-OlL-6l44.js create mode 100644 assets/index.html-P7BZhZZ3.js create mode 100644 assets/index.html-Prj9iPTA.js create mode 100644 assets/index.html-QSycEhOj.js create mode 100644 assets/index.html-SLeyy5iI.js create mode 100644 assets/index.html-T5wPpx5i.js create mode 100644 assets/index.html-TuBE6nT4.js create mode 100644 assets/index.html-VZNNIAqy.js create mode 100644 assets/index.html-WyFvweeV.js create mode 100644 assets/index.html-XULjGA2d.js create mode 100644 assets/index.html-YC-dEbWq.js create mode 100644 assets/index.html-YeQQJRDb.js create mode 100644 assets/index.html-YtSVVbX9.js create mode 100644 assets/index.html-gD7ZdfDI.js create mode 100644 assets/index.html-h8W5zSaK.js create mode 100644 assets/index.html-hCmlVboM.js create mode 100644 assets/index.html-i1cBLBTr.js create mode 100644 assets/index.html-iMotbL4n.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-mNLKf94V.js create mode 100644 assets/index.html-nAXzS96k.js create mode 100644 assets/index.html-oIxwfSaO.js create mode 100644 assets/index.html-qzfzgXy9.js create mode 100644 assets/index.html-raEG4bsB.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-uaK_Ufl7.js create mode 100644 assets/index.html-va_I8g1i.js create mode 100644 assets/index.html-vgYoWX9F.js create mode 100644 assets/index.html-wXTpok86.js create mode 100644 assets/index.html-xgoJibcf.js create mode 100644 assets/index.html-xrX_JdJz.js create mode 100644 assets/index.html-yuZKtvix.js create mode 100644 assets/index.html-zEn3PTqR.js create mode 100644 assets/index.html-zcQ2zC0z.js create mode 100644 assets/index.html-zdhpQIq5.js create mode 100644 assets/jenkins-x.html-gi90zyZ8.js create mode 100644 assets/jenkins-x.html-zCVNj34k.js create mode 100644 assets/kafka.html-F6asoFaN.js create mode 100644 assets/kafka.html-vXPGDb5r.js create mode 100644 assets/photoswipe.esm-08_zHRDQ.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-rNePPmRD.js" create mode 100644 "assets/redis\347\274\223\345\255\230.html-ypr-mvgs.js" create mode 100644 assets/serverlog.html-Hm6VMJqE.js create mode 100644 assets/serverlog.html-ib9svlbN.js create mode 100644 assets/spark on k8s operator.html-Uq_G4U-U.js create mode 100644 assets/spark on k8s operator.html-VI4MG2dr.js create mode 100644 assets/starcraft-ai.html-cchZINBe.js create mode 100644 assets/starcraft-ai.html-jENBJ0MN.js create mode 100644 assets/style-izZKCT-g.css create mode 100644 assets/tekton.html-7q40Qc0_.js create mode 100644 assets/tekton.html-U0tQ1pPN.js create mode 100644 assets/tesla.html-2JZEV-fS.js create mode 100644 assets/tesla.html-NVSkMPRC.js create mode 100644 assets/tiktok2023.html-VVmqvR2f.js create mode 100644 assets/tiktok2023.html-qCFByo0Z.js create mode 100644 assets/webflux.html-BMCSAQQq.js create mode 100644 assets/webflux.html-L1PizKRY.js create mode 100644 assets/wewe.html-dxhYsqpt.js create mode 100644 assets/wewe.html-yoLO0ZeB.js create mode 100644 assets/zookeeper.html-YcPoe8IG.js create mode 100644 assets/zookeeper.html-t3PHJ53M.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-dRj9fBxw.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\200\346\254\241jvm\350\260\203\344\274\230\350\277\207\347\250\213.html-uFoGHpCT.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-Q7C0m6N_.js" create mode 100644 "assets/\345\206\205\345\255\230\345\261\217\351\232\234.html-NZo4BJww.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-HbXCZyjO.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-HKqWtH4o.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\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--2YXMPa3.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/\346\225\260\346\215\256\345\272\223\347\274\223\345\255\230.html-914rF9h2.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 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/\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 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 "personalWebsite/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html" create mode 100644 "personalWebsite/10.\347\275\221\347\253\231\351\207\215\346\236\204.html" create mode 100644 "personalWebsite/2.Lucene\347\232\204\344\275\277\347\224\250.html" create mode 100644 "personalWebsite/3.\345\256\232\346\227\266\344\273\273\345\212\241.html" create mode 100644 "personalWebsite/4.\346\227\245\345\277\227\347\263\273\347\273\237.html" create mode 100644 "personalWebsite/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html" create mode 100644 "personalWebsite/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html" create mode 100644 "personalWebsite/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 "personalWebsite/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 "personalWebsite/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html" create mode 100644 personalWebsite/index.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..920c0a4d --- /dev/null +++ b/404.html @@ -0,0 +1,46 @@ + + +
+ + + + + + +留空
普通人
运行流程分析
日志系统架构如下:
',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-hY3Aapwp.js" "b/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-hY3Aapwp.js" new file mode 100644 index 00000000..f9faba7d --- /dev/null +++ "b/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-hY3Aapwp.js" @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-37ac02fe","path":"/personalWebsite/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/personalWebsite/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-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\\":\\"1.历史与架构\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-26T03:58:56.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":1706182936000,"updatedTime":1706241536000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":6.79,"words":2038},"filePathRelative":"personalWebsite/1.历史与架构.md","localizedDate":"2024年1月25日","excerpt":"各位大佬瞄一眼我的个人网站呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。
\\n大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。
因原本的
\\n","autoDesc":true}');export{e as data}; diff --git "a/assets/10.\347\275\221\347\253\231\351\207\215\346\236\204.html-Mp3R-WY2.js" "b/assets/10.\347\275\221\347\253\231\351\207\215\346\236\204.html-Mp3R-WY2.js" new file mode 100644 index 00000000..1d2ada1c --- /dev/null +++ "b/assets/10.\347\275\221\347\253\231\351\207\215\346\236\204.html-Mp3R-WY2.js" @@ -0,0 +1 @@ +import{_,o as t,c as a,a as e,d as c}from"./app-slTLQ-pc.js";const o={},s=e("h1",{id:"_10-网站重构",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_10-网站重构","aria-hidden":"true"},"#"),c(" 10.网站重构")],-1),n=e("p",null,"因原本的",-1),r=[s,n];function d(i,l){return t(),a("div",null,r)}const f=_(o,[["render",d],["__file","10.网站重构.html.vue"]]);export{f as default}; diff --git a/assets/1mysql.html-K9WVG0vy.js b/assets/1mysql.html-K9WVG0vy.js new file mode 100644 index 00000000..ea23ffa0 --- /dev/null +++ b/assets/1mysql.html-K9WVG0vy.js @@ -0,0 +1 @@ +import{_ as t,o as s,c as a,a as e,d as i}from"./app-slTLQ-pc.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":"首先,帮忙点击一下我的网站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-iRWlAkDH.js" "b/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-iRWlAkDH.js" new file mode 100644 index 00000000..74bf9f0f --- /dev/null +++ "b/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-iRWlAkDH.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-slTLQ-pc.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,版本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); //通过解析要查询的String,获取查询对象
+ TopDocs docs = searcher.search(query, 10);//开始查询,查询前10条数据,将记录保存在docs中,
+ for (ScoreDoc scoreDoc : docs.scoreDocs) { //取出每条查询结果
+ Document doc = searcher.doc(scoreDoc.doc); //scoreDoc.doc相当于docID,根据这个docID来获取文档
+ System.out.println(doc.get("title")); //fullPath是刚刚建立索引的时候我们定义的一个字段
+ }
+ 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); //scoreDoc.doc相当于docID,根据这个docID来获取文档
+ 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>堆.栈和常量池 笔记
+
ScoreDoc lastBottom = null;//相当于pageSize
+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); //lastBottom(pageSize),pagehits(pagenum)
+
<dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-suggest</artifactId>
+ <version>6.6.0</version>
+</dependency>
+
public class Blog implements Serializable {
+
InputIterator的几个方法:
+long weight():返回的权重值,大小会影响排序,默认是1L
+BytesRef payload():对某个对象进行序列化
+boolean hasPayloads():是否有设置payload信息
+Set<BytesRef> contexts():存入context,context里可以是任意的自定义数据,一般用于数据过滤
+boolean hasContexts():判断是否有下一个,默认为false
+
public class BlogIterator implements InputIterator {
+ /**
+ * logger
+ */
+ 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 {
+ //返回当前Project的name值,把blog类的name属性值作为key
+ return new BytesRef(Jsoup.parse(currentBlog.getTitle()).text().getBytes("utf8"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * 将Blog对象序列化存入payload
+ * 可以只将所需要的字段存入payload,这里对整个实体类进行序列化,方便以后需求,不建议采用这种方法
+ */
+ @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");
+ }
+ }
+
+ /**
+ * 返回权重值,这个值会影响排序
+ * 这里以产品的销售量作为权重值,weight值即最终返回的热词列表里每个热词的权重值
+ */
+ @Override
+ public long weight() {
+ return currentBlog.getHits(); //change to hits
+ }
+}
+
/**
+ * ajax建立索引
+ */
+@Override
+public void ajaxbuild() {
+ try {
+ Directory dir = FSDirectory.open(Paths.get("autocomplete"));
+ SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();
+ AnalyzingInfixSuggester suggester = new AnalyzingInfixSuggester(dir, analyzer);
+ //创建Blog测试数据
+ List<Blog> blogs = blogMapper.getAllBlog();
+ suggester.build(new BlogIterator(blogs.iterator()));
+ } catch (IOException e) {
+ System.err.println("Error!");
+ }
+}
+
@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;
+ }
+}
+
@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));//返回的数据使用json
+}
+
<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 start **********************/
+ $('#remote_input').autocomplete({
+ source: [
+ {
+ url: "ajaxsearch.html?keyword=%QUERY%",
+ type: 'remote'
+ }
+ ]
+ });
+ /********************* remote end ********************/
+</script>
+
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月,宣告了自己春招结束,宣告自己要去外包,同时也宣告自己大学这些努力全部白费,跟那个灌毒鸡汤天天打游戏的人同一起跑线。
七月初入职的时候,问了问那些一起应届入职的同学,跟别人交流一下面试被问的问题,只有线程池,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":"2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。
\\n17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?
and ... 广州拜拜,晚上人少的时候,跟妹纸去珠江新城真的很美好
入职的时候是做日志收集的,就是flume+kafka+es这一套,遇到了不少大佬,嗯,感觉挺好的,打算好好干,一个半月后不知怎么滴,被拉去做容器云了,然后就开始了天天调jenkins、gitlab这些没什么用的api,开始了增删改查的历程,很烦,研究jenkins、gitlab对于自己的技术没什么提升,又不得不做,而且大小周+加班这么做,回到家自己看java、netty、golang的书籍,可是没项目做没实践,过几个月就忘光了,有段时间真的很烦很烦,根本不想工作,天天调api,而且是jenkins、gitlab这些没什么卵用的api,至今也没找到什么办法。。。。
公司发展太快,也实在让人不知所措,一不小心部门被架空了,什么预兆都没有,被分到其他部门,然后发现这个部门领导内斗真的是,“三国争霸”吧,无奈成为炮灰,不同的领导不同的要求,安安静静敲个代码怎么这么难。。。。
去年的学习拉下了不少,文章也写的少了,总写那些入门的文章确实没有什么意思,买的书虽然没有17年的多吧,不过也不少了,也看了挺多本书的,虽然我还是不满意自己的阅读量。
这几年要开始抓准一个框架了,好好专研一下,也要开始学习一下go了,希望能参与一些github的项目,好好努力吧。
平时没事总是宅在家里打游戏,差不多持续到下半年吧,那会打游戏去楼下吃东西的时候老是觉得眼神恍惚,盯着电子产品太多了,然后就跟别人跑步去了,每周去一次人才公园,跑步健身,人才公园真的是深圳跑步最好的一个地方了,桥上总有一群摄影师,好想在深圳湾买一套房子,看了看房价,算了算了,深圳的房,真的贵的离谱。19年也要多多运动,健康第一健康第一。
想不起来还有什么要说的了,毕竟程序员,好像每天的生活都一样,就展望一下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":"年底老姐结婚,跑回家去了,忙着一直没写,本来想回深圳的时候空余的时候写写,没想到一直加班,嗯,9点半下班那种,偶尔也趁着间隙的时间,一段一段的凑着吧。
\\n想着17年12月31号写的那篇文章https://www.cnblogs.com/w1570631036/p/8158284.html,感叹18年还算恢复了点。
\\n2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。
19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。
从18年底开始吧,大概就知道领导对容器云这么快的完全架构设计错误,就是一个完完全全错误的产品,其他人也觉得有点很有问题,但老板就是固执不听,结果一个跑路,一个被压得懒得反抗,然后我一个人跟老板和项目经理怼了前前后后半年,真是惨啊,还要被骂,各种拉到小黑屋里批斗,一直在对他们强调:没有这么做的!!!然后被以年轻人,不懂事,不要抱怨,长大了以后就领会了怼回来,当时气得真是无语。。。。。自己调研的阿里云、腾讯云、青云,还有其他小公司的容器,发现真的只有我们这么设计,完全错误的方向,,,,直到老板走了之后,才开始决定重构,走上正轨。
之后有了点起色,然后开始着重强调了DevOps的重要性,期初也没人理解,还被骂天天研究技术不干活。。。这东西没技术,但是真的是公司十分需要的公司好么!!可惜公司对这个产品很失望,也不给人,期间还说要暂停项目,唉,这么大的项目就给几个人怎么做,谁都不乐意,就这么过的很憋屈吧,开始了维护的日子。。。
工作上,蛮多人对我挺好的,领导,同事,不过有时候憋屈的时候还是有了点情绪化,有时候有点悲伤的想法,浮躁、暴躁,出去面试了几次,感觉不是自己能力不好,而是市场上的真的需要3+年以上的。。。。不过感觉自己能在这里憋屈的过了这么久,也是很佩服自己的,哈哈,用同事的话来说就是:当做游戏里的练级,锻炼自己哈哈哈
项目的方向错误,导致自己写的代码都是很简单的增删改查,没有技术含量的那种,也最终导致自己浪费了不少时间,上半年算是很气愤吧,不想就这么浪费掉这些时间,虽然期间看了各种各样的东西,比如Netty、Go、操作系统什么的,最终发现,如果不在项目中使用的话,真的会忘,而且很快就忘掉,最后的还是决定学习项目相关度比较大的东西了,比如Go,如果项目不是很大,小项目的话,就用Go来写,这么做感觉提升还是挺大的。
过去一年往南山图书馆借了不少书,省了不少钱,虽然没怎么看,但我至少有个奋斗的心啊,哈哈哈哈哈哈哈哈,文章写得少了,因为感觉写不出好东西,总是入门的那种,不深,不值得学习,想想到时候把别人给坑了,也不好意思。
操作系统感觉还是要好好学学了,加油
Kubernetes就是未来的方向,有时候翻开源码看看,又不敢往下面看了,对底层不熟吧,今年要多多研究下Kubernetes的源码了,至于Spring那一套,也不知道该不该放弃,或者都学习一下?云原生就是趋势。
吵架了,没心思写
过去一年还是把运动算是坚持了下来,每个月必去深圳湾跑一次。还是没怎么睡好,工作感情上都有点不顺,加上自己本身就难以入睡,有时候躺床上就是怎么也睡不着,还长了痘痘,要跑去医院那种,可怕,老了,还是要早点睡觉,多走走多运动,好久没打羽毛球了,自己也不想有空的时候只会打游戏,今年继续加油,多运动吧。
还爬了两次南山
看了周围蛮多同事去了腾讯阿里,有点心动,好想去csig,没到3年真的让人很抓狂。
过去一年过的蛮憋屈的,特别是工作不顺,加上跟女朋友吵架,心态爆炸。。。
每年这个时候,都不敢有太大的期望了,祝大家都健健康康的,工作顺利!!
当然,如果有可能的话,我想去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/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,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。
\\n19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。
从18年底开始吧,大概就知道领导对容器云这么快的完全架构设计错误,就是一个完完全全错误的产品,其他人也觉得有点很有问题,但老板就是固执不听,结果一个跑路,一个被压得懒得反抗,然后我一个人跟老板和项目经理怼了前前后后半年,真是惨啊,还要被骂,各种拉到小黑屋里批斗,一直在对他们强调:没有这么做的!!!然后被以年轻人,不懂事,不要抱怨,长大了以后就领会了怼回来,当时气得真是无语。。。。。自己调研的阿里云、腾讯云、青云,还有其他小公司的容器,发现真的只有我们这么设计,完全错误的方向,,,,直到老板走了之后,才开始决定重构,走上正轨。
","autoDesc":true}');export{e as data}; diff --git "a/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-3ziLr-Ev.js" "b/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-3ziLr-Ev.js" new file mode 100644 index 00000000..d76df3d4 --- /dev/null +++ "b/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-3ziLr-Ev.js" @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-731a76b6","path":"/personalWebsite/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/personalWebsite/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-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\\":\\"3.定时任务\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-26T03:58:56.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":1706182936000,"updatedTime":1706241536000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":3.55,"words":1064},"filePathRelative":"personalWebsite/3.定时任务.md","localizedDate":"2024年1月25日","excerpt":"先看一下Quartz的架构图:
\\n\\n先看一下Quartz的架构图:
<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")//在spring中注册一个mysqlService的Bean
+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);//执行linux语句
+ 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"/>
+ <!-- cron表达式,每周五2点59分运行-->
+ <property name="cronExpression" value="0 59 2 ? * FRI"/>
+</bean>
+<!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
+<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
+ <property name="triggers">
+ <list>
+ <ref bean="myTrigger"/>
+ </list>
+ </property>
+</bean>
+
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)
+
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
+
先在百度统计中注册登录之后,进入管理页面,新增网站,然后在代码管理中获取安装代码,大部分人的代码都是类似的,除了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,然后开始使用三个参数来获取数据。
参数名称 | 参数类型 | 描述 |
---|---|---|
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("-", "") # 格式化成yyyyMMdd格式
+
说明: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")
+
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['body'][key] = kw[key]
+
使用方式:
result = self.getresult(start, end, "source/all/a",
+ "pv_count,visitor_count,avg_visit_time", viewType='visitor') #其中viewTYpe便是可变参数
+
(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') # TODO redis地址
+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)
+# json
+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]))
+
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)
+
+
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, //间隔x轴的间隔
+ y: 0 //间隔Y轴的间隔
+ },
+ 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': '江苏'}]
+
<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>
+
结果如下:
欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
","autoDesc":true}');export{e as data}; 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/404.html-bFP867g4.js b/assets/404.html-bFP867g4.js new file mode 100644 index 00000000..363c4d2c --- /dev/null +++ b/assets/404.html-bFP867g4.js @@ -0,0 +1 @@ +import{_ as e,o as c,c as t}from"./app-slTLQ-pc.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/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-3yoX3jO9.js" "b/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-3yoX3jO9.js" new file mode 100644 index 00000000..7669550e --- /dev/null +++ "b/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-3yoX3jO9.js" @@ -0,0 +1,105 @@ +import{_ as l,r,o,c as i,a,d as n,b as s,e}from"./app-slTLQ-pc.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
+
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;
+ ...
+ }
+ ...
+
之前有使用过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;
+ ...
+
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;即可
配置好了负载均衡之后,如果有一台服务器挂了怎么办?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;
+}
+
首先,添加相关依赖
<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中添加:
<!-- redis -->
+ <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>
+
+ <!-- 将session放入redis -->
+ <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查看结果:
欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com,个人网站代码地址:https://github.com/Zephery/newblog。
\\n洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。
先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地:
\\n\\n由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下:
","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-EACVFara.js" "b/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-EACVFara.js" new file mode 100644 index 00000000..85bb9e40 --- /dev/null +++ "b/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-EACVFara.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-slTLQ-pc.js";const m={},c=t(`先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地:
由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下:
果然,36ms。。。看起来挺小的,但是对比一下sql执行语句的时间:
大部分都能在10ms内完成,而最长的语句是insert语句,可见,由于异地导致的36ms延时还是比较大的,捣鼓了一下,最后还是选择换个架构,每个服务器读取自己的数据库,然后数据库底层做一下主主复制,让数据同步。最终架构如下:
数据库复制的基本问题就是让一台服务器的数据与其他服务器保持同步。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》。
由于是个自己的小网站,就不做过多的操作了,直接使用root账号
接下来要对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为要备份的数据库。
从库的配置跟主库类似,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流)
代码样式,这一点是不如WORDPRESS的插件了,不过已经可以了。
目前最常用的是highcharts跟echart,目前个人博客中的日志系统主要还是采用了highcharts,主要还是颜色什么的格调比较相符吧,其次是因为对echarts印象不太友好,比如下面做这张,打开网页后,缩小浏览器,百度的地域图却不能自适应,出现了越界,而highcharts的全部都能自适应调整。想起有次面试,我说我用的highcharts,面试官一脸嫌弃。。。(网上这么多人鄙视百度是假的?)
不过地图确确实实是echarts的优势,毕竟还是自家的东西了解自家,不过前段时间去看了看echarts的官网,已经不提供下载了。如果有需要,还是去csdn上搜索吧,或者替换为highmap。
#share a {
+ width: 34px;
+ height: 34px;
+ padding: 0;
+ margin: 6px;
+ border-radius: 25px;
+ transition: all .4s;
+}
+/*主要的是替换掉backgound的背景图片*/
+#share a.bds_qzone {
+ background: url(http://image.wenzhihuai.com/t_QQZone.png) no-repeat;
+ background-size: 34px 34px;
+}
+
改完之后的效果。
欢迎访问我的网站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.标签云
JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
\\njava -Xmx3550m -Xms3550m -Xmn2g -Xss128k\\n
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会根据当前系统配置进行判断。
如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等。
典型配置:
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区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开。
如上文所述,并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。
典型配置:
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:与上面几个配合使用,把相关日志信息记录到文件以便分析。
常见配置汇总
-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:设置持久代大小
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得:
并发垃圾收集信息
持久代并发收集次数
传统GC信息
花在年轻代和年老代回收上的时间比例
减少年轻代和年老代花费的时间,一般会提高应用的效率
吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他 会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么 并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩
Prometheus的基本原理是通过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-tEZFyQZb.js" "b/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-tEZFyQZb.js" new file mode 100644 index 00000000..0a559f77 --- /dev/null +++ "b/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-tEZFyQZb.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-slTLQ-pc.js";const l={},u=t(`Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。
<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就可以看到
`,11),r={href:"https://cloud.tencent.com/document/product/1416/56031%EF%BC%89",target:"_blank",rel:"noopener noreferrer"},d=t(`大部分现实场景中,如果每增加一个服务,都需要开发去配置的话,不仅沟通成本高,也导致因配错而起的运维成本很高,采用主动上报方式比较简单,方便规避一些问题。
主动上报除了需要引入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>
+
之后,为了安全考虑,需要把endpoints的所有信息都关闭掉,免得被泄露出去。
management:
+ endpoints:
+ #一定要设为false,防止不小心暴露/actuator相关接口触发安全工单
+ 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
大致看了下 simpleclient_pushgateway和spring-boot-starter-actuator的源码,并没有对http的请求发起日志,调试的时候都不知道是不是正常上报过去了,只能采取抓包来研究下。
平均间隔5s左右,符合配置文件里的设置。
除了通用的封装好的指标之外,也可以自定义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-MaOjAA3t.js b/assets/aop.html-MaOjAA3t.js new file mode 100644 index 00000000..0306cda2 --- /dev/null +++ b/assets/aop.html-MaOjAA3t.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-slTLQ-pc.js";const d={},c=r('在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了。AOP关注的是横向的,而OOP的是纵向。
Spring自2.0版本开始采用@AspectJ注解非常容易的定义一个切面。@AspectJ注解使用AspectJ切点表达式语法进行切点定义,可以通过切点函数、运算符、通配符等高级功能进行切点定义,拥有强大的连接点描述能力。
AOP(Aspect Oriented Programming)面向切面编程,通过预编译方式和运行期动态代理实现程序功能的横向多模块统一控制的一种技术。AOP是OOP的补充,是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP可以分为静态织入与动态织入,静态织入即在编译前将需织入内容写入目标模块中,这样成本非常高。动态织入则不需要改变目标模块。Spring框架实现了AOP,使用注解配置完成AOP比使用XML配置要更加方便与直观。
Aspect:一个模块用来关注多个类的切面。在JAVA EE的应用中,事务是AOP的典型例子。
Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.
Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.
Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
Target(目标对象):代理的目标对象
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入.
Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类Aspect(切面): 是切入点和通知(引介)的结合
Spring实现AOP主要是由IOC容器来负责生成、管理的。其创建的方式有两种:
[1] Before:前置通知,在方法执行之前执行
[2] After:后置通知,在方法执行之后执行
[3] AfterRunning:返回通知,在方法返回结果之后执行
[4] AfterThrowing:异常通知,在方法抛出异常之后执行
[5] Around:环绕通知,围绕着方法执行
其中,环绕通知是最常见的一种通知注解,特别是在缓存的使用中,例如:Spring-Cache中的使用,在service的方法中添加一个cache的注解,通过AOP来拦截,如果缓存中已经存在,则直接返回结果,如果没有,再进行service的访问。
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(` <!--自动扫描自定义切面-->
+ <aop:aspectj-autoproxy/>
+
/**
+ * 可以使用 @Order 注解指定切面的优先级, 值越小优先级越高
+ */
+@Order(2)
+@Aspect
+@Component
+public class TimeInterceptor {
+}
+
@Pointcut("execution(* com.myblog.service.impl.BlogServiceImpl.*(..))")
+ public void pointcut() {
+ }
+
@Before("pointcut()")
+ public void before(JoinPoint jp) {
+ logger.info(jp.getSignature().getName());
+ logger.info("----------前置通知----------");
+ }
+
@After("pointcut()")
+ public void after(JoinPoint jp) {
+ logger.info("----------最终通知----------");
+ }
+
+
这里,特别要注意的是要抛出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;
+ }
+
@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("----------返回结果----------");
+ }
+
@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("----------异常通知----------");
+ }
+
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/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":"在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了。AOP关注的是横向的,而OOP的是纵向。
\\n","autoDesc":true}');export{e as data}; diff --git a/assets/app-slTLQ-pc.js b/assets/app-slTLQ-pc.js new file mode 100644 index 00000000..a66cddc5 --- /dev/null +++ b/assets/app-slTLQ-pc.js @@ -0,0 +1,247 @@ +/** +* @vue/shared v3.4.15 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function ia(e,t){const n=new Set(e.split(","));return t?r=>n.has(r.toLowerCase()):r=>n.has(r)}const Le={},fn=[],Qe=()=>{},Vu=()=>!1,Xn=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),sa=e=>e.startsWith("onUpdate:"),Pe=Object.assign,ca=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},$u=Object.prototype.hasOwnProperty,fe=(e,t)=>$u.call(e,t),X=Array.isArray,Mn=e=>el(e)==="[object Map]",Nu=e=>el(e)==="[object Set]",re=e=>typeof e=="function",oe=e=>typeof e=="string",Xr=e=>typeof e=="symbol",Ae=e=>e!==null&&typeof e=="object",Ti=e=>(Ae(e)||re(e))&&re(e.then)&&re(e.catch),Hu=Object.prototype.toString,el=e=>Hu.call(e),zu=e=>el(e).slice(8,-1),ju=e=>el(e)==="[object Object]",ua=e=>oe(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Fn=ia(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),tl=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},qu=/-(\w)/g,nt=tl(e=>e.replace(qu,(t,n)=>n?n.toUpperCase():"")),Wu=/\B([A-Z])/g,Ln=tl(e=>e.replace(Wu,"-$1").toLowerCase()),er=tl(e=>e.charAt(0).toUpperCase()+e.slice(1)),ml=tl(e=>e?`on${er(e)}`:""),$t=(e,t)=>!Object.is(e,t),gl=(e,t)=>{for(let n=0;nW?Ve(v,T,R,!0,!1,Q):V(m,L,I,T,R,j,O,M,Q)},St=(v,m,L,I,T,R,j,O,M)=>{let P=0;const W=m.length;let Q=v.length-1,Z=W-1;for(;P<=Q&&P<=Z;){const te=v[P],ae=m[P]=M?Bt(m[P]):ot(m[P]);if(Jt(te,ae))E(te,ae,L,null,T,R,j,O,M);else break;P++}for(;P<=Q&&P<=Z;){const te=v[Q],ae=m[Z]=M?Bt(m[Z]):ot(m[Z]);if(Jt(te,ae))E(te,ae,L,null,T,R,j,O,M);else break;Q--,Z--}if(P>Q){if(P<=Z){const te=Z+1,ae=teZ)for(;P<=Q;)He(v[P],T,R,!0),P++;else{const te=P,ae=P,ye=new Map;for(P=ae;P<=Z;P++){const We=m[P]=M?Bt(m[P]):ot(m[P]);We.key!=null&&ye.set(We.key,P)}let we,Oe=0;const at=Z-ae+1;let sn=!1,to=0;const Pn=new Array(at);for(P=0;P =at){He(We,T,R,!0);continue}let ft;if(We.key!=null)ft=ye.get(We.key);else for(we=ae;we<=Z;we++)if(Pn[we-ae]===0&&Jt(We,m[we])){ft=we;break}ft===void 0?He(We,T,R,!0):(Pn[ft-ae]=P+1,ft>=to?to=ft:sn=!0,E(We,m[ft],L,null,T,R,j,O,M),Oe++)}const no=sn?kf(Pn):fn;for(we=no.length-1,P=at-1;P>=0;P--){const We=ae+P,ft=m[We],ro=We+1 {const{el:R,type:j,transition:O,children:M,shapeFlag:P}=v;if(P&6){dt(v.component.subTree,m,L,I);return}if(P&128){v.suspense.move(m,L,I);return}if(P&64){j.move(v,m,L,U);return}if(j===Ue){r(R,m,L);for(let Q=0;Q O.enter(R),T);else{const{leave:Q,delayLeave:Z,afterLeave:te}=O,ae=()=>r(R,m,L),ye=()=>{Q(R,()=>{ae(),te&&te()})};Z?Z(R,ae,ye):ye()}else r(R,m,L)},He=(v,m,L,I=!1,T=!1)=>{const{type:R,props:j,ref:O,children:M,dynamicChildren:P,shapeFlag:W,patchFlag:Q,dirs:Z}=v;if(O!=null&&Ur(O,null,L,v,!0),W&256){m.ctx.deactivate(v);return}const te=W&1&&Z,ae=!$n(v);let ye;if(ae&&(ye=j&&j.onVnodeBeforeUnmount)&&Ze(ye,m,v),W&6)Er(v.component,L,I);else{if(W&128){v.suspense.unmount(L,I);return}te&&pt(v,null,m,"beforeUnmount"),W&64?v.type.remove(v,m,L,T,U,I):P&&(R!==Ue||Q>0&&Q&64)?Ve(P,m,L,!1,!0):(R===Ue&&Q&384||!T&&W&16)&&Ve(M,m,L),I&&an(v)}(ae&&(ye=j&&j.onVnodeUnmounted)||te)&&ze(()=>{ye&&Ze(ye,m,v),te&&pt(v,null,m,"unmounted")},L)},an=v=>{const{type:m,el:L,anchor:I,transition:T}=v;if(m===Ue){on(L,I);return}if(m===Hn){S(v);return}const R=()=>{l(L),T&&!T.persisted&&T.afterLeave&&T.afterLeave()};if(v.shapeFlag&1&&T&&!T.persisted){const{leave:j,delayLeave:O}=T,M=()=>j(L,R);O?O(v.el,R,M):M()}else R()},on=(v,m)=>{let L;for(;v!==m;)L=p(v),l(v),v=L;l(m)},Er=(v,m,L)=>{const{bum:I,scope:T,update:R,subTree:j,um:O}=v;I&&gl(I),T.stop(),R&&(R.active=!1,He(j,v,m,L)),O&&ze(O,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())},Ve=(v,m,L,I=!1,T=!1,R=0)=>{for(let j=R;j v.shapeFlag&6?C(v.component.subTree):v.shapeFlag&128?v.suspense.next():p(v.anchor||v.el);let q=!1;const z=(v,m,L)=>{v==null?m._vnode&&He(m._vnode,null,null,!0):E(m._vnode||null,v,m,null,null,null,L),q||(q=!0,po(),jr(),q=!1),m._vnode=v},U={p:E,um:He,m:dt,r:an,mt:Se,mc:V,pc:K,pbc:N,n:C,o:e};let ve,ke;return t&&([ve,ke]=t(U)),{render:z,hydrate:ve,createApp:df(z,ve)}}function kl({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 Gt({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function bs(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function _s(e,t,n=!1){const r=e.children,l=t.children;if(X(r)&&X(l))for(let a=0;a >1,e[n[s]]0&&(t[r]=n[a-1]),n[a]=r)}}for(a=n.length,o=n[a-1];a-- >0;)n[a]=o,o=t[o];return n}function ys(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:ys(t)}const wf=e=>e.__isTeleport,Ue=Symbol.for("v-fgt"),bn=Symbol.for("v-txt"),vt=Symbol.for("v-cmt"),Hn=Symbol.for("v-stc"),zn=[];let it=null;function Lf(e=!1){zn.push(it=e?null:[])}function xf(){zn.pop(),it=zn[zn.length-1]||null}let Yn=1;function xo(e){Yn+=e}function Es(e){return e.dynamicChildren=Yn>0?it||fn:null,xf(),Yn>0&&it&&it.push(e),e}function t3(e,t,n,r,l,a){return Es(lr(e,t,n,r,l,a,!0))}function Af(e,t,n,r,l){return Es(Ce(e,t,n,r,l,!0))}function Gl(e){return e?e.__v_isVNode===!0:!1}function Jt(e,t){return e.type===t.type&&e.key===t.key}const sl="__vInternal",ks=({key:e})=>e??null,$r=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?oe(e)||Be(e)||re(e)?{i:Xe,r:e,k:t,f:!!n}:e:null);function lr(e,t=null,n=null,r=0,l=null,a=e===Ue?0:1,o=!1,s=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ks(t),ref:t&&$r(t),scopeId:ns,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:a,patchFlag:r,dynamicProps:l,dynamicChildren:null,appContext:null,ctx:Xe};return s?(Sa(c,n),a&128&&e.normalize(c)):n&&(c.shapeFlag|=oe(n)?8:16),Yn>0&&!o&&it&&(c.patchFlag>0||a&6)&&c.patchFlag!==32&&it.push(c),c}const Ce=Sf;function Sf(e,t=null,n=null,r=0,l=null,a=!1){if((!e||e===Nd)&&(e=vt),Gl(e)){const s=Nt(e,t,!0);return n&&Sa(s,n),Yn>0&&!a&&it&&(s.shapeFlag&6?it[it.indexOf(e)]=s:it.push(s)),s.patchFlag|=-2,s}if(Vf(e)&&(e=e.__vccOpts),t){t=Tf(t);let{class:s,style:c}=t;s&&!oe(s)&&(t.class=fa(s)),Ae(c)&&(Wi(c)&&!X(c)&&(c=Pe({},c)),t.style=da(c))}const o=oe(e)?1:zd(e)?128:wf(e)?64:Ae(e)?4:re(e)?2:0;return lr(e,t,n,r,l,o,a,!0)}function Tf(e){return e?Wi(e)||sl in e?Pe({},e):e:null}function Nt(e,t,n=!1){const{props:r,ref:l,patchFlag:a,children:o}=e,s=t?Cf(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:s,key:s&&ks(s),ref:t&&t.ref?n&&l?X(l)?l.concat($r(t)):[l,$r(t)]:$r(t):l,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:o,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Ue?a===-1?16:a|16:a,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Nt(e.ssContent),ssFallback:e.ssFallback&&Nt(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function ws(e=" ",t=0){return Ce(bn,null,e,t)}function n3(e,t){const n=Ce(Hn,null,e);return n.staticCount=t,n}function ot(e){return e==null||typeof e=="boolean"?Ce(vt):X(e)?Ce(Ue,null,e.slice()):typeof e=="object"?Bt(e):Ce(bn,null,String(e))}function Bt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Nt(e)}function Sa(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(X(t))n=16;else if(typeof t=="object")if(r&65){const l=t.default;l&&(l._c&&(l._d=!1),Sa(e,l()),l._c&&(l._d=!0));return}else{n=32;const l=t._;!l&&!(sl in t)?t._ctx=Xe:l===3&&Xe&&(Xe.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else re(t)?(t={default:t,_ctx:Xe},n=32):(t=String(t),r&64?(n=16,t=[ws(t)]):n=8);e.children=t,e.shapeFlag|=n}function Cf(...e){const t={};for(let n=0;n Re||Xe;let Kr,Ul;{const e=Ci(),t=(n,r)=>{let l;return(l=e[n])||(l=e[n]=[]),l.push(r),a=>{l.length>1?l.forEach(o=>o(a)):l[0](a)}};Kr=t("__VUE_INSTANCE_SETTERS__",n=>Re=n),Ul=t("__VUE_SSR_SETTERS__",n=>or=n)}const ar=e=>{const t=Re;return Kr(e),e.scope.on(),()=>{e.scope.off(),Kr(t)}},Ao=()=>{Re&&Re.scope.off(),Kr(null)};function Ls(e){return e.vnode.shapeFlag&4}let or=!1;function Rf(e,t=!1){t&&Ul(t);const{props:n,children:r}=e.vnode,l=Ls(e);ff(e,n,l,t),vf(e,r);const a=l?Bf(e,t):void 0;return t&&Ul(!1),a}function Bf(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=Gi(new Proxy(e.ctx,rf));const{setup:r}=n;if(r){const l=e.setupContext=r.length>1?Mf(e):null,a=ar(e);en();const o=Vt(r,e,0,[e.props,l]);if(tn(),a(),Ti(o)){if(o.then(Ao,Ao),t)return o.then(s=>{So(e,s,t)}).catch(s=>{nr(s,e,0)});e.asyncDep=o}else So(e,o,t)}else xs(e,t)}function So(e,t,n){re(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Ae(t)&&(e.setupState=Ji(t)),xs(e,n)}let To;function xs(e,t,n){const r=e.type;if(!e.render){if(!t&&To&&!r.render){const l=r.template||xa(e).template;if(l){const{isCustomElement:a,compilerOptions:o}=e.appContext.config,{delimiters:s,compilerOptions:c}=r,u=Pe(Pe({isCustomElement:a,delimiters:s},o),c);r.render=To(l,u)}}e.render=r.render||Qe}{const l=ar(e);en();try{lf(e)}finally{tn(),l()}}}function Df(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return qe(e,"get","$attrs"),t[n]}}))}function Mf(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return Df(e)},slots:e.slots,emit:e.emit,expose:t}}function Ta(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Ji(Gi(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Nn)return Nn[n](e)},has(t,n){return n in t||n in Nn}}))}function Ff(e,t=!0){return re(e)?e.displayName||e.name:e.name||t&&e.__name}function Vf(e){return re(e)&&"__vccOpts"in e}const y=(e,t)=>wd(e,t,or);function i(e,t,n){const r=arguments.length;return r===2?Ae(t)&&!X(t)?Gl(t)?Ce(e,null,[t]):Ce(e,t):Ce(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&Gl(n)&&(n=[n]),Ce(e,t,n))}const $f="3.4.15";/** +* @vue/runtime-dom v3.4.15 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/const Nf="http://www.w3.org/2000/svg",Hf="http://www.w3.org/1998/Math/MathML",Dt=typeof document<"u"?document:null,Co=Dt&&Dt.createElement("template"),zf={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 l=t==="svg"?Dt.createElementNS(Nf,e):t==="mathml"?Dt.createElementNS(Hf,e):Dt.createElement(e,n?{is:n}:void 0);return e==="select"&&r&&r.multiple!=null&&l.setAttribute("multiple",r.multiple),l},createText:e=>Dt.createTextNode(e),createComment:e=>Dt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Dt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,l,a){const o=n?n.previousSibling:t.lastChild;if(l&&(l===a||l.nextSibling))for(;t.insertBefore(l.cloneNode(!0),n),!(l===a||!(l=l.nextSibling)););else{Co.innerHTML=r==="svg"?``:r==="mathml"?``:e;const s=Co.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]}},It="transition",On="animation",_n=Symbol("_vtc"),Ht=(e,{slots:t})=>i(Ud,Ss(e),t);Ht.displayName="Transition";const As={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},jf=Ht.props=Pe({},is,As),Ut=(e,t=[])=>{X(e)?e.forEach(n=>n(...t)):e&&e(...t)},Io=e=>e?X(e)?e.some(t=>t.length>1):e.length>1:!1;function Ss(e){const t={};for(const H in e)H in As||(t[H]=e[H]);if(e.css===!1)return t;const{name:n="v",type:r,duration:l,enterFromClass:a=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:s=`${n}-enter-to`,appearFromClass:c=a,appearActiveClass:u=o,appearToClass:d=s,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:h=`${n}-leave-to`}=e,g=qf(l),E=g&&g[0],k=g&&g[1],{onBeforeEnter:b,onEnter:A,onEnterCancelled:_,onLeave:S,onLeaveCancelled:B,onBeforeAppear:x=b,onAppear:G=A,onAppearCancelled:V=_}=t,D=(H,ee,Se)=>{Pt(H,ee?d:s),Pt(H,ee?u:o),Se&&Se()},N=(H,ee)=>{H._isLeaving=!1,Pt(H,f),Pt(H,h),Pt(H,p),ee&&ee()},ne=H=>(ee,Se)=>{const Te=H?G:A,J=()=>D(ee,H,Se);Ut(Te,[ee,J]),Po(()=>{Pt(ee,H?c:a),yt(ee,H?d:s),Io(Te)||Oo(ee,r,E,J)})};return Pe(t,{onBeforeEnter(H){Ut(b,[H]),yt(H,a),yt(H,o)},onBeforeAppear(H){Ut(x,[H]),yt(H,c),yt(H,u)},onEnter:ne(!1),onAppear:ne(!0),onLeave(H,ee){H._isLeaving=!0;const Se=()=>N(H,ee);yt(H,f),Cs(),yt(H,p),Po(()=>{H._isLeaving&&(Pt(H,f),yt(H,h),Io(S)||Oo(H,r,k,Se))}),Ut(S,[H,Se])},onEnterCancelled(H){D(H,!1),Ut(_,[H])},onAppearCancelled(H){D(H,!0),Ut(V,[H])},onLeaveCancelled(H){N(H),Ut(B,[H])}})}function qf(e){if(e==null)return null;if(Ae(e))return[wl(e.enter),wl(e.leave)];{const t=wl(e);return[t,t]}}function wl(e){return Uu(e)}function yt(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[_n]||(e[_n]=new Set)).add(t)}function Pt(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[_n];n&&(n.delete(t),n.size||(e[_n]=void 0))}function Po(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Wf=0;function Oo(e,t,n,r){const l=e._endId=++Wf,a=()=>{l===e._endId&&r()};if(n)return setTimeout(a,n);const{type:o,timeout:s,propCount:c}=Ts(e,t);if(!o)return r();const u=o+"end";let d=0;const f=()=>{e.removeEventListener(u,p),a()},p=h=>{h.target===e&&++d>=c&&f()};setTimeout(()=>{d (n[g]||"").split(", "),l=r(`${It}Delay`),a=r(`${It}Duration`),o=Ro(l,a),s=r(`${On}Delay`),c=r(`${On}Duration`),u=Ro(s,c);let d=null,f=0,p=0;t===It?o>0&&(d=It,f=o,p=a.length):t===On?u>0&&(d=On,f=u,p=c.length):(f=Math.max(o,u),d=f>0?o>u?It:On:null,p=d?d===It?a.length:c.length:0);const h=d===It&&/\b(transform|all)(,|$)/.test(r(`${It}Property`).toString());return{type:d,timeout:f,propCount:p,hasTransform:h}}function Ro(e,t){for(;e.length Bo(n)+Bo(e[r])))}function Bo(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Cs(){return document.body.offsetHeight}function Gf(e,t,n){const r=e[_n];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Uf=Symbol("_vod"),Kf=Symbol("");function Jf(e,t,n){const r=e.style,l=r.display,a=oe(n);if(n&&!a){if(t&&!oe(t))for(const o in t)n[o]==null&&Kl(r,o,"");for(const o in n)Kl(r,o,n[o])}else if(a){if(t!==n){const o=r[Kf];o&&(n+=";"+o),r.cssText=n}}else t&&e.removeAttribute("style");Uf in e&&(r.display=l)}const Do=/\s*!important$/;function Kl(e,t,n){if(X(n))n.forEach(r=>Kl(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Yf(e,t);Do.test(n)?e.setProperty(Ln(r),n.replace(Do,""),"important"):e[r]=n}}const Mo=["Webkit","Moz","ms"],Ll={};function Yf(e,t){const n=Ll[t];if(n)return n;let r=nt(t);if(r!=="filter"&&r in e)return Ll[t]=r;r=er(r);for(let l=0;l xl||(rp.then(()=>xl=0),xl=Date.now());function ap(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;et(op(r,n.value),t,5,[r])};return n.value=e,n.attached=lp(),n}function op(e,t){if(X(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>l=>!l._stopped&&r&&r(l))}else return t}const No=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,ip=(e,t,n,r,l,a,o,s,c)=>{const u=l==="svg";t==="class"?Gf(e,r,u):t==="style"?Jf(e,n,r):Xn(t)?sa(t)||tp(e,t,n,r,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):sp(e,t,r,u))?Qf(e,t,r,a,o,s,c):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Zf(e,t,r,u))};function sp(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&No(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 l=e.tagName;if(l==="IMG"||l==="VIDEO"||l==="CANVAS"||l==="SOURCE")return!1}return No(t)&&oe(n)?!1:t in e}const Is=new WeakMap,Ps=new WeakMap,Jr=Symbol("_moveCb"),Ho=Symbol("_enterCb"),Os={name:"TransitionGroup",props:Pe({},jf,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=An(),r=os();let l,a;return us(()=>{if(!l.length)return;const o=e.moveClass||`${e.name||"v"}-move`;if(!pp(l[0].el,n.vnode.el,o))return;l.forEach(up),l.forEach(dp);const s=l.filter(fp);Cs(),s.forEach(c=>{const u=c.el,d=u.style;yt(u,o),d.transform=d.webkitTransform=d.transitionDuration="";const f=u[Jr]=p=>{p&&p.target!==u||(!p||/transform$/.test(p.propertyName))&&(u.removeEventListener("transitionend",f),u[Jr]=null,Pt(u,o))};u.addEventListener("transitionend",f)})}),()=>{const o=ce(e),s=Ss(o);let c=o.tag||Ue;l=a,a=t.default?La(t.default()):[];for(let u=0;u delete e.mode;Os.props;const Rs=Os;function up(e){const t=e.el;t[Jr]&&t[Jr](),t[Ho]&&t[Ho]()}function dp(e){Ps.set(e,e.el.getBoundingClientRect())}function fp(e){const t=Is.get(e),n=Ps.get(e),r=t.left-n.left,l=t.top-n.top;if(r||l){const a=e.el.style;return a.transform=a.webkitTransform=`translate(${r}px,${l}px)`,a.transitionDuration="0s",e}}function pp(e,t,n){const r=e.cloneNode(),l=e[_n];l&&l.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 a=t.nodeType===1?t:t.parentNode;a.appendChild(r);const{hasTransform:o}=Ts(r);return a.removeChild(r),o}const hp=Pe({patchProp:ip},zf);let Al,zo=!1;function vp(){return Al=zo?Al:yf(hp),zo=!0,Al}const mp=(...e)=>{const t=vp().createApp(...e),{mount:n}=t;return t.mount=r=>{const l=bp(r);if(l)return n(l,!0,gp(l))},t};function gp(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function bp(e){return oe(e)?document.querySelector(e):e}const _p="modulepreload",yp=function(e){return"/"+e},jo={},w=function(t,n,r){let l=Promise.resolve();if(n&&n.length>0){const a=document.getElementsByTagName("link");l=Promise.all(n.map(o=>{if(o=yp(o),o in jo)return;jo[o]=!0;const s=o.endsWith(".css"),c=s?'[rel="stylesheet"]':"";if(!!r)for(let f=a.length-1;f>=0;f--){const p=a[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":_p,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 l.then(()=>t()).catch(a=>{const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=a,window.dispatchEvent(o),!o.defaultPrevented)throw a})},Ep={"v-8daa1a0e":()=>w(()=>import("./index.html-tMixJPN7.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-728c3a8f":()=>w(()=>import("./index.html-t2KDSwiJ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-cfe8b6c8":()=>w(()=>import("./index.html-N_67P6-s.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2e25198a":()=>w(()=>import("./index.html-2xQqwR-V.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-50cb12f2":()=>w(()=>import("./index.html-mNLKf94V.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-71fde78e":()=>w(()=>import("./index.html-zEn3PTqR.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-580db9be":()=>w(()=>import("./devops-ping-tai.html-kDtCSXpk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-06d5cd4c":()=>w(()=>import("./gitlab-ci.html-HyFv5Ls3.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-132efcd1":()=>w(()=>import("./jenkins-x.html-gi90zyZ8.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1a2ca7a7":()=>w(()=>import("./tekton.html-7q40Qc0_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-091223ce":()=>w(()=>import("./tiktok2023.html-VVmqvR2f.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0a27b598":()=>w(()=>import("./JVM调优参数.html-RmR4uDpi.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-60eda44c":()=>w(()=>import("./serverlog.html-ib9svlbN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-399e07b6":()=>w(()=>import("./一次jvm调优过程.html-Fez3X8xk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-660266c1":()=>w(()=>import("./内存屏障.html-YpsEGPcG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-90f2343c":()=>w(()=>import("./在 Spring 6 中使用虚拟线程.html-aSy3Jyqy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0b5d4df0":()=>w(()=>import("./基于kubernetes的分布式限流.html-SsVfGmol.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-21e54510":()=>w(()=>import("./index.html-k7gT6RRu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-57ae83ac":()=>w(()=>import("./spark on k8s operator.html-Uq_G4U-U.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-22e4234a":()=>w(()=>import("./2017.html-zfvjl-5A.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1f7a720c":()=>w(()=>import("./2018.html-pd4XfNXB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1c10c0ce":()=>w(()=>import("./2019.html-QgZCLsLC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-258f309e":()=>w(()=>import("./index.html-xgoJibcf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-510415f9":()=>w(()=>import("./chatgpt.html-soLgBokY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-68e0ce3f":()=>w(()=>import("./starcraft-ai.html-jENBJ0MN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3c114a75":()=>w(()=>import("./tesla.html-NVSkMPRC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-90e5bb66":()=>w(()=>import("./广州图书馆借阅抓取.html-DyyYunsJ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-37ac02fe":()=>w(()=>import("./1.历史与架构.html-hY3Aapwp.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-523e9724":()=>w(()=>import("./10.网站重构.html-8BbyrcnW.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-65b5c81c":()=>w(()=>import("./2.Lucene的使用.html-Dotj8RrP.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-731a76b6":()=>w(()=>import("./3.定时任务.html-3ziLr-Ev.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-bea2ce1e":()=>w(()=>import("./4.日志系统.html-irQFt6qr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3efc517e":()=>w(()=>import("./5.小集群部署.html-M8m-ZELy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-79ad699f":()=>w(()=>import("./6.数据库备份.html-02CCztL7.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-8658e60a":()=>w(()=>import("./7.那些牛逼的插件.html-x2q9y-pD.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7e9e4a32":()=>w(()=>import("./8.基于贝叶斯的情感分析.html-O9J2qs51.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0b62f72e":()=>w(()=>import("./9.网站性能优化.html-npDz6nv1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-dc384366":()=>w(()=>import("./index.html-5Ud_mAI1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-70796e0a":()=>w(()=>import("./redis缓存.html-B4MmbAQF.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-43e9e6b0":()=>w(()=>import("./wewe.html-dxhYsqpt.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-33bd146f":()=>w(()=>import("./个人作品.html-HGTJItSS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-04e32b44":()=>w(()=>import("./elastic-spark.html-yTkDwYPM.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d73a9aee":()=>w(()=>import("./elasticsearch源码debug.html-MPOlcYKm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3f2a15ee":()=>w(()=>import("./【elasticsearch】搜索过程详解.html-NGfX8s6C.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-aa93dec0":()=>w(()=>import("./1mysql.html-_FE7EY_e.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0a0b7a54":()=>w(()=>import("./数据库缓存.html-D5OE_lZE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-137d5dcc":()=>w(()=>import("./redis缓存.html-rKUKwNSH.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-16aa42ca":()=>w(()=>import("./Spring Boot Prometheus使用.html-C4jpqxXi.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5089f9f3":()=>w(()=>import("./aop.html-rc4rLz6V.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7586af98":()=>w(()=>import("./webflux.html-BMCSAQQq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d7d7df80":()=>w(()=>import("./kafka.html-vXPGDb5r.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7d9b9318":()=>w(()=>import("./zookeeper.html-YcPoe8IG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3706649a":()=>w(()=>import("./404.html-WhIsgby4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-71b3ae87":()=>w(()=>import("./index.html-vgYoWX9F.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-14c69af4":()=>w(()=>import("./index.html-yuZKtvix.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-14e6315a":()=>w(()=>import("./index.html-T5wPpx5i.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-25b47c13":()=>w(()=>import("./index.html-zdhpQIq5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-525c5e4d":()=>w(()=>import("./index.html-hCmlVboM.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5d3e6196":()=>w(()=>import("./index.html-SLeyy5iI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3e13af88":()=>w(()=>import("./index.html-sgH7oDMT.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-60fc7530":()=>w(()=>import("./index.html-5KP2soWP.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-02bc92be":()=>w(()=>import("./index.html-8MJuJxlA.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-380c630d":()=>w(()=>import("./index.html-TuBE6nT4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-21ba2ec8":()=>w(()=>import("./index.html-DLDIhIzm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2921a50f":()=>w(()=>import("./index.html-NupEPZnP.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-862c4448":()=>w(()=>import("./index.html-j3N_gv-O.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a32329e6":()=>w(()=>import("./index.html-NPk7ZlMe.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4d194044":()=>w(()=>import("./index.html-Prj9iPTA.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6e21a4b2":()=>w(()=>import("./index.html-VZNNIAqy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5bc93818":()=>w(()=>import("./index.html-KA0_6BkE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-744d024e":()=>w(()=>import("./index.html-48vkkelG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e52c881c":()=>w(()=>import("./index.html-IZIHDPXq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-154dc4c4":()=>w(()=>import("./index.html-XULjGA2d.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-01560935":()=>w(()=>import("./index.html-P7BZhZZ3.js"),__vite__mapDeps([])).then(({data:e})=>e)},kp=JSON.parse('{"base":"/","lang":"zh-CN","title":"个人博客","description":"个人博客","head":[["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 wp=([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]),Lp=e=>{const t=new Set,n=[];return e.forEach(r=>{const l=wp(r);t.has(l)||(t.add(l),n.push(r))}),n},xp=e=>e[0]==="/"?e:`/${e}`,Bs=e=>e[e.length-1]==="/"||e.endsWith(".html")?e:`${e}/`,Sn=e=>/^(https?:)?\/\//.test(e),Ap=/.md((\?|#).*)?$/,Yr=(e,t="/")=>!!(Sn(e)||e.startsWith("/")&&!e.startsWith(t)&&!Ap.test(e)),Ds=e=>/^[a-z][a-z0-9+.-]*:/.test(e),Ca=e=>Object.prototype.toString.call(e)==="[object Object]",Ia=e=>e[e.length-1]==="/"?e.slice(0,-1):e,Ms=e=>e[0]==="/"?e.slice(1):e,Sp=(e,t)=>{const n=Object.keys(e).sort((r,l)=>{const a=l.split("/").length-r.split("/").length;return a!==0?a:l.length-r.length});for(const r of n)if(t.startsWith(r))return r;return"/"};const Fs={"v-8daa1a0e":$(()=>w(()=>import("./index.html-NqrU9ViM.js"),__vite__mapDeps([]))),"v-728c3a8f":$(()=>w(()=>import("./index.html-wXTpok86.js"),__vite__mapDeps([]))),"v-cfe8b6c8":$(()=>w(()=>import("./index.html-oIxwfSaO.js"),__vite__mapDeps([]))),"v-2e25198a":$(()=>w(()=>import("./index.html-YtSVVbX9.js"),__vite__mapDeps([]))),"v-50cb12f2":$(()=>w(()=>import("./index.html-va_I8g1i.js"),__vite__mapDeps([]))),"v-71fde78e":$(()=>w(()=>import("./index.html-OlL-6l44.js"),__vite__mapDeps([]))),"v-580db9be":$(()=>w(()=>import("./devops-ping-tai.html-eRtFukrp.js"),__vite__mapDeps([]))),"v-06d5cd4c":$(()=>w(()=>import("./gitlab-ci.html-mSez-CGs.js"),__vite__mapDeps([]))),"v-132efcd1":$(()=>w(()=>import("./jenkins-x.html-zCVNj34k.js"),__vite__mapDeps([]))),"v-1a2ca7a7":$(()=>w(()=>import("./tekton.html-U0tQ1pPN.js"),__vite__mapDeps([]))),"v-091223ce":$(()=>w(()=>import("./tiktok2023.html-qCFByo0Z.js"),__vite__mapDeps([]))),"v-0a27b598":$(()=>w(()=>import("./JVM调优参数.html-h5u7_TmA.js"),__vite__mapDeps([]))),"v-60eda44c":$(()=>w(()=>import("./serverlog.html-Hm6VMJqE.js"),__vite__mapDeps([]))),"v-399e07b6":$(()=>w(()=>import("./一次jvm调优过程.html-uFoGHpCT.js"),__vite__mapDeps([]))),"v-660266c1":$(()=>w(()=>import("./内存屏障.html-NZo4BJww.js"),__vite__mapDeps([]))),"v-90f2343c":$(()=>w(()=>import("./在 Spring 6 中使用虚拟线程.html-HbXCZyjO.js"),__vite__mapDeps([]))),"v-0b5d4df0":$(()=>w(()=>import("./基于kubernetes的分布式限流.html-HKqWtH4o.js"),__vite__mapDeps([]))),"v-21e54510":$(()=>w(()=>import("./index.html-GvvIZ3im.js"),__vite__mapDeps([]))),"v-57ae83ac":$(()=>w(()=>import("./spark on k8s operator.html-VI4MG2dr.js"),__vite__mapDeps([]))),"v-22e4234a":$(()=>w(()=>import("./2017.html-dyRb1VL5.js"),__vite__mapDeps([]))),"v-1f7a720c":$(()=>w(()=>import("./2018.html-ibX-zlXM.js"),__vite__mapDeps([]))),"v-1c10c0ce":$(()=>w(()=>import("./2019.html-9VeA33Ol.js"),__vite__mapDeps([]))),"v-258f309e":$(()=>w(()=>import("./index.html-xrX_JdJz.js"),__vite__mapDeps([]))),"v-510415f9":$(()=>w(()=>import("./chatgpt.html-KMWnqK_m.js"),__vite__mapDeps([]))),"v-68e0ce3f":$(()=>w(()=>import("./starcraft-ai.html-cchZINBe.js"),__vite__mapDeps([]))),"v-3c114a75":$(()=>w(()=>import("./tesla.html-2JZEV-fS.js"),__vite__mapDeps([]))),"v-90e5bb66":$(()=>w(()=>import("./广州图书馆借阅抓取.html--2YXMPa3.js"),__vite__mapDeps([]))),"v-37ac02fe":$(()=>w(()=>import("./1.历史与架构.html-5y0SHOi3.js"),__vite__mapDeps([]))),"v-523e9724":$(()=>w(()=>import("./10.网站重构.html-Mp3R-WY2.js"),__vite__mapDeps([]))),"v-65b5c81c":$(()=>w(()=>import("./2.Lucene的使用.html-iRWlAkDH.js"),__vite__mapDeps([]))),"v-731a76b6":$(()=>w(()=>import("./3.定时任务.html-YWN_AF8s.js"),__vite__mapDeps([]))),"v-bea2ce1e":$(()=>w(()=>import("./4.日志系统.html-Vr6wBNUl.js"),__vite__mapDeps([]))),"v-3efc517e":$(()=>w(()=>import("./5.小集群部署.html-3yoX3jO9.js"),__vite__mapDeps([]))),"v-79ad699f":$(()=>w(()=>import("./6.数据库备份.html-EACVFara.js"),__vite__mapDeps([]))),"v-8658e60a":$(()=>w(()=>import("./7.那些牛逼的插件.html-rNj4FqCC.js"),__vite__mapDeps([]))),"v-7e9e4a32":$(()=>w(()=>import("./8.基于贝叶斯的情感分析.html-6PQREPEX.js"),__vite__mapDeps([]))),"v-0b62f72e":$(()=>w(()=>import("./9.网站性能优化.html-dTPlQo4Y.js"),__vite__mapDeps([]))),"v-dc384366":$(()=>w(()=>import("./index.html-3vTjthN3.js"),__vite__mapDeps([]))),"v-70796e0a":$(()=>w(()=>import("./redis缓存.html-ypr-mvgs.js"),__vite__mapDeps([]))),"v-43e9e6b0":$(()=>w(()=>import("./wewe.html-yoLO0ZeB.js"),__vite__mapDeps([]))),"v-33bd146f":$(()=>w(()=>import("./个人作品.html-Q7C0m6N_.js"),__vite__mapDeps([]))),"v-04e32b44":$(()=>w(()=>import("./elastic-spark.html-_qX2JCGa.js"),__vite__mapDeps([]))),"v-d73a9aee":$(()=>w(()=>import("./elasticsearch源码debug.html-ux_5qZGG.js"),__vite__mapDeps([]))),"v-3f2a15ee":$(()=>w(()=>import("./【elasticsearch】搜索过程详解.html-dRj9fBxw.js"),__vite__mapDeps([]))),"v-aa93dec0":$(()=>w(()=>import("./1mysql.html-K9WVG0vy.js"),__vite__mapDeps([]))),"v-0a0b7a54":$(()=>w(()=>import("./数据库缓存.html-914rF9h2.js"),__vite__mapDeps([]))),"v-137d5dcc":$(()=>w(()=>import("./redis缓存.html-rNePPmRD.js"),__vite__mapDeps([]))),"v-16aa42ca":$(()=>w(()=>import("./Spring Boot Prometheus使用.html-tEZFyQZb.js"),__vite__mapDeps([]))),"v-5089f9f3":$(()=>w(()=>import("./aop.html-MaOjAA3t.js"),__vite__mapDeps([]))),"v-7586af98":$(()=>w(()=>import("./webflux.html-L1PizKRY.js"),__vite__mapDeps([]))),"v-d7d7df80":$(()=>w(()=>import("./kafka.html-F6asoFaN.js"),__vite__mapDeps([]))),"v-7d9b9318":$(()=>w(()=>import("./zookeeper.html-t3PHJ53M.js"),__vite__mapDeps([]))),"v-3706649a":$(()=>w(()=>import("./404.html-bFP867g4.js"),__vite__mapDeps([]))),"v-71b3ae87":$(()=>w(()=>import("./index.html-iMotbL4n.js"),__vite__mapDeps([]))),"v-14c69af4":$(()=>w(()=>import("./index.html-gD7ZdfDI.js"),__vite__mapDeps([]))),"v-14e6315a":$(()=>w(()=>import("./index.html-nAXzS96k.js"),__vite__mapDeps([]))),"v-25b47c13":$(()=>w(()=>import("./index.html-QSycEhOj.js"),__vite__mapDeps([]))),"v-525c5e4d":$(()=>w(()=>import("./index.html-YeQQJRDb.js"),__vite__mapDeps([]))),"v-5d3e6196":$(()=>w(()=>import("./index.html-h8W5zSaK.js"),__vite__mapDeps([]))),"v-3e13af88":$(()=>w(()=>import("./index.html-uaK_Ufl7.js"),__vite__mapDeps([]))),"v-60fc7530":$(()=>w(()=>import("./index.html-Og8tRCl2.js"),__vite__mapDeps([]))),"v-02bc92be":$(()=>w(()=>import("./index.html-i1cBLBTr.js"),__vite__mapDeps([]))),"v-380c630d":$(()=>w(()=>import("./index.html-2NIkjES-.js"),__vite__mapDeps([]))),"v-21ba2ec8":$(()=>w(()=>import("./index.html-YC-dEbWq.js"),__vite__mapDeps([]))),"v-2921a50f":$(()=>w(()=>import("./index.html-Lbi6MibC.js"),__vite__mapDeps([]))),"v-862c4448":$(()=>w(()=>import("./index.html-ALK8A2OJ.js"),__vite__mapDeps([]))),"v-a32329e6":$(()=>w(()=>import("./index.html-qzfzgXy9.js"),__vite__mapDeps([]))),"v-4d194044":$(()=>w(()=>import("./index.html-raEG4bsB.js"),__vite__mapDeps([]))),"v-6e21a4b2":$(()=>w(()=>import("./index.html-G7ri16RO.js"),__vite__mapDeps([]))),"v-5bc93818":$(()=>w(()=>import("./index.html-zcQ2zC0z.js"),__vite__mapDeps([]))),"v-744d024e":$(()=>w(()=>import("./index.html-6zSBWJFl.js"),__vite__mapDeps([]))),"v-e52c881c":$(()=>w(()=>import("./index.html-WyFvweeV.js"),__vite__mapDeps([]))),"v-154dc4c4":$(()=>w(()=>import("./index.html-K0NPFYN4.js"),__vite__mapDeps([]))),"v-01560935":$(()=>w(()=>import("./index.html-FrLYPym2.js"),__vite__mapDeps([])))};var Tp=Symbol(""),Vs=Symbol(""),Cp=nn({key:"",path:"",title:"",lang:"",frontmatter:{},headers:[]}),ie=()=>{const e=he(Vs);if(!e)throw new Error("pageData() is called without provider.");return e},$s=Symbol(""),_e=()=>{const e=he($s);if(!e)throw new Error("usePageFrontmatter() is called without provider.");return e},Ns=Symbol(""),Ip=()=>{const e=he(Ns);if(!e)throw new Error("usePageHead() is called without provider.");return e},Pp=Symbol(""),Hs=Symbol(""),Pa=()=>{const e=he(Hs);if(!e)throw new Error("usePageLang() is called without provider.");return e},zs=Symbol(""),Op=()=>{const e=he(zs);if(!e)throw new Error("usePageLayout() is called without provider.");return e},Rp=Y(Ep),Oa=Symbol(""),bt=()=>{const e=he(Oa);if(!e)throw new Error("useRouteLocale() is called without provider.");return e},dn=Y(kp),js=()=>dn,qs=Symbol(""),ir=()=>{const e=he(qs);if(!e)throw new Error("useSiteLocaleData() is called without provider.");return e},Bp=Symbol(""),Dp="Layout",Mp="NotFound",Et=tr({resolveLayouts:e=>e.reduce((t,n)=>({...t,...n.layouts}),{}),resolvePageData:async e=>{const t=Rp.value[e];return await(t==null?void 0:t())??Cp},resolvePageFrontmatter:e=>e.frontmatter,resolvePageHead:(e,t,n)=>{const r=oe(t.description)?t.description:n.description,l=[...X(t.head)?t.head:[],...n.head,["title",{},e],["meta",{name:"description",content:r}]];return Lp(l)},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=Dp}else n=Mp;return t[n]},resolveRouteLocale:(e,t)=>Sp(e,t),resolveSiteLocaleData:(e,t)=>({...e,...e.locales[t]})}),cl=F({name:"ClientOnly",setup(e,t){const n=Y(!1);return Ee(()=>{n.value=!0}),()=>{var r,l;return n.value?(l=(r=t.slots).default)==null?void 0:l.call(r):null}}}),Ws=F({name:"Content",props:{pageKey:{type:String,required:!1,default:""}},setup(e){const t=ie(),n=y(()=>Fs[e.pageKey||t.value.key]);return()=>n.value?i(n.value):i("div","404 Not Found")}}),Je=(e={})=>e,xe=e=>Sn(e)?e:`/${Ms(e)}`;const Fp={};/*! + * vue-router v4.2.5 + * (c) 2023 Eduardo San Martin Morote + * @license MIT + */const cn=typeof window<"u";function Vp(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const ge=Object.assign;function Sl(e,t){const n={};for(const r in t){const l=t[r];n[r]=ct(l)?l.map(e):e(l)}return n}const jn=()=>{},ct=Array.isArray,$p=/\/$/,Np=e=>e.replace($p,"");function Tl(e,t,n="/"){let r,l={},a="",o="";const s=t.indexOf("#");let c=t.indexOf("?");return s =0&&(c=-1),c>-1&&(r=t.slice(0,c),a=t.slice(c+1,s>-1?s:t.length),l=e(a)),s>-1&&(r=r||t.slice(0,s),o=t.slice(s,t.length)),r=qp(r??t,n),{fullPath:r+(a&&"?")+a+o,path:r,query:l,hash:o}}function Hp(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 zp(e,t,n){const r=t.matched.length-1,l=n.matched.length-1;return r>-1&&r===l&&yn(t.matched[r],n.matched[l])&&Gs(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function yn(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function Gs(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!jp(e[n],t[n]))return!1;return!0}function jp(e,t){return ct(e)?Wo(e,t):ct(t)?Wo(t,e):e===t}function Wo(e,t){return ct(t)?e.length===t.length&&e.every((n,r)=>n===t[r]):e.length===1&&e[0]===t}function qp(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),l=r[r.length-1];(l===".."||l===".")&&r.push("");let a=n.length-1,o,s;for(o=0;o 1&&a--;else break;return n.slice(0,a).join("/")+"/"+r.slice(o-(o===r.length?1:0)).join("/")}var Zn;(function(e){e.pop="pop",e.push="push"})(Zn||(Zn={}));var qn;(function(e){e.back="back",e.forward="forward",e.unknown=""})(qn||(qn={}));function Wp(e){if(!e)if(cn){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),Np(e)}const Gp=/^[^#]+#/;function Up(e,t){return e.replace(Gp,"#")+t}function Kp(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 ul=()=>({left:window.pageXOffset,top:window.pageYOffset});function Jp(e){let t;if("el"in e){const n=e.el,r=typeof n=="string"&&n.startsWith("#"),l=typeof n=="string"?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!l)return;t=Kp(l,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 Go(e,t){return(history.state?history.state.position-t:-1)+e}const Jl=new Map;function Yp(e,t){Jl.set(e,t)}function Zp(e){const t=Jl.get(e);return Jl.delete(e),t}let Qp=()=>location.protocol+"//"+location.host;function Us(e,t){const{pathname:n,search:r,hash:l}=t,a=e.indexOf("#");if(a>-1){let s=l.includes(e.slice(a))?e.slice(a).length:1,c=l.slice(s);return c[0]!=="/"&&(c="/"+c),qo(c,"")}return qo(n,e)+r+l}function Xp(e,t,n,r){let l=[],a=[],o=null;const s=({state:p})=>{const h=Us(e,location),g=n.value,E=t.value;let k=0;if(p){if(n.value=h,t.value=p,o&&o===g){o=null;return}k=E?p.position-E.position:0}else r(h);l.forEach(b=>{b(n.value,g,{delta:k,type:Zn.pop,direction:k?k>0?qn.forward:qn.back:qn.unknown})})};function c(){o=n.value}function u(p){l.push(p);const h=()=>{const g=l.indexOf(p);g>-1&&l.splice(g,1)};return a.push(h),h}function d(){const{history:p}=window;p.state&&p.replaceState(ge({},p.state,{scroll:ul()}),"")}function f(){for(const p of a)p();a=[],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 Uo(e,t,n,r=!1,l=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:l?ul():null}}function e1(e){const{history:t,location:n}=window,r={value:Us(e,n)},l={value:t.state};l.value||a(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function a(c,u,d){const f=e.indexOf("#"),p=f>-1?(n.host&&document.querySelector("base")?e:e.slice(f))+c:Qp()+e+c;try{t[d?"replaceState":"pushState"](u,"",p),l.value=u}catch(h){console.error(h),n[d?"replace":"assign"](p)}}function o(c,u){const d=ge({},t.state,Uo(l.value.back,c,l.value.forward,!0),u,{position:l.value.position});a(c,d,!0),r.value=c}function s(c,u){const d=ge({},l.value,t.state,{forward:c,scroll:ul()});a(d.current,d,!0);const f=ge({},Uo(r.value,c,null),{position:d.position+1},u);a(c,f,!1),r.value=c}return{location:r,state:l,push:s,replace:o}}function t1(e){e=Wp(e);const t=e1(e),n=Xp(e,t.state,t.location,t.replace);function r(a,o=!0){o||n.pauseListeners(),history.go(a)}const l=ge({location:"",base:e,go:r,createHref:Up.bind(null,e)},t,n);return Object.defineProperty(l,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(l,"state",{enumerable:!0,get:()=>t.state.value}),l}function n1(e){return typeof e=="string"||e&&typeof e=="object"}function Ks(e){return typeof e=="string"||typeof e=="symbol"}const kt={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0},Js=Symbol("");var Ko;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(Ko||(Ko={}));function En(e,t){return ge(new Error,{type:e,[Js]:!0},t)}function _t(e,t){return e instanceof Error&&Js in e&&(t==null||!!(e.type&t))}const Jo="[^/]+?",r1={sensitive:!1,strict:!1,start:!0,end:!0},l1=/[.+*?^${}()[\]/\\]/g;function a1(e,t){const n=ge({},r1,t),r=[];let l=n.start?"^":"";const a=[];for(const u of e){const d=u.length?[]:[90];n.strict&&!u.length&&(l+="/");for(let f=0;f t.length?t.length===1&&t[0]===80?1:-1:0}function i1(e,t){let n=0;const r=e.score,l=t.score;for(;n 0&&t[t.length-1]<0}const s1={type:0,value:""},c1=/[a-zA-Z0-9_]/;function u1(e){if(!e)return[[]];if(e==="/")return[[s1]];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 l=[];let a;function o(){a&&l.push(a),a=[]}let s=0,c,u="",d="";function f(){u&&(n===0?a.push({type:0,value:u}):n===1||n===2||n===3?(a.length>1&&(c==="*"||c==="+")&&t(`A repeatable param (${u}) must be alone in its segment. eg: '/:ids+.`),a.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(A)}:jn}function o(d){if(Ks(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||!Ys(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,E;if("name"in d&&d.name){if(p=r.get(d.name),!p)throw En(1,{location:d});E=p.record.name,h=ge(Zo(f.params,p.keys.filter(A=>!A.optional).map(A=>A.name)),d.params&&Zo(d.params,p.keys.map(A=>A.name))),g=p.stringify(h)}else if("path"in d)g=d.path,p=n.find(A=>A.re.test(g)),p&&(h=p.parse(g),E=p.record.name);else{if(p=f.name?r.get(f.name):n.find(A=>A.re.test(f.path)),!p)throw En(1,{location:d,currentLocation:f});E=p.record.name,h=ge({},f.params,d.params),g=p.stringify(h)}const k=[];let b=p;for(;b;)k.unshift(b.record),b=b.parent;return{name:E,path:g,params:h,matched:k,meta:v1(k)}}return e.forEach(d=>a(d)),{addRoute:a,resolve:u,removeRoute:o,getRoutes:s,getRecordMatcher:l}}function Zo(e,t){const n={};for(const r of t)r in e&&(n[r]=e[r]);return n}function p1(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:h1(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 h1(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 v1(e){return e.reduce((t,n)=>ge(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 Ys(e,t){return t.children.some(n=>n===e||Ys(e,n))}const Zs=/#/g,m1=/&/g,g1=/\//g,b1=/=/g,_1=/\?/g,Qs=/\+/g,y1=/%5B/g,E1=/%5D/g,Xs=/%5E/g,k1=/%60/g,ec=/%7B/g,w1=/%7C/g,tc=/%7D/g,L1=/%20/g;function Ra(e){return encodeURI(""+e).replace(w1,"|").replace(y1,"[").replace(E1,"]")}function x1(e){return Ra(e).replace(ec,"{").replace(tc,"}").replace(Xs,"^")}function Yl(e){return Ra(e).replace(Qs,"%2B").replace(L1,"+").replace(Zs,"%23").replace(m1,"%26").replace(k1,"`").replace(ec,"{").replace(tc,"}").replace(Xs,"^")}function A1(e){return Yl(e).replace(b1,"%3D")}function S1(e){return Ra(e).replace(Zs,"%23").replace(_1,"%3F")}function T1(e){return e==null?"":S1(e).replace(g1,"%2F")}function Zr(e){try{return decodeURIComponent(""+e)}catch{}return""+e}function C1(e){const t={};if(e===""||e==="?")return t;const r=(e[0]==="?"?e.slice(1):e).split("&");for(let l=0;l a&&Yl(a)):[r&&Yl(r)]).forEach(a=>{a!==void 0&&(t+=(t.length?"&":"")+n,a!=null&&(t+="="+a))})}return t}function I1(e){const t={};for(const n in e){const r=e[n];r!==void 0&&(t[n]=ct(r)?r.map(l=>l==null?null:""+l):r==null?r:""+r)}return t}const P1=Symbol(""),ti=Symbol(""),dl=Symbol(""),Ba=Symbol(""),Zl=Symbol("");function Rn(){let e=[];function t(r){return e.push(r),()=>{const l=e.indexOf(r);l>-1&&e.splice(l,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function Mt(e,t,n,r,l){const a=r&&(r.enterCallbacks[l]=r.enterCallbacks[l]||[]);return()=>new Promise((o,s)=>{const c=f=>{f===!1?s(En(4,{from:n,to:t})):f instanceof Error?s(f):n1(f)?s(En(2,{from:t,to:f})):(a&&r.enterCallbacks[l]===a&&typeof f=="function"&&a.push(f),o())},u=e.call(r&&r.instances[l],t,n,c);let d=Promise.resolve(u);e.length<3&&(d=d.then(c)),d.catch(f=>s(f))})}function Cl(e,t,n,r){const l=[];for(const a of e)for(const o in a.components){let s=a.components[o];if(!(t!=="beforeRouteEnter"&&!a.instances[o]))if(O1(s)){const u=(s.__vccOpts||s)[t];u&&l.push(Mt(u,n,r,a,o))}else{let c=s();l.push(()=>c.then(u=>{if(!u)return Promise.reject(new Error(`Couldn't resolve component "${o}" at "${a.path}"`));const d=Vp(u)?u.default:u;a.components[o]=d;const p=(d.__vccOpts||d)[t];return p&&Mt(p,n,r,a,o)()}))}}return l}function O1(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function Ql(e){const t=he(dl),n=he(Ba),r=y(()=>t.resolve(Xt(e.to))),l=y(()=>{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(yn.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(yn.bind(null,c[u-2])):p}),a=y(()=>l.value>-1&&M1(n.params,r.value.params)),o=y(()=>l.value>-1&&l.value===n.matched.length-1&&Gs(n.params,r.value.params));function s(c={}){return D1(c)?t[Xt(e.replace)?"replace":"push"](Xt(e.to)).catch(jn):Promise.resolve()}return{route:r,href:y(()=>r.value.href),isActive:a,isExactActive:o,navigate:s}}const R1=F({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:Ql,setup(e,{slots:t}){const n=tr(Ql(e)),{options:r}=he(dl),l=y(()=>({[ri(e.activeClass,r.linkActiveClass,"router-link-active")]:n.isActive,[ri(e.exactActiveClass,r.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const a=t.default&&t.default(n);return e.custom?a:i("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:l.value},a)}}}),B1=R1;function D1(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 M1(e,t){for(const n in t){const r=t[n],l=e[n];if(typeof r=="string"){if(r!==l)return!1}else if(!ct(l)||l.length!==r.length||r.some((a,o)=>a!==l[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,F1=F({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const r=he(Zl),l=y(()=>e.route||r.value),a=he(ti,0),o=y(()=>{let u=Xt(a);const{matched:d}=l.value;let f;for(;(f=d[u])&&!f.components;)u++;return u}),s=y(()=>l.value.matched[o.value]);st(ti,y(()=>o.value+1)),st(P1,s),st(Zl,l);const c=Y();return me(()=>[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||!yn(d,h)||!p)&&(d.enterCallbacks[f]||[]).forEach(E=>E(u))},{flush:"post"}),()=>{const u=l.value,d=e.name,f=s.value,p=f&&f.components[d];if(!p)return li(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,ge({},g,t,{onVnodeUnmounted:b=>{b.component.isUnmounted&&(f.instances[d]=null)},ref:c}));return li(n.default,{Component:k,route:u})||k}}});function li(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const nc=F1;function V1(e){const t=f1(e.routes,e),n=e.parseQuery||C1,r=e.stringifyQuery||ei,l=e.history,a=Rn(),o=Rn(),s=Rn(),c=ut(kt);let u=kt;cn&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const d=Sl.bind(null,C=>""+C),f=Sl.bind(null,T1),p=Sl.bind(null,Zr);function h(C,q){let z,U;return Ks(C)?(z=t.getRecordMatcher(C),U=q):U=C,t.addRoute(U,z)}function g(C){const q=t.getRecordMatcher(C);q&&t.removeRoute(q)}function E(){return t.getRoutes().map(C=>C.record)}function k(C){return!!t.getRecordMatcher(C)}function b(C,q){if(q=ge({},q||c.value),typeof C=="string"){const m=Tl(n,C,q.path),L=t.resolve({path:m.path},q),I=l.createHref(m.fullPath);return ge(m,L,{params:p(L.params),hash:Zr(m.hash),redirectedFrom:void 0,href:I})}let z;if("path"in C)z=ge({},C,{path:Tl(n,C.path,q.path).path});else{const m=ge({},C.params);for(const L in m)m[L]==null&&delete m[L];z=ge({},C,{params:f(m)}),q.params=f(q.params)}const U=t.resolve(z,q),ve=C.hash||"";U.params=d(p(U.params));const ke=Hp(r,ge({},C,{hash:x1(ve),path:U.path})),v=l.createHref(ke);return ge({fullPath:ke,hash:ve,query:r===ei?I1(C.query):C.query||{}},U,{redirectedFrom:void 0,href:v})}function A(C){return typeof C=="string"?Tl(n,C,c.value.path):ge({},C)}function _(C,q){if(u!==C)return En(8,{from:q,to:C})}function S(C){return G(C)}function B(C){return S(ge(A(C),{replace:!0}))}function x(C){const q=C.matched[C.matched.length-1];if(q&&q.redirect){const{redirect:z}=q;let U=typeof z=="function"?z(C):z;return typeof U=="string"&&(U=U.includes("?")||U.includes("#")?U=A(U):{path:U},U.params={}),ge({query:C.query,hash:C.hash,params:"path"in U?{}:C.params},U)}}function G(C,q){const z=u=b(C),U=c.value,ve=C.state,ke=C.force,v=C.replace===!0,m=x(z);if(m)return G(ge(A(m),{state:typeof m=="object"?ge({},ve,m.state):ve,force:ke,replace:v}),q||z);const L=z;L.redirectedFrom=q;let I;return!ke&&zp(r,U,z)&&(I=En(16,{to:L,from:U}),dt(U,U,!0,!1)),(I?Promise.resolve(I):N(L,U)).catch(T=>_t(T)?_t(T,2)?T:St(T):K(T,L,U)).then(T=>{if(T){if(_t(T,2))return G(ge({replace:v},A(T.to),{state:typeof T.to=="object"?ge({},ve,T.to.state):ve,force:ke}),q||L)}else T=H(L,U,!0,v,ve);return ne(L,U,T),T})}function V(C,q){const z=_(C,q);return z?Promise.reject(z):Promise.resolve()}function D(C){const q=on.values().next().value;return q&&typeof q.runWithContext=="function"?q.runWithContext(C):C()}function N(C,q){let z;const[U,ve,ke]=$1(C,q);z=Cl(U.reverse(),"beforeRouteLeave",C,q);for(const m of U)m.leaveGuards.forEach(L=>{z.push(Mt(L,C,q))});const v=V.bind(null,C,q);return z.push(v),Ve(z).then(()=>{z=[];for(const m of a.list())z.push(Mt(m,C,q));return z.push(v),Ve(z)}).then(()=>{z=Cl(ve,"beforeRouteUpdate",C,q);for(const m of ve)m.updateGuards.forEach(L=>{z.push(Mt(L,C,q))});return z.push(v),Ve(z)}).then(()=>{z=[];for(const m of ke)if(m.beforeEnter)if(ct(m.beforeEnter))for(const L of m.beforeEnter)z.push(Mt(L,C,q));else z.push(Mt(m.beforeEnter,C,q));return z.push(v),Ve(z)}).then(()=>(C.matched.forEach(m=>m.enterCallbacks={}),z=Cl(ke,"beforeRouteEnter",C,q),z.push(v),Ve(z))).then(()=>{z=[];for(const m of o.list())z.push(Mt(m,C,q));return z.push(v),Ve(z)}).catch(m=>_t(m,8)?m:Promise.reject(m))}function ne(C,q,z){s.list().forEach(U=>D(()=>U(C,q,z)))}function H(C,q,z,U,ve){const ke=_(C,q);if(ke)return ke;const v=q===kt,m=cn?history.state:{};z&&(U||v?l.replace(C.fullPath,ge({scroll:v&&m&&m.scroll},ve)):l.push(C.fullPath,ve)),c.value=C,dt(C,q,z,v),St()}let ee;function Se(){ee||(ee=l.listen((C,q,z)=>{if(!Er.listening)return;const U=b(C),ve=x(U);if(ve){G(ge(ve,{replace:!0}),U).catch(jn);return}u=U;const ke=c.value;cn&&Yp(Go(ke.fullPath,z.delta),ul()),N(U,ke).catch(v=>_t(v,12)?v:_t(v,2)?(G(v.to,U).then(m=>{_t(m,20)&&!z.delta&&z.type===Zn.pop&&l.go(-1,!1)}).catch(jn),Promise.reject()):(z.delta&&l.go(-z.delta,!1),K(v,U,ke))).then(v=>{v=v||H(U,ke,!1),v&&(z.delta&&!_t(v,8)?l.go(-z.delta,!1):z.type===Zn.pop&&_t(v,20)&&l.go(-1,!1)),ne(U,ke,v)}).catch(jn)}))}let Te=Rn(),J=Rn(),le;function K(C,q,z){St(C);const U=J.list();return U.length?U.forEach(ve=>ve(C,q,z)):console.error(C),Promise.reject(C)}function lt(){return le&&c.value!==kt?Promise.resolve():new Promise((C,q)=>{Te.add([C,q])})}function St(C){return le||(le=!C,Se(),Te.list().forEach(([q,z])=>C?z(C):q()),Te.reset()),C}function dt(C,q,z,U){const{scrollBehavior:ve}=e;if(!cn||!ve)return Promise.resolve();const ke=!z&&Zp(Go(C.fullPath,0))||(U||!z)&&history.state&&history.state.scroll||null;return rn().then(()=>ve(C,q,ke)).then(v=>v&&Jp(v)).catch(v=>K(v,C,q))}const He=C=>l.go(C);let an;const on=new Set,Er={currentRoute:c,listening:!0,addRoute:h,removeRoute:g,hasRoute:k,getRoutes:E,resolve:b,options:e,push:S,replace:B,go:He,back:()=>He(-1),forward:()=>He(1),beforeEach:a.add,beforeResolve:o.add,afterEach:s.add,onError:J.add,isReady:lt,install(C){const q=this;C.component("RouterLink",B1),C.component("RouterView",nc),C.config.globalProperties.$router=q,Object.defineProperty(C.config.globalProperties,"$route",{enumerable:!0,get:()=>Xt(c)}),cn&&!an&&c.value===kt&&(an=!0,S(l.location).catch(ve=>{}));const z={};for(const ve in kt)Object.defineProperty(z,ve,{get:()=>c.value[ve],enumerable:!0});C.provide(dl,q),C.provide(Ba,qi(z)),C.provide(Zl,c);const U=C.unmount;on.add(C),C.unmount=function(){on.delete(C),on.size<1&&(u=kt,ee&&ee(),ee=null,c.value=kt,an=!1,le=!1),U()}}};function Ve(C){return C.reduce((q,z)=>q.then(()=>D(z)),Promise.resolve())}return Er}function $1(e,t){const n=[],r=[],l=[],a=Math.max(t.matched.length,e.matched.length);for(let o=0;oyn(u,s))?r.push(s):n.push(s));const c=e.matched[o];c&&(t.matched.find(u=>yn(u,c))||l.push(c))}return[n,r,l]}function Fe(){return he(dl)}function rt(){return he(Ba)}const ue=({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))};ue.displayName="IconBase";const rc=({size:e=48,stroke:t=4,wrapper:n=!0,height:r=2*e})=>{const l=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`},l):l};rc.displayName="LoadingIcon";const lc=(e,{slots:t})=>{var n;return(n=t.default)==null?void 0:n.call(t)},Da=(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},fl=(e,t)=>{let n=1;for(let r=0;r >6;return n+=n<<3,n^=n>>11,n%t},ac=Array.isArray,N1=e=>typeof e=="function",H1=e=>typeof e=="string";var sr=e=>/^(https?:)?\/\//.test(e),z1=/.md((\?|#).*)?$/,j1=(e,t="/")=>!!(sr(e)||e.startsWith("/")&&!e.startsWith(t)&&!z1.test(e)),Ma=e=>Object.prototype.toString.call(e)==="[object Object]",q1=e=>e[e.length-1]==="/"?e.slice(0,-1):e;function W1(){const e=Y(!1);return An()&&Ee(()=>{e.value=!0}),e}function G1(e){return W1(),y(()=>!!e())}const Il=e=>typeof e=="number",mt=e=>typeof e=="string",zt=(e,t)=>mt(e)&&e.startsWith(t),Pr=(e,t)=>mt(e)&&e.endsWith(t),Tn=Object.entries,U1=Object.fromEntries,gt=Object.keys,K1=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),oc=e=>{const[t,n=""]=e.split("#");return t?`${K1(t)}${n?`#${n}`:""}`:e},ai=e=>Ma(e)&&mt(e.name),Qn=(e,t=!1)=>e?ac(e)?e.map(n=>mt(n)?{name:n}:ai(n)?n:null).filter(n=>n!==null):mt(e)?[{name:e}]:ai(e)?[e]:(console.error(`Expect "author" to be \`AuthorInfo[] | AuthorInfo | string[] | string ${t?"":"| false"} | undefined\`, but got`,e),[]):[],ic=(e,t)=>{if(e){if(ac(e)&&e.every(mt))return e;if(mt(e))return[e];console.error(`Expect ${t||"value"} to be \`string[] | string | undefined\`, but got`,e)}return[]},sc=e=>ic(e,"category"),cc=e=>ic(e,"tag"),cr=e=>zt(e,"/");class J1{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"),l=Date.now();return r.className="message move-in",r.innerHTML=t,this.containerElement.appendChild(r),this.messageElements[l]=r,n>0&&setTimeout(()=>{this.close(l)},n),l}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 gt(this.messageElements).forEach(n=>this.close(Number(n)))}destroy(){document.body.removeChild(this.containerElement)}}const uc=/#.*$/u,Y1=e=>{const t=uc.exec(e);return t?t[0]:""},oi=e=>decodeURI(e).replace(uc,"").replace(/(index)?\.html$/i,"").replace(/(README|index)?\.md$/i,""),dc=(e,t)=>{if(t===void 0)return!1;const n=oi(e.path),r=oi(t),l=Y1(t);return l?l===e.hash&&(!r||n===r):n===r},Z1=e=>sr(e)?e:`https://github.com/${e}`,fc=e=>!sr(e)||/github\.com/.test(e)?"GitHub":/bitbucket\.org/.test(e)?"Bitbucket":/gitlab\.com/.test(e)?"GitLab":/gitee\.com/.test(e)?"Gitee":null,kn=(e,...t)=>{const n=e.resolve(...t),r=n.matched[n.matched.length-1];if(!(r!=null&&r.redirect))return n;const{redirect:l}=r,a=N1(l)?l(n):l,o=H1(a)?{path:a}:a;return kn(e,{hash:n.hash,query:n.query,params:n.params,...o})},Q1=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},Ie=({to:e="",class:t="",...n},{slots:r})=>{var s;const l=Fe(),a=oc(e),o=(c={})=>Q1(c)?l.push(e).catch():Promise.resolve();return i("a",{...n,class:["vp-link",t],href:zt(a,"/")?xe(a):a,onClick:o},(s=r.default)==null?void 0:s.call(r))};Ie.displayName="VPLink";const pc=()=>i(ue,{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"}));pc.displayName="GitHubIcon";const hc=()=>i(ue,{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"}));hc.displayName="GitLabIcon";const vc=()=>i(ue,{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"}));vc.displayName="GiteeIcon";const mc=()=>i(ue,{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"}));mc.displayName="BitbucketIcon";const gc=()=>i(ue,{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"}));gc.displayName="SourceIcon";const xt=(e,t)=>{var r;const n=(r=(t==null?void 0:t._instance)||An())==null?void 0:r.appContext.components;return n?e in n||nt(e)in n||er(nt(e))in n:!1},X1=()=>G1(()=>typeof window<"u"&&window.navigator&&"userAgent"in window.navigator),eh=()=>{const e=X1();return y(()=>e.value&&/\b(?:Android|iPhone)/i.test(navigator.userAgent))},Cn=e=>{const t=bt();return y(()=>e[t.value])},bc=({type:e="info",text:t="",vertical:n,color:r},{slots:l})=>{var a;return i("span",{class:["vp-badge",e,{diy:r}],style:{verticalAlign:n??!1,backgroundColor:r??!1}},((a=l.default)==null?void 0:a.call(l))||t)};bc.displayName="Badge";var th=F({name:"FontIcon",props:{icon:{type:String,default:""},color:{type:String,default:""},size:{type:[String,Number],default:""}},setup(e){const t=y(()=>{const r=["font-icon icon"],l=`${e.icon}`;return r.push(l),r}),n=y(()=>{const r={};return e.color&&(r.color=e.color),e.size&&(r["font-size"]=Number.isNaN(Number(e.size))?e.size:`${e.size}px`),gt(r).length?r:null});return()=>e.icon?i("span",{key:e.icon,class:t.value,style:n.value}):null}});function ii(e,t){var n;const r=ut();return ka(()=>{r.value=e()},{...t,flush:(n=t==null?void 0:t.flush)!=null?n:"sync"}),nn(r)}function Fa(e,t){let n,r,l;const a=Y(!0),o=()=>{a.value=!0,l()};me(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,l=f,{get(){return a.value&&(n=s(),a.value=!1),r(),n},set(p){c==null||c(p)}}));return Object.isExtensible(u)&&(u.trigger=o),u}function In(e){return Pi()?(nd(e),!0):!1}function tt(e){return typeof e=="function"?e():Xt(e)}const ur=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const nh=Object.prototype.toString,rh=e=>nh.call(e)==="[object Object]",Qr=()=>{},si=lh();function lh(){var e,t;return ur&&((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 _c(e,t){function n(...r){return new Promise((l,a)=>{Promise.resolve(e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})).then(l).catch(a)})}return n}const yc=e=>e();function ah(e,t=!0,n=!0,r=!1){let l=0,a,o=!0,s=Qr,c;const u=()=>{a&&(clearTimeout(a),a=void 0,s(),s=Qr)};return f=>{const p=tt(e),h=Date.now()-l,g=()=>c=f();return u(),p<=0?(l=Date.now(),g()):(h>p&&(n||!o)?(l=Date.now(),g()):t&&(c=new Promise((E,k)=>{s=r?k:E,a=setTimeout(()=>{l=Date.now(),o=!0,E(g()),u()},Math.max(0,p-h))})),!n&&!a&&(a=setTimeout(()=>o=!0,p)),o=!1,c)}}function oh(e=yc){const t=Y(!0);function n(){t.value=!1}function r(){t.value=!0}const l=(...a)=>{t.value&&e(...a)};return{isActive:nn(t),pause:n,resume:r,eventFilter:l}}function ih(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 sh(e){return e||An()}function ch(...e){if(e.length!==1)return xn(...e);const t=e[0];return typeof t=="function"?nn(Yi(()=>({get:t,set:Qr}))):Y(t)}function uh(e,t=200,n=!1,r=!0,l=!1){return _c(ah(t,n,r,l),e)}function dh(e,t,n={}){const{eventFilter:r=yc,...l}=n;return me(e,_c(r,t),l)}function fh(e,t,n={}){const{eventFilter:r,...l}=n,{eventFilter:a,pause:o,resume:s,isActive:c}=oh(r);return{stop:dh(e,t,{...l,eventFilter:a}),pause:o,resume:s,isActive:c}}function Va(e,t=!0,n){sh()?Ee(e,n):t?e():rn(e)}function ph(e,t,n={}){const{immediate:r=!0}=n,l=Y(!1);let a=null;function o(){a&&(clearTimeout(a),a=null)}function s(){l.value=!1,o()}function c(...u){o(),l.value=!0,a=setTimeout(()=>{l.value=!1,a=null,e(...u)},tt(t))}return r&&(l.value=!0,ur&&c()),In(s),{isPending:nn(l),start:c,stop:s}}function ci(e=!1,t={}){const{truthyValue:n=!0,falsyValue:r=!1}=t,l=Be(e),a=Y(e);function o(s){if(arguments.length)return a.value=s,a.value;{const c=tt(n);return a.value=a.value===c?tt(r):c,a.value}}return l?o:[a,o]}function wt(e){var t;const n=tt(e);return(t=n==null?void 0:n.$el)!=null?t:n}const jt=ur?window:void 0,hh=ur?window.document:void 0,Ec=ur?window.navigator:void 0;function De(...e){let t,n,r,l;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,r,l]=e,t=jt):[t,n,r,l]=e,!t)return Qr;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const a=[],o=()=>{a.forEach(d=>d()),a.length=0},s=(d,f,p,h)=>(d.addEventListener(f,p,h),()=>d.removeEventListener(f,p,h)),c=me(()=>[wt(t),tt(l)],([d,f])=>{if(o(),!d)return;const p=rh(f)?{...f}:f;a.push(...n.flatMap(h=>r.map(g=>s(d,h,g,p))))},{immediate:!0,flush:"post"}),u=()=>{c(),o()};return In(u),u}function vh(){const e=Y(!1);return An()&&Ee(()=>{e.value=!0}),e}function dr(e){const t=vh();return y(()=>(t.value,!!e()))}function kc(e,t={}){const{window:n=jt}=t,r=dr(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let l;const a=Y(!1),o=u=>{a.value=u.matches},s=()=>{l&&("removeEventListener"in l?l.removeEventListener("change",o):l.removeListener(o))},c=ka(()=>{r.value&&(s(),l=n.matchMedia(tt(e)),"addEventListener"in l?l.addEventListener("change",o):l.addListener(o),a.value=l.matches)});return In(()=>{c(),s(),l=void 0}),a}function ui(e,t={}){const{controls:n=!1,navigator:r=Ec}=t,l=dr(()=>r&&"permissions"in r);let a;const o=typeof e=="string"?{name:e}:e,s=Y(),c=()=>{a&&(s.value=a.state)},u=ih(async()=>{if(l.value){if(!a)try{a=await r.permissions.query(o),De(a,"change",c),c()}catch{s.value="prompt"}return a}});return u(),n?{state:s,isSupported:l,query:u}:s}function mh(e={}){const{navigator:t=Ec,read:n=!1,source:r,copiedDuring:l=1500,legacy:a=!1}=e,o=dr(()=>t&&"clipboard"in t),s=ui("clipboard-read"),c=ui("clipboard-write"),u=y(()=>o.value||a),d=Y(""),f=Y(!1),p=ph(()=>f.value=!1,l);function h(){o.value&&s.value!=="denied"?t.clipboard.readText().then(b=>{d.value=b}):d.value=k()}u.value&&n&&De(["copy","cut"],h);async function g(b=tt(r)){u.value&&b!=null&&(o.value&&c.value!=="denied"?await t.clipboard.writeText(b):E(b),d.value=b,f.value=!0,p.start())}function E(b){const A=document.createElement("textarea");A.value=b??"",A.style.position="absolute",A.style.opacity="0",document.body.appendChild(A),A.select(),document.execCommand("copy"),A.remove()}function k(){var b,A,_;return(_=(A=(b=document==null?void 0:document.getSelection)==null?void 0:b.call(document))==null?void 0:A.toString())!=null?_:""}return{isSupported:u,text:d,copied:f,copy:g}}const Or=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Rr="__vueuse_ssr_handlers__",gh=bh();function bh(){return Rr in Or||(Or[Rr]=Or[Rr]||{}),Or[Rr]}function _h(e,t){return gh[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 Eh={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()}},di="vueuse-storage";function wc(e,t,n,r={}){var l;const{flush:a="pre",deep:o=!0,listenToStorageChanges:s=!0,writeDefaults:c=!0,mergeDefaults:u=!1,shallow:d,window:f=jt,eventFilter:p,onError:h=D=>{console.error(D)},initOnMounted:g}=r,E=(d?ut:Y)(typeof t=="function"?t():t);if(!n)try{n=_h("getDefaultStorage",()=>{var D;return(D=jt)==null?void 0:D.localStorage})()}catch(D){h(D)}if(!n)return E;const k=tt(t),b=yh(k),A=(l=r.serializer)!=null?l:Eh[b],{pause:_,resume:S}=fh(E,()=>B(E.value),{flush:a,deep:o,eventFilter:p});return f&&s&&Va(()=>{De(f,"storage",V),De(f,di,G),g&&V()}),g||V(),E;function B(D){try{if(D==null)n.removeItem(e);else{const N=A.write(D),ne=n.getItem(e);ne!==N&&(n.setItem(e,N),f&&f.dispatchEvent(new CustomEvent(di,{detail:{key:e,oldValue:ne,newValue:N,storageArea:n}})))}}catch(N){h(N)}}function x(D){const N=D?D.newValue:n.getItem(e);if(N==null)return c&&k!=null&&n.setItem(e,A.write(k)),k;if(!D&&u){const ne=A.read(N);return typeof u=="function"?u(ne,k):b==="object"&&!Array.isArray(ne)?{...k,...ne}:ne}else return typeof N!="string"?N:A.read(N)}function G(D){V(D.detail)}function V(D){if(!(D&&D.storageArea!==n)){if(D&&D.key==null){E.value=k;return}if(!(D&&D.key!==e)){_();try{(D==null?void 0:D.newValue)!==A.write(E.value)&&(E.value=x(D))}catch(N){h(N)}finally{D?rn(S):S()}}}}}function kh(e){return kc("(prefers-color-scheme: dark)",e)}function wh(e,t,n={}){const{window:r=jt,...l}=n;let a;const o=dr(()=>r&&"ResizeObserver"in r),s=()=>{a&&(a.disconnect(),a=void 0)},c=y(()=>Array.isArray(e)?e.map(f=>wt(f)):[wt(e)]),u=me(c,f=>{if(s(),o.value&&r){a=new ResizeObserver(t);for(const p of f)p&&a.observe(p,l)}},{immediate:!0,flush:"post",deep:!0}),d=()=>{s(),u()};return In(d),{isSupported:o,stop:d}}function Lh(e,t={width:0,height:0},n={}){const{window:r=jt,box:l="content-box"}=n,a=y(()=>{var f,p;return(p=(f=wt(e))==null?void 0:f.namespaceURI)==null?void 0:p.includes("svg")}),o=Y(t.width),s=Y(t.height),{stop:c}=wh(e,([f])=>{const p=l==="border-box"?f.borderBoxSize:l==="content-box"?f.contentBoxSize:f.devicePixelContentBoxSize;if(r&&a.value){const h=wt(e);if(h){const g=r.getComputedStyle(h);o.value=Number.parseFloat(g.width),s.value=Number.parseFloat(g.height)}}else if(p){const h=Array.isArray(p)?p:[p];o.value=h.reduce((g,{inlineSize:E})=>g+E,0),s.value=h.reduce((g,{blockSize:E})=>g+E,0)}else o.value=f.contentRect.width,s.value=f.contentRect.height},n);Va(()=>{const f=wt(e);f&&(o.value="offsetWidth"in f?f.offsetWidth:t.width,s.value="offsetHeight"in f?f.offsetHeight:t.height)});const u=me(()=>wt(e),f=>{o.value=f?t.width:0,s.value=f?t.height:0});function d(){c(),u()}return{width:o,height:s,stop:d}}const fi=["fullscreenchange","webkitfullscreenchange","webkitendfullscreen","mozfullscreenchange","MSFullscreenChange"];function $a(e,t={}){const{document:n=hh,autoExit:r=!1}=t,l=y(()=>{var b;return(b=wt(e))!=null?b:n==null?void 0:n.querySelector("html")}),a=Y(!1),o=y(()=>["requestFullscreen","webkitRequestFullscreen","webkitEnterFullscreen","webkitEnterFullScreen","webkitRequestFullScreen","mozRequestFullScreen","msRequestFullscreen"].find(b=>n&&b in n||l.value&&b in l.value)),s=y(()=>["exitFullscreen","webkitExitFullscreen","webkitExitFullScreen","webkitCancelFullScreen","mozCancelFullScreen","msExitFullscreen"].find(b=>n&&b in n||l.value&&b in l.value)),c=y(()=>["fullScreen","webkitIsFullScreen","webkitDisplayingFullscreen","mozFullScreen","msFullscreenElement"].find(b=>n&&b in n||l.value&&b in l.value)),u=["fullscreenElement","webkitFullscreenElement","mozFullScreenElement","msFullscreenElement"].find(b=>n&&b in n),d=dr(()=>l.value&&n&&o.value!==void 0&&s.value!==void 0&&c.value!==void 0),f=()=>u?(n==null?void 0:n[u])===l.value:!1,p=()=>{if(c.value){if(n&&n[c.value]!=null)return n[c.value];{const b=l.value;if((b==null?void 0:b[c.value])!=null)return!!b[c.value]}}return!1};async function h(){if(!(!d.value||!a.value)){if(s.value)if((n==null?void 0:n[s.value])!=null)await n[s.value]();else{const b=l.value;(b==null?void 0:b[s.value])!=null&&await b[s.value]()}a.value=!1}}async function g(){if(!d.value||a.value)return;p()&&await h();const b=l.value;o.value&&(b==null?void 0:b[o.value])!=null&&(await b[o.value](),a.value=!0)}async function E(){await(a.value?h():g())}const k=()=>{const b=p();(!b||b&&f())&&(a.value=b)};return De(n,fi,k,!1),De(()=>wt(l),fi,k,!1),r&&In(h),{isSupported:d,isFullscreen:a,enter:g,exit:h,toggle:E}}function Pl(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function Lc(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth 1?!0:(t.preventDefault&&t.preventDefault(),!1)}const Br=new WeakMap;function xc(e,t=!1){const n=Y(t);let r=null,l;me(ch(e),s=>{const c=Pl(tt(s));if(c){const u=c;Br.get(u)||Br.set(u,l),n.value&&(u.style.overflow="hidden")}},{immediate:!0});const a=()=>{const s=Pl(tt(e));!s||n.value||(si&&(r=De(s,"touchmove",c=>{xh(c)},{passive:!1})),s.style.overflow="hidden",n.value=!0)},o=()=>{var s;const c=Pl(tt(e));!c||!n.value||(si&&(r==null||r()),c.style.overflow=(s=Br.get(c))!=null?s:"",Br.delete(c),n.value=!1)};return In(o),y({get(){return n.value},set(s){s?a():o()}})}function Ah(e={}){const{window:t=jt,behavior:n="auto"}=e;if(!t)return{x:Y(0),y:Y(0)};const r=Y(t.scrollX),l=Y(t.scrollY),a=y({get(){return r.value},set(s){scrollTo({left:s,behavior:n})}}),o=y({get(){return l.value},set(s){scrollTo({top:s,behavior:n})}});return De(t,"scroll",()=>{r.value=t.scrollX,l.value=t.scrollY},{capture:!1,passive:!0}),{x:a,y:o}}function Sh(e={}){const{window:t=jt,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:r=Number.POSITIVE_INFINITY,listenOrientation:l=!0,includeScrollbar:a=!0}=e,o=Y(n),s=Y(r),c=()=>{t&&(a?(o.value=t.innerWidth,s.value=t.innerHeight):(o.value=t.document.documentElement.clientWidth,s.value=t.document.documentElement.clientHeight))};if(c(),Va(c),De("resize",c,{passive:!0}),l){const u=kc("(orientation: portrait)");me(u,()=>c())}return{width:o,height:s}}const Ac=()=>i(ue,{name:"back-to-top"},()=>[i("path",{d:"M512 843.2c-36.2 0-66.4-13.6-85.8-21.8-10.8-4.6-22.6 3.6-21.8 15.2l7 102c.4 6.2 7.6 9.4 12.6 5.6l29-22c3.6-2.8 9-1.8 11.4 2l41 64.2c3 4.8 10.2 4.8 13.2 0l41-64.2c2.4-3.8 7.8-4.8 11.4-2l29 22c5 3.8 12.2.6 12.6-5.6l7-102c.8-11.6-11-20-21.8-15.2-19.6 8.2-49.6 21.8-85.8 21.8z"}),i("path",{d:"m795.4 586.2-96-98.2C699.4 172 513 32 513 32S324.8 172 324.8 488l-96 98.2c-3.6 3.6-5.2 9-4.4 14.2L261.2 824c1.8 11.4 14.2 17 23.6 10.8L419 744s41.4 40 94.2 40c52.8 0 92.2-40 92.2-40l134.2 90.8c9.2 6.2 21.6.6 23.6-10.8l37-223.8c.4-5.2-1.2-10.4-4.8-14zM513 384c-34 0-61.4-28.6-61.4-64s27.6-64 61.4-64c34 0 61.4 28.6 61.4 64S547 384 513 384z"})]);Ac.displayName="BackToTopIcon";const Sc=()=>i(ue,{name:"close"},()=>i("path",{d:"m925.468 822.294-303.27-310.288L925.51 201.674c34.683-27.842 38.3-75.802 8.122-107.217-30.135-31.37-82.733-34.259-117.408-6.463L512.001 399.257 207.777 87.993C173.1 60.197 120.504 63.087 90.369 94.456c-30.179 31.415-26.561 79.376 8.122 107.217L401.8 512.005l-303.27 310.29c-34.724 27.82-38.34 75.846-8.117 107.194 30.135 31.437 82.729 34.327 117.408 6.486L512 624.756l304.177 311.22c34.68 27.84 87.272 24.95 117.408-6.487 30.223-31.348 26.56-79.375-8.118-107.195z"}));Sc.displayName="CloseIcon";var Th={"/":{backToTop:"返回顶部"}},Ch=F({name:"BackToTop",props:{threshold:{type:Number,default:100},noProgress:Boolean},setup(e){const t=_e(),n=Cn(Th),r=ut(),{height:l}=Lh(r),{height:a}=Sh(),{y:o}=Ah(),s=y(()=>t.value.backToTop!==!1&&o.value>e.threshold),c=y(()=>o.value/(l.value-a.value)*100);return Ee(()=>{r.value=document.body}),()=>i(Ht,{name:"fade"},()=>s.value?i("button",{type:"button",class:"vp-back-to-top-button","aria-label":n.value.backToTop,"data-balloon-pos":"left",onClick:()=>{window.scrollTo({top:0,behavior:"smooth"})}},[e.noProgress?null:i("span",{class:"vp-scroll-progress",role:"progressbar","aria-labelledby":"loadinglabel","aria-valuenow":c.value},i("svg",i("circle",{cx:"50%",cy:"50%",style:{"stroke-dasharray":`calc(${Math.PI*c.value}% - ${4*Math.PI}px) calc(${Math.PI*100}% - ${4*Math.PI}px)`}}))),i(Ac)]):null)}}),Ih=F({name:"NoticeItem",props:{path:{type:String,default:""},match:{type:String,default:""},title:{type:String,required:!0},content:{type:String,required:!0},actions:{type:Array,default:()=>[]},noticeKey:{type:String,default:""},showOnce:Boolean,confirm:Boolean,fullscreen:Boolean},setup(e){const t=rt(),n=Fe(),r=Y(!1),l=y(()=>e.noticeKey?`notice-${e.noticeKey}`:`${e.title}${e.content}`),a=y(()=>e.match?new RegExp(e.match).test(t.path):zt(t.path,e.path));Ee(()=>{const c=(e.showOnce?localStorage:sessionStorage).getItem(l.value);r.value=!c});const o=()=>{r.value=!1,(e.showOnce?localStorage:sessionStorage).setItem(l.value,"true")},s=c=>{c&&(cr(c)?n.push(c):sr(c)&&window.open(c)),o()};return()=>i(Rs,{name:"notice-fade"},()=>a.value&&r.value?[e.fullscreen?i("div",{key:"mask",class:"vp-notice-mask",onClick:()=>{e.confirm||o()}}):null,i("div",{key:"popup",class:["vp-notice-wrapper",{fullscreen:e.fullscreen}]},[i("header",{class:"vp-notice-title"},[e.confirm?null:i(Sc,{onClick:()=>o()}),i("span",{innerHTML:e.title})]),i("div",{class:"vp-notice-content",innerHTML:e.content}),i("div",{class:"vp-notice-footer"},e.actions.map(({text:c,link:u,type:d=""})=>i("button",{type:"button",class:["vp-notice-footer-action",d],onClick:()=>s(u),innerHTML:c})))])]:[])}});const Xl=({config:e})=>{const t=rt(),n=e.find(r=>"match"in r?new RegExp(r.match).test(t.path):zt(t.path,r.path));return n?i(Ih,n):null};Xl.displayName="Notice",Xl.props={config:{type:Array,required:!0}};const Ph=Je({enhance:({app:e})=>{xt("Badge")||e.component("Badge",bc),xt("FontIcon")||e.component("FontIcon",th)},setup:()=>{},rootComponents:[()=>i(Ch,{}),()=>i(Xl,{config:[]})]});function Oh(e,t,n){var r,l,a;t===void 0&&(t=50),n===void 0&&(n={});var o=(r=n.isImmediate)!=null&&r,s=(l=n.callback)!=null&&l,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(E,k){var b=o&&a===void 0;if(a!==void 0&&clearTimeout(a),a=setTimeout(function(){if(a=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 A=e.apply(g,h);return s&&s(A),E(A)}d.push({resolve:E,reject:k})})};return p.cancel=function(h){a!==void 0&&clearTimeout(a),d.forEach(function(g){return(0,g.reject)(h)}),d=[]},p}const Rh=({headerLinkSelector:e,headerAnchorSelector:t,delay:n,offset:r=5})=>{const l=Fe(),o=Oh(()=>{var E,k;const s=Math.max(window.scrollY,document.documentElement.scrollTop,document.body.scrollTop);if(Math.abs(s-0) p.some(A=>A.hash===b.hash));for(let b=0;b =(((E=A.parentElement)==null?void 0:E.offsetTop)??0)-r,B=!_||s<(((k=_.parentElement)==null?void 0:k.offsetTop)??0)-r;if(!(S&&B))continue;const G=decodeURIComponent(l.currentRoute.value.hash),V=decodeURIComponent(A.hash);if(G===V)return;if(f){for(let D=b+1;D {window.addEventListener("scroll",o)}),ol(()=>{window.removeEventListener("scroll",o)})},pi=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)},Bh=".vp-sidebar-link, .toc-link",Dh=".header-anchor",Mh=200,Fh=5,Vh=Je({setup(){Rh({headerLinkSelector:Bh,headerAnchorSelector:Dh,delay:Mh,offset:Fh})}});let Tc=e=>oe(e.title)?{title:e.title}:null;const Cc=Symbol(""),$h=e=>{Tc=e},Nh=()=>he(Cc),Hh=e=>{e.provide(Cc,Tc)};var zh={"/":{title:"目录",empty:"暂无目录"}},jh=F({name:"AutoCatalog",props:{base:{type:String,default:""},level:{type:Number,default:3},index:Boolean,hideHeading:Boolean},setup(e){const t=Nh(),n=Cn(zh),r=ie(),l=Fe(),a=js(),o=Y(l.getRoutes().map(({meta:u,path:d})=>{const f=t(u);if(!f)return null;const p=d.split("/").length;return{level:Pr(d,"/")?p-2:p-1,base:d.replace(/\/[^/]+\/?$/,"/"),path:d,...f}}).filter(u=>Ma(u)&&oe(u.title))),s=()=>{const u=e.base?xp(Bs(e.base)):r.value.path.replace(/\/[^/]+$/,"/"),d=u.split("/").length-2,f=[];return o.value.filter(({level:p,path:h})=>{if(!zt(h,u)||h===u)return!1;if(u==="/"){const g=gt(a.value.locales).filter(E=>E!=="/");if(h==="/404.html"||g.some(E=>zt(h,E)))return!1}return p-d<=e.level&&(Pr(h,".html")&&!Pr(h,"/index.html")||Pr(h,"/"))}).sort(({title:p,level:h,order:g},{title:E,level:k,order:b})=>h-k||(Il(g)?Il(b)?g>0?b>0?g-b:-1:b<0?g-b:1:g:Il(b)?b:p.localeCompare(E))).forEach(p=>{var E;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=(E=k.children)==null?void 0:E.find(A=>A.path===h);b&&(b.children??(b.children=[])).push(p)}}}}),f},c=y(()=>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(Ie,{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:E=[],content:k,path:b,title:A})=>i("li",{class:"vp-child-catalog"},[i("div",{class:["vp-catalog-sub-title",{"has-children":E.length}]},[i("a",{href:`#${A}`,class:"header-anchor"},"#"),i(Ie,{class:"vp-catalog-title",to:b},()=>k?i(k):A)]),E.length?i(e.index?"ol":"div",{class:e.index?"vp-sub-catalogs":"vp-sub-catalogs-wrapper"},E.map(({content:_,path:S,title:B})=>e.index?i("li",{class:"vp-sub-catalog"},i(Ie,{to:S},()=>_?i(_):B)):i(Ie,{class:"vp-sub-catalog-link",to:S},()=>_?i(_):B))):null]))):null]:i("div",{class:"vp-catalog-child-title"},g))})):i("p",{class:"vp-empty-catalog"},n.value.empty)])}}}),qh=Je({enhance:({app:e})=>{Hh(e),xt("AutoCatalog",e)||e.component("AutoCatalog",jh)}});const Wh=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"})]),Ic=F({name:"ExternalLinkIcon",props:{locales:{type:Object,required:!1,default:()=>({})}},setup(e){const t=bt(),n=y(()=>e.locales[t.value]??{openInNewWindow:"open in new window"});return()=>i("span",[Wh,i("span",{class:"external-link-icon-sr-only"},n.value.openInNewWindow)])}});var Gh={};const Uh=Gh,Kh=Je({enhance({app:e}){e.component("ExternalLinkIcon",i(Ic,{locales:Uh}))}});/** + * NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress + * @license MIT + */const de={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=de.isStarted();e=Ol(e,de.settings.minimum,1),de.status=e===1?null:e;const n=de.render(!t),r=n.querySelector(de.settings.barSelector),l=de.settings.speed,a=de.settings.easing;return n.offsetWidth,Jh(o=>{Dr(r,{transform:"translate3d("+hi(e)+"%,0,0)",transition:"all "+l+"ms "+a}),e===1?(Dr(n,{transition:"none",opacity:"1"}),n.offsetWidth,setTimeout(function(){Dr(n,{transition:"all "+l+"ms linear",opacity:"0"}),setTimeout(function(){de.remove(),o()},l)},l)):setTimeout(()=>o(),l)}),de},isStarted:()=>typeof de.status=="number",start:()=>{de.status||de.set(0);const e=()=>{setTimeout(()=>{de.status&&(de.trickle(),e())},de.settings.trickleSpeed)};return de.settings.trickle&&e(),de},done:e=>!e&&!de.status?de:de.inc(.3+.5*Math.random()).set(1),inc:e=>{let t=de.status;return t?(typeof e!="number"&&(e=(1-t)*Ol(Math.random()*t,.1,.95)),t=Ol(t+e,0,.994),de.set(t)):de.start()},trickle:()=>de.inc(Math.random()*de.settings.trickleRate),render:e=>{if(de.isRendered())return document.getElementById("nprogress");vi(document.documentElement,"nprogress-busy");const t=document.createElement("div");t.id="nprogress",t.innerHTML=de.settings.template;const n=t.querySelector(de.settings.barSelector),r=e?"-100":hi(de.status||0),l=document.querySelector(de.settings.parent);return Dr(n,{transition:"all 0 linear",transform:"translate3d("+r+"%,0,0)"}),l!==document.body&&vi(l,"nprogress-custom-parent"),l==null||l.appendChild(t),t},remove:()=>{mi(document.documentElement,"nprogress-busy"),mi(document.querySelector(de.settings.parent),"nprogress-custom-parent");const e=document.getElementById("nprogress");e&&Yh(e)},isRendered:()=>!!document.getElementById("nprogress")},Ol=(e,t,n)=>e n?n:e,hi=e=>(-1+e)*100,Jh=function(){const e=[];function t(){const n=e.shift();n&&n(t)}return function(n){e.push(n),e.length===1&&t()}}(),Dr=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 l(o){return o=n(o),t[o]??(t[o]=r(o))}function a(o,s,c){s=l(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)&&a(o,c,u)}}}(),Pc=(e,t)=>(typeof e=="string"?e:Na(e)).indexOf(" "+t+" ")>=0,vi=(e,t)=>{const n=Na(e),r=n+t;Pc(n,t)||(e.className=r.substring(1))},mi=(e,t)=>{const n=Na(e);if(!Pc(e,t))return;const r=n.replace(" "+t+" "," ");e.className=r.substring(1,r.length-1)},Na=e=>(" "+(e.className||"")+" ").replace(/\s+/gi," "),Yh=e=>{e&&e.parentNode&&e.parentNode.removeChild(e)},Zh=()=>{Ee(()=>{const e=Fe(),t=new Set;t.add(e.currentRoute.value.path),e.beforeEach(n=>{t.has(n.path)||de.start()}),e.afterEach(n=>{t.add(n.path),de.done()})})},Qh=Je({setup(){Zh()}}),Xh=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":"personalWebsite.ts","link":"/personalWebsite/"},{"text":"其他","icon":"others","link":"/others/"},{"text":"捐赠","icon":"donate","link":"/donate/"},{"text":"网站相关","icon":"about","children":[{"text":"关于作者","icon":"zuozhe","link":"/about-the-author/"}]}],"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"}],"/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"}],"/personalWebsite/":[{"text":"个人网站","icon":"personalWebsite","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"}]}}}}'),e0=Y(Xh),Oc=()=>e0,Rc=Symbol(""),t0=()=>{const e=he(Rc);if(!e)throw new Error("useThemeLocaleData() is called without provider.");return e},n0=(e,t)=>{const{locales:n,...r}=e;return{...r,...n==null?void 0:n[t]}},r0=Je({enhance({app:e}){const t=Oc(),n=e._context.provides[Oa],r=y(()=>n0(t.value,n.value));e.provide(Rc,r),Object.defineProperties(e.config.globalProperties,{$theme:{get(){return t.value}},$themeLocale:{get(){return r.value}}})}});var l0={"/":{copy:"复制代码",copied:"已复制",hint:"复制成功"}},a0=['.theme-hope-content div[class*="language-"] pre'];const o0=800,i0=2e3,s0=l0,c0=a0,gi=!1,Rl=new Map,u0=()=>{const{copy:e}=mh({legacy:!0}),t=Cn(s0),n=ie(),r=eh(),l=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","")}},a=()=>rn().then(()=>new Promise(s=>{setTimeout(()=>{c0.forEach(c=>{document.querySelectorAll(c).forEach(l)}),s()},o0)})),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(Rl.get(u));const f=setTimeout(()=>{u.classList.remove("copied"),u.blur(),Rl.delete(u)},i0);Rl.set(u,f)})};Ee(()=>{(!r.value||gi)&&a(),De("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)}}),me(()=>n.value.path,()=>{(!r.value||gi)&&a()})})};var d0=Je({setup:()=>{u0()}}),f0={"/":{author:"著作权归:author所有",license:"基于:license协议",link:"原文链接::link"}};const Bl="https://wenzhihuai.com/",p0=()=>{const e=_e(),t=Cn(f0),n=ie(),r=y(()=>!!e.value.copy||e.value.copy!==!1&&!0),l=y(()=>Ma(e.value.copy)?e.value.copy:null),a=y(()=>{var h;return((h=l.value)==null?void 0:h.disableCopy)??!1}),o=y(()=>{var h;return r.value?((h=l.value)==null?void 0:h.disableSelection)??!1:!1}),s=y(()=>{var h;return r.value?((h=l.value)==null?void 0:h.maxLength)??700:0}),c=y(()=>{var h;return((h=l.value)==null?void 0:h.triggerLength)??100}),u=()=>`${q1(sr(Bl)?Bl:`https://${Bl}`)}${n.value.path}`,d=(h,g)=>{const{author:E,license:k,link:b}=t.value;return[h?E.replace(":author",h):"",g?k.replace(":license",g):"",b.replace(":link",u())].filter(A=>A).join(` +`)},f=()=>{if(mt(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 E=g.getRangeAt(0);if(r.value){const k=E.toString().length;if(a.value||s.value&&k>s.value)return h.preventDefault();if(k>=c.value){h.preventDefault();const b=f(),A=document.createElement("div");A.appendChild(g.getRangeAt(0).cloneContents()),h.clipboardData&&(h.clipboardData.setData("text/html",`${A.innerHTML} ${b.replace(/\\n/g,"`),h.clipboardData.setData("text/plain",`${g.getRangeAt(0).cloneContents().textContent||""} +------ +${b}`))}}}};Ee(()=>{const h=document.querySelector("#app");De(h,"copy",p),ka(()=>{h.style.userSelect=o.value?"none":"auto"})})};var h0=Je({setup:()=>{p0()}});const Mr=wc("VUEPRESS_CODE_TAB_STORE",{});var v0=F({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=Y(e.active),r=ut([]),l=()=>{e.tabId&&(Mr.value[e.tabId]=e.data[n.value].id)},a=(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(),a()):u.key==="ArrowLeft"&&(u.preventDefault(),o()),e.tabId&&(Mr.value[e.tabId]=e.data[n.value].id)},c=()=>{if(e.tabId){const u=e.data.findIndex(({id:d})=>Mr.value[e.tabId]===d);if(u!==-1)return u}return e.active};return Ee(()=>{n.value=c(),me(()=>Mr.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,l()},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 m0=()=>{De("beforeprint",()=>{document.querySelectorAll("details").forEach(e=>{e.open=!0})})},g0=Je({enhance:({app:e})=>{e.component("CodeTabs",v0)},setup:()=>{m0()}});let b0={};const Bc=Symbol(""),_0=()=>he(Bc),y0=e=>{e.provide(Bc,b0)};var E0={"/":{closeTitle:"关闭",downloadTitle:"下载图片",fullscreenTitle:"切换全屏",zoomTitle:"缩放",arrowPrevTitle:"上一个 (左箭头)",arrowNextTitle:"下一个 (右箭头)"}};const k0=".theme-hope-content :not(a) > img:not([no-view])",w0=E0,L0=800,x0='',A0=e=>oe(e)?Array.from(document.querySelectorAll(e)):e.map(t=>Array.from(document.querySelectorAll(t))).flat(),Dc=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(Dc(e)),e.onerror=r=>n(r))}),S0=()=>{const e=Cn(w0),t=_e(),n=ie(),{isSupported:r,toggle:l}=$a(),a=_0();let o;const s=y(()=>t.value.photoSwipe===!1?!1:t.value.photoSwipe||k0),c=d=>{d.on("uiRegister",()=>{r&&d.ui.registerElement({name:"fullscreen",order:7,isButton:!0,html:'',onClick:()=>{l()}}),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 E=0;E {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([w(()=>import("./photoswipe.esm-08_zHRDQ.js"),__vite__mapDeps([])),rn().then(()=>new Promise(d=>setTimeout(d,L0)).then(()=>A0(s.value)))]).then(([{default:d},f])=>{const p=f.map(h=>({html:x0,element:h,msrc:h.src}));f.forEach((h,g)=>{const E=()=>{o=new d({preloaderDelay:0,showHideAnimationType:"zoom",...e.value,...a,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",()=>{E()}),h.addEventListener("keypress",({key:k})=>{k==="Enter"&&E()})}),f.forEach((h,g)=>{Dc(h).then(E=>{p.splice(g,1,E),o==null||o.refreshSlideContent(g)})})})};Ee(()=>{De("wheel",()=>{o==null||o.close()}),me(()=>n.value.path,u,{immediate:!0})})};var T0=Je({enhance:({app:e})=>{y0(e)},setup:()=>{S0()}});const C0=e=>e instanceof Element?document.activeElement===e&&(["TEXTAREA","SELECT","INPUT"].includes(e.tagName)||e.hasAttribute("contenteditable")):!1,I0=(e,t)=>t.some(n=>{if(oe(n))return n===e.key;const{key:r,ctrl:l=!1,shift:a=!1,alt:o=!1}=n;return r===e.key&&l===e.ctrlKey&&a===e.shiftKey&&o===e.altKey}),P0=/[^\x00-\x7F]/,O0=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=O0(e);if(P0.test(e))return r.some(o=>n.toLowerCase().indexOf(o)>-1);const l=e.endsWith(" ");return new RegExp(r.map((o,s)=>r.length===s+1&&!l?`(?=.*\\b${bi(o)})`:`(?=.*\\b${bi(o)}\\b)`).join("")+".+","gi").test(n)},R0=({input:e,hotKeys:t})=>{if(t.value.length===0)return;const n=r=>{e.value&&I0(r,t.value)&&!C0(r.target)&&(r.preventDefault(),e.value.focus())};Ee(()=>{document.addEventListener("keydown",n)}),ol(()=>{document.removeEventListener("keydown",n)})},B0=[{title:"关于我",headers:[],path:"/about-the-author/",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/cloudnative/",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/database/",pathLocale:"/",extraFields:[]},{title:"微信支付",headers:[],path:"/donate/",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:"/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:"/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:"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:"/personalWebsite/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html",pathLocale:"/",extraFields:[]},{title:"10.网站重构",headers:[],path:"/personalWebsite/10.%E7%BD%91%E7%AB%99%E9%87%8D%E6%9E%84.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:"/personalWebsite/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:"/personalWebsite/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:"/personalWebsite/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:"/personalWebsite/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:"/personalWebsite/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:"/personalWebsite/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:"/personalWebsite/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:"/personalWebsite/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%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:"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:"Others",headers:[],path:"/others/",pathLocale:"/",extraFields:[]},{title:"Personal Website",headers:[],path:"/personalWebsite/",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:"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:[]}],D0=Y(B0),M0=()=>D0,F0=({searchIndex:e,routeLocale:t,query:n,maxSuggestions:r})=>{const l=y(()=>e.value.filter(a=>a.pathLocale===t.value));return y(()=>{const a=n.value.trim().toLowerCase();if(!a)return[];const o=[],s=(c,u)=>{_i(a,[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 l.value){if(o.length>=r.value)break;if(_i(a,[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})},V0=e=>{const t=Y(0);return{focusIndex:t,focusNext:()=>{t.value {t.value>0?t.value-=1:t.value=e.value.length-1}}},$0=F({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),l=Fe(),a=bt(),o=M0(),s=Y(null),c=Y(!1),u=Y(""),d=y(()=>t.value[a.value]??{}),f=F0({searchIndex:o,routeLocale:a,query:u,maxSuggestions:r}),{focusIndex:p,focusNext:h,focusPrev:g}=V0(f);R0({input:s,hotKeys:n});const E=y(()=>c.value&&!!f.value.length),k=()=>{E.value&&g()},b=()=>{E.value&&h()},A=_=>{if(!E.value)return;const S=f.value[_];S&&l.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(),A(p.value);break}}}}),E.value&&i("ul",{class:"suggestions",onMouseleave:()=>p.value=-1},f.value.map(({link:_,title:S,header:B},x)=>i("li",{class:["suggestion",{focus:p.value===x}],onMouseenter:()=>p.value=x,onMousedown:()=>A(x)},i("a",{href:_,onClick:G=>G.preventDefault()},[i("span",{class:"page-title"},S),B&&i("span",{class:"page-header"},`> ${B}`)]))))])}});var N0=["s","/"],H0={"/":{placeholder:"搜索"}};const z0=H0,j0=N0,q0=10,W0=Je({enhance({app:e}){e.component("SearchBox",t=>i($0,{locales:z0,hotKeys:j0,maxSuggestions:q0,...t}))}}),Me=e=>{const{icon:t="",color:n,size:r}=e,l={};return n&&(l.color=n),r&&(l.height=Number.isNaN(Number(r))?r:`${r}px`),Sn(t)?i("img",{class:"icon",src:t,"no-view":"",style:l}):cr(t)?i("img",{class:"icon",src:xe(t),"aria-hidden":"","no-view":"",style:l}):i(Ke("FontIcon"),e)};Me.displayName="HopeIcon";const fr=()=>{const e=Fe(),t=rt();return n=>{if(n)if(cr(n))t.path!==n&&e.push(n);else if(Ds(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 Mc=()=>{const e=ie();return y(()=>e.value.readingTime??null)},ea=typeof yi>"u"?null:yi,Fc=(e,t)=>{const{minutes:n,words:r}=e,{less1Minute:l,word:a,time:o}=t;return{time:n<1?l:o.replace("$time",Math.round(n).toString()),words:a.replace("$word",r.toString())}},Ei={words:"",time:""},Vc=()=>ea?Cn(ea):y(()=>null),G0=()=>{if(typeof ea>"u")return y(()=>Ei);const e=Mc(),t=Vc();return y(()=>e.value&&t.value?Fc(e.value,t.value):Ei)},qt=()=>Oc(),se=()=>t0(),ln=()=>y(()=>!!qt().value.pure),$c=()=>{const e=se(),t=_e();return y(()=>{const{author:n}=t.value;return n?Qn(n):n===!1?[]:Qn(e.value.author,!1)})},U0=()=>{const e=_e();return y(()=>sc(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)||""}}))},K0=()=>{const e=_e();return y(()=>cc(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)||""}}))},J0=()=>{const e=_e(),t=ie();return y(()=>{const n=Da(e.value.date);if(n)return n;const{createdTime:r}=t.value.git||{};return r?new Date(r):null})},Y0=()=>{const e=se(),t=ie(),n=_e(),r=$c(),l=U0(),a=K0(),o=J0(),s=Mc(),c=G0(),u=y(()=>({author:r.value,category:l.value,date:o.value,localizedDate:t.value.localizedDate,tag:a.value,isOriginal:n.value.isOriginal||!1,readingTime:s.value,readingTimeLocale:c.value,pageview:"pageview"in n.value?n.value.pageview:!0})),d=y(()=>"pageInfo"in n.value?n.value.pageInfo:"pageInfo"in e.value?e.value.pageInfo:null);return{info:u,items:d}};let Dl=null,Bn=null;const Z0={wait:()=>Dl,pending:()=>{Dl=new Promise(e=>Bn=e)},resolve:()=>{Bn==null||Bn(),Dl=null,Bn=null}},Nc=()=>Z0,Q0="719px",X0="1440px",e2="true",Ha={mobileBreakPoint:Q0,pcBreakPoint:X0,enableThemeColor:e2,"theme-1":"#2196f3","theme-2":"#f26d6d","theme-3":"#3eaf7c","theme-4":"#fb9b5f"},{mobileBreakPoint:t2,pcBreakPoint:n2}=Ha,ki=e=>e.endsWith("px")?Number(e.slice(0,-2)):null,pr=()=>{const e=Y(!1),t=Y(!1),n=()=>{e.value=window.innerWidth<=(ki(t2)??719),t.value=window.innerWidth>=(ki(n2)??1440)};return Ee(()=>{n(),De("resize",n,!1),De("orientationchange",n,!1)}),{isMobile:e,isPC:t}},Hc=Symbol(""),hr=()=>{const e=he(Hc);if(!e)throw new Error("useDarkmode() is called without provider.");return e},r2=e=>{const t=qt(),n=kh(),r=wc("vuepress-theme-hope-scheme","auto"),l=y(()=>t.value.darkmode||"switch"),a=y(()=>{const s=l.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=y(()=>{const s=l.value;return s==="switch"||s==="toggle"});e.provide(Hc,{canToggle:o,config:l,isDarkmode:a,status:r}),Object.defineProperties(e.config.globalProperties,{$isDarkmode:{get:()=>a.value}})},l2=()=>{const{isDarkmode:e}=hr(),t=(n=e.value)=>document.documentElement.setAttribute("data-theme",n?"dark":"light");Ee(()=>{me(e,t,{immediate:!0})})},je=F({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 l=rt(),a=js(),o=xn(e,"config"),s=y(()=>Sn(o.value.link)),c=y(()=>!s.value&&Ds(o.value.link)),u=y(()=>o.value.target||(s.value?"_blank":void 0)),d=y(()=>u.value==="_blank"),f=y(()=>!s.value&&!c.value&&!d.value),p=y(()=>o.value.rel||(d.value?"noopener noreferrer":void 0)),h=y(()=>o.value.ariaLabel||o.value.text),g=y(()=>{if(e.exact)return!1;const k=gt(a.value.locales);return k.length?k.every(b=>b!==o.value.link):o.value.link!=="/"}),E=y(()=>f.value?o.value.activeMatch?new RegExp(o.value.activeMatch).test(l.path):g.value?zt(l.path,o.value.link):l.path===o.value.link:!1);return()=>{const{before:k,after:b,default:A}=r,{text:_,icon:S,link:B}=o.value;return f.value?i(Ie,{to:B,"aria-label":h.value,...t,class:["nav-link",{active:E.value},t.class],onFocusout:()=>n("focusout")},()=>A?A():[k?k():i(Me,{icon:S}),_,b==null?void 0:b()]):i("a",{href:B,rel:p.value,target:u.value,"aria-label":h.value,...t,class:["nav-link",t.class],onFocusout:()=>n("focusout")},A?A():[k?k():i(Me,{icon:S}),_,e.noExternalLinkIcon?null:i(Ic),b==null?void 0:b()])}}}),wn=(e,t,n=!1)=>"activeMatch"in t?new RegExp(t.activeMatch).test(e.path):dc(e,t.link)?!0:t.children&&!n?t.children.some(r=>wn(e,r)):!1,zc=(e,t)=>t.type==="group"?t.children.some(n=>n.type==="group"?zc(e,n):n.type==="page"&&wn(e,n,!0))||"prefix"in t&&dc(e,t.prefix):!1,jc=(e,t)=>oe(e.link)?i(je,{...t,config:e}):i("p",t,[i(Me,{icon:e.icon}),e.text]),qc=e=>{const t=rt();return e?i("ul",{class:"vp-sidebar-sub-headers"},e.map(n=>i("li",{class:"vp-sidebar-sub-header"},[jc(n,{class:["vp-sidebar-link","vp-heading",{active:wn(t,n,!0)}]}),qc(n.children)]))):null},za={"/database/mysql/":["1mysql","数据库缓存"],"/database/redis/":["redis缓存"],"/database/elasticsearch/":["【elasticsearch】搜索过程详解","elasticsearch源码debug"],"/database/mongodb/":[],"/bigdata/spark/":["elastic-spark"],"/middleware/kafka/":["kafka"],"/middleware/zookeeper/":["zookeeper"],"/personalWebsite/":["1.历史与架构","2.Lucene的使用","3.定时任务","4.日志系统","5.小集群部署","6.数据库备份","7.那些牛逼的插件","8.基于贝叶斯的情感分析","9.网站性能优化","10.网站重构"],"/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调优过程","内存屏障","在 Spring 6 中使用虚拟线程","基于kubernetes的分布式限流","serverlog"]},a2=(e,t)=>{const n=e.replace(t,"/").split("/"),r=[];let l=Ia(t);return n.forEach((a,o)=>{o!==n.length-1?(l+=`${a}/`,r.push({link:l,name:a||"Home"})):a!==""&&(l+=a,r.push({link:l,name:a}))}),r};var be;(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"})(be||(be={}));var ta;(function(e){e.article="a",e.home="h",e.slide="s",e.page="p"})(ta||(ta={}));const Yt=(e="",t="")=>cr(t)?t:`${Bs(e)}${t}`,vn=(e,t,n=!1)=>{let r=kn(e,oc(encodeURI(t)));r.name==="404"&&(r=kn(e,t));const{fullPath:l,meta:a,name:o}=r;return{text:!n&&a[be.shortTitle]?a[be.shortTitle]:a[be.title]||t,link:o==="404"?t:l,...a[be.icon]?{icon:a[be.icon]}:{}}},o2=(e,t)=>{const n=ie();return{type:"heading",text:e.title,link:`${n.value.path}#${e.slug}`,children:ja(e.children,t)}},ja=(e,t)=>t>0?e.map(n=>o2(n,t-1)):[],Wc=e=>{const t=ie();return ja(t.value.headers,e)},na=(e,t,n="")=>{const r=Fe(),l=ie(),a=(o,s=n)=>{var u;const c=oe(o)?vn(r,Yt(s,o)):o.link?{...o,...Yr(o.link)?{}:{link:vn(r,Yt(s,o.link)).link}}:o;if("children"in c){const d=Yt(s,c.prefix),f=c.children==="structure"?za[d]:c.children;return{type:"group",...c,prefix:d,children:f.map(p=>a(p,d))}}return{type:"page",...c,children:c.link===l.value.path?ja(((u=l.value.headers[0])==null?void 0:u.level)===1?l.value.headers[0].children:l.value.headers,t):[]}};return e.map(o=>a(o))},i2=(e,t)=>{const n=ie(),r=gt(e).sort((l,a)=>a.length-l.length);for(const l of r)if(zt(decodeURI(n.value.path),l)){const a=e[l];return a?na(a==="structure"?za[l]:a==="heading"?Wc(t):a,t,l):[]}return console.warn(`${n.value.path} is missing sidebar config.`),[]},s2=(e,t)=>{const n=bt();return e===!1?[]:e==="heading"?Wc(t):e==="structure"?na(za[n.value],t,n.value):X(e)?na(e,t):Ca(e)?i2(e,t):[]},Gc=Symbol(""),c2=()=>{const e=_e(),t=se(),n=ie(),r=y(()=>e.value.home?!1:e.value.sidebar??t.value.sidebar??"structure"),l=y(()=>e.value.headerDepth??t.value.headerDepth??2),a=Fa(()=>[r.value,l.value,n.value.path,null],()=>s2(r.value,l.value));st(Gc,a)},qa=()=>{const e=he(Gc);if(!e)throw new Error("useSidebarItems() is called without provider.");return e},u2=F({name:"PageFooter",setup(){const e=qt(),t=se(),n=_e(),r=$c(),l=y(()=>{const{copyright:u,footer:d}=n.value;return d!==!1&&!!(u||d||t.value.displayFooter)}),a=y(()=>{const{footer:u}=n.value;return u===!1?!1:oe(u)?u:t.value.footer||""}),o=y(()=>r.value.map(({name:u})=>u).join(", ")),s=u=>`Copyright © ${new Date().getFullYear()} ${o.value} ${u?`${u} Licensed`:""}`,c=y(()=>{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()=>l.value?i("footer",{class:"vp-footer-wrapper"},[a.value?i("div",{class:"vp-footer",innerHTML:a.value}):null,c.value?i("div",{class:"vp-copyright",innerHTML:c.value}):null]):null}});var Ml=F({name:"EmptyComponent",setup:()=>()=>null});const d2=F({name:"NavbarDropdownLink",props:{config:{type:Object,required:!0}},slots:Object,setup(e,{slots:t}){const n=ie(),r=xn(e,"config"),l=y(()=>r.value.ariaLabel||r.value.text),a=Y(!1);me(()=>n.value.path,()=>{a.value=!1});const o=s=>{s.detail===0&&(a.value=!a.value)};return()=>{var s;return i("div",{class:["dropdown-wrapper",{open:a.value}]},[i("button",{type:"button",class:"dropdown-title","aria-label":l.value,onClick:o},[((s=t.title)==null?void 0:s.call(t))||i("span",{class:"title"},[i(Me,{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(je,{config:c,onFocusout:()=>{c.children.length===0&&d&&(a.value=!1)}}):i("span",c.text)),i("ul",{class:"dropdown-subitem-wrapper"},c.children.map((f,p)=>i("li",{class:"dropdown-subitem"},i(je,{config:f,onFocusout:()=>{p===c.children.length-1&&d&&(a.value=!1)}}))))]:i(je,{config:c,onFocusout:()=>{d&&(a.value=!1)}}))}))])])}}}),Uc=(e,t,n="")=>oe(t)?vn(e,Yt(n,t)):"children"in t?{...t,...t.link&&!Yr(t.link)?vn(e,Yt(n,t.link)):{},children:t.children.map(r=>Uc(e,r,Yt(n,t.prefix)))}:{...t,link:Yr(t.link)?t.link:vn(e,Yt(n,t.link)).link},Kc=()=>{const e=se(),t=Fe(),n=()=>(e.value.navbar||[]).map(l=>Uc(t,l));return Fa(()=>e.value.navbar,()=>n())},f2=()=>{const e=se(),t=y(()=>e.value.repo||null),n=y(()=>t.value?Z1(t.value):null),r=y(()=>t.value?fc(t.value):null),l=y(()=>n.value?e.value.repoLabel??(r.value===null?"Source":r.value):null);return y(()=>!n.value||!l.value||e.value.repoDisplay===!1?null:{type:r.value||"Source",label:l.value,link:n.value})},p2=F({name:"NavScreenDropdown",props:{config:{type:Object,required:!0}},setup(e){const t=ie(),n=xn(e,"config"),r=y(()=>n.value.ariaLabel||n.value.text),l=Y(!1);me(()=>t.value.path,()=>{l.value=!1});const a=(o,s)=>s[s.length-1]===o;return()=>[i("button",{type:"button",class:["nav-screen-dropdown-title",{active:l.value}],"aria-label":r.value,onClick:()=>{l.value=!l.value}},[i("span",{class:"title"},[i(Me,{icon:n.value.icon}),e.config.text]),i("span",{class:["arrow",l.value?"down":"end"]})]),i("ul",{class:["nav-screen-dropdown",{hide:!l.value}]},n.value.children.map(o=>i("li",{class:"dropdown-item"},"children"in o?[i("h4",{class:"dropdown-subtitle"},o.link?i(je,{config:o,onFocusout:()=>{a(o,n.value.children)&&o.children.length===0&&(l.value=!1)}}):i("span",o.text)),i("ul",{class:"dropdown-subitem-wrapper"},o.children.map(s=>i("li",{class:"dropdown-subitem"},i(je,{config:s,onFocusout:()=>{a(s,o.children)&&a(o,n.value.children)&&(l.value=!1)}}))))]:i(je,{config:o,onFocusout:()=>{a(o,n.value.children)&&(l.value=!1)}}))))]}}),h2=F({name:"NavScreenLinks",setup(){const e=Kc();return()=>e.value.length?i("nav",{class:"nav-screen-links"},e.value.map(t=>i("div",{class:"navbar-links-item"},"children"in t?i(p2,{config:t}):i(je,{config:t})))):null}}),Jc=()=>i(ue,{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"}));Jc.displayName="DarkIcon";const Yc=()=>i(ue,{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"}));Yc.displayName="LightIcon";const Zc=()=>i(ue,{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"}));Zc.displayName="AutoIcon";const Qc=()=>i(ue,{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"}));Qc.displayName="EnterFullScreenIcon";const Xc=()=>i(ue,{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"}));Xc.displayName="CancelFullScreenIcon";const eu=()=>i(ue,{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"})]);eu.displayName="OutlookIcon";const tu=F({name:"AppearanceSwitch",setup(){const{config:e,isDarkmode:t,status:n}=hr(),r=ln(),l=()=>{e.value==="switch"?n.value={light:"dark",dark:"auto",auto:"light"}[n.value]:n.value=n.value==="light"?"dark":"light"},a=async o=>{if(!(document.startViewTransition&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches&&!r.value)||!o){l();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()=>{l(),await rn()}).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:a},[i(Zc,{style:{display:n.value==="auto"?"block":"none"}}),i(Jc,{style:{display:n.value==="dark"?"block":"none"}}),i(Yc,{style:{display:n.value==="light"?"block":"none"}})])}}),v2=F({name:"AppearanceMode",setup(){const e=se(),{canToggle:t}=hr(),n=y(()=>e.value.outlookLocales.darkmode);return()=>t.value?i("div",{class:"appearance-wrapper"},[i("label",{class:"appearance-title",for:"appearance-switch"},n.value),i(tu)]):null}}),Fl="VUEPRESS_THEME_COLOR",m2=F({name:"ThemeColorPicker",props:{themeColor:{type:Object,required:!0}},setup(e){const t=(n="")=>{const r=document.documentElement.classList,l=gt(e.themeColor);if(!n){localStorage.removeItem(Fl),r.remove(...l);return}r.remove(...l.filter(a=>a!==n)),r.add(n),localStorage.setItem(Fl,n)};return Ee(()=>{const n=localStorage.getItem(Fl);n&&t(n)}),()=>i("ul",{id:"theme-color-picker"},[i("li",i("span",{class:"theme-color",onClick:()=>t()})),Tn(e.themeColor).map(([n,r])=>i("li",i("span",{style:{background:r},onClick:()=>t(n)})))])}}),mn=Ha.enableThemeColor==="true",g2=mn?U1(Tn(Ha).filter(([e])=>e.startsWith("theme-"))):{},b2=F({name:"ThemeColor",setup(){const e=se(),t=y(()=>e.value.outlookLocales.themeColor);return()=>mn?i("div",{class:"theme-color-wrapper"},[i("label",{class:"theme-color-title",for:"theme-color-picker"},t.value),i(m2,{themeColor:g2})]):null}}),nu=F({name:"ToggleFullScreenButton",setup(){const e=se(),{isSupported:t,isFullscreen:n,toggle:r}=$a(),l=y(()=>e.value.outlookLocales.fullscreen);return()=>t?i("div",{class:"full-screen-wrapper"},[i("label",{class:"full-screen-title",for:"full-screen-switch"},l.value),i("button",{type:"button",id:"full-screen-switch",class:"full-screen",ariaPressed:n.value,onClick:()=>r()},n.value?i(Xc):i(Qc))]):null}}),ru=F({name:"OutlookSettings",setup(){const e=qt(),t=ln(),n=y(()=>!t.value&&e.value.fullscreen);return()=>i(cl,()=>[mn?i(b2):null,i(v2),n.value?i(nu):null])}}),_2=F({name:"NavScreen",props:{show:Boolean},emits:["close"],slots:Object,setup(e,{emit:t,slots:n}){const r=ie(),{isMobile:l}=pr(),a=ut(),o=xc(a);return Ee(()=>{a.value=document.body,me(l,s=>{!s&&e.show&&(o.value=!1,t("close"))}),me(()=>r.value.path,()=>{o.value=!1,t("close")})}),il(()=>{o.value=!1}),()=>i(Ht,{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(h2),i("div",{class:"vp-outlook-wrapper"},i(ru)),(c=n.after)==null?void 0:c.call(n)])):null})}}),y2=F({name:"NavbarBrand",setup(){const e=bt(),t=ir(),n=se(),r=y(()=>n.value.home||e.value),l=y(()=>t.value.title),a=y(()=>n.value.navTitle??l.value),o=y(()=>n.value.logo?xe(n.value.logo):null),s=y(()=>n.value.logoDark?xe(n.value.logoDark):null);return()=>i(Ie,{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,a.value?i("span",{class:["vp-site-name",{"hide-in-pad":o.value&&n.value.hideSiteNameOnMobile!==!1}]},a.value):null])}}),E2=F({name:"NavbarLinks",setup(){const e=Kc();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(d2,{config:t}):i(je,{config:t})))):null}}),k2=F({name:"RepoLink",components:{BitbucketIcon:mc,GiteeIcon:vc,GitHubIcon:pc,GitLabIcon:hc,SourceIcon:gc},setup(){const e=f2();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(Ke(`${e.value.type}Icon`),{style:{width:"1.25rem",height:"1.25rem",verticalAlign:"middle"}}))):null}}),lu=({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"})]));lu.displayName="ToggleNavbarButton";const Wa=(e,{emit:t})=>i("button",{type:"button",class:"vp-toggle-sidebar-button",title:"Toggle Sidebar",onClick:()=>t("toggle")},i("span",{class:"icon"}));Wa.displayName="ToggleSidebarButton";Wa.emits=["toggle"];const w2=F({name:"OutlookButton",setup(){const{isSupported:e}=$a(),t=qt(),n=ln(),r=ie(),{canToggle:l}=hr(),a=Y(!1),o=y(()=>!n.value&&t.value.fullscreen&&e);return me(()=>r.value.path,()=>{a.value=!1}),()=>l.value||o.value||mn?i("div",{class:"nav-item hide-in-mobile"},l.value&&!o.value&&!mn?i(tu):o.value&&!l.value&&!mn?i(nu):i("button",{type:"button",class:["outlook-button",{open:a.value}],tabindex:"-1","aria-hidden":!0},[i(eu),i("div",{class:"outlook-dropdown"},i(ru))])):null}}),L2=F({name:"NavBar",emits:["toggleSidebar"],slots:Object,setup(e,{emit:t,slots:n}){const r=se(),{isMobile:l}=pr(),a=Y(!1),o=y(()=>{const{navbarAutoHide:d="mobile"}=r.value;return d!=="none"&&(d==="always"||l.value)}),s=y(()=>r.value.navbarLayout||{start:["Brand"],center:["Links"],end:["Language","Repo","Outlook","Search"]}),c={Brand:y2,Language:Ml,Links:E2,Repo:k2,Outlook:w2,Search:xt("Docsearch")?Ke("Docsearch"):xt("SearchBox")?Ke("SearchBox"):Ml},u=d=>c[d]??(xt(d)?Ke(d):Ml);return()=>{var d,f,p,h,g,E;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(Wa,{onToggle:()=>{a.value&&(a.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))),(E=n.endAfter)==null?void 0:E.call(n),i(lu,{active:a.value,onToggle:()=>{a.value=!a.value}})])]),i(_2,{show:a.value,onClose:()=>{a.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)}})]}}}),x2=F({name:"SidebarChild",props:{config:{type:Object,required:!0}},setup(e){const t=rt();return()=>[jc(e.config,{class:["vp-sidebar-link",`vp-sidebar-${e.config.type}`,{active:wn(t,e.config,!0)}],exact:!0}),qc(e.config.children)]}}),A2=F({name:"SidebarGroup",props:{config:{type:Object,required:!0},open:{type:Boolean,required:!0}},emits:["toggle"],setup(e,{emit:t}){const n=rt(),r=y(()=>wn(n,e.config)),l=y(()=>wn(n,e.config,!0));return()=>{const{collapsible:a,children:o=[],icon:s,prefix:c,link:u,text:d}=e.config;return i("section",{class:"vp-sidebar-group"},[i(a?"button":"p",{class:["vp-sidebar-heading",{clickable:a||u,exact:l.value,active:r.value}],...a?{type:"button",onClick:()=>t("toggle"),onKeydown:f=>{f.key==="Enter"&&t("toggle")}}:{}},[i(Me,{icon:s}),u?i(je,{class:"vp-sidebar-title",config:{text:d,link:u},noExternalLinkIcon:!0}):i("span",{class:"vp-sidebar-title"},d),a?i("span",{class:["vp-arrow",e.open?"down":"end"]}):null]),e.open||!a?i(au,{key:c,config:o}):null])}}}),au=F({name:"SidebarLinks",props:{config:{type:Array,required:!0}},setup(e){const t=rt(),n=Y(-1),r=l=>{n.value=l===n.value?-1:l};return me(()=>t.path,()=>{const l=e.config.findIndex(a=>zc(t,a));n.value=l},{immediate:!0,flush:"post"}),()=>i("ul",{class:"vp-sidebar-links"},e.config.map((l,a)=>i("li",l.type==="group"?i(A2,{config:l,open:a===n.value,onToggle:()=>r(a)}):i(x2,{config:l}))))}}),S2=F({name:"SideBar",slots:Object,setup(e,{slots:t}){const n=rt(),r=se(),l=qa(),a=ut();return Ee(()=>{me(()=>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}=a.value.getBoundingClientRect(),{top:d,height:f}=s.getBoundingClientRect();d c+u&&s.scrollIntoView(!1)},{immediate:!0})}),()=>{var o,s,c;return i("aside",{ref:a,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(au,{config:l.value}),(c=t.bottom)==null?void 0:c.call(t)])}}}),Ga=F({name:"CommonWrapper",props:{containerClass:{type:String,default:""},noNavbar:Boolean,noSidebar:Boolean,noToc:Boolean},slots:Object,setup(e,{slots:t}){const n=Fe(),r=ie(),l=_e(),a=se(),{isMobile:o,isPC:s}=pr(),[c,u]=ci(!1),[d,f]=ci(!1),p=qa(),h=Y(!1),g=y(()=>e.noNavbar||l.value.navbar===!1||a.value.navbar===!1?!1:!!(r.value.title||a.value.logo||a.value.repo||a.value.navbar)),E=y(()=>e.noSidebar?!1:l.value.sidebar!==!1&&p.value.length!==0&&!l.value.home),k=y(()=>e.noToc||l.value.home?!1:l.value.toc||a.value.toc!==!1&&l.value.toc!==!1),b={x:0,y:0},A=x=>{b.x=x.changedTouches[0].clientX,b.y=x.changedTouches[0].clientY},_=x=>{const G=x.changedTouches[0].clientX-b.x,V=x.changedTouches[0].clientY-b.y;Math.abs(G)>Math.abs(V)*1.5&&Math.abs(G)>40&&(G>0&&b.x<=80?u(!0):u(!1))},S=()=>window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;let B=0;return De("scroll",uh(()=>{const x=S();x<=58||x{x||u(!1)}),Ee(()=>{const x=xc(document.body);me(c,V=>{x.value=V});const G=n.afterEach(()=>{u(!1)});il(()=>{x.value=!1,G()})}),()=>i(xt("GlobalEncrypt")?Ke("GlobalEncrypt"):lc,()=>i("div",{class:["theme-container",{"no-navbar":!g.value,"no-sidebar":!E.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,l.value.containerClass||""],onTouchStart:A,onTouchEnd:_},[g.value?i(L2,{onToggleSidebar:()=>u()},{startBefore:()=>{var x;return(x=t.navbarStartBefore)==null?void 0:x.call(t)},startAfter:()=>{var x;return(x=t.navbarStartAfter)==null?void 0:x.call(t)},centerBefore:()=>{var x;return(x=t.navbarCenterBefore)==null?void 0:x.call(t)},centerAfter:()=>{var x;return(x=t.navbarCenterAfter)==null?void 0:x.call(t)},endBefore:()=>{var x;return(x=t.navbarEndBefore)==null?void 0:x.call(t)},endAfter:()=>{var x;return(x=t.navbarEndAfter)==null?void 0:x.call(t)},screenTop:()=>{var x;return(x=t.navScreenTop)==null?void 0:x.call(t)},screenBottom:()=>{var x;return(x=t.navScreenBottom)==null?void 0:x.call(t)}}):null,i(Ht,{name:"fade"},()=>c.value?i("div",{class:"vp-sidebar-mask",onClick:()=>u(!1)}):null),i(Ht,{name:"fade"},()=>o.value?null:i("div",{class:"toggle-sidebar-wrapper",onClick:()=>f()},i("span",{class:["arrow",d.value?"end":"start"]}))),i(S2,{},{...t.sidebar?{default:()=>t.sidebar()}:{},top:()=>{var x;return(x=t.sidebarTop)==null?void 0:x.call(t)},bottom:()=>{var x;return(x=t.sidebarBottom)==null?void 0:x.call(t)}}),t.default(),i(u2)]))}}),ra=(e,{slots:t})=>{var f,p;const{bgImage:n,bgImageDark:r,bgImageStyle:l,color:a,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})`},l]}):null,r?i("div",{class:"vp-feature-bg dark",style:[{"background-image":`url(${r})`},l]}):null,i("div",{class:"vp-feature",style:a?{color:a}:{}},[((f=t.image)==null?void 0:f.call(t,e))||[s?i("img",{class:["vp-feature-image",{light:c}],src:xe(s),alt:""}):null,c?i("img",{class:"vp-feature-image dark",src:xe(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:E,link:k})=>{const b=[i("h3",{class:"vp-feature-title"},[i(Me,{icon:h}),i("span",{innerHTML:g})]),i("p",{class:"vp-feature-details",innerHTML:E})];return k?Yr(k)?i("a",{class:"vp-feature-item link",href:k,"aria-label":g,target:"_blank"},b):i(Ie,{class:"vp-feature-item link",to:k,"aria-label":g},()=>b):i("div",{class:"vp-feature-item"},b)})):null])])};ra.displayName="FeaturePanel";const pe=F({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=l=>{l.style.transition=`transform ${e.duration}s ease-in-out ${e.delay}s, opacity ${e.duration}s ease-in-out ${e.delay}s`,l.style.transform="translateY(-20px)",l.style.opacity="0"},r=l=>{l.style.transform="translateY(0)",l.style.opacity="1"};return()=>i(e.type==="single"?Ht:Rs,{name:"drop",appear:e.appear,onAppear:n,onAfterAppear:r,onEnter:n,onAfterEnter:r,onBeforeLeave:n},()=>t.default())}}),T2=F({name:"HeroInfo",slots:Object,setup(e,{slots:t}){const n=_e(),r=ir(),l=y(()=>n.value.heroFullScreen??!1),a=y(()=>{const{heroText:u,tagline:d}=n.value;return{text:u??r.value.title??"Hello",tagline:d??r.value.description??"",isFullScreen:l.value}}),o=y(()=>{const{heroText:u,heroImage:d,heroImageDark:f,heroAlt:p,heroImageStyle:h}=n.value;return{image:d?xe(d):null,imageDark:f?xe(f):null,heroStyle:h,alt:p||u||"",isFullScreen:l.value}}),s=y(()=>{const{bgImage:u,bgImageDark:d,bgImageStyle:f}=n.value;return{image:mt(u)?xe(u):null,imageDark:mt(d)?xe(d):null,bgStyle:f,isFullScreen:l.value}}),c=y(()=>n.value.actions??[]);return()=>{var u,d,f;return i("header",{class:["vp-hero-info-wrapper",{fullscreen:l.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(pe,{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,a.value))??i("div",{class:"vp-hero-infos"},[a.value.text?i(pe,{appear:!0,delay:.04},()=>i("h1",{id:"main-title"},a.value.text)):null,a.value.tagline?i(pe,{appear:!0,delay:.08},()=>i("p",{id:"main-description",innerHTML:a.value.tagline})):null,c.value.length?i(pe,{appear:!0,delay:.12},()=>i("p",{class:"vp-hero-actions"},c.value.map(p=>i(je,{class:["vp-hero-action",p.type||"default"],config:p,noExternalLinkIcon:!0},p.icon?{before:()=>i(Me,{icon:p.icon})}:{})))):null])])])}}}),ou=(e,{slots:t})=>{var p,h,g;const{bgImage:n,bgImageDark:r,bgImageStyle:l,color:a,description:o,image:s,imageDark:c,header:u,highlights:d=[],type:f="un-order"}=e;return i("div",{class:"vp-highlight-wrapper",style:a?{color:a}:{}},[n?i("div",{class:["vp-highlight-bg",{light:r}],style:[{"background-image":`url(${n})`},l]}):null,r?i("div",{class:"vp-highlight-bg dark",style:[{"background-image":`url(${r})`},l]}):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:xe(s),alt:""}):null,c?i("img",{class:"vp-highlight-image dark",src:xe(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:E,title:k,details:b,link:A})=>{const _=[i(f==="no-order"?"dt":"h3",{class:"vp-highlight-title"},[E?i(Me,{class:"vp-highlight-icon",icon:E}):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:A}]},A?j1(A)?i("a",{class:"vp-highlight-item link",href:A,"aria-label":k,target:"_blank"},_):i(Ie,{class:"vp-highlight-item link",to:A,"aria-label":k},()=>_):i("div",{class:"vp-highlight-item"},_))}))]))]])])};ou.displayName="HighlightPanel";const vr=({custom:e})=>i(Ws,{class:["theme-hope-content",{custom:e}]});vr.displayName="MarkdownContent";vr.props={custom:Boolean};const C2=F({name:"HomePage",slots:Object,setup(e,{slots:t}){const n=ln(),r=_e(),l=y(()=>{const{features:o}=r.value;return X(o)?o:null}),a=y(()=>{const{highlights:o}=r.value;return X(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(T2),((s=a.value)==null?void 0:s.map(d=>"features"in d?i(ra,d):i(ou,d)))||(l.value?i(pe,{appear:!0,delay:.24},()=>i(ra,{features:l.value})):null),(c=t.center)==null?void 0:c.call(t),i(pe,{appear:!0,delay:.32},()=>i(vr)),(u=t.bottom)==null?void 0:u.call(t)])}}}),I2=F({name:"BreadCrumb",setup(){const e=Fe(),t=ie(),n=bt(),r=_e(),l=se(),a=ut([]),o=y(()=>(r.value.breadcrumb||r.value.breadcrumb!==!1&&l.value.breadcrumb!==!1)&&a.value.length>1),s=y(()=>r.value.breadcrumbIcon||r.value.breadcrumbIcon!==!1&&l.value.breadcrumbIcon!==!1),c=()=>{const u=e.getRoutes(),d=a2(t.value.path,n.value).map(({link:f,name:p})=>{const h=u.find(g=>g.path===f);if(h){const{meta:g,path:E}=kn(e,h.path);return{title:g[be.shortTitle]||g[be.title]||p,icon:g[be.icon],path:E}}return null}).filter(f=>f!==null);d.length>1&&(a.value=d)};return Ee(()=>{me(()=>t.value.path,c,{immediate:!0})}),()=>i("nav",{class:["vp-breadcrumb",{disable:!o.value}]},o.value?i("ol",{vocab:"https://schema.org/",typeof:"BreadcrumbList"},a.value.map((u,d)=>i("li",{class:{"is-active":a.value.length-1===d},property:"itemListElement",typeof:"ListItem"},[i(Ie,{to:u.path,property:"item",typeof:"WebPage"},()=>[s.value?i(Me,{icon:u.icon}):null,i("span",{property:"name"},u.title||"Unknown")]),i("meta",{property:"position",content:d+1})]))):[])}}),wi=e=>{const t=Fe();return e===!1?!1:oe(e)?vn(t,e,!0):Ca(e)?e:null},la=(e,t,n)=>{const r=e.findIndex(l=>l.link===t);if(r!==-1){const l=e[r+n];return l!=null&&l.link?l:null}for(const l of e)if(l.children){const a=la(l.children,t,n);if(a)return a}return null},P2=F({name:"PageNav",setup(){const e=se(),t=_e(),n=qa(),r=ie(),l=fr(),a=y(()=>{const s=wi(t.value.prev);return s===!1?null:s||(e.value.prevLink===!1?null:la(n.value,r.value.path,-1))}),o=y(()=>{const s=wi(t.value.next);return s===!1?null:s||(e.value.nextLink===!1?null:la(n.value,r.value.path,1))});return De("keydown",s=>{s.altKey&&(s.key==="ArrowRight"?o.value&&(l(o.value.link),s.preventDefault()):s.key==="ArrowLeft"&&a.value&&(l(a.value.link),s.preventDefault()))}),()=>a.value||o.value?i("nav",{class:"vp-page-nav"},[a.value?i(je,{class:"prev",config:a.value},()=>{var s,c;return[i("div",{class:"hint"},[i("span",{class:"arrow start"}),e.value.metaLocales.prev]),i("div",{class:"link"},[i(Me,{icon:(s=a.value)==null?void 0:s.icon}),(c=a.value)==null?void 0:c.text])]}):null,o.value?i(je,{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(Me,{icon:(c=o.value)==null?void 0:c.icon})])]}):null]):null}}),iu=()=>i(ue,{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"}));iu.displayName="AuthorIcon";const su=()=>i(ue,{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"}));su.displayName="CalendarIcon";const cu=()=>i(ue,{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"}));cu.displayName="CategoryIcon";const uu=()=>i(ue,{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"}));uu.displayName="PrintIcon";const du=()=>i(ue,{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"}));du.displayName="TagIcon";const fu=()=>i(ue,{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"}));fu.displayName="TimerIcon";const pu=()=>i(ue,{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"})]);pu.displayName="WordIcon";const Wt=()=>{const e=se();return y(()=>e.value.metaLocales)},O2={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"},R2=({docsRepo:e,docsBranch:t,docsDir:n,filePathRelative:r,editLinkPattern:l})=>{if(!r)return null;const a=fc(e);let o;return l?o=l:a!==null&&(o=O2[a]),o?o.replace(/:repo/,Sn(e)?e:`https://github.com/${e}`).replace(/:branch/,t).replace(/:path/,Ms(`${Ia(n)}/${r}`)):null},B2=()=>{const e=se(),t=ie(),n=_e();return y(()=>{const{repo:r,docsRepo:l=r,docsBranch:a="main",docsDir:o="",editLink:s,editLinkPattern:c=""}=e.value;if(!(n.value.editLink??s??!0)||!l)return null;const d=R2({docsRepo:l,docsBranch:a,docsDir:o,editLinkPattern:c,filePathRelative:t.value.filePathRelative});return d?{text:e.value.metaLocales.editLink,link:d}:null})},D2=()=>{const e=ir(),t=se(),n=ie(),r=_e();return y(()=>{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)})},M2=()=>{const e=se(),t=ie(),n=_e();return y(()=>{var l;return n.value.contributors??e.value.contributors??!0?((l=t.value.git)==null?void 0:l.contributors)??null:null})},F2=F({name:"AuthorInfo",inheritAttrs:!1,props:{author:{type:Array,required:!0},pure:Boolean},setup(e){const t=Wt();return()=>e.author.length?i("span",{class:"page-author-info","aria-label":`${t.value.author}${e.pure?"":"🖊"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[i(iu),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}}),V2=F({name:"CategoryInfo",inheritAttrs:!1,props:{category:{type:Array,required:!0},pure:Boolean},setup(e){const t=Fe(),n=ie(),r=Wt(),l=(a,o="")=>{o&&n.value.path!==o&&(a.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(cu),e.category.map(({name:a,path:o})=>i("span",{class:["page-category-item",{[`category${fl(a,9)}`]:!e.pure,clickable:o}],role:o?"navigation":"",onClick:s=>l(s,o)},a)),i("meta",{property:"articleSection",content:e.category.map(({name:a})=>a).join(",")})]):null}}),$2=F({name:"DateInfo",inheritAttrs:!1,props:{date:{type:Object,default:null},localizedDate:{type:String,default:""},pure:Boolean},setup(e){const t=Pa(),n=Wt();return()=>e.date?i("span",{class:"page-date-info","aria-label":`${n.value.date}${e.pure?"":"📅"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[i(su),i("span",i(cl,()=>e.localizedDate||e.date.toLocaleDateString(t.value))),i("meta",{property:"datePublished",content:e.date.toISOString()||""})]):null}}),N2=F({name:"OriginalInfo",inheritAttrs:!1,props:{isOriginal:Boolean},setup(e){const t=Wt();return()=>e.isOriginal?i("span",{class:"page-original-info"},t.value.origin):null}}),H2=F({name:"ReadingTimeInfo",inheritAttrs:!1,props:{readingTime:{type:Object,default:()=>null},readingTimeLocale:{type:Object,default:()=>null},pure:Boolean},setup(e){const t=Wt(),n=y(()=>{if(!e.readingTime)return null;const{minutes:r}=e.readingTime;return r<1?"PT1M":`PT${Math.round(r)}M`});return()=>{var r,l;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(fu),i("span",(l=e.readingTimeLocale)==null?void 0:l.time),i("meta",{property:"timeRequired",content:n.value})]):null}}}),z2=F({name:"TagInfo",inheritAttrs:!1,props:{tag:{type:Array,default:()=>[]},pure:Boolean},setup(e){const t=Fe(),n=ie(),r=Wt(),l=(a,o="")=>{o&&n.value.path!==o&&(a.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(du),e.tag.map(({name:a,path:o})=>i("span",{class:["page-tag-item",{[`tag${fl(a,9)}`]:!e.pure,clickable:o}],role:o?"navigation":"",onClick:s=>l(s,o)},a)),i("meta",{property:"keywords",content:e.tag.map(({name:a})=>a).join(",")})]):null}}),j2=F({name:"ReadTimeInfo",inheritAttrs:!1,props:{readingTime:{type:Object,default:()=>null},readingTimeLocale:{type:Object,default:()=>null},pure:Boolean},setup(e){const t=Wt();return()=>{var n,r,l;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(pu),i("span",(r=e.readingTimeLocale)==null?void 0:r.words),i("meta",{property:"wordCount",content:(l=e.readingTime)==null?void 0:l.words})]):null}}}),hu=F({name:"PageInfo",components:{AuthorInfo:F2,CategoryInfo:V2,DateInfo:$2,OriginalInfo:N2,PageViewInfo:()=>null,ReadingTimeInfo:H2,TagInfo:z2,WordInfo:j2},props:{items:{type:[Array,Boolean],default:()=>["Author","Original","Date","PageView","ReadingTime","Category","Tag"]},info:{type:Object,required:!0}},setup(e){const t=ln();return()=>e.items?i("div",{class:"page-info"},e.items.map(n=>i(Ke(`${n}Info`),{...e.info,pure:t.value}))):null}}),q2=F({name:"PageTitle",setup(){const e=ie(),t=_e(),n=se(),{info:r,items:l}=Y0();return()=>i("div",{class:"vp-page-title"},[i("h1",[n.value.titleIcon===!1?null:i(Me,{icon:t.value.icon}),e.value.title]),i(hu,{info:r.value,...l.value===null?{}:{items:l.value}}),i("hr")])}}),vu=()=>i(ue,{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"})]);vu.displayName="EditIcon";const W2=F({name:"PageMeta",setup(){const e=se(),t=B2(),n=D2(),r=M2();return()=>{const{metaLocales:l}=e.value;return i("footer",{class:"page-meta"},[t.value?i("div",{class:"meta-item edit-link"},i(je,{class:"label",config:t.value},{before:()=>i(vu)})):null,i("div",{class:"meta-item git-info"},[n.value?i("div",{class:"update-time"},[i("span",{class:"label"},`${l.lastUpdated}: `),i(cl,()=>i("span",{class:"info"},n.value))]):null,r.value&&r.value.length?i("div",{class:"contributors"},[i("span",{class:"label"},`${l.contributors}: `),r.value.map(({email:a,name:o},s)=>[i("span",{class:"contributor",title:`email: ${a}`},o),s!==r.value.length-1?",":""])]):null])])}}}),G2=F({name:"PrintButton",setup(){const e=qt(),t=se();return()=>e.value.print===!1?null:i("button",{type:"button",class:"print-button",title:t.value.metaLocales.print,onClick:()=>{window.print()}},i(uu))}}),U2=({title:e,level:t,slug:n})=>i(Ie,{to:`#${n}`,class:["toc-link",`level${t}`]},()=>e),aa=(e,t)=>{const n=rt();return e.length&&t>0?i("ul",{class:"toc-list"},e.map(r=>{const l=aa(r.children,t-1);return[i("li",{class:["toc-item",{active:n.hash===`#${r.slug}`}]},U2(r)),l?i("li",l):null]})):null},mu=F({name:"TOC",props:{items:{type:Array,default:()=>[]},headerDepth:{type:Number,default:2}},slots:Object,setup(e,{slots:t}){const n=rt(),r=ie(),l=Wt(),a=ut(),o=Y("-1.7rem"),s=u=>{var d;(d=a.value)==null||d.scrollTo({top:u,behavior:"smooth"})},c=()=>{if(a.value){const u=document.querySelector(".toc-item.active");u?o.value=`${u.getBoundingClientRect().top-a.value.getBoundingClientRect().top+a.value.scrollTop}px`:o.value="-1.7rem"}else o.value="-1.7rem"};return Ee(()=>{me(()=>n.hash,u=>{if(a.value){const d=document.querySelector(`#toc a.toc-link[href$="${u}"]`);if(!d)return;const{top:f,height:p}=a.value.getBoundingClientRect(),{top:h,height:g}=d.getBoundingClientRect();h f+p&&s(a.value.scrollTop+h+g-f-p)}}),me(()=>n.fullPath,c,{flush:"post",immediate:!0})}),()=>{var d,f;const u=e.items.length?aa(e.items,e.headerDepth):r.value.headers?aa(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"},[l.value.toc,i(G2)]),i("div",{class:"toc-wrapper",ref:a},[u,i("div",{class:"toc-marker",style:{top:o.value}})]),(f=t.after)==null?void 0:f.call(t)])]):null}}}),K2=F({name:"NormalPage",slots:Object,setup(e,{slots:t}){const n=_e(),{isDarkmode:r}=hr(),l=se(),a=y(()=>n.value.toc||n.value.toc!==!1&&l.value.toc!==!1);return()=>i("main",{id:"main-content",class:"vp-page"},i(xt("LocalEncrypt")?Ke("LocalEncrypt"):lc,()=>{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:xe(n.value.cover),alt:"","no-view":""})):null,i(I2),i(q2),a.value?i(mu,{headerDepth:n.value.headerDepth??l.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(vr),(c=t.contentAfter)==null?void 0:c.call(t),i(W2),i(P2),xt("CommentService")?i(Ke("CommentService"),{darkmode:r.value}):null,(u=t.bottom)==null?void 0:u.call(t)]}))}}),J2=(e,t)=>{const n=e.__vccOpts||e;for(const[r,l]of t)n[r]=l;return n},Y2={name:"adsense-inline",components:{"normal-page":K2},mounted(){this.adsenseAddLoad(),this.adsenseAddLoadAfter(),this.adsenseAddLoadRight()},methods:{adsenseAddLoad(){let e=document.createElement("script");e.type="text/javascript",e.text="(adsbygoogle = window.adsbygoogle || []).push({});",document.getElementsByTagName("body")[0].appendChild(e)},adsenseAddLoadAfter(){let e=document.createElement("script");e.type="text/javascript",e.text="(adsbygoogleAfter = window.adsbygoogleAfter || []).push({});",document.getElementsByTagName("body")[0].appendChild(e)},adsenseAddLoadRight(){let e=document.createElement("script");e.type="text/javascript",e.text="(adsbygoogleRight = window.adsbygoogleRight || []).push({});",document.getElementsByTagName("body")[0].appendChild(e)}}},Z2=lr("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),Q2=lr("ins",{class:"adsbygoogleAfter",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":"3248671754"},null,-1),X2=lr("ins",{class:"adsbygoogleRight",style:{display:"block"},"data-ad-client":"ca-pub-9037099208128116","data-ad-slot":"3862119113","data-ad-format":"auto","data-full-width-responsive":"true"},null,-1);function ev(e,t,n,r,l,a){const o=Ke("normal-page",!0);return Lf(),Af(o,null,{contentBefore:Vr(()=>[Z2]),contentAfter:Vr(()=>[Q2]),tocAfter:Vr(()=>[X2]),_:1})}const tv=J2(Y2,[["render",ev],["__file","NormalPage.vue"]]),Ua=F({name:"SkipLink",props:{content:{type:String,default:"main-content"}},setup(e){const t=ie(),n=se(),r=ut(),l=({target:a})=>{const o=document.querySelector(a.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(()=>{me(()=>t.value.path,()=>r.value.focus())}),()=>[i("span",{ref:r,tabindex:"-1"}),i("a",{href:`#${e.content}`,class:"vp-skip-link sr-only",onClick:l},n.value.routeLocales.skipToContent)]}}),nv=F({name:"FadeSlideY",slots:Object,setup(e,{slots:t}){const{resolve:n,pending:r}=Nc();return()=>i(Ht,{name:"fade-slide-y",mode:"out-in",onBeforeEnter:n,onBeforeLeave:r},()=>{var l;return(l=t.default)==null?void 0:l.call(t)})}}),rv=F({name:"Layout",slots:Object,setup(e,{slots:t}){const n=qt(),r=se(),l=ie(),a=_e(),{isMobile:o}=pr(),s=y(()=>{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(Ua),i(Ga,{},{default:()=>{var c;return((c=t.default)==null?void 0:c.call(t))||(a.value.home?i(C2):i(nv,()=>i(tv,{key:l.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(Ke("BloggerInfo"))}:{},...!o.value&&s.value==="always"?{sidebar:()=>i(Ke("BloggerInfo"))}:{}})]}}),lv=F({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())])}}),av=F({name:"NotFound",slots:Object,setup(e,{slots:t}){const n=bt(),r=se(),{navigate:l}=Ql({to:r.value.home??n.value});return()=>[i(Ua),i(Ga,{noSidebar:!0},()=>{var a;return i("main",{id:"main-content",class:"vp-page not-found"},((a=t.default)==null?void 0:a.call(t))||[i(lv),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:()=>l()},r.value.routeLocales.home)])])})]}}),ov={Zhihu:'',Github:'',Gitee:''},iv={category:{"/":{path:"/category/",map:{}}},tag:{"/":{path:"/tag/",map:{}}}},sv={article:{"/":{path:"/article/",keys:["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-37ac02fe","v-523e9724","v-65b5c81c","v-731a76b6","v-bea2ce1e","v-3efc517e","v-79ad699f","v-8658e60a","v-7e9e4a32","v-0b62f72e","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-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-37ac02fe","v-523e9724","v-65b5c81c","v-731a76b6","v-bea2ce1e","v-3efc517e","v-79ad699f","v-8658e60a","v-7e9e4a32","v-0b62f72e","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"]}}},Li=Y(iv),gu=(e="")=>{const t=ie(),n=Fe(),r=bt();return y(()=>{var c;const l=e||((c=_e().value.blog)==null?void 0:c.key)||"";if(!l)return console.warn("useBlogCategory: key not found"),{path:"/",map:{}};const a=n.getRoutes();if(!Li.value[l])throw new Error(`useBlogCategory: key ${l} is invalid`);const o=Li.value[l][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=a.find(({name:h})=>h===f);if(p){const h=kn(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})},xi=Y(sv),pl=(e="")=>{const t=Fe(),n=bt();return y(()=>{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(!xi.value[r])throw new Error(`useBlogType: key ${e} is invalid`);const l=t.getRoutes(),a=xi.value[r][n.value],o={path:a.path,items:[]};for(const c of a.keys){const u=l.find(({name:d})=>d===c);if(u){const d=kn(t,u.path);o.items.push({path:d.path,info:d.meta})}}return o})},bu=Symbol.for("categoryMap"),mr=()=>{const e=he(bu);if(!e)throw new Error("useCategoryMap() is called without provider.");return e},cv=()=>{const e=gu("category");st(bu,e)},gr=()=>{const e=qt(),t=se();return y(()=>({...e.value.blog,...t.value.blog}))},_u=Symbol.for("tagMap"),br=()=>{const e=he(_u);if(!e)throw new Error("useTagMap() is called without provider.");return e},uv=()=>{const e=gu("tag");st(_u,e)},dv=e=>{const t=se();return y(()=>{const{[be.author]:n}=e.value;return n?Qn(n):n===!1?[]:Qn(t.value.author,!1)})},fv=e=>{const t=mr();return y(()=>sc(e.value[be.category]).map(n=>({name:n,path:t.value.map[n].path})))},pv=e=>{const t=br();return y(()=>cc(e.value[be.tag]).map(n=>({name:n,path:t.value.map[n].path})))},hv=e=>y(()=>{const{[be.date]:t}=e.value;return Da(t)}),vv=e=>{const t=xn(e,"info"),n=gr(),r=dv(t),l=fv(t),a=pv(t),o=hv(t),s=Vc(),c=y(()=>({author:r.value,category:l.value,date:o.value,localizedDate:t.value[be.localizedDate]||"",tag:a.value,isOriginal:t.value[be.isOriginal]||!1,readingTime:t.value[be.readingTime]||null,readingTimeLocale:t.value[be.readingTime]&&s.value?Fc(t.value[be.readingTime],s.value):null,pageview:e.path})),u=y(()=>n.value.articleInfo);return{info:c,items:u}},yu=Symbol(""),_r=()=>{const e=he(yu);if(!e)throw new Error("useArticles() is called without provider.");return e},mv=()=>{const e=pl("article");st(yu,e)},Eu=Symbol(""),Ka=()=>{const e=he(Eu);if(!e)throw new Error("useStars() is called without provider.");return e},gv=()=>{const e=pl("star");st(Eu,e)},ku=Symbol(""),Ja=()=>{const e=he(ku);if(!e)throw new Error("useTimelines() is called without provider.");return e},bv=()=>{const e=pl("timeline"),t=y(()=>{const n=[];return e.value.items.forEach(({info:r,path:l})=>{const a=Da(r[be.date]),o=a==null?void 0:a.getFullYear(),s=a?a.getMonth()+1:null,c=a==null?void 0:a.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:l}))}),{...e.value,config:n.reverse()}});st(ku,t)},_v=()=>{mv(),cv(),gv(),uv(),bv()},yv=F({name:"SocialMedia",setup(){const e=gr(),t=ln(),n=y(()=>{const r=e.value.medias;return r?Tn(r).map(([l,a])=>({name:l,icon:ov[l],url:a})):[]});return()=>n.value.length?i("div",{class:"vp-social-medias"},n.value.map(({name:r,icon:l,url:a})=>i("a",{class:"vp-social-media",href:a,rel:"noopener noreferrer",target:"_blank","aria-label":r,...t.value?{}:{"data-balloon-pos":"up"},innerHTML:l}))):null}}),Ya=F({name:"BloggerInfo",setup(){const e=gr(),t=ir(),n=se(),r=_r(),l=mr(),a=br(),o=Ja(),s=fr(),c=y(()=>{var p;return e.value.name||((p=Qn(n.value.author)[0])==null?void 0:p.name)||t.value.title}),u=y(()=>e.value.avatar||n.value.logo),d=y(()=>n.value.blogLocales),f=y(()=>e.value.intro);return()=>{const{article:p,category:h,tag:g,timeline:E}=d.value,k=[[r.value.path,r.value.items.length,p],[l.value.path,gt(l.value.map).length,h],[a.value.path,gt(a.value.map).length,g],[o.value.path,o.value.items.length,E]];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:xe(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:xe(f.value)}):null]),i("div",{class:"vp-blog-counts"},k.map(([b,A,_])=>i(Ie,{class:"vp-blog-count",to:b},()=>[i("div",{class:"count"},A),i("div",_)]))),i(yv)])}}}),Za=()=>i(ue,{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"}));Za.displayName="CategoryIcon";const Qa=()=>i(ue,{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"}));Qa.displayName="TagIcon";const Xa=()=>i(ue,{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"}));Xa.displayName="TimelineIcon";const wu=()=>i(ue,{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"}));wu.displayName="SlideIcon";const Lu=()=>i(ue,{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"})]);Lu.displayName="StickyIcon";const hl=()=>i(ue,{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"}));hl.displayName="ArticleIcon";const xu=()=>i(ue,{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"}));xu.displayName="BookIcon";const Au=()=>i(ue,{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"}));Au.displayName="LinkIcon";const Su=()=>i(ue,{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"}));Su.displayName="ProjectIcon";const Tu=()=>i(ue,{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"}));Tu.displayName="FriendIcon";const oa=()=>i(ue,{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"}));oa.displayName="SlideDownIcon";const Cu=()=>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:' '});Cu.displayName="EmptyIcon";const Iu=()=>i(ue,{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"}));Iu.displayName="LockIcon";const Ev=F({name:"ArticleItem",props:{info:{type:Object,required:!0},path:{type:String,required:!0}},slots:Object,setup(e,{slots:t}){const n=xn(e,"info"),{info:r,items:l}=vv(e);return()=>{var p,h,g;const{[be.title]:a,[be.type]:o,[be.isEncrypted]:s=!1,[be.cover]:c,[be.excerpt]:u,[be.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:xe(c),loading:"lazy"}),i("meta",{property:"image",content:xe(c)})]:[]),d?i(Lu):null,i(Ie,{to:e.path},()=>{var E;return((E=t.title)==null?void 0:E.call(t,{title:a,isEncrypted:s,type:o}))||i("header",{class:"vp-article-title"},[s?i(Iu):null,o===ta.slide?i(wu):null,i("span",{property:"headline"},a)])}),((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(hu,{info:f,...l.value?{items:l.value}:{}})]))}}}),kv=F({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(),l=Y(""),a=y(()=>r.value.paginationLocales),o=y(()=>Math.ceil(e.total/e.perPage)),s=y(()=>!!o.value&&o.value!==1),c=y(()=>o.value<7?!1:e.current>4),u=y(()=>o.value<7?!1:e.current {const{current:h}=e;let g=1,E=o.value;const k=[];o.value>=7&&(h<=4&&h 4&&h>=o.value-3?(E=o.value,g=o.value-4):o.value>7&&(g=h-2,E=h+2));for(let b=g;b<=E;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(`${a.value.errorText.replace(/\$page/g,o.value.toString())}`)};return Ee(()=>{n=new J1}),()=>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)},a.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.current f(e.current+1)},a.value.next):null]),i("div",{class:"vp-pagination-nav"},[i("label",{for:"navigation-text"},`${a.value.navigate}: `),i("input",{id:"navigation-text",value:l.value,onInput:({target:h})=>{l.value=h.value},onKeydown:h=>{h.key==="Enter"&&(h.preventDefault(),p(l.value))}}),i("button",{class:"vp-pagination-button",role:"navigation",title:a.value.action,onClick:()=>p(l.value)},a.value.action)])]):[])}}),eo=F({name:"ArticleList",props:{items:{type:Array,default:()=>[]}},setup(e){const t=rt(),n=Fe(),r=gr(),l=Y(1),a=y(()=>r.value.articlePerPage||10),o=y(()=>e.items.slice((l.value-1)*a.value,l.value*a.value)),s=async c=>{l.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),me(l,()=>{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(pe,{appear:!0,delay:d*.04},()=>i(Ev,{key:u,info:c,path:u}))),i(kv,{current:l.value,perPage:a.value,total:e.items.length,onUpdateCurrentPage:s})]:i(Cu))}}),Pu=F({name:"CategoryList",setup(){const e=ie(),t=mr();return()=>i("ul",{class:"vp-category-list"},Tn(t.value.map).sort(([,n],[,r])=>r.items.length-n.items.length).map(([n,{path:r,items:l}])=>i("li",{class:["vp-category",`vp-category${fl(n,9)}`,{active:r===e.value.path}]},i(Ie,{to:r},()=>[n,i("span",{class:"count"},l.length)]))))}}),Ou=F({name:"TagList",setup(){const e=_e(),t=br(),n=r=>{var l;return r===((l=e.value.blog)==null?void 0:l.name)};return()=>i("ul",{class:"tag-list-wrapper"},Tn(t.value.map).sort(([,r],[,l])=>l.items.length-r.items.length).map(([r,{path:l,items:a}])=>i("li",{class:["tag",`tag${fl(r,9)}`,{active:n(r)}]},i(Ie,{to:l},()=>[r,i("span",{class:"tag-num"},a.length)]))))}}),wv=F({name:"TimelineList",setup(){const e=se(),t=Ja(),n=fr(),r=y(()=>e.value.blogLocales.timeline);return()=>i("div",{class:"timeline-list-wrapper"},[i("div",{class:"timeline-list-title",onClick:()=>n(t.value.path)},[i(Xa),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:l,items:a},o)=>i(pe,{appear:!0,delay:.08*(o+1)},()=>i("li",[i("h3",{class:"timeline-year"},l),i("ul",{class:"timeline-year-wrapper"},a.map(({date:s,info:c,path:u})=>i("li",{class:"timeline-item"},[i("span",{class:"timeline-date"},s),i(Ie,{class:"timeline-title",to:u},()=>c[be.title])])))])))))])}}),Lv={article:hl,category:Za,tag:Qa,timeline:Xa},Ru=F({name:"InfoList",setup(){const e=se(),t=_r(),n=mr(),r=y(()=>gt(n.value.map).length),l=Ka(),a=br(),o=y(()=>gt(a.value.map).length),s=fr(),c=Y("article"),u=y(()=>e.value.blogLocales);return()=>i("div",{class:"vp-blog-infos"},[i("div",{class:"vp-blog-type-switcher"},Tn(Lv).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(pe,()=>c.value==="article"?i("div",{class:"vp-star-article-wrapper"},[i("div",{class:"title",onClick:()=>s(t.value.path)},[i(hl),i("span",{class:"num"},t.value.items.length),u.value.article]),i("hr"),l.value.items.length?i("ul",{class:"vp-star-articles"},l.value.items.map(({info:d,path:f},p)=>i(pe,{appear:!0,delay:.08*(p+1)},()=>i("li",{class:"vp-star-article"},i(Ie,{to:f},()=>d[be.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(Za),i("span",{class:"num"},r.value),u.value.category]),i("hr"),i(pe,{delay:.04},()=>i(Pu))]: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(a.value.path)},[i(Qa),i("span",{class:"num"},o.value),u.value.tag]),i("hr"),i(pe,{delay:.04},()=>i(Ou))]:i("div",{class:"vp-tag-empty"},u.value.empty.replace("$text",u.value.tag))]):i(pe,()=>i(wv)))])}}),vl=F({name:"BlogWrapper",slots:Object,setup(e,{slots:t}){const{isMobile:n}=pr();return()=>[i(Ua),i(Ga,{noSidebar:!0,noToc:!0},{default:()=>t.default(),navScreenBottom:()=>i(Ya),...n.value?{sidebar:()=>i(Ru)}:{}})]}}),yr=()=>i("aside",{class:"vp-blog-info-wrapper"},[i(pe,()=>i(Ya)),i(pe,{delay:.04},()=>i(Ru))]);yr.displayName="InfoPanel";const xv=F({name:"BlogPage",setup(){const e=ie(),t=_e(),n=mr(),r=br();return()=>{const{key:l="",name:a=""}=t.value.blog||{},o=a?l==="category"?n.value.map[a].items:l==="tag"?r.value.map[a].items:[]:[];return i(vl,()=>i("div",{class:"vp-page vp-blog"},i("div",{class:"blog-page-wrapper"},[i("main",{id:"main-content",class:"vp-blog-main"},[i(pe,()=>l==="category"?i(Pu):l==="tag"?i(Ou):null),a?i(pe,{appear:!0,delay:.24},()=>i(eo,{key:e.value.path,items:o})):null]),i(pe,{delay:.16},()=>i(yr,{key:"blog"}))])))}}}),Av="//theme-hope-assets.vuejs.press/hero/default.jpg",Sv=F({name:"BlogHero",slots:Object,setup(e,{slots:t}){const n=_e(),r=ir(),l=ut(),a=y(()=>n.value.heroFullScreen??!1),o=y(()=>{const{heroText:c,heroImage:u,heroImageDark:d,heroAlt:f,heroImageStyle:p,tagline:h}=n.value;return{text:c??r.value.title??"Hello",image:u?xe(u):null,imageDark:d?xe(d):null,heroStyle:p,alt:f||c||"",tagline:h??"",isFullScreen:a.value}}),s=y(()=>{const{bgImage:c,bgImageDark:u,bgImageStyle:d}=n.value;return{image:oe(c)?xe(c):c===!1?null:Av,imageDark:oe(u)?xe(u):null,bgStyle:d,isFullScreen:a.value}});return()=>{var c,u;return n.value.hero===!1?null:i("div",{ref:l,class:["vp-blog-hero",{fullscreen:a.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(pe,{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(pe,{appear:!0,delay:.08},()=>o.value.text?i("h1",{class:"vp-blog-hero-title"},o.value.text):null),i(pe,{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:l.value.clientHeight,behavior:"smooth"})}},[i(oa),i(oa)]):null])}}}),Tv=["link","article","book","project","friend"],Cv=F({name:"ProjectPanel",components:{ArticleIcon:hl,BookIcon:xu,FriendIcon:Tu,LinkIcon:Au,ProjectIcon:Su},props:{items:{type:Array,required:!0}},setup(e){const t=ln(),n=fr(),r=(l="",a="icon")=>Tv.includes(l)?i(Ke(`${l}-icon`)):Sn(l)?i("img",{class:"vp-project-image",src:l,alt:a}):cr(l)?i("img",{class:"vp-project-image",src:xe(l),alt:a}):i(Me,{icon:l});return()=>i("div",{class:"vp-project-panel"},e.items.map(({icon:l,link:a,name:o,desc:s},c)=>i("div",{class:["vp-project-card",{[`project${c%9}`]:!t.value}],onClick:()=>n(a)},[r(l,o),i("div",{class:"vp-project-name"},o),i("div",{class:"vp-project-desc"},s)])))}}),Iv=F({name:"BlogHome",setup(){const e=_r(),t=_e(),n=y(()=>t.value.projects??[]);return()=>i("div",{class:"vp-page vp-blog"},[i(Sv),i("div",{class:"blog-page-wrapper"},[i("main",{id:"main-content",class:"vp-blog-main"},[n.value.length?i(pe,{appear:!0,delay:.16},()=>i(Cv,{items:n.value})):null,i(pe,{appear:!0,delay:.24},()=>i(eo,{items:e.value.items}))]),i(pe,{appear:!0,delay:.16},()=>i(yr,{key:"blog"}))]),i(pe,{appear:!0,delay:.28},()=>i(vr))])}}),Bu=()=>i(vl,()=>i(Iv));Bu.displayName="BlogHomeLayout";var Pv=[];const Ov=F({name:"ArticleType",setup(){const e=ie(),t=bt(),n=se(),r=_r(),l=Ka(),a=y(()=>{const o=n.value.blogLocales;return[{text:o.all,path:r.value.path},{text:o.star,path:l.value.path},...Pv.map(({key:s,path:c})=>({text:o[s],path:c.replace(/^\//,t.value)}))]});return()=>i("ul",{class:"vp-article-type-wrapper"},a.value.map(o=>i("li",{class:["vp-article-type",{active:o.path===e.value.path}]},i(Ie,{to:o.path},()=>o.text))))}}),Rv=F({name:"BlogPage",setup(){const e=pl(),t=_e(),n=ie(),r=_r(),l=Ka(),a=y(()=>{const{key:o="",type:s}=t.value.blog||{};return o==="star"?l.value.items:s==="type"&&o?e.value.items:r.value.items});return()=>i(vl,()=>i("div",{class:"vp-page vp-blog"},i("div",{class:"blog-page-wrapper"},[i("main",{id:"main-content",class:"vp-blog-main"},[i(pe,()=>i(Ov)),i(pe,{appear:!0,delay:.24},()=>i(eo,{key:n.value.path,items:a.value}))]),i(pe,{delay:.16},()=>i(yr,{key:"blog"}))])))}}),Bv=F({name:"TimelineItems",setup(){const e=gr(),t=se(),n=Ja(),r=y(()=>e.value.timeline||t.value.blogLocales.timelineTitle),l=y(()=>n.value.config.map(({year:a})=>({title:a.toString(),level:2,slug:a.toString(),children:[]})));return()=>i("div",{class:"timeline-wrapper"},i("ul",{class:"timeline-content"},[i(pe,()=>i("li",{class:"motto"},r.value)),i(mu,{items:l.value}),n.value.config.map(({year:a,items:o},s)=>i(pe,{appear:!0,delay:.08*(s+1),type:"group"},()=>[i("h3",{key:"title",id:a,class:"timeline-year-title"},i("span",a)),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(Ie,{class:"timeline-title",to:d},()=>u[be.title])])))])]))]))}}),Du=()=>i(vl,()=>i("div",{class:"vp-page vp-blog"},i("div",{class:"blog-page-wrapper"},[i("main",{id:"main-content",class:"vp-blog-main"},[i(pe,{appear:!0,delay:.24},()=>i(Bv))]),i(pe,{delay:.16},()=>i(yr,{key:"blog"}))])));Du.displayName="Timeline";$h(e=>{const t=e.t,n=e.I!==!1,r=e.i;return n?{title:t,content:r?()=>[i(Me,{icon:r}),t]:null,order:e.O,index:e.I}:null});const Dv=Je({enhance:({app:e,router:t})=>{const{scrollBehavior:n}=t.options;t.options.scrollBehavior=async(...r)=>(await Nc().wait(),n(...r)),r2(e),e.component("HopeIcon",Me),e.component("VPLink",Ie),e.component("BloggerInfo",Ya)},setup:()=>{l2(),c2(),_v()},layouts:{Layout:rv,NotFound:av,BlogCategory:xv,BlogHome:Bu,BlogType:Rv,Timeline:Du}});var Mv={provider:"Giscus",comment:!0,repo:"Zephery/MyWebsite",repoId:"MDEwOlJlcG9zaXRvcnkyMDM2MDIyMDQ=",category:"General",categoryId:"DIC_kwDODCK5HM4Ccp32"};const Fv=Mv;let Vv=Fv;const Mu=Symbol(""),Fu=()=>he(Mu),$v=Fu,Nv=e=>{e.provide(Mu,Vv)},Ai=["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 Hv=F({name:"GiscusComment",props:{identifier:{type:String,required:!0},darkmode:Boolean},setup(e){const t=$v(),n=!!(t.repo&&t.repoId&&t.category&&t.categoryId),{repo:r,repoId:l,category:a,categoryId:o}=t,s=Y(!1),c=y(()=>{const d=Pa().value;if(Ai.includes(d))return d;const f=d.split("-")[0];return Ai.includes(f)?f:"en"}),u=y(()=>({repo:r,repoId:l,category:a,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 w(()=>import("./giscus-NkhROb6B.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(rc)):null}}),zv=F({name:"CommentService",props:{darkmode:Boolean},setup(e){const t=Fu(),n=ie(),r=_e(),l=t.comment!==!1,a=y(()=>r.value.comment||l&&r.value.comment!==!1);return()=>i(Hv,{identifier:r.value.commentID||n.value.path,darkmode:e.darkmode,style:{display:a.value?"block":"none"}})}}),jv=Je({enhance:({app:e})=>{Nv(e),e.component("CommentService",zv)}});const Fr=[Fp,Ph,Vh,qh,Kh,Qh,r0,d0,h0,g0,T0,W0,Dv,jv],qv=[["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-50cb12f2","/donate/",{d:1706182936e3,e:`- 八、mysql + +
+微信支付
+ +`,r:{minutes:.04,words:12},y:"a",t:"微信支付"},["/donate/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平台
+- Gitlab-ci
+- jenkins-x.md
+- tekton
+3.1 DevOps平台.md
+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-091223ce","/interview/tiktok2023.html",{d:1706066758e3,e:`tt一面:
+
+1.全程项目
+2.lc3,最长无重复子串,滑动窗口解决tt二面:
`,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:`
+全程基础,一直追问
+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流拉取,评论,转发,点赞等操作JVM调优参数
+一、堆大小设置
+JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
+典型设置:
+`,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:`java -Xmx3550m -Xms3550m -Xmn2g -Xss128k +
被挖矿攻击
+服务器被黑,进程占用率高达99%,查看了一下,是/usr/sbin/bashd的原因,怎么删也删不掉,使用ps查看:
`,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:`
+
+stratum+tcp://get.bi-chi.com:3333 -u 47EAoaBc5TWDZKVaAYvQ7Y4ZfoJMFathAR882gabJ43wHEfxEp81vfJ3J3j6FQGJxJNQTAwvmJYS2Ei8dbkKcwfPFst8FhG一次jvm调优过程
+前端时间把公司的一个分布式定时调度的系统弄上了容器云,部署在kubernetes,在容器运行的动不动就出现问题,特别容易jvm溢出,导致程序不可用,终端无法进入,日志一直在刷错误,kubernetes也没有将该容器自动重启。业务方基本每天都在反馈task不稳定,后续就协助接手看了下,先主要讲下该程序的架构吧。
`,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:`
+该程序task主要分为三个模块:
+console进行一些cron的配置(表达式、任务名称、任务组等);
+schedule主要从数据库中读取配置然后装载到quartz再然后进行命令下发;
+client接收任务执行,然后向schedule返回运行的信息(成功、失败原因等)。
+整体架构跟github上开源的xxl-job类似,也可以参考一下。内存屏障
+四个内存屏障指令: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 使用场景
+限流可以应对:
++
`,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:`- 热点业务带来的突发请求;
+- 调用方 bug 导致的突发请求;
+- 恶意攻击请求。
+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月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。
+`,r:{minutes:11.22,words:3366},y:"a",t:"2017"},[":md"]],["v-1f7a720c","/life/2018.html",{d:1706066758e3,e:`
+17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?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-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-37ac02fe","/personalWebsite/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html",{d:1706182936e3,e:`1.历史与架构
+各位大佬瞄一眼我的个人网站呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。
`,r:{minutes:6.79,words:2038},y:"a",t:"1.历史与架构"},["/personalWebsite/1.历史与架构.html","/personalWebsite/1.历史与架构.md",":md"]],["v-523e9724","/personalWebsite/10.%E7%BD%91%E7%AB%99%E9%87%8D%E6%9E%84.html",{d:1706182936e3,e:`
+大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。10.网站重构
+因原本的
+`,r:{minutes:.03,words:9},y:"a",t:"10.网站重构"},["/personalWebsite/10.网站重构.html","/personalWebsite/10.网站重构.md",":md"]],["v-65b5c81c","/personalWebsite/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html",{d:1706182936e3,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的使用"},["/personalWebsite/2.Lucene的使用.html","/personalWebsite/2.Lucene的使用.md",":md"]],["v-731a76b6","/personalWebsite/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html",{d:1706182936e3,e:`3.定时任务
+先看一下Quartz的架构图:
+ +一.特点:
++
`,r:{minutes:3.55,words:1064},y:"a",t:"3.定时任务"},["/personalWebsite/3.定时任务.html","/personalWebsite/3.定时任务.md",":md"]],["v-bea2ce1e","/personalWebsite/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html",{d:1706182936e3,e:`- 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;
+- 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;
+- 分布式和集群能力。
+4.日志系统.md
+欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
`,r:{minutes:9.64,words:2891},y:"a",t:"4.日志系统.md"},["/personalWebsite/4.日志系统.html","/personalWebsite/4.日志系统.md",":md"]],["v-3efc517e","/personalWebsite/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html",{d:1706182936e3,e:`5.小集群部署.md
+欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com,个人网站代码地址:https://github.com/Zephery/newblog。
`,r:{minutes:9.5,words:2849},y:"a",t:"5.小集群部署.md"},["/personalWebsite/5.小集群部署.html","/personalWebsite/5.小集群部署.md",":md"]],["v-79ad699f","/personalWebsite/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html",{d:1706182936e3,e:`
+洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。6.数据库备份
+先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地:
+ +由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下:
`,r:{minutes:5.77,words:1732},y:"a",t:"6.数据库备份"},["/personalWebsite/6.数据库备份.html","/personalWebsite/6.数据库备份.md",":md"]],["v-8658e60a","/personalWebsite/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html",{d:1706182936e3,e:`7.那些牛逼的插件
+欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
`,r:{minutes:7.24,words:2173},y:"a",t:"7.那些牛逼的插件"},["/personalWebsite/7.那些牛逼的插件.html","/personalWebsite/7.那些牛逼的插件.md",":md"]],["v-7e9e4a32","/personalWebsite/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:1706182936e3,e:`
+建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Java的程序员,前端的东西一碰脑子就有“我又不是前端,浪费时间在这合适么?”这种想法,捣鼓来捣鼓去,做出的东西实在是没法看,我就觉得,如果自己的“产品”连自己都看不下去了,那还好意思给别人看?特别是留言板那块,初版的页面简直low的要死。所以,还是踏踏实实的“站在巨人的肩膀上”吧,改用别人的插件。但不要纯粹的使用别人的博客模板了,如hexo,wordpress这些,就算是自己拼凑过来的也比这些强。下面是本博客中所用到的插件,给大家介绍介绍,共同学习学习。
+本站主要用到的插件有:
+1.wowslider
+2.畅言
+3.Editor.md
+4.highchart、echart
+5.百度分享
+6.waterfall.js
+7.心知天气
+8.标签云8.基于贝叶斯的情感分析
+`,r:{minutes:.04,words:11},y:"a",t:"8.基于贝叶斯的情感分析"},["/personalWebsite/8.基于贝叶斯的情感分析.html","/personalWebsite/8.基于贝叶斯的情感分析.md",":md"]],["v-0b62f72e","/personalWebsite/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html",{d:1706182936e3,e:`9.网站性能优化
+`,r:{minutes:.02,words:7},y:"a",t:"9.网站性能优化"},["/personalWebsite/9.网站性能优化.html","/personalWebsite/9.网站性能优化.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语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能。
`,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:`
+缓存常用语:
+数据不一致性、缓存更新机制、缓存可用性、缓存服务降级、缓存预热、缓存穿透
+可查看Redis实战(一) 使用缓存合理性自我介绍
+普通人
+`,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:`小程序
+ +`,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支持的数据源有:
`,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:`
+(1)文件系统:LocalFS、HDFS、Hive、text、parquet、orc、json、csv
+(2)数据RDBMS:mysql、oracle、mssql
+(3)NOSQL数据库:HBase、ES、Redis
+(4)消息对象:Redis【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是相等的。
`,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:`
+DFS_QUERY_THEN_FETCH:比第1种方式多了一个初始化散发(initial scatter)步骤。mysql
+ +`,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语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能。
`,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:`
+缓存常用语:
+数据不一致性、缓存更新机制、缓存可用性、缓存服务降级、缓存预热、缓存穿透
+可查看Redis实战(一) 使用缓存合理性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-d7d7df80","/middleware/kafka/kafka.html",{d:1706204085e3,e:`kafka面试题
+1、请说明什么是Apache Kafka?
+
+Apache Kafka是由Apache开发的一种发布订阅消息系统,它是一个分布式的、分区的和可复制的提交日志服务。2、说说Kafka的使用场景?
+
+①异步处理
+②应用解耦
+③流量削峰
+④日志处理
+⑤消息通讯等。3、使用Kafka有什么优点和缺点?
`,r:{minutes:17.01,words:5103},y:"a",t:"kafka面试题"},[":md"]],["v-7d9b9318","/middleware/zookeeper/zookeeper.html",{d:1706204085e3,e:`
+优点:
+①支持跨数据中心的消息复制;
+②单机吞吐量:十万级,最大的优点,就是吞吐量高;
+③topic数量都吞吐量的影响:topic从几十个到几百个的时候,吞吐量会大幅度下降。所以在同等机器下,kafka尽量保证topic数量不要过多。如果要支撑大规模topic,需要增加更多的机器资源;
+④时效性:ms级;
+⑤可用性:非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用;
+⑥消息可靠性:经过参数优化配置,消息可以做到0丢失;
+⑦功能支持:功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用。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-25b47c13","/others/",{y:"p",t:"Others"},[]],["v-525c5e4d","/personalWebsite/",{y:"p",t:"Personal Website"},[]],["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-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=F({name:"Vuepress",setup(){const e=Op();return()=>i(e.value)}}),Wv=()=>qv.reduce((e,[t,n,r,l])=>(e.push({name:t,path:n,component:Si,meta:r},{path:n.endsWith("/")?n+"index.html":n.substring(0,n.length-5),redirect:n},...l.map(a=>({path:a===":md"?n.substring(0,n.length-5)+".md":a,redirect:n}))),e),[{name:"404",path:"/:catchAll(.*)",component:Si}]),Gv=t1,Uv=()=>{const e=V1({history:Gv(Ia("/")),routes:Wv(),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===kt)&&([t.meta._data]=await Promise.all([Et.resolvePageData(t.name),(r=Fs[t.name])==null?void 0:r.__asyncLoader()]))}),e},Kv=e=>{e.component("ClientOnly",cl),e.component("Content",Ws)},Jv=(e,t,n)=>{const r=ii(()=>t.currentRoute.value.path),l=ii(()=>Et.resolveRouteLocale(dn.value.locales,r.value)),a=Fa(r,()=>t.currentRoute.value.meta._data),o=y(()=>Et.resolveLayouts(n)),s=y(()=>Et.resolveSiteLocaleData(dn.value,l.value)),c=y(()=>Et.resolvePageFrontmatter(a.value)),u=y(()=>Et.resolvePageHeadTitle(a.value,s.value)),d=y(()=>Et.resolvePageHead(u.value,c.value,s.value)),f=y(()=>Et.resolvePageLang(a.value,s.value)),p=y(()=>Et.resolvePageLayout(a.value,o.value));return e.provide(Tp,o),e.provide(Vs,a),e.provide($s,c),e.provide(Pp,u),e.provide(Ns,d),e.provide(Hs,f),e.provide(zs,p),e.provide(Oa,l),e.provide(qs,s),Object.defineProperties(e.config.globalProperties,{$frontmatter:{get:()=>c.value},$head:{get:()=>d.value},$headTitle:{get:()=>u.value},$lang:{get:()=>f.value},$page:{get:()=>a.value},$routeLocale:{get:()=>l.value},$site:{get:()=>dn.value},$siteLocale:{get:()=>s.value},$withBase:{get:()=>xe}}),{layouts:o,pageData:a,pageFrontmatter:c,pageHead:d,pageHeadTitle:u,pageLang:f,pageLayout:p,routeLocale:l,siteData:dn,siteLocaleData:s}},Yv=()=>{const e=Ip(),t=Pa(),n=Y([]),r=()=>{e.value.forEach(a=>{const o=Zv(a);o&&n.value.push(o)})},l=()=>{document.documentElement.lang=t.value,n.value.forEach(a=>{a.parentNode===document.head&&document.head.removeChild(a)}),n.value.splice(0,n.value.length),e.value.forEach(a=>{const o=Qv(a);o!==null&&(document.head.appendChild(o),n.value.push(o))})};st(Bp,l),Ee(()=>{r(),l(),me(()=>e.value,l)})},Zv=([e,t,n=""])=>{const r=Object.entries(t).map(([s,c])=>oe(c)?`[${s}=${JSON.stringify(c)}]`:c===!0?`[${s}]`:"").join(""),l=`head > ${e}${r}`;return Array.from(document.querySelectorAll(l)).find(s=>s.innerText===n)||null},Qv=([e,t,n])=>{if(!oe(e))return null;const r=document.createElement(e);return Ca(t)&&Object.entries(t).forEach(([l,a])=>{oe(a)?r.setAttribute(l,a):a===!0&&r.setAttribute(l,"")}),oe(n)&&r.appendChild(document.createTextNode(n)),r},Xv=mp,e3=async()=>{var n;const e=Xv({name:"VuepressApp",setup(){var r;Yv();for(const l of Fr)(r=l.setup)==null||r.call(l);return()=>[i(nc),...Fr.flatMap(({rootComponents:l=[]})=>l.map(a=>i(a)))]}}),t=Uv();Kv(e),Jv(e,t,Fr);for(const r of Fr)await((n=r.enhance)==null?void 0:n.call(r,{app:e,router:t,siteData:dn}));return e.use(t),{app:e,router:t}};e3().then(({app:e,router:t})=>{t.isReady().then(()=>{e.mount("#app")})});export{J2 as _,lr as a,Ce as b,t3 as c,e3 as createVueApp,ws as d,n3 as e,Lf as o,Ke as r,Vr 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-KMWnqK_m.js b/assets/chatgpt.html-KMWnqK_m.js new file mode 100644 index 00000000..951e3cb5 --- /dev/null +++ b/assets/chatgpt.html-KMWnqK_m.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-slTLQ-pc.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 +Authorization: Bearer YOUR_API_KEY +Content-Type: application/json + +{ + "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) + // 从 header 中取appid,如果 from-appid 不存在,则不是资源复用场景,可以直接传空字符串,使用环境所属账号发起云调用 + 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内返回给用户。
订阅号的消息推送分几种:
`,19),g={href:"https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Explanation_of_interface_privileges.html",target:"_blank",rel:"noopener noreferrer"},b=t(`
- 被动消息回复:指用户给公众号发一条消息,系统接收到后,可以回复一条消息。
- 主动回复/客服消息:可以脱离被动消息的5秒超时权限,在48小时内可以主动回复。但需要公众号完成微信认证。
对于有微信认证的订阅号或者服务号,可以调用微信官方的/cgi-bin/message/custom/send接口来实现主动回复,但是对于个人的公众号,没有权限调用,只能尝试别的办法。想来想去,只能在3s内返回让用户重新复制发送的信息,同时后台里保存记录异步调用,用户重新发送的时候再从数据库里提取回复。
1.先往数据库存一条 回复记录,把用户的提问存下来,以便后续查询。设置回复的内容为空,设置状态为 回复中(thinking)。
// 因为AI响应比较慢,容易超时,先插入一条记录,维持状态,待后续更新记录。 + await Message.create({ + fromUser: FromUserName, + response: '', + request: Content, + aiType: AI_TYPE_TEXT, // 为其他AI回复拓展,比如AI作画 + }); +
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([ + // 3秒微信服务器就会超时,超过2.9秒要提示用户重试 + sleep(2900).then(() => AI_THINKING_MESSAGE), + getAIMessage({ Content, FromUserName }), + ]); +
这样子大概就能实现超时之前返回了。
# 五、会话保存
掉接口是一次性的,一次接口调用完之后怎么做到下一次通话的时候,还能继续保持会话,是不是应该类似客户端与服务端那种有个session这种,但是实际上在openai里是没有session这种东西的,令人震惊的是,chatgpt里是通过前几次会话拼接起来一起发送给chatgpt里的,需要通过回车符来拼接。
async function buildCtxPrompt({ FromUserName }) { + // 获取最近10条对话 + 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/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注册
\\n1.1 短信手机号申请
\\nopenai提供服务的区域,美国最好,这个解决办法是搞个翻墙,或者买一台美国的服务器更好。
\\n国外邮箱,hotmail或者google最好,qq邮箱可能会对这些平台进行邮件过滤。
\\n国外手机号,没有的话也可以去https://sms-activate.org,费用大概需要1美元,这个网站记得也用国外邮箱注册,需要先充值,使用支付宝支付。
","autoDesc":true}');export{t as data}; diff --git a/assets/devops-ping-tai.html-eRtFukrp.js b/assets/devops-ping-tai.html-eRtFukrp.js new file mode 100644 index 00000000..42fa070d --- /dev/null +++ b/assets/devops-ping-tai.html-eRtFukrp.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-slTLQ-pc.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":"3.1 DevOps平台.md
\\nDevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
\\n公司技术部目前几百人左右吧,但是整个技术栈还是比较落后的,尤其是DevOps、容器这一块,需要将全线打通,当时进来也主要是负责DevOps这一块的工作,应该说也是没怎么做好,其中也走了不少弯路,下面主要是自己踩过的坑吧。
","autoDesc":true}');export{e as data}; diff --git a/assets/elastic-spark.html-_qX2JCGa.js b/assets/elastic-spark.html-_qX2JCGa.js new file mode 100644 index 00000000..1b6eff5a --- /dev/null +++ b/assets/elastic-spark.html-_qX2JCGa.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-slTLQ-pc.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)消息对象:Rediselasticsearch相对hdfs来说,容易搭建、并且有可视化kibana支持,非常方便spark的初学入门,本文主要讲解用elasticsearch-spark的入门。
# 一、原生RDD支持
# 1.1 基础配置
相关库引入:
`,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(`<dependency> + <groupId>org.elasticsearch</groupId> + <artifactId>elasticsearch-spark-30_2.13</artifactId> + <version>8.1.3</version> + </dependency> +
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/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支持的数据源有:
","autoDesc":true}');export{e as data}; 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":"
\\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【elasticsearch】源码debug
\\n一、下载源代码
\\n直接用idea下载代码https://github.com/elastic/elasticsearch.git
","autoDesc":true}');export{e as data}; diff --git "a/assets/elasticsearch\346\272\220\347\240\201debug.html-ux_5qZGG.js" "b/assets/elasticsearch\346\272\220\347\240\201debug.html-ux_5qZGG.js" new file mode 100644 index 00000000..71f0ab70 --- /dev/null +++ "b/assets/elasticsearch\346\272\220\347\240\201debug.html-ux_5qZGG.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-slTLQ-pc.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('
\\n切换到特定版本的分支:比如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
',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/giscus-NkhROb6B.js b/assets/giscus-NkhROb6B.js new file mode 100644 index 00000000..28de2fa3 --- /dev/null +++ b/assets/giscus-NkhROb6B.js @@ -0,0 +1,66 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const H=globalThis,q=H.ShadowRoot&&(H.ShadyCSS===void 0||H.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,K=Symbol(),J=new WeakMap;let ot=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==K)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(q&&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,K),$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,K)},_t=(i,t)=>{if(q)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=q?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:"",z=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}},Y=(i,t)=>!gt(i,t),Z={attribute:!0,type:String,converter:L,reflect:!1,hasChanged:Y};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._$Eg=new Promise(e=>this.enableUpdating=e),this._$AL=new Map,this._$ES(),this.requestUpdate(),(t=this.constructor.l)==null||t.forEach(e=>e(this))}addController(t){var e;(this._$E_??(this._$E_=new Set)).add(t),this.renderRoot!==void 0&&this.isConnected&&((e=t.hostConnected)==null||e.call(t))}removeController(t){var e;(e=this._$E_)==null||e.delete(t)}_$ES(){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._$E_)==null||t.forEach(e=>{var s;return(s=e.hostConnected)==null?void 0:s.call(e)})}enableUpdating(t){}disconnectedCallback(){var t;(t=this._$E_)==null||t.forEach(e=>{var s;return(s=e.hostDisconnected)==null?void 0:s.call(e)})}attributeChangedCallback(t,e,s){this._$AK(t,s)}_$EO(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??Y)(this[t],e))return;this.C(t,e,s)}this.isUpdatePending===!1&&(this._$Eg=this._$EP())}C(t,e,s){this._$AL.has(t)||this._$AL.set(t,e),s.reflect===!0&&this._$Em!==t&&(this._$ET??(this._$ET=new Set)).add(t)}async _$EP(){this.isUpdatePending=!0;try{await this._$Eg}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.C(o,this[o],n)}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),(s=this._$E_)==null||s.forEach(r=>{var o;return(o=r.hostUpdate)==null?void 0:o.call(r)}),this.update(e)):this._$Ej()}catch(r){throw t=!1,this._$Ej(),r}t&&this._$AE(e)}willUpdate(t){}_$AE(t){var e;(e=this._$E_)==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)}_$Ej(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$Eg}shouldUpdate(t){return!0}update(t){this._$ET&&(this._$ET=this._$ET.forEach(e=>this._$EO(e,this[e]))),this._$Ej()}updated(t){}firstUpdated(t){}}E.elementStyles=[],E.shadowRootOptions={mode:"open"},E[U("elementProperties")]=new Map,E[U("finalized")]=new Map,z==null||z({ReactiveElement:E}),(A.reactiveElementVersions??(A.reactiveElementVersions=[])).push("2.0.3");/** + * @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",B=`[ +\f\r]`,w=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,tt=/-->/g,et=/>/g,y=RegExp(`>|${B}(?:([^\\s"'>=/]+)(${B}*=${B}*(?:[^ +\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?"":"")),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;f
打开浏览器http://localhost:9200即可看到es相关信息了2||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 O=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;O._$litElement$=!0,O.finalized=!0,(nt=globalThis.litElementHydrateSupport)==null||nt.call(globalThis,{LitElement:O});const W=globalThis.litElementPolyfillSupport;W==null||W({LitElement:O});(globalThis.litElementVersions??(globalThis.litElementVersions=[])).push("4.0.3");/** + * @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:Y},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.C(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},Gt=i=>(...t)=>({_$litDirective$:i,values:t});let Dt=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 T=(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),T(r,t);return!0},G=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),jt(t)}};function zt(i){this._$AN!==void 0?(G(this),this._$AM=i,pt(this)):this._$AM=i}function Bt(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=Bt),i._$AQ??(i._$AQ=zt))};class Wt extends Dt{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&&(T(this,t),G(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 Vt=()=>new qt;class qt{}const V=new WeakMap,Kt=Gt(class extends Wt{render(i){return l}update(i,[t]){var s;const e=t!==this.G;return e&&this.G!==void 0&&this.ot(void 0),(e||this.rt!==this.lt)&&(this.G=t,this.ct=(s=i.options)==null?void 0:s.host,this.ot(this.lt=i.element)),l}ot(i){if(typeof this.G=="function"){const t=this.ct??globalThis;let e=V.get(t);e===void 0&&(e=new WeakMap,V.set(t,e)),e.get(this.G)!==void 0&&this.G.call(this.ct,void 0),e.set(this.G,i),i!==void 0&&this.G.call(this.ct,i)}else this.G.value=i}get rt(){var i,t;return typeof this.G=="function"?(i=V.get(this.ct??globalThis))==null?void 0:i.get(this.G):(t=this.G)==null?void 0:t.value}disconnected(){this.rt===this.lt&&this.ot(void 0)}reconnected(){this.ot(this.lt)}});var Yt=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&&Yt(t,e,r),r};function Ft(i){return customElements.get(i)?t=>t:Mt(i)}let p=class extends O{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=Vt(),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-mSez-CGs.js b/assets/gitlab-ci.html-mSez-CGs.js new file mode 100644 index 00000000..a1e553bc --- /dev/null +++ b/assets/gitlab-ci.html-mSez-CGs.js @@ -0,0 +1 @@ +import{_ as t,o as a,c,a as e,d as i}from"./app-slTLQ-pc.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 zcmV+p4Ds`cP)+9>&D=XlHh1f?&_4V~(q3G{ZP#lKk++ktm<>hUn#^3k(Du?9nR#qj5 z;z)+89bedZg#(=D*kJ6J)^W=H}bm+vn!y9BrLDc%(^!s^Q_`WRTEblCooywQQTZ zjJeJrZk{=Lr0!y1;o{=s =f~w==;{ars 4%2_WSH(+S2=m4D{-GYd8A8)t97u)^Yim2aGw@vngfR6>1AR=fT$B}qWAjx zEN;azaKz(WRa1zq +f)HK8&p6k&T0S!|PX6) GW=yGrik%JFtn*aa**h4qu UMMhtDfsjOaK4>`T6 Hv=FJ$J{Eje-DEyv51UWRTfOuB6yeQRaJrYKykoHy4&yM1GypJ9Wi8kL8Y%iu(Wm zSeoYVgM{qE!=ZtBJdWi6lIvBBu=&r=0CB7T|Nqo3Fz`}O_xJbyS5)0FFx@yf0Bofo zk@WHL@gbA=8*R?wFfagT#sG`$0&Ag$XQJ9I0sv;65pAILODvyqtoBk*0d}$|miy5v zEA3HE**7-c-rfdd!X0g%CUMUrX~PD4xe;=x8gZleSytIAEci=D*&zlEYRn;t>NBmN z**!pKjLVd9uEb+q+B%850001#bW%=J00aI6{`yC|{D}GXlwBtY`u?ni`oUBW`egn6 z_|uz|c4J#N9qziXjZU@bux%CAm61|`a!Ns|ntMnXw5FbybxGgMhIw%+9{ua3bjMmR zANJacfMrT4`{bdEfNDTFI1v8#@7T%1wv2ODMfv#j+RKY)R{Z(p+s415p8oy&!MwG! zj{W!T#=)zXc5!R?*vPQ0D3lPG000QxNkl E6R(Uw-G@vvY?kDk>@}Dk}b;Amm>K#5LaYK|*+9#3=y ucaGB1XMk zSwe_D7>wj{xo5v;_)GXCOV&hDjL32%qF-CzdeF<)RgF<+L>41OYwN4J%?GWBFSUe9 zxUis$pW&;Ft!=Vcnh 0eE74vhEN~p|5 zo&ti0M5Ghy;y$j5sI1(j3Bl?vPgAj2#?l(<;x5h-ViXu63%dP;t1!%55cWYvqi;99 zS-4W-yDn%g#mUW#!#D7H3%nliIrzAv5m3$5bEQT`ChqT<7#X1&Mn}We#v4ixwqS5S zCYL{#NG4YblF5?OJ26GtJ6gj!BNTDxbeXdS)JaobYTI*{aYp#I>E!aEc4B!62pQ{P zp3yja>QL6Z3TxOKOPNyXM&=ohL9%*Gri52woe`iTyOlDTm=86;W`DEYZf|b3n{5Vo zFS743o6Xh0V6fS2)g2Rw3)^p5FFhDJH= Cxqnmn>@ielJs4Z48O4F!dTSa; x;Tq_lzu;8wl80+m 4=g3HV^1|#o@oO`rsD7kv?|(*zquUhXe;lR@#$~ zzn%Do;9q{<;{5Ow{OQ2gy8Umg9=`4AiM}(k@_q9Bx|40^FAB!S#?GHP^WrhjKD17r zJUMm|9UR=;@HQ8*o}ayazHIRT_8k)3yWc*t_T u|(QRBm_uy2vz$=V8P9C>){>B0Vyyselg-`nD%`(xjH{rD2R zM1rT2YwaV?4(x(2AHBSH5e@w4 n!GrCdRk{F}fP$foK97vxELtRGAr6rT~+@B#ZZ^pJul!q&k zis{HtoO%=+$H&KJsgVq+<#Mr6Nr3PR#DKC>O^!q&7@9=ls)(Ho0`X0w8nB#+9m SyeCN52hJyZA|pjgV!m8DX?j3W&ZJg|Oo+=M0T?xhJFe3u*P zseCC1aVm4aR4C=A!b6K AKn9Oui=Gp8Ijyh| zpgMHLXa(m?riDMtwo8m}P)Z{Za!ah?fUK3LEhgjVGr&P_ba08epn};aaZ3}^hN#BR zHqJe6iBL^t+lek;zZ=zM$o?9|%4X4WT%j^FsCIqvI=&Y4OmKk92U}v=Ooc7MQ88^` zrvAE)szV)a2?t8dnNE8aBBH-aOm x=R_~A?k)(yNqF{WSC=wXg z>nw^wTu}^1bj(rF$8k>!YBVY=2-y-dV$DI QADwaP9$AnRxU }*nJ5j=UWzDRgB^>SRQ-4~hYi-flm#!|DhT~_CvZyFCF3|k^x>FLVstjU(F zzDP4AY?7V%y+8feGAU(BgDZsXtBWYwcic@}s|$~AuDZl1)hiVm0f6Z$9>UZ{w^o;w zj*iCbPGlIX3lYn2Gr-@u*JvUV%o)_Q*Jyj3I)|%p5U;DbMGE wIk%OHu>#fJ54Z%MuFQxY|}l6IJSd(?{5xd|2(Vg )QwjyM{>g(%Eg|Ts?$L5TT z^7i%=WWeq1?cw3!X`H+7@9*d6=#RkI*-lO%Zk 0`VqfFn;9r-t z0c4orb#~?A;sAf#-i3lSiR12CSVMlN3}%_);^H}jr}0}@+8h8hZ^PF^LP2!I;o;yu zcE#>mSLc0x?2(Zxa-cYM#`E;_>}z1`et!4%_U&h7=we~xYi{alVpWUN{QUhTZ=OVb z$TxJLnpi{tsGI _mIWQiiLJkA rqbp{r>A@WYve7#$RnIq?lia$kj gwtM zitYhxqyTZO0B4@vGc)y3Ox-#<yC_W*6E7;vQ4C>$D# z>`rjH0Ccd*MNkZJre=Q15Nw|mY|iIZQXz1l_*YcoL_-i}#QRfFDQ?KoHb4V;wpE1L z`AJ4Blld&Orsg|41dV>iMq~g&x&TwYY=(L#f45yT0kQx90GD)9PE!B{{RsRE`${Y9 z{yOtL`(XTaBl_~_;>p>k8RkQ!ZT)C3CK3_*G1*l>IuWV%u M 8jC8=U# 86LGtu0n7;&j<; zuAYLS>GzM(@2#zKz@qA2Z8Q>zMztN S$-HB+wa^$${2f3 1+gZAaH$;Z{ wFIP-SD~>csW#_06=`eFWrCc&*h~n&m`k<3Zcl_z%(e(cYQT ziqdQq6%~zy!YK8VM{+%SbmW`l05)@Vqv65glRy&{6kc7*wZ6W-kb>>(oy&qGZXPTI zdZ?gy`LK+uDY-jFOcFjA7R<#!4HcXySz6eGuq4QvOu=ycB2c7%^1wfvyp`k-!n}zO z$NPaIO$Yy3VN;>xSbw(= -GA~$1UY833V-Xb#=FI-#$~< za%l=XykI^_Pf66!<_&mL0&X{M$Or_|t>l5ve>uV?in=?2wte&a_H2Is$xjDWorFNu z+ vf|t _ujx<%Dg1eeD>;Yl|{FW#bPlwJP%SfkEm4X zKn4u+>e;{m21psWcekp+pq820!#p3OY0%n9U4t{X5ohvRoz7STvI>Xeym+of(S4$( z3)!x0bK)c_+@Yv=&@9Bnv)>|m3eta|wPc&t6tO+xxFa!(ONJvR#A3Wj9D6CDf})b8 z<$OkBD4Z6 URgw}uDnD}WZnb-z=4&F so|EzKEUE%CH{& zi&HM300E~q!g)APq_eNRT8^6Rj)G!HM#UVf_C7VRjDQV?TyFJg4={~L4{m+-f*Q+p z)F!FQIFy#yY-_`#EJ l1>` H_7kM9DIm|0Za4%3lg!OE)Tf( z!0X355P0vg% M WtEP{fFW2pE5SqxYtPzt5Qf~`jJ0klh(ZYptU)ZxB?C5zyT^*b?`(n?7)9e=1K zpUeFM-~Dq=;_tZ|l!d)BBafHqVxl#YiFHCBPX9wUFPMQv-EfVK*+t1MJa)HJ0-B~M zno<=UK-LY%*fjJRDp`A$-#DlSQ$XA R60q(NAQ 9(Tgc^CmbI#o$a2sCH?ID;4v;NZDqFT|2uT+qCg zbv-9+h7{S!Ksw|k+ddaZPR}bnIMTER?NkI_xU3~`;v|48okbM31;GM1vF=@}YCW7p zg3YVhRA@BU?)q~QiPOn~i4h{%Y>Xx!(b&E{u`xp9Xf^wVLIxjve~|eTt0fr0<&l1o zZw9T215p5eK>{XW5%x5MBoOIAkO&PT5t n(5XkWwU9x1@;!Nc*h|74~*7wJztnJ6jtq zh=s^&7-&Xh4A5CENRcBe&d(NT(Rm<=1qQ{?18_r!4K7nFKi`WBl3(^x?$ZK!R|HUD zo`-jOR1AQTq$n@QY1MhixX2|;+HXb#r1V6}$)qGlMJ+o3Q+hIZwtEh-0Ah#W$z(w? zMLjZ+n9=~Qkpnt_3ZKkneTYrId5y^LX>)~&Fn&%jKPQ3LjL7Cl=ay~vLQ2(~i5Lp; zMRsY_1?z;-y=}WDRfWh4#rIG#7BCT9Ba#F}HC@~8jHoI^(kjeKB|*Ol5hKDuTV&QO zg$N9=!amRx@&L(_A`LixDMSLwzanVQ9~pBGc6A~#QK!K1f>MnP=qVT(qT)h&+%zFF zC62+L@En7O_$ozB#cYsQ*oKxp06qvKAriideEV4xS@ztn712=^N-$>gvW(D312bb` z1j#7d={FZ?!>TYP-iqv%;v-+>-3Sj`3Cad72=Pt^&KN9Ol@^l}=ub~S=IXLWBs0N1 zmDZnK&17NZIT>}w-&rYsZ}}`mw-=F@MS6K+Z$UczeN&R&M$LO5jfe>qhLbUo4Zdpj z7aX;vA$>2>Ax^InftWaLPr;MNiivu(Zu)0J^8X^@A&d~+B_O{OX+Nv^>#v(M;3B(P zk;O%1N)#qS)#6+T2t8YH6GVhDFIMEis2E(AmgwwX?VQhxqc9Z5y9`224~3pWaRld7 z5QUb(TZ^zL>uyoX2=%sQ?)?K6|Ccm(JuD)4o4;*eUeuO7E*^&EedwVHn(&hM;~PPx zUN!$O*Mc4?11N~Pir|ib{{_&%Us& MmQGzhe$<)L zAjZ~|-BP7lNWVHLYn^^^-Kz+lY)roqreDCWnGEpgWbFKwLAscKm!_@!b(u2BhxFSp zZs}>5RO$CBLbSwnR?Z}K#5h!p?=R&cVa*;5Yh=yXPt_8Q9m8A>f zu)@;I%1aq~s@BcXwj?YszH0NaAXdzLhKt(1AVxPmP4<=f$JrEEua!XRXBT%Os+E>V zlth6T(WK#c`sgLfRT+XTd0XKSm0++Vc#*)iXG(sTC=K>iCPzbzeXS+S$Lmzdcj2e4 z5MBW8pg=YE8+73|sy_xp?w?@XWFQ)wv^;kp8Z|F(nTbc;h~KVr93k+aoozrg8V{l| z5yJenfHS++rh%G }Ovt532 zb;qtKU_>Ve8Gp)m!&8VNw!T2;X+2K!{<+@U|Ihd|Z-@{CK@bE%5ClOG1VIo4K@bG- aFZ=--2|INIa z_u+kbzYk~bse5AX+?jiBjGBrp_Diyt00016UQS8_06+x;04S+o;IqWWndRTJAW}_9 zOZu5z+rK=!xW2u=-`LnVxVc@@)ZF~=Va>+o= aDjr$=^XCtlOCD3~#`ez6jF6C!f60-y=GNBM>Dk#c#k9{; z&)(SH+OkQh%jsU&4+vOaUl&f^mJY9sZkWjEUP2}$e3{trsT{;{&PTP*%IezK+S+~w zvwHz=*cYRWR`-(LLl5`oC@%TkhH+z>F;xtKWpwTZ`X8#9W7au+izQ>K@9*zPJ&Pi$ zMoNcPq(aLTKQ;z`9egfo_d}d aQGLSyw29eJ%ClFcf|l#VA%`nEH3wc z-K=(yb(U3jt43no a=pYMKXz%#qAtGTGA zcIfZBUs_z`Y+{?c@>f%K+|n@5N=NQn5nIeA(#DMQ ?R zk8v-WHMByp`3Z^(N>+MH?)vkeo;F433P#M 5=)CVabI~vGAX;)5YRl ztXvS?C$n5rq3zplU)xk}x<`b5=GVPnk$Q7=J|o{wjyoPUX9XUt$)_5V#^XuOgxBmu zuA=q|_us5kWjh>qYBd%PbeARHrM33ew=YasN|06ZobPYfme~Iq2tDg)%u+$l`ddG) z%nlW6?QPBtg-+L6sq8Ngq+Lvox8;T2BmW)j+?6k^FEJ4@aRC6(BzY;gmhaNR%98`W z8^z%1crNd#IbIq(`eBCtmU}lN_O`@?3;~IU!^N@9ACh($++(A!dujPRzXi$L#i_HI zGd<9IG)s{>jQ*&pzj*RQDvK$;TNQNu*D)`dxwUY=H;fd^PxKjiZqNT4p-k{|WQ~gU z#hc7XaV>^wO8;@u9RCHMOGDj^+%WkMsvjy7RT>UA9~KuYhKKv*`?W&&fgX5{CfWq} znu{*tSq6rNh9+Mh_0}>az@=Pbh40@OU~kM}GXR|}tj?%_9=jCO+CmFrZ*56WaC9`l z-Mn>prD=H1vpxkdaH*TzDo!EN(Fh&ft#v>Bo5nEj>oK4VjmJ$_(w9b$s*2w;bog_O zp_(KKc8%~-Xmv+z1Yvq&pMJtME)`zANj+ZQqF28ROWKlJo(^wC2NjwWr8jQkqDZ&t zN!u(RpS8!`S9@?r)s?vRyLa#Qr>zw*HxNUiv~c%Ml9<%Ew>vg;REcCgag#eG63R>U z_Z}Xa7#pW%X!JMX5Z$G;)$Sd4cJ_0N`|EU#9=6pWdU+*(x;>dTROgEA`?sgT=_v3= z%i_#An+jfjUAN#&YgocAHB0G*Pr=Ywq(u`|7{yw2H;z^eNji34^hVtzj+PleP=S8Y zssLD(`j4le*O`Zx$~6rKR|N-wh4#U#OB $aEFBz6 z`h3#k&~pKjBq-wNfN&T7M~ZGFd&2|@fAk(L#^=}7WjH_bfLP$9&&i&eR;%##13bPo zxumwLR|7x}@^~&NEVgk5g_z137D{MW0p#Es3I#AvX`mZM#iO8T7|NoPKz36${e`+H z!bF%?zXB1aFEs*PC@rnnsO6K|I7BH;sl$Yr$?QsiIKpwf(Rp2YLPG{_NOBB`p?AEi zC>j0x$zU$S=M|E|1{PsBw}`@_R5(gD@f(Fho9@uGZowa&N6fH5Y9QPF3#FyadsjhW z${N e7hvELNKwxDQjEYFy%gH=4Q^GX zW|zaxG^jwSuKFts=NJ40H<6*}wB!Jp`=ew?&fRgr$?PNqzg3mYXLIIvqxgPXZinww zdBEG16;V;|UvI9G+pl)A{x&aPtn55mZv+(8FRvZmwm8hMiOw4aEUx+7o4b^SPLGH+ zf3r@yiORVx&sf~czN}Mw`0Ky)q-zrOh4QXJNX ua|T zM)CY{r0#J?@V|fiFVGIXFBi&`exKry{X%wr?fBd2L0%il7f_$RNZb}7b8doGMY-Q? zxnTm1Eby#u4NH7z$66Zv%#UdBE*PUY5^L!$aFWWUsrv%t5I?zP=}>P9GTz~K8WgtW zW-=5SDNw#$t@k<|5}vTQ;1x62;1BS*TjIqVL=nm0ldx}rxOzfuWe0N{SsY)aUBs&q zex=2s`CMcn&8h^irrq=;pl+xrAcVWEt3}09GDfsCy~wXuqh2tMeiSw4c*mJlKUTH+ z`5}lyG24?hBDmQwrImt}No$}c42}af5*$L2xs1viSE{`b)J235$xFy$qc1EFDttF* zb+5}zhA_D7Vuly6yju@M<>?q}nG^Ch5bn<(GB5b{wwNilMa_}{odo{XEt(F~NIx(v zS3yOW(p}bcHF3Y!Woa7XCey7ZB%l^4@(zaqTQ<#=utQSk^^KZ_j}`{|gz;Au4ONwT z&2=r0w50`$-OCgVuOtKuQS?Frjz9O0e4utksr;li3kDK@;cWP`bVJq}9XNdZ)Q?^s zZ|Df$Qr#Orhn_rfSoTEh@8OG>t4S7=pH5ME4s3<*UD x#CTqrP#?^B(Z_ve^TwH9i8gNPN!zO_%`ub;)?W7}# zaTfwl>lfnw*VT*1^_MqsYzU92kSbq!uC>0u6G}Q#>~oIJ^NgD@H8} Ay_)6sNHJELFN+)ZzY@so;b*ky3&|D+rFDznO>FA1 zFqaN8*}=`d6sBmy^-C_|)O=h}`D*kHXx*ztxcM*RnrYc@YBwpdt2aW-3Gw*)ld%Us zI@=%ktvwo`6yb_V2L-mr+aNyq^c^0%2lTAA%4tm1HzQ$`VoTZn`&5hSWFR{HbpUIi z>vct(rECf>SW=ndI`T;jY;gb6+QZyn}v_z 8|(AGOpv;Q|q~`VIhc}9)83Y#?oH-;@@#w#JR#p9j4544Rtf>hqtuZ46XNw#_}G; z(HdU?iV(}=1k>UT4WOdj$Nnw72{yg0{f@BJjqc%?vIQy9U*g#mZPUMnC+4eLYJ~MP zd@OwEUSUxYTM7EpxE$9mpw#xWzuty?UNNG_ir6tsP%x^Mn3$y`WXSvA#m (x5Z|L5#-Rm09!JRxY+LX z>MYb++I7g)AgUd5eUMRry9qQFu8O~HTm9v`i>YbBJg-O~atw+gvrm@ZGqln5E0hS8 zI#DfaD@RK~wP!)L5#A>IQJRaa-oU4nBU?;UmtTx*C_D-|(&r;Z2$Ye03c!nE6FEMW z;|1(&Tsi7!N!AZjM?S`CqZNKyahk){WD2t7M6Zk^T;Ts)j=9Yzsp_pG^iCpea%#yS zN)et?GRoFj6LbzgM+=bmf(HS5sq{Cl43)kcm_UkfIRvDCF_?2$YL6s+{Ds7l)TR7j zSxjIM>j;|Snb!Q{D5hDLlosT`CANdT!o;BKTg)0O6FN1U%-D3!LZ0`JH{y;pW0=H# z13+GQp?Ngg9ntP;s7K$Zv~y1EZo1By;A)>m qNt)a61>5lLfpZfbPWj@h z?A>K;#?00~Vd^pxDCO9hl7=?71bI{K2O5)G;rM$M5t<_(Zu+*$TpV|gJA BkLcJdQcX=9tO<>X}9`58x)QQ*||vQmFO#QXm3 2cJ zA+Fc2D$NC)q9`tJM=FLFja%S@R}0kjSH?NR9s}RVUEH?sL@ffj 2U&4C|$)uhbuk#*fk$z z7-;(n)TO=yi^Bqb32?QkJ$+oW{rIE18o)!?yss+yk6^wQ4e7Gh@$EhamH3TW*7uo? z$hjtitChQRG2V$3DGG0+zA29U1GtZ<-OCKy__;_5lQY6nGV`V)zZV?n!ya4`Sd9TV zK^LHX)lTTZG$soDM1ae;EU+YBOlnpOQ(vTjT)Ajm4A7y9$zGLzRAX3=ncPZel#`rL zci-#2M-kGA`qm_iJFp}_t7Kx0-%C#5>}p1mX6`ZBnXG;btr-|nA4@FA#%jYw-r3+< z9$BlG6xsHDA&k0l^SgO-{O(%m+N;C@g5Io!PEYkA*u3J7#bUE?b}G1A*Ryf0+SI<8 z?*qGsw-8BTC|}lJ87`Y+5?PLJi&g<)D@F!8V6E2orB-X2Mkt=ZUk9dj{a%tS=(V(I zLo%NXQ586+B#OzBo5!JfJWfxbA-5m9Po`*EP*BiN=rW&bw&J3oW@vu#1F1n?BeiIU zeoH%sSj~kguokB>*?IWKP4V}t-6F#!A#X$liSgv!{a= ksFXQWp;jMYj!P?{vQmP-^IEEt<=HC$(U z7K71@R&@*f6RVbfC?J?ziS~ibeU_Xj%=EzcQ<%FYkWt;e1m}nfJoZOo B&b5YWyxREyZNBR;5olk^kjFSoCg_Vcts=994!xLLm6`uCkqG-p# zQoBOI8<9F%vBBX1M`!&BY-7Lf8w`7Y&aDKTZyH_pYp@poaZ!Pzg$wiTSss=d=uQ@e zBrbi#!;A(VEx |(BM$)ItbyG6!K!nzDj6j&=(I;nh7s()rGSs!k&V-kmy>^5 z^fM0GbM&^McSBjeLepw6VUqoU8pq>LhUCFy0*biogbih%1n?;WG6cM3qhRao4@=TC zIs~#3HR_{Fe}7n} r1dUNqvC~J|4lUF!yl94j-_L+V@;eigkXknzQ>>yCS!A^ zb(9>ddG8#q|LbWi06WqSod|_~a*>3q4cPR>fHnq6X0FtNM3pO;u6R#kd?mIVFC3G~ zVcxuYy-6rR<3`2HUN=Cl{OmL8b9rQ3Z$|R6w|Yx$5SvC4-HUmZ%t*=w?s>dCi)Rt; zD8)>AKtp2}g_YZ;>uEn}u>CeEPC?`~DFe=RK-EUS*pT?^RAhkgss_U!lz*5Rms6-2 zSKmu3(r-pB 0;+_IHNS>ufuh$mn-)vz;5Vo<$q9mit#B>)}jR=dkkmNJ<)GN z@!Cw?YO2$n(U%;NnUJ<7C#_GOl(ruYVlcxw%_{gXCUNR|e&RnW)qZ8ua!}!AMjHfo zV0(0Y=~Hl~Q%KdbLGk4u&d^pGChJ`M&)D&Qu-0=oKlYP=O6%WmU+=5metnHx4}5u| zA^G LJt-K)|JGx%#vv)V+9?Nx@slK#`V<9>& zl|R!1Pcvhus~02L`J}Vco_VdGGtV%>$C_#_OUVgSlhD;3mgydLd`SC2+BZv!`N>0o z!u=xU&MAqr*=^^__2;o2=UqZGT+m9dqFWC^ET4;+?(|#dvG}nkXsW4m95cmya@CZ` zuOy{2WTdCj&vaM1l}Rg0578NI>MXzjDe%7fW~bla*Cm5~@go)@ke99K@EZ 2_P@=**9sH>lT$TcHoi484vAd@E%w_`% z6`+$+0-etBF^`C#7%S#LJ~N_zHO@>8CJLL!w?PcWxbk@6OSlC~Jtj(Dqtn9FgKs-_ zaHcEleimQThhbyf2*ahiqP%6_Q5wURRtW3@%5sxq!{D**FV##{xiBu3K;KbfeYP=3 z5Hyn{Z-9Uyfzvl#s`$d{!v>pHkR(Ro)2(uavkzc3vbtBwvrF85yTd>XR5z(u;!Lbf zehsw{%X^E4%p^=NYZIQX`sAvQ20>aW=uUubMrIBMSm<7?G=HqZtBx}#+1K5_dK=TW z&67d81}So0CIu^D%K@2st>q`77)Oxs)0CRsa4 yGJb!b zipm(!; G1$K zJq0?!wge%rYzt$CAP5~3YLBLuxW&7`h>1a!CA~9G7LoI5jbXgRT^Ivaw>$MtKsqZb zTgAV;Knx02Q~@zMTd&zbMwWcAlVqdhaT|&3C?XULKE55})A_RD+Qbr&j&X@9%#Qie zPEZ+0>;_*$c^B zQ<}tH&qr(s&AElodjQJyuBb%7+#BY5r%T6axQvL&k3w3KQKK|tye#GW;kl{R> b6jlwyARzOmS}L4=YvGNzYW!2d`p`{G!7 zFT*N`meBLopZI#jrBxRv8i3`_f3-W)#hZJp;(W)(n=Rtu`}_ygE3LPAa{M-+@nQ${ zTn4gim5=-9!gJ*^8Y+lUIQ>#2X!xit9>*Ah|8KOW6V_e((6&R=ZS;FlqUVk(nI0RI zZGduL@YTFi7U5$F;^p|5Q=bF__ysYc{xYsUn#@F}*G!&uLyV<8R(ptb+V!eYB*y#O z!lJ38n9w;=7EoAVX-smE(LO@c6sDxf3Ob3;29W(Qc?$pC!YKPErK(dCfiuT_5~@Yc zL%`pwy07CkTY=U2`6gdOVJoN+n8Y<~SKhD*VTy!dSUj7Q u|ggDA{6G-Osa&c0*ukhy8fK4>Z9u}yRxl)6`KYGntauPn*47`3*uJY^Q zc#etdmwulv_M(0lEJXZml6x4ZCzHXxARR2p$vl$|_90{P$hJ5Xz= z5S+AEcZzuUJUosw!n(aPl(KxeG8v%{)7bX**c+uKTl)M=P^`R-*J1JR-=wh8p~@jK z0cFzleVHgs)aT~YC`YYGVA158m#Bv)P;7^Om6q2Kys4cY>d+*XS@TMHDQ{}K2vx-8 z8Ea_^hN@4p=qDODO4w5@P*GMHoxn?K{kRp{#>sw@fV+&gbIb>h&n I1)pv6OqpC@SJu8!!?B+MxeYbsv*zvs2cmHw-b z0#}S~8!!}>55@)+4H8J5K+KxZ5m^LVv05%WXUTe%iJ^aQd~^EmrB#|9%v4V*ZZW9G zWyeXt1_VO6aVzB9LcN6}MYX4GrQt9k(LZraJKw`xU(y^eVJXs=q;GAxfx4(%r3WDx z;e4OY!kjMzW!7-rUX%HGN275I_UX7dCA&t;U7->pMD7!s!Uc~>_nuZ>Ux6?gzy&ia z0|cCT_sjYSYM*L;Jws-03Xqe?@^S2LIu@79K F{28c#eq3H>F( z?w%zU5H6MO!-rW(eK z*62DPk|d$-@)JR?C=mbje YPJh5k6wXwW7Z)isiqvUy)hH z4qK!+s$w-HMnK!N^aMzR2_&=S@hoE>>b;}_MmOw-^u?#!D*x$UIdLZG>y9+6HzdlU zz1b;(COPVX8E4@CI&T1@U5%QJ=TU+nkUilxoOG1m^UK62cnVGrt|sq__bMrg%ju*> zj98|;ahkBL2rL_$!76!NK -QXR;zZ-xe(YOZ#^ zerQ?Mq_in4ON5p OV$;e!bVtmfLpjId7)@5C}6`M`C1(aA%`2Kq;~Bs_O4uRzyY zxT#-U6c|3t_0BpA36q+{EyxH$PF-|N5U;ckC!~G=_yfOAyo+SrnyvhImgazG6h1kY zN +NtD3P`Aar%yD(^~2h_OJX)pIEq*b z8Z+?rd{&P1+(bYvq53 SavLcH(;ibQGzv9eVo6Fo63pcM~>Fc#>CG#z^K%FrEYN z)xUnv;3NtJH3OPhB@$ #-d- zsW~*Xax^kR;%DYB^Yklf6KC?;pZz3jo=bA7DijSyBd1u+cTJGyWORGE=_SqcQ1L*e z4+gz3(KCOc+KHyDyqv2UO^KYm43W+iT#3%W7|Qo(TJ=@H(m5gO)Y(9gcG|J=uvQu5 zRYQTEnk-0dKimJwbm=zzX)%Vmc#286Q6Xr2+JgwB7Cd7=pW5+8F@76`gOX0DCOxtt zm*Cv2y?Qxh8A$mp{RM%NzOz&FzM308tt1?Jr0L;OA3yuUNum@uvrlSf{*nM%Fg33G zbEl;uYZSuz(+g8WMC_MTlZ5-U-m85^;Lnr7ADn)5s31mo5}EH`4Z#r25s$Y{*r<{X z?HX+l6Ap!Tf59Do^kp_aKbOnusT3?S1}x4mCA$sZeIkxKPaRS-FgY3)E0W *iuozH@214LT#REoOe9Nn15tF38|^HFanI%`TX79u1Yx z7C6+vymwVn;vaD1vW?Q8&v&I7myOrPZt7nU7pdF6ul?PB7WZ-;_TO*hp{II?miGTf r+U0uEe^juEr}?UCl>fH+Kgk<#{j{G0n?j7pf7J5QDpFMvrs4ku6VP0E 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 zcmV m=KlHl)IB`_b>h$f z0PgPY Oqg@-+zD78XDPDQ~-kH`1}10h2_4~@&Hhf?^aX! hSdA>+v{k!thj4);c=!_W1xsjP&{Z`uh5=$nOAQm(d>|`u+X_ zWSIa}lG89T0BgknSd#!tyP#o@07;DiJBZRcLE0t&*Wv2C&FEf@u*=!xu*KB?LW|Vk z=>Ul60Epz8w#${W$naiVzR=zPU6s3OlI`^OqPx!0D=Yu}{HnpzbDFsASzX)Y>%7g{ zC27I#I5WuC;`dA{g{Hs&T)qHXlmIe@004gOM?>D{?!(jGm#e~gox1>OoA6my@J&n4 z007Y4<^Wc{exkhrY@XjhKj!W9pRvY@s>4Knrzvxx5p12d%Gm%yxoMNM8fu#W8-nm- zU_Wug08qSRk+T3MgYGaY&)V&|#L;Y)woHVpM|h$Hq?qC7?U1g CFKogZWWedPv^#sIA9SJx zaiIWPl>h*B0F3VY?Cd0q=B~ctxXIb~+1RbT&5NPCk#M&3wzO1+tn{p_?TCl~41n!; zb?pEE{`2xbjpdlK;Fze@g`m?xd&^XV%J;y)0ARoCyuCPeqU@8B?`~|_Vqn-wOZ@Ne z?BU +~nl)($eLcnkJ>009lnb zkb~cOdEISi(Ge8cAOP9|08NwT0CLSfY`&&skpPEy0DNlFI6wGJEcQw!g*FY^E&ziK z0D!IO)4|f4hr<$T!;;3ox3{ UTn`4~!_>yop4vnxiq) z$Z}fd%Q+|fz;=X#@csJx|J9>HNl8gbNl8gbNy&c-;duHWl}Zta5CYD0b`dr}AR8OQ z5P erTG_%JZzCL|?c{SoI@H0O*fkUDxV0V$3{Fa{uE{bIdb&lw*GxA#$9+7Nf z3?LNoW%5s3YCCg56axT2&=GKvS&zSX_Aobsn&F5qE5BlXMM@<3xds}a-N)w7P*}vW z12~9nFmm0(s^GB4rFC_CF<}n?{dzzMPF%cNchzR$R4lLaj9!4O{0M}8g{BK#`Sj)5 zwQFA=Etq$p267Qj2Lz^t4Oz_Q tr&SjIE8Th4N{U6x2`JYqPYs*RJ1} zrebgZev0vWy-j|{U~-8t8Z<(*tLw(xY(2ZD^kknHxYfck(2Q4`RI~MY*9behYP;$S zqf)J49Gpbl(2|(wUnYPVAb@;WDLx> z5MIl;Js_9-Be`;?mfHhDcq!uwNVun#!j((PtNZ=5P@aVV5YEC1hf~n1b;J`xO9U{0 z;u1s$7 dw^slQ2#08W{f(ZvGxf~v8MtN0iMyuMGEDCxzON}U3~`r~s;>39)UR-8 za~tye{mghP@SGpRrrt^Ssy5_wQ@bLcfx-Tm2@t>en*lIQ$I(#e(3_39++La2?Wd+j z02~325C)J6`NHAw;lTZ^*&f_~@cG;7d>&ozJ_3{!_=FI2hMW;S>9YE)n`f|YKE5ii zdu{hT$DkSbgaA55B5o_2o-`6OIc-;$=V$SJPw`%0k6v$eS;=rDVAs#!+`jaWj`RJ6 z0R|lbr`2e++YcR0>2lEgk*<^H{0L51+5BXrJ5}@VK?LwKMg*a-l_2Z~i(AJCVf^OD zK%+MrN&B$OBr8H0@C}250T=1)K6zd)`FHX;fPhyBYDSzS;oQ4RQeFhfEWQggLrPDO z`tI3M3a2O>$GN}sp#T&`@&5b2AMKm_ixN>3$Ir#FqBp&$5T-^bhfrhEfq@wi9R*EM za#0ddbJa=|SGUjtjoheh+pT`7peI2Tz56XHD*B}e3ZftSANnskceJ%PS(XL!VRv@# zInK=edd|6X?>KIQGso7g+kO=OSGK|Z1MB8)e_&m{;Fp*KLx#Z3?f6jTgI9|d{tAnR zUc?5tt_k2*EdCW%EQcYZ)xf6hH^D%F^vlpM!kU27+c&M-c#HfiAGP &YLx2s 9S$p7t$0wy}AG7%iU}GXa4Rj|G*a_Xb#^y^ZxDH{(18F4Ezi85CX`ymA}A}e_%@Y zd$)JUzxWs?`KA&1C+=zy@@so_`HmC*Dx~inn4jJk{l45Z4-EVvtg*vZApHl8u^c{p zxMKQdk1ad_(rc=h#3C5s4-wyYG12GI8I&DQo(oAAC-YanQg49lB skd46}J^VE%vr27r$rJQ%D%VmeM7@#&zJ8Bn}>m3H+o^;y6(Hj4eNN~yXDj2I9M zl$KnstE#o5nRv#6X3N!SUXyJZJ$Ud+41!t>U^{!|;K5M~x&|&_Gg$pKE|ZZaA~TtD zCh%V>_^2wY`;yz<@!e+K{^q5o75IlC!PR*?8G29Jv>BqUHx(e7fa)c;+2_4I3Rnu! z8)7D-JUnuQ+vCGiRH_ecnM~@2>HucY0w6qMOOIcB?o3OK5O$fLl>GoE7 >jhNvxROy1HD 0{5=6t-|wbwKUgAm3;vG4V!ZA+KY>d zSVaYc6wpY3>4+luEsTjzij5QsFbC2TJP=1onXy92b}?dMjM=1koE@=3M6gAnL)aCI z#auk7A_{ t WsBZ(29*z+k71^7eq-fod!u{E4i-XpM=`&@v)jY9T ;Twvoxfm?V+a)W+&P(TMcRTR4v>&4K7ZI>|NIqS1 ze4Gm@g)CoA30@n;D+^rxx4$GrdeZ`>;4`=P%|@V2BftQ5sxc*(OgNG%{;mLfejf^O z 6>0s^5OiWFAoQET= zW*CeF?R;6JDP(}``OtCE0|ZL)gdG?{O_NIA4&V`lP!JGm NWvHA;g0PBQ1?*hbLlB8y56pEEa9ElNARdN=5Sk!_C289t^1@A<> zV)5itQaOevNh;2$9UvT#8Y!)a4Nxq2_tIE7+OnW(KD-WS0!(>MVCz@1mRNLxJ !%W@%sl|^R| z444TsHrvElZrm$5wFuCXtz%*vXjauY?~SqCc}3C$Fz7mRF(unVLdwet$2lw?h={CA z4;N~P_3nktKEjIl8qOA)5^yR3zDcj_9?O+mnVJO{_+16zWFf?IlG9xTLa3r-0VgWl zRCQus4F%9DPy+xA{jrqx*fO_m50maoO%y yTBN_j&H07NOxoGt=R@acX`Bo+3v0S$k#rGd}boX zp3P{SU9=ITBeS~#V`zKuD>8bbubVyNk9|GcXYKChJFod~KY-TJ(b3V-(b3V-(b3V- h(b3V-(b4%Ud;oR_3fSphSH1uM002ovPDHLkV1h;|2|@q> 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 zcmbVyRZyH=(B?bC;1XPd4H_V52*E-aoB+XsdyqhIhoFN)aJQhr-7U!A!Civ81ef3p zf4;rit=fyNJvS{+Rd-dNKHaCfI!swn1{do&761Ua?`0)b0Ra4u1w~{3ElM@{j)% z*UAcNQcq7$Q(T; D-mhA1%&(8t9 z#FLW~Kt1;M0SU55KUMy)y}b<>bO7G#`)5~S6?=d|;v_9C$R-PrivohSucoI@{@!2Q zK5QRf0>)kIPEM1XN7r|cSN;7RQ){!kr+!6Upl=7v1!*a+>3?tU<2w(<;YGwly<0 zCx36O9bU*g{X9@nVt2|}+B=P|Ul(!fZ=Bl5A6RUk+cNX%Z!~pV5a2(*x=pGd0z8WW z=e*;~n~chyU%$5wE^pokmj~C6Mpyp=lw&BYGfouV13GQ{^6&qFhS4?M3p)=-hmRK* zHu+sRCWvDhiNV#~ih%{~ga!t?O#PJRc*G$rZU^}0)i}2J=lJ~i$B!c&P4(oK?zxlD zihf1EVqD8~0A4n+x?eTAdh||cWc^@fWhcLD_M)S`q<1d0bwa{3Uo&9verM;6dmbPW zzOi?Bx3TfPYc{#G^T^I7x_R8atUv4LRzuHZPW!}hV8D@w`>GhsHoZkFyiz5s0+f?@ z_?im{*v@Pi^2qOW&TeD%DLyj& 3TSsfcf zaqQpdMi@0$1;vJb@EM?YABgJhNdM}PXQ?|}UFTA=w>dWxR9n^< MWaJVRMK_o_n zcFL2j9Qe&BNzLRXeU1wFFM$g|IM=r#Xis`!UI^~8p0PZsow^6N5iGQa#**vHM=^^M z;z{{Ss7e@(Dr#b%%uJDu_olAWD09O{!fD0qm%=_BU5ZyTL)WXR1INMt-2OkG2clA% z0|PFG;SC$VsHms_KbR3EXd+T6QpHX)Ca%T1KiV*hWy>S2gBUC58X|dpmt$**IbpNx zP&58xh;P@iE)@!GnPZrfmX_|5L&ax#JvO-#1;$^!;nM-; M0BEj7Tf4>KPQYv z|4sT#`c 3y+>D2Q%;%=!Eu zzua8}&;^=&sd&()g_=Bv0#;=+o$;b3r5y^0!!ndYwTcId0lt5Hg38EHy66Fz9-_cm zc4qJt!Qsb=xa2Iw8-1WCZlIZh#eWP|KYpOl?FQHoOPpB__Pb+C18(aE@a6$e>ZM!W z3NH*)BinOr GRjw!0-n}&3Mt5aL9l74mZ zGbp#9{s&|k@aD&V;KlBkEUN pPg#`2pr2xnY2Ajtt`jcNI~P*A>0p?BMXjglnNm z^SK;vb|i=)bHgGmX}(mfKK(f()_S`>(X+&cNW@wf;RemzBq|T?+%0bV_9s>A@;s5n z8$a8&d6Rq@a=E`3Z5W8nzNEey ISEB}=d=VwixXh}{nKDzBBE^!Q-2sV?{b>S6cMIx{c672q5%;R7Iix((#Gdl` zUQ#_IqLGf`?Z(#JVqKfw$B&iqLyu#czF*HbcEWyoCkIE_{)Qoxt>Qk6t^_^x-8$Js zPI yz}9>u3}C?s{Zvq1Oe1L+EmBVDUD|H$VJZQE~#4 z{PUA{)NsVFtSj&_injy{NMhPXZ+8o0B=o`M-Rj65Gx(y?mQ@Bso+P^MWVlcljCcrl z!~q3wE7dpKok*aPLkA~N$YVsOT+e!{%ON|9I#Jr$1h>4$eT%vn!#|TWM^{!>nC0vW zCX{M5=Komd$ItiIcy}yrJse)CXE*vUkS6||oD(-%slPnBtvmP?t1siaKcrumzgN=! z#UtpAHJSb&T;a5%lukt!PWh(_=kY?K#7t39`?cIfeFK!pWNr-d> 7! z_-KH;kY8L~FS?eYK5b}E5r#&&jwG>HE{zwJq*7Q&(p8>?9G7Y}IyNa*;;ejIow}Gs zsk{EQGI3|yp8rpDRN5l+zw|6Lmqu1gqdj+JsRBYz$ !wVre}R_q%wol1kAZZsVk0$FdKV=9oCYkez4~^u zej8*`h>t(8@o_Ua*|-iLe{kbcD;*CWGET*qGE+`AEdldXkwh?Ik&V|F`+oy|plt@| z $2M?}lE^V^LMfOhf_ z4Lp-v+4`l_Fa$20AoMZx(DUhR QU(HvQUGftCm~srR|THMTM0>J-ha76krgjIOW=s-n%S^utJW5 zbpYKwYB<>>ZlooKrI;{alE)N76hiY{4annX7(emFgHM@fbFCF3cYz}PfEC#F#3m@O z10EsV R_rP7lB zEl9H3XQU#YKeLX=;G3(>wHQQ8SJXR^q2SpeqBCG 0Ea|C?kO@0!rk6I5_x8m-B1eP0=tu0Z=c+{ z>+lap1Y5mWL-w<{7dAgw05?2Qvp9}IkGM8 ?G6d9m ez2ca9{(^dR{{B?j4fPhc%BYCa|4fUWKY@=jUz{(oM1$*?a-O-c z6=xWRpzf59{G+I^uKrLss&uB{@N2l9;a{FFvLt@gI_mP37CAXnNZn7}xZPATPZzvc zVS;Fd%N(GJ#7|VCxMp4p>?4svVC&wCxzg_UBqn%MtDC9byoFFi6yXr*@!mY^t_WVb zHxH#GJVQQ+xbLB$V;9+bfDat@)S{{$IzgXSPtIU?r_U&g$=I3#rgl5j(SAu#z+=~B z-;dd6B42(^!{8=-ms_eQ`XsC|9Fhdp$Q44;{Jq}4H?Oc?di-tGjZsCwVQx>$r%gfA z{_*|sgUw7m&Jy-+Hsn|EtH~^+WkD|4u(gac@Cof4gFEh}3CZG~N69pIEe`~OUwS=< zEM?krBj_6^uud*ZsTNRck|N+V YkQ;LyF2QqRq{D26C-y}bx~_`)F;1N~3NDbK zN;q|_Cj*0a%A*Pa)9WmzPvT*GszS#TGoI0;qkpt7=Z13?f>@2n2hG)%eiX<>dlT=6 zfG5XL(ORia32KeF1%x~4JRS^d9um^Gp`lX$!V!_Mj|1y?;eY{#=j329zsfJH>7m5{ zf@``{WYgN=(ZV1Wl&W~%Vk#KNTM?dU3G5tF#ITDl_4qJd??$7mPe;ek6Q8p9+4W@6 zS(o$Va;I5--xItmt_&rm>o}M8pN$R3r;geHTh`CRI3i$(5Io34gS(nH1a34e?970F z3Bumx#01)OLJVLNJ(MJ>= z+h-O4#Gr9S>|6kDPw7t?$y9f>CF#{ zL8&5awX#AFy*EE)fwcJzr;HP_ywNp;Q3wSDqO|$>m(r>f-@=UE!tHA=t;7bbtuLmz z#C=z%-}7ekho(O0d&nx^79ZCBlHcmE3EQfb R50Hi#rZQw%yiS?4B8Q4YH|B9`#i-*s++-*Ih! ZK*@ zi@{bjtY?W+dP8}6!E5eh0va|MQ*5vM_;htw`H dEc!eHgL{4Z_ut9zORNUF+4 zWJJ_a)7|6A9y>KA!D(1q?d_MW2$UO>$t_H6n#hdjrC|lOZS3`u4W>@^^S#nZ5!7hu zIP(f Ww5a>` zZ*x0K ?>xuXlKW|!1m7ap0=()cU8XGY+Ryf*4Mpx2L)=!W-rfH(Lq42$3_NDFo}EQU zFHsrnbi<#7`2Q?dhjy>q3sB*O{O?3KXYKAMj1?~MBtt)QIM&wICTfR9u=^y-cvZrV z;cuQz`?$In3r~LQgVC7U$;R#DIn@n>Xm(4WaaC;2dx|hMV#F`RkfKX^vwF-$ca2 zmRqC>7g;t#^--e;jnZdp&OlqNiOIX4k>0qawhXTti)^Tobp|-d{6*2Wnq7x@vTj1M zY@#!=C4YGDz#1+qh`zaUs6W*pn%$TkNGZxxuyZtd?eP~wzq%fWG}IjN!U1F(1guQ& zHP*=VhzsZHj%prDXl}Kiagfy1^UQUlHj#jbZCJjIgB;bI_0{1_oCq7jY`Zi2G@~38 zdYUW4daM+k5hJnJCBO<=6DoMGo+B3vhrNY2)gVBjkAau9XUjjZA~=C1%IwvKbPzw- z&JVcbepmSr#)fRUyHz@Q{%|?9pUK=scAo6CH<;Ib(k@K3wTwvTf^WSHm&`VzyWd%G zRCqQqcE3YPSvhN7{qOfsg!_(gUIZM->?-L;w<#Rd z1{hLGF*gCr zOfX|4+(_frQ&FBPXrW`2qxH&+ICUND91rA7F!+rxWIYJ!oeFF0IANLwV~>9TUvlxE z__p$UHK%3%C*Fjo!3bn5eVkeU8Dm5&6|e*3b6$IK_Mi%F_~rEA9WO$TolVTQtm?d? z`me13B(kR1d{25H$?)UBVR-xOS}AdP#ni`gE`@voDt)hD+nrIj6j~K+6#GrbeOi`w z>=!9Ybm+P4hgx7d&6hiGz-J_+lX84}N9+KER(O?nC2^?tJL;)syMeDt{3rI&A2!LW zv@=YvFH5T}{v56NdE!zN@*LS{iPclfXgmzv*qCrNA132VVMVkXzU#6jpN@|&JTTN$ zWpQEdp3uQm@wfz0NFZP8{>T|hB Jb78PkIVC0Fn(56eNPa-=&!O7nc1JD4hO=v8AUKE z(In 2wK`xpi8?bC_@8gw7^;@ENWzA1y2;HR&rX#Ybpw7G3wwTa;N@p)0 z-|BwVC)@564xjSWdcX5b*a9ka>hHex5+Nd=mMu{6iv7iSJ$6i*fU-4jlvb(_Z}=i) zod3IjmVPOdGXE!{Y`aeid2SpIwfh46pZF_6gOUJQ9lymS7TjgCw6Stae>y-gOf~)v z{dH{Bgop=Qbi{sGj ckMK4gefXSZu#ruR9WLnzT0yM2-ZZ9TG! zj;WB4$g>d VS^U;s%(*K)X#wezHR!3?UqFNI{+r&i%R=#Ze6Dt~9dpQ>{2-v4A z>vgT^eEnmfLqDy!s%8z&>qnPz-Dy7{h1O(OcbVVK_>qtFwill-WW#O1mme(Xaec04 zBDH8Cm0WLD)U>|ja5$^TSABpR84v?snO7bRTUC{cp5#B&VZysAKjG*%`Zub#Pm1Rl z$al_;zdKm6+7yaQfwHKBJIcT}N$ACL10-B6pFt&yuS(A^#NNlv&op12QTs1K>^W-I z!p?1a7pJ_QEwtqmSWwj}D$W^^AUb05QvH;MaUCn|zVz4-L0j03Wry=&R$ |}QR0ft)xWB!l!IF#8RF!q1~AuFrxPFBPXaf|sP_Amb?PrpIQE$5^x9AJ zD0LyHSG1EN%L8T?I$N^q3Iud&HuN)m-k?$-2(2vyU1_0Y6UOo0J{>^X$2HuvQ%DgH zh~k)_{26tJ5L!7X1vBb#6vR->>7fvX1AfBVH!u-Sdf}Y;l|>37J73DDA#h+Yo`o#> z%l!sg)-GFSkg9wD`wyjD4eCMzgj!C$*4#s>M>w#OpT|ai%x}$5a~EdJ3IZOb(wt1& zD^u$W$K@Pp`@ZlyXwuc`UH^Dv{Ilc-Afx^Qv{7o?8F=4Y+`$e%k-|@~AZqBIym 8WnB^}Xez~4Q9K>t_1p#XGf2-PV0`p3rj4ZnmZpU&i!-tF(>$K(BZPFl8}G{v zr$%9O+B14jOOsu~wKUXFg(ES}QeIS3hP!+tLa2VARj+uBsa4{QCb77AIX1yGbqXp* zuZG!PbfSxCH+p`qI$-z2*f%mrdH7X~u1Y IlVQEnK2C+6~htfv#z>gZ5X_hm0t^*Rp zU!M6D1pJV37TBEA0t+S^j^EFyxEYZ`y=556BI+3O`S~UZ;RNY >*Ok5v>2~CV64_tD2 z>%FbTbC}{??%#qE55y_jp)^xT;RW{jk}RU0CSn$R$o)4OrW>lBuq!Z=c+ca? j7|JQ1Ug-LM-Z0}n3~RI P;6!OLt(Bv#cqdhFZnnY zAsi1`qOxbv*lUAF-5IQNR8upkk1a_+#0Ew=N*`97fd<{jT6XU#?3-t4a(=1oJR_)( z97jJIlm2F)Ak2dfvBxjj^so0FK2Q|bS!YAOVQ@|bHV zAmC8;;%5-2HYK5NwLXw<(eb*$x| E7rtBbeBEbPls4m*lTGt^9lvMOF z+dK|YIr)nT(D?zqL)haK_}TI;pz7rUAm@S&KJ3N@I#dTrzE2#-*9c;MEo#@nO@-j& z`HwOoGRm}p;=vXVV{aZ8K@gVtMj~ocW8OF$qWOumn5M1-{*(w*(Ok4bLT$Tk*tzzj z!0a}~t{|^^_HrWig?OSjD4dW>5|a5wnrjC1%UbPPK*SFeyOL46y2bed=37gaZCFl# z0X9|AnVnC1#RHnG-%)0|MX|4b<^qayOL5)i;qXS`t)sj#!~boR;qwz%86=hMR(7+z z{25L Tyxx<{38O>{q6i{b*f+ov*fzV- z>|}%4cXv RuEs!8Zk1^%_wM@d95(qZ3NaJg z?rI@jj2UBA#8h!CqRVO6RS7uhSOhG8juXE8f#bFcmu1Fv_0O{bWgPh22OdgM%->PT zUtz)>S4RoSBekoJs90XkYyaz)Rn5mxQ>E{lv(`{@IsLhvpLrQFsa9)Vh?z_szN8Pf zu9~v@Afc@I@1b=+ ui5Db#5-yE{PGz2*4 zC@c0Htyst(jCFtV6myLBdN;1I!}%NgzTI{=k!iD9dki0djyWdk%WoFJe@Gd91z8nW z!|1Wwr9R{oSB&t-oBCk?0UWGZ{L9ovxk rF{2gs~RF16{EArsLx<@*(6J&Dlx= zubjY|40g_8HRA6#t+e~MfwlA1QY!~2yR9V5S#LLnL*~=oCc3rgF4HHckXO2=LSHzS z9%nwVDC&UWGA^-bqDxHCC>~B+EcEP0S>I`K-S=Pk6<<@b5AY}&3@^wt-5HDcKMQ~N zkucKMvSf_~z+VmKTD a)26^}g8=GW#E+!d =}7Hrr+9;+l6n>zt}qs0<5>$WhaG{( zr9iJ-TNopRvGFlGnDP4qB&|uHe9`ItX6V{NuLJtEu JSXtdch(TGCPOJ1{Hz=d)wFNI z^V8W}qMCO|!?q}wS*+5dcJi#(uqwx}jN@!Cs{0)pCSw(7w?Ea1wBLl$Z5fN9Fy|`U z2`EPWkzd6%j!n5z!+R4z^)LVVZSACF=IY_`b3SBmleb3&u>176Gn{Ha{0Q%} zIcjiRM#b*#ygxn;Sbz>S`3k)-($Ef7s7aXEdIU8EbLU{n{=Ieo;U{)e1#~wSkd8}# zvL`#WmaIv*AKnSZIb~<RQ`>E?$Rnrl@9e|;i}EH zQ)GFtx)_#}%&*AxfXjDerWG!}5z+-p$It$=lJIzho_NmCL@`Os7;w=M882S!_RTHs z6(c##fTjz>&0^$Svgae~;DMkJ{WL`f^6tQT%t9ykgHXe5)YK y<&{2wE{+i4Qm zf}{bJ7j)i25KEz7+a`<6b>$HghK+hE-)y8M3Q}xxU*ul?ng2afs5Cz~a | z008^@`| gxFT`0noRP*6|}4GrAf+>nrv*Vor`b93Y4 z *_RLPA0n6&3UI^X28`)6>&uXJ_Bv-<_SE zZf b8t5C-7xW?wY|YTWl-qsjZf+ezX{24ypfFjUQVtyTR)4~{bc z2!bF8f*=TjAP9mW2!bF8f*|CJB*}ydo5=6uTAiS(+%|r)M^I7b0>2$4s3yb4Z@~nr zsiESxbsefn1o$Hn;98?s@c>pEzwL)mP1JSpi(J{+g!Q&Y>?{qaEJf@3UR8gGg>sQ% zHAdcHx7q9t-e_Vee9WndZu=MG>eKCq+QI)i>gp&TT n~-^gbdQip9L5r z7*91Tt2nCrOaD24fk@wfRpCpJf*PAy6BE6TyRHc-l#Pmr>W(0P4g1^ r)?%@rBnoAJNk~?_Th5U8#$F>16tgekW>iGu5FcuE} z_ePLA-N7HTAzUNv#lhQ+Ju`X)TKH=Y`7_%1OQy)-SMg7RsR5U0&W?aRfhW*b_@ixI z4e(YU|HwJHR|ELOTFfJOhWhyT2pN~x?l#_Gr4fWk@A#js5j@A_glEUWMf=-$m!3{B zt4P=$5j@MV<>05L4h(sFypwt`fzi&xXy(EbS#p55- 6f)%YZM+ z0uwAv$Wp*X$k72 =pdGW)t}KrV+o2wwe${RBnz0-9y%&eAV0N($R&uNiIUnwHG%@^sU0*N z>lEDyZ@Z~I)P*9A)@dE2J3W?wZDr2WddTshNQRx#L1qn6)#2k!=y# >~`=Wjy!-;4Qlw1 ztpz0;j`0C27fR H^$0nY##Jjw3 zF#^7LeN4g0)^-}>1MjeJ053?sYY21nr21VwbO3%BHvXB)!7L)YSe>E#<>+)irYe6+ zDT|J&%HLATGV0)8>A({=z%a+2y -sei&|{k zy8>I=X_Q*^*3~afKC18-eHu^28#Q^@n2Dl8aAW;*jusWeNblhdf(@tj1JG#ZV3xMW zZT+9D`3h6nK3{X72paB=JqKes>dU;r9#XK%es2F(+^SGaRMKarx$Ms6ruo-0t5nG; E3FR%- zl~*2N>r&S&k2|K-_#`5aJnHI~`}y2|;GWMp=lkRN?a aVYHmH{)E~7YxM)gNE_D;3>s8rFSNGSQr23E$-&M$0fG|2!cV=lxXwL~!`6QnipfZ5ql(>g+Tg z4k5L4EmkY$Mi8)T2|5(aqF*AdU9dSGArsI;x8o@CSIU|!hVd+Fzg5&!%x*B)l4C%u zh#-7{)dALn4B$`)$7U0HN0#e|^ pz^yf(;#U6uYIJA|g@t zW=n!>REbtT(a!XgBC{NH&+(bQnvQ06)wgd&&NVp oo`{tiS%_lFOobkbdS-)Gp*5--jGm#XX3(aAzqn@|8Q|Ya>yrne0Bzz4=8shw$_b z3}ZYtd~QWr7gC-ild&tQ (D0{g%{(vf#BPWD6ajo2^-T^G8* z`CfQ7#se;ezl_!CDhg2=-yl#6>I|gsvlpyB6q0^xAhJba81vJQZqD`&)#+>2Mbi`t zsuB4EL{?5RXxx3?%D2lxtj+-d7S_NmC}nd+<&Jw6 zA^9|f&Gv3t*@O1vObL^33F7NpDgK$CowsDxkFLysRARfmltN~Jf>7s{=Mh6R*tt*4 z3x@Zj$DRSTRG5j0j;({F?e$T9J_EjS`PVyk;A*B~hA76sF#uU~REvu&SLT_eJI-ZB z`eelUm1zemg<=ly^3ZYauJ=mZeheQN{HVHnj53i}H6}XPCPR4%Jej*ngl+p*#fk$J zE}5-r*bv@VstqJ1vsRCJO%VGC3T!HXLvbhkt@&(@ZYHEvCAb+sv>52P$utsYfL+=p z#vf5dB%yMP@+n}bFCAbl8Sf(|htz$e0g$r04FOVYg(y1Uu&w&&ydm1 w)gs9>}YhN HRZWg6raiBJ+4}Prxq GUsj_7};r53m2?O?&EcR}@S|cLzRO9q^#|UrZ8-6vXwAnp$a~9WJWPSot qU2^DKjYST552^IhSo%NSa=!}P!zUyR&axMO9 KMr+&@7khus&7 z>*(j_)+Q I^q<>B=90A
gR;^N~Rai$+{qAPTyFnOs;gQ{JRwCi+p_f0YYitTBex98{QK7X%0 ze5gHrsTFLV=j7vKnbDxZ)9LByCUc}Lc&bW+s@&Y%>FMd^<>gzCvQLMs<>~GwbEf9z z=1hpMEQ;py^Yb=%rA~;i=jiC^=H(b{peu>!6l1{dQ&2T?$KvAR;^X5%fUiV?txSZg z+#diNaHTSQs~&EjJAJApbfsyP&fkZK04k35T2~EY!6$dC9BrOJfUF8?p=On~ r#6o0;^N{ibfn~FWEyLoQ;e_d>*_gusQ?$jEpW*A`uhI< z{_ybd?eFhUgUSPF$@oY`3T4FvWt%y4$Ms)b^kQE@e8=!)Vh3lO>{wLqX=gBbr|R$T z>1%59^YQjwTKoI^L3qgZTUXmhM)g})Gjzw_Qc^T_qe_Iy?R$IUb8;4#)81`uF^}ys zucMZagaEFi=_Mx>ai|KFi2zW%?>RTCbg2LT|D%en?`>}Q{QTzR ~Ht&3c#5?5C#W!oZ?vTIomt0B4;#i`-3+*xXoI?M?vNUt$21=>TrU(=9FY z^YigjP~b8$@9*y|k@4*8>>`u*197Vabg&t7s`^@1foG=wT2}h{`t OV&~#ExQvd=4{sIRC{&4X#{0aSH1Nmk0 zH~!o|Iw=zn1^)iN9v1oA&bMU^4F3N2+r?i}PyYQJ?zgX}KQb^H{^ihb`SR&DEg9}i zAoAtFdt5F3`1bbQ)61HWRQ&L>gn?&H9}oKZ*`SGUNGBuy{{H^>_Qa=BQAj{P9`NJ0 zkAipp{rvpm-m;{ll!JVFX`&&