diff --git a/404.html b/404.html
new file mode 100644
index 00000000..e2fcb701
--- /dev/null
+++ b/404.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+ 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/CNAME b/CNAME
new file mode 100644
index 00000000..2f77233b
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+wenzhihuai.com
\ No newline at end of file
diff --git a/about-the-author/index.html b/about-the-author/index.html
new file mode 100644
index 00000000..dd7aa150
--- /dev/null
+++ b/about-the-author/index.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+ 关于我 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/about-the-author/personal-life/2024-07-24.html b/about-the-author/personal-life/2024-07-24.html
new file mode 100644
index 00000000..df3e682e
--- /dev/null
+++ b/about-the-author/personal-life/2024-07-24.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+ 2024-07-24 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git "a/about-the-author/personal-life/2024-11-09\344\270\212\346\265\267\350\277\252\346\226\257\345\260\274.html" "b/about-the-author/personal-life/2024-11-09\344\270\212\346\265\267\350\277\252\346\226\257\345\260\274.html"
new file mode 100644
index 00000000..f30f932f
--- /dev/null
+++ "b/about-the-author/personal-life/2024-11-09\344\270\212\346\265\267\350\277\252\346\226\257\345\260\274.html"
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+ 2024-11-09上海迪斯尼 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/about-the-author/personal-life/index.html b/about-the-author/personal-life/index.html
new file mode 100644
index 00000000..4f2d11f4
--- /dev/null
+++ b/about-the-author/personal-life/index.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+ Personal Life | 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/about-the-author/personal-life/wewe.html b/about-the-author/personal-life/wewe.html
new file mode 100644
index 00000000..f88427a3
--- /dev/null
+++ b/about-the-author/personal-life/wewe.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+ 自我介绍 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/about-the-author/works/index.html b/about-the-author/works/index.html
new file mode 100644
index 00000000..86dfd915
--- /dev/null
+++ b/about-the-author/works/index.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+ Works | 个人博客
+
+
+
+
+
+
+
+
+
diff --git "a/about-the-author/works/\344\270\252\344\272\272\344\275\234\345\223\201.html" "b/about-the-author/works/\344\270\252\344\272\272\344\275\234\345\223\201.html"
new file mode 100644
index 00000000..5a2ccee9
--- /dev/null
+++ "b/about-the-author/works/\344\270\252\344\272\272\344\275\234\345\223\201.html"
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+ 小程序 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git a/ads.txt b/ads.txt
new file mode 100644
index 00000000..be5a5540
--- /dev/null
+++ b/ads.txt
@@ -0,0 +1 @@
+google.com, pub-9037099208128116, DIRECT, f08c47fec0942fa0
\ No newline at end of file
diff --git a/article/index.html b/article/index.html
new file mode 100644
index 00000000..e3902b25
--- /dev/null
+++ b/article/index.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+ 文章 | 个人博客
+
+
+
+
+
+
+
+
+
diff --git "a/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-B9tl8qmz.js" "b/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-B9tl8qmz.js"
new file mode 100644
index 00000000..e44a73f9
--- /dev/null
+++ "b/assets/1.\345\216\206\345\217\262\344\270\216\346\236\266\346\236\204.html-B9tl8qmz.js"
@@ -0,0 +1 @@
+import{_ as t,c as r,d as a,o as i}from"./app-ftEjETWs.js";const n={};function l(o,e){return i(),r("div",null,e[0]||(e[0]=[a('各位大佬瞄一眼我的个人网站 呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。 大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。
由原本的ssh变成ssm,再变成ssm+shiro+lucene,到现在的前后台分离。前台使用ssm+lucene,后台使用spring boot+shiro。其中,使用pagehelper作为分页,lucene用来搜索和自动补全,使用百度统计的API做了个日志系统,统计pv和uv什么的,同时,还有使用了JMX来观察JVM的使用和cpu的使用率,机器学习方面,使用了adaboost和朴素贝叶斯对微博进行分类,有兴趣的可以点点有点意思 这个页面。 本文从下面这几个方面来讲讲网站的建立:
建站故事与网站架构 lucene搜索的使用 使用quartz来定时备份数据库 使用百度统计api做日志系统 Nginx小集群的搭建 [数据库] 使用机器学习对微博进行分析 网站性能优化 SEO优化 起初,是因为学习的时候老是找不到什么好玩而又有挑战性的项目,看着struts、spring、hibernate的书,全都是一些小项目,做了感觉也没啥意义,有时候在博客园看到别人还有自己的网站,特羡慕,最终就选择了自己做一个个人网站。期初刚学的ssh,于是开始了自己的ssh搭建个人网站的行程,但是对于一个后端的人来说,前端是个大问题啊。。。。所以初版的时候差不多全是纯生的html、css、js,至少发博客这个功能实现了,但是确实没法看。前前后后折腾了一个多月,决定推翻重做,到百度看看别人怎么做的。首先看到的是杨青 的网站,已经好几年没更新了,前端的代码看起来比较简单,也是自己能够掌握的,但是不够美观,继续找,在模板之家发现了一个高大上的模板。
第二版的界面确实是这样的,只是把图片的切换变成了wowslider,也是简单的用bootstrap和pagehelper做了下分页,现在的最终版保留了它的header,然后评论框使用了多说(超级怀念多说)。后端也由原来的ssh变成了ssm,之后加上了lucene来对文章进行索引。之后,随着多说要关闭了,突然之间有很多div都不适应了(我写死了的。。。),再一次,没法看,不想看,一怒之下再次推翻重做,变成了现在这个版本。
最终版本在考虑时,也找了很多模板,影响深刻的是tale 和欲思 这两个主题,期中,tale使用的是java语言写的,刚知道的那一刻我就没好感了,java后端我是要自己全部写的,tale这个页面简洁但是不够炫,而且内容量太低,可能就只是个纯博客,之后发现了欲思,拓展性强,只可惜没有静态的版本,后台是纯生的PHP(嗯,PHP是世界上最好的语言),看了看,没事,保存网页,前端自己改,后端自己全部重写,最终变成了现在这个版本,虽然拼接的时候各种css、js混入。。。。还好在做网站性能优化的时候差不多全部去掉了。最终版加入redis、quartz、shiro等,还有python机器学习、flask的restful api,可谓是大杂烩了。 页面看着还算凑合,至少不是那种看都看不过去的那种了,但是仔细看看,还是有不少问题的,比如瀑布流,还有排版什么的。只能等自己什么时候想认真学学前端的东西了。 已经部署在腾讯云服务器上,存储使用了七牛云的cdn。
最终版的技术架构图如下:
网站核心主要采用Spring SpringMVC和Mybatis,下图是当访问一篇博客的时候的运行流程,参考了张开涛 的博客。
运行流程分析
浏览器发送http请求。/blogdetail.html?blogid=1。 tomcat容器初始化,顺序为context-param>listener>filter>servlet,此时,spring中的bean还没有被注入的,不建议在此处加载bean,网站声明了两个类(IPFilter和CacheControlFilter),IPFilter用来拦截IP,CacheControlFilter用来缓存。 初始化Spring。 DispatcherServlet——>HandlerMapping进行请求到处理的映射,HandlerMapping将“/blogdetail”路径直接映射到名字为“/blogdetail”的Bean进行处理,即BlogController。 自定义拦截器,其中BaseIntercepter实现了HandleInterceptor的接口,用来记录每次访问的链接以及后台响应的时间。 DispatcherServlet——> SimpleControllerHandlerAdapter,SimpleControllerHandlerAdapter将HandlerExecutionChain中的处理器适配为BlogController。 BlogController执行查询,取得结果集返回数据。 blogdetail(ModelAndView的逻辑视图名)——>InternalResourceViewResolver, InternalResourceViewResolver使用JstlView,具体视图页面在/blogdetail.jsp。 JstlView(/blogdetail.jsp)——>渲染,将在处理器传入的模型数据(blog=Blog!)在视图中展示出来。 返回响应。 日志系统架构如下:
日志系统 曾经尝试采用过ELK,实时监控实在是让人不能不称赞,本地也跑起来了,但是一到服务器,卡卡卡,毕竟(1Ghz CPU、1G内存),只能放弃ELK,采用百度统计。百度统计提供了Tongji API供开发者使用,只是有次数限制,2000/日,实时的话实在有点低,只能统计前几天的PV、UV等开放出来。其实这个存放在mysql也行,不过这些零碎的数据还是放在redis中,方便管理。 出了日志系统,自己对服务器的一些使用率也是挺关心的,毕竟服务器配置太低,于是利用了使用了tomcat的JMX来对CPU和jvm使用情况进行监控,这两个都是实时的。出了这两个,对内存的分配做了监控,Eden、Survivor、Tenured的使用情况。
本人大学里的毕业设计就是基于AdaBoost算法的情感分类,学到的东西还是要经常拿出来看看,要不然真的浪费了我这么久努力做的毕业设计啊。构建了一个基本的情感分类小系统,每天抓取微博进行分类存储在MySql上,并使用flask提供Restful API给java调用,可以点击这里 尝试(请忽略Google的图片)。目前分类效果不是很明显,准确率大概只有百分之70%,因为训练样本只有500条(找不到训练样本),机器学习真的太依赖样本的标注。这个,只能请教各位路人大神指导指导了。
断断续续,也总算做了一个能拿得出手仍要遮遮掩掩才能给别人看的网站,哈哈哈哈哈,也劳烦各位帮忙找找bug。前前后后从初学Java EE就一直设想的事也还算有了个了结,以后要多多看书,写点精品文章。PS:GitHub上求给个Star ,以后面试能讲讲这个网站。
',27)]))}const s=t(n,[["render",l],["__file","1.历史与架构.html.vue"]]),p=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html","title":"1.历史与架构","lang":"zh-CN","frontmatter":{"description":"1.历史与架构 各位大佬瞄一眼我的个人网站呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。 大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。 由原本的ssh变成ssm,再变成ssm+shi...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"1.历史与架构"}],["meta",{"property":"og:description","content":"1.历史与架构 各位大佬瞄一眼我的个人网站呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。 大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。 由原本的ssh变成ssm,再变成ssm+shi..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/600-20240126113210252.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"1.历史与架构\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/600-20240126113210252.png\\",\\"https://github-images.wenzhihuai.com/images/500.png\\",\\"https://github-images.wenzhihuai.com/images/awfawefwefwef.png\\",\\"https://github-images.wenzhihuai.com/images/awefaweagregrgbwerbwer.png\\",\\"https://github-images.wenzhihuai.com/images/awfawefwefawefwef.png\\",\\"https://github-images.wenzhihuai.com/images/QQ%E6%88%AA%E5%9B%BE20170825141127.png\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.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":1579574285000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":6.79,"words":2038},"filePathRelative":"interesting/个人网站/1.历史与架构.md","localizedDate":"2020年1月21日","excerpt":"\\n各位大佬瞄一眼我的个人网站 呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。 \\n大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。
","autoDesc":true}');export{s as comp,p as data};
diff --git "a/assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-BVYNR54w.js" "b/assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-BVYNR54w.js"
new file mode 100644
index 00000000..01e28e78
--- /dev/null
+++ "b/assets/10.\345\216\206\346\227\2668\345\271\264\346\234\200\347\273\210\346\224\271\347\211\210.html-BVYNR54w.js"
@@ -0,0 +1,72 @@
+import{_ as i,c as a,d as e,o as n}from"./app-ftEjETWs.js";const t={};function l(h,s){return n(),a("div",null,s[0]||(s[0]=[e(`不知不觉,自建站https://www.wenzhihuai.com 已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。有时候因为要用服务器搞一些别的东西,直接没有备份数据库就重装,导致不少文章丢失,虽然别的平台可能零散分布。
早年的网站截图 总体而言,自建站对学习知识,了解整个建站的原理能够起到非常重要的作用,但是维护成本实在是太高了,每个月要支付服务器的费用,而且一旦想拿服务器来做点什么,都得提防一下会不会造成破坏。最终还是选择采用vuepress2来重构一下自建站,毕竟把markdown放到github,把图片放到cos里减少了不少的维护量。下面是使用vuepress2建站的代码地址 。
具体vuepress2官网 讲解的很详细了,不用再处理什么,按照步骤创建一个项目即可,为了网站的美观,个人使用了theme hope 这款主题。
导航栏、侧边栏官网也有详细的讲解,也不再阐述,需要注意的是自动目录,之前看JavaGuide 的样式,他那边的每篇文章都需要写一次ts文件(children),后来发现官网可以把children设置为structure,即可实现根据md文件生成侧边栏目录。注意的是,这里不是根据markdown的文件名来目录名,而是取markdown文件的标题。
{
+ text : "Redis" ,
+ prefix : "redis/" ,
+ icon : "redis" ,
+ collapsible : false ,
+ children : "structure"
+ },
vuepress-plugin-comment2 ,使用了Giscus,Giscus绑定了github账号,所以可以从一定程度上防止被别人刷广告,需要再个人的项目Settings->General把Discussions这个选项给勾选上。
一定要开启discussions 然后去config.ts配置插件。
commentPlugin({
+ provider: "Giscus",
+ comment: true, //启用评论功能
+ repo: "Zephery/MyWebsite", //远程仓库
+ repoId: "MDEwOlJlcG9zaXRvcnkyMDM2MDIyMDQ=", //对应自己的仓库Id
+ category: "General",
+ categoryId: "DIC_kwDODCK5HM4Ccp32" //对应自己的分类Id
+ }),
即可在页面上看到效果
颜色可自定义 官网也有讲解部署的情况,具体可以看官网Github Pages ,整体上看速度还是挺慢的,可以尝试去gitee上部署看一下,之后就可以在pages通过域名访问了。需要在项目下创建.github/workflows/docs.yml文件,具体配置参考官网 ,不需做任何改动。
github自带的io域名zephery.github.io ,做为一名开发,肯定是用自己的域名是比较好的。需要注意下中间的红色框,前面的是分支,后面的是你项目的路径。一般默认即可,不用修改。
pages的配置 购买域名->域名解析,即把我的个人域名wenzhihuai.com指向zephery.github.io (通过cname)即可,然后开启强制https。如果DNS一直没有校验通过,那么可能是CAA的原因。通过DNS诊断工具 来判断。
DNS诊断工具 上面的custom domain配置好了之后,但DNS一直没有校验正确,原因是CAA没有正确解析,需要加上即可。
0 issue "trust-provider.com"
+0 issuewild "trust-provider.com"
CAA记录解析 之后就可以看到Github Pages的DNS校验成功,并且可以强制开启https了。
之前的图床使用的是七牛云和又拍云,都有免费的额度吧,不过看情况未来前景似乎经营不太好,目前改用了腾讯云。存储容量50GB,每个月外网访问流量10GB,满足个人网站使用。具体的配置过程比较简单,就不再阐述了,可以直接看uPic 的官方介绍。
有钱才有写作的动力,之前的网站开启了几年的捐赠,总共都没有收到过50块钱,只能从广告这一处想想办法,百度、腾讯广告似乎都不支持个人网站,谷歌可以。配置谷歌广告,网上的教程不少,例如: vuepress配置谷歌广告-通过vue-google-adsense库 ,缺点是,大部分的文章都是需要在自己的markdown文件中新增特定的标识符。比如:
# js 模板引擎 mustache 用法
+
+< ArticleTopAd ></ ArticleTopAd >
+
+## 一. 使用步骤
每一篇文章都要新增显然不符合懒惰的人,下面是个人尝试的解决办法,用的是vuepress2提供的slots插槽。
谷歌广告adsense 上面的目的是为了获取data-ad-client和data-ad-slot,其中,data-ad-slot为广告单元,不一样。并且,配置完之后可能需要等一个小时才会生效,不要着急。
docs/.vuepress/config.ts
head: [
+ [
+ "script",
+ {
+ "data-ad-client": "ca-pub-9037099208128116",
+ async: true,
+ src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
+ }
+ ],
+]
+
+...
+alias: {
+ "@theme-hope/components/NormalPage": path.resolve(
+ __dirname,
+ "./components/NormalPage.vue",
+ ),
+},
docs/.vuepress/components/NormalPage.vue
< template >
+ < normal-page >
+ < template # contentBefore >
+ < ins class = "adsbygoogle"
+ style = " display:block; text-align:center;width: 90%;margin: 0 auto; "
+ data-ad-layout = "in-article"
+ data-ad-format = "fluid"
+ data-ad-client = "ca-pub-9037099208128116"
+ data-ad-slot = "8206550629" ></ ins >
+ </ template >
+ </ normal-page >
+</ template >
+< script >
+import NormalPage from "vuepress-theme-hope/components/NormalPage.js" ;
+
+export default {
+ name : "adsense-inline" ,
+ components : {
+ 'normal-page' : NormalPage ,
+ },
+ mounted () {
+ this . adsenseAddLoad ();
+ },
+ methods : {
+ adsenseAddLoad () {
+ let inlineScript = document . createElement ( "script" );
+ inlineScript . type = "text/javascript" ;
+ inlineScript . text = '(adsbygoogle = window.adsbygoogle || []).push({});'
+ document . getElementsByTagName ( 'body' )[ 0 ]. appendChild ( inlineScript );
+ }
+ }
+}
+</ script >
+
+
+< style lang = "scss" scoped >
+</ style >
本地是没办法进行调试的,可以从官网插槽演示 的文章中用div进行调试,等修改完毕发布之后,即可在自己的网站上看到相关的广告和收入(浏览器要把封禁广告的插件关闭)。
出现的广告 谷歌广告收入 收入虽然低,但是基本上个人没有成本,只需要域名的85块钱。
为什么广告不能正常显示?
"建议多写原创高质量的文章出来,AdSense才会匹配出合适的广告,用户感兴趣了才会浏览量增加,你才会有更多的广告收入。"
还是得多写一写优质的文章。
最后,多帮忙点一下个人网站的广告吧,感恩
网站地址:https://www.wenzhihuai.com
源码地址:https://github.com/Zephery/MyWebsite
`,50)]))}const r=i(t,[["render",l],["__file","10.历时8年最终改版.html.vue"]]),k=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/10.%E5%8E%86%E6%97%B68%E5%B9%B4%E6%9C%80%E7%BB%88%E6%94%B9%E7%89%88.html","title":"10.历时8年最终改版","lang":"zh-CN","frontmatter":{"description":"10.历时8年最终改版 不知不觉,自建站https://www.wenzhihuai.com已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/10.%E5%8E%86%E6%97%B68%E5%B9%B4%E6%9C%80%E7%BB%88%E6%94%B9%E7%89%88.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"10.历时8年最终改版"}],["meta",{"property":"og:description","content":"10.历时8年最终改版 不知不觉,自建站https://www.wenzhihuai.com已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/600-20240126113210252-20240131213935629.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"10.历时8年最终改版\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/600-20240126113210252-20240131213935629.png\\",\\"https://github-images.wenzhihuai.com/github/image-20240201153605099.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240201205909384.png\\",\\"https://github-images.wenzhihuai.com/github/image-20240201144459067.png\\",\\"https://github-images.wenzhihuai.com/github/image-20240201151253084.png\\",\\"https://github-images.wenzhihuai.com/github/image-20240201151243938.png\\",\\"https://github-images.wenzhihuai.com/github/image-20240201150802070.png\\",\\"https://github-images.wenzhihuai.com/github/image-20240201151218077.png\\",\\"https://github-images.wenzhihuai.com/github/image-20240201151334064.png\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、博客的安装","slug":"一、博客的安装","link":"#一、博客的安装","children":[]},{"level":2,"title":"二、配置","slug":"二、配置","link":"#二、配置","children":[]},{"level":2,"title":"三、为文章增加评论","slug":"三、为文章增加评论","link":"#三、为文章增加评论","children":[]},{"level":2,"title":"四、博客的部署","slug":"四、博客的部署","link":"#四、博客的部署","children":[]},{"level":2,"title":"五、Github pages自定义域名","slug":"五、github-pages自定义域名","link":"#五、github-pages自定义域名","children":[]},{"level":2,"title":"六、Typora图床","slug":"六、typora图床","link":"#六、typora图床","children":[]},{"level":2,"title":"七、为自己的内容增加收入","slug":"七、为自己的内容增加收入","link":"#七、为自己的内容增加收入","children":[]},{"level":2,"title":"常见问题","slug":"常见问题","link":"#常见问题","children":[]}],"git":{"createdTime":1706165044000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":5.78,"words":1733},"filePathRelative":"interesting/个人网站/10.历时8年最终改版.md","localizedDate":"2024年1月25日","excerpt":"\\n不知不觉,自建站https://www.wenzhihuai.com 已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。有时候因为要用服务器搞一些别的东西,直接没有备份数据库就重装,导致不少文章丢失,虽然别的平台可能零散分布。
","autoDesc":true}');export{r as comp,k as data};
diff --git a/assets/1mysql.html-CW43wjS_.js b/assets/1mysql.html-CW43wjS_.js
new file mode 100644
index 00000000..114bea80
--- /dev/null
+++ b/assets/1mysql.html-CW43wjS_.js
@@ -0,0 +1 @@
+import{_ as i,c as a,a as e,o as m}from"./app-ftEjETWs.js";const n={};function o(s,t){return m(),a("div",null,t[0]||(t[0]=[e("h1",{id:"mysql",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#mysql"},[e("span",null,"Mysql")])],-1),e("figure",null,[e("img",{src:"https://github-images.wenzhihuai.com/images/img.png",alt:"img",tabindex:"0",loading:"lazy"}),e("figcaption",null,"img")],-1)]))}const l=i(n,[["render",o],["__file","1mysql.html.vue"]]),c=JSON.parse('{"path":"/database/mysql/1mysql.html","title":"Mysql","lang":"zh-CN","frontmatter":{"description":"Mysql imgimg","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 imgimg"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/img.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-06T07:53:39.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-06T07:53:39.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Mysql\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/img.png\\"],\\"dateModified\\":\\"2024-02-06T07:53:39.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1679834663000,"updatedTime":1707206019000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":4}]},"readingTime":{"minutes":0.02,"words":5},"filePathRelative":"database/mysql/1mysql.md","localizedDate":"2023年3月26日","excerpt":"\\nimg ","autoDesc":true}');export{l as comp,c as data};
diff --git "a/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-9FjHGi9W.js" "b/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-9FjHGi9W.js"
new file mode 100644
index 00000000..7a4cdfc3
--- /dev/null
+++ "b/assets/2.Lucene\347\232\204\344\275\277\347\224\250.html-9FjHGi9W.js"
@@ -0,0 +1,226 @@
+import{_ as s,c as a,d as n,o as h}from"./app-ftEjETWs.js";const l={};function k(t,i){return h(),a("div",null,i[0]||(i[0]=[n(`首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。
image 倒排索引:将文档中的词作为关键字,建立词与文档的映射关系,通过对倒排索引的检索,可以根据词快速获取包含这个词的文档列表。倒排索引一般需要对句子做去除停用词。
停用词:在一段句子中,去掉之后对句子的表达意向没有印象的词语,如“非常”、“如果”,中文中主要包括冠词,副词等。
排序:搜索引擎在对一个关键词进行搜索时,可能会命中许多文档,这个时候,搜索引擎就需要快速的查找的用户所需要的文档,因此,相关度大的结果需要进行排序,这个设计到搜索引擎的相关度算法。
文档(Document):文档是一系列域的组合,文档的域则代表一系列域文档相关的内容。 域(Field):每个文档可以包含一个或者多个不同名称的域。 词(Term):Term是搜索的基本单元,与Field相对应,包含了搜索的域的名称和关键词。 查询(Query):一系列Term的条件组合,成为TermQuery,但也有可能是短语查询等。 分词器(Analyzer):主要是用来做分词以及去除停用词的处理。 索引的建立
索引的搜索
搜索 2. 自动分词 注意:本文使用最新的lucene,版本6.6.0。lucene的版本更新很快,每跨越一次大版本,使用方式就不一样。首先需要导入lucene所使用的包。使用maven:
< dependency >
+ < groupId > org . apache . lucene </ groupId >
+ < artifactId > lucene - core </ artifactId ><! -- lucene核心 -- >
+ < version > \${ lucene . version } </ version >
+</ dependency >
+< dependency >
+ < groupId > org . apache . lucene </ groupId >
+ < artifactId > lucene - analyzers - common </ artifactId ><! -- 分词器 -- >
+ < version > \${ lucene . version } </ version >
+</ dependency >
+< dependency >
+ < groupId > org . apache . lucene </ groupId >
+ < artifactId > lucene - analyzers - smartcn </ artifactId ><! -- 中文分词器 -- >
+ < version > \${ lucene . version } </ version >
+</ dependency >
+< dependency >
+ < groupId > org . apache . lucene </ groupId >
+ < artifactId > lucene - queryparser </ artifactId ><! -- 格式化 -- >
+ < version > \${ lucene . version } </ version >
+</ dependency >
+< dependency >
+ < groupId > org . apache . lucene </ groupId >
+ < artifactId > lucene - highlighter </ artifactId ><! -- lucene高亮 -- >
+ < version > \${ lucene . version } </ version >
+</ dependency >
构建索引 Directory dir = FSDirectory . open ( Paths . get ( "blog_index" )); //索引存储的位置
+SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer () ; //简单的分词器
+IndexWriterConfig config = new IndexWriterConfig (analyzer) ;
+IndexWriter writer = new IndexWriter (dir , config) ;
+Document doc = new Document () ;
+doc . add ( new TextField ( "title" , blog . getTitle (), Field . Store . YES )); //对标题做索引
+doc . add ( new TextField ( "content" , Jsoup . parse ( blog . getContent ()). text (), Field . Store . YES )); //对文章内容做索引
+writer . addDocument (doc);
+writer . close ();
更新与删除 IndexWriter writer = getWriter () ;
+Document doc = new Document () ;
+doc . add ( new TextField ( "title" , blog . getTitle (), Field . Store . YES ));
+doc . add ( new TextField ( "content" , Jsoup . parse ( blog . getContent ()). text (), Field . Store . YES ));
+writer . updateDocument ( new Term ( "blogid" , String . valueOf ( blog . getBlogid ())), doc); //更新索引
+writer . close ();
查询 private static void search_index ( String keyword) {
+ try {
+ Directory dir = FSDirectory . open ( Paths . get ( "blog_index" )); //获取要查询的路径,也就是索引所在的位置
+ IndexReader reader = DirectoryReader . open (dir);
+ IndexSearcher searcher = new IndexSearcher (reader) ;
+ SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer () ;
+ QueryParser parser = new QueryParser ( "content" , analyzer) ; //查询解析器
+ Query query = parser . parse (keyword); //通过解析要查询的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 >堆.栈和常量池 笔记
分页 目前lucene分页的方式主要有两种: (1). 每次都全部查询,然后通过截取获得所需要的记录。由于采用了分词与倒排索引,所有速度是足够快的,但是在数据量过大的时候,占用内存过大,容易造成内存溢出 (2). 使用searchAfter把数据保存在缓存里面,然后再去取。这种方式对大量的数据友好,但是当数据量比较小的时候,速度会相对慢。 lucene中使用searchafter来筛选顺序 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)
使用效果 全部代码放在这里 ,代码写的不太好,光从代码规范上就不咋地。在网页上的使用效果如下: 百度、谷歌等在输入文字的时候会弹出补全框,如下图:
在搭建lucene自动补全的时候,也有考虑过使用SQL语句中使用like来进行,主要还是like对数据库压力会大,而且相关度没有lucene的高。主要使用了官方suggest库以及autocompelte.js 这个插件。 suggest的原理看这 ,以及索引结构看这 。
导入maven包 < dependency >
+ < groupId >org.apache.lucene</ groupId >
+ < artifactId >lucene-suggest</ artifactId >
+ < version >6.6.0</ version >
+</ dependency >
如果想将结果反序列化,声明实体类的时候要加上: public class Blog implements Serializable {
实现InputIterator接口 InputIterator的几个方法:
+long weight():返回的权重值,大小会影响排序,默认是1L
+BytesRef payload():对某个对象进行序列化
+boolean hasPayloads():是否有设置payload信息
+Set<BytesRef> contexts():存入context,context里可以是任意的自定义数据,一般用于数据过滤
+boolean hasContexts():判断是否有下一个,默认为false
public class BlogIterator implements InputIterator {
+ /**
+ * 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 建立索引 /**
+ * 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!" );
+ }
+}
查找 因为有些文章的标题是一样的,先对list排序,将标题短的放前面,长的放后面,然后使用LinkHashSet来存储。 @ Override
+public Set < String > ajaxsearch ( String keyword) {
+ try {
+ Directory dir = FSDirectory . open ( Paths . get ( "autocomplete" ));
+ SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer () ;
+ AnalyzingInfixSuggester suggester = new AnalyzingInfixSuggester (dir , analyzer) ;
+ List < String > list = lookup (suggester , keyword) ;
+ list . sort ( new Comparator < String >() {
+ @ Override
+ public int compare ( String o1 , String o2 ) {
+ if ( o1 . length () > o2 . length ()) {
+ return 1 ;
+ } else {
+ return - 1 ;
+ }
+ }
+ });
+ Set < String > set = new LinkedHashSet <> () ;
+ for ( String string : list) {
+ set . add (string);
+ }
+ ssubSet (set , 7 ) ;
+ return set ;
+ } catch ( IOException e ) {
+ System . err . println ( "Error!" );
+ return null ;
+ }
+}
controller层 @ RequestMapping ( "ajaxsearch" )
+public void ajaxsearch ( HttpServletRequest request , HttpServletResponse response) throws IOException {
+ String keyword = request . getParameter ( "keyword" );
+ if ( StringUtils . isEmpty (keyword) ) {
+ return ;
+ }
+ Set < String > set = blogService . ajaxsearch (keyword);
+ Gson gson = new Gson () ;
+ response . getWriter (). write ( gson . toJson (set)); //返回的数据使用json
+}
ajax来提交请求 autocomplete.js源代码与介绍:https://github.com/xdan/autocomplete < 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 >
效果: 参考:https://www.ibm.com/developerworks/cn/java/j-lo-lucene1/
http://iamyida.iteye.com/blog/2205114
`,55)]))}const p=s(l,[["render",k],["__file","2.Lucene的使用.html.vue"]]),r=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html","title":"2.Lucene的使用","lang":"zh-CN","frontmatter":{"description":"2.Lucene的使用 首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。 Lucene的整体架构 imageimage 搜索引擎的几个重要概念: 倒排索引:将...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"2.Lucene的使用"}],["meta",{"property":"og:description","content":"2.Lucene的使用 首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。 Lucene的整体架构 imageimage 搜索引擎的几个重要概念: 倒排索引:将..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/lucenejoijfoaiwheifuwhifu.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2.Lucene的使用\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/lucenejoijfoaiwheifuwhifu.png\\",\\"https://github-images.wenzhihuai.com/images/fewfwaefawe20170903183124.png\\",\\"https://github-images.wenzhihuai.com/images/fweafwe170903175148.png\\",\\"https://github-images.wenzhihuai.com/images/fwefawfagergwerg20170903184512.png\\",\\"https://github-images.wenzhihuai.com/images/bervererfwaefewf20170903200915.png\\",\\"https://github-images.wenzhihuai.com/images/QQ%E6%88%AA%E5%9B%BE20170728102929.png\\",\\"https://github-images.wenzhihuai.com/images/QQ%E6%88%AA%E5%9B%BE20170728105628.png\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":3,"title":"Lucene的整体架构","slug":"lucene的整体架构","link":"#lucene的整体架构","children":[]},{"level":3,"title":"搜索引擎的几个重要概念:","slug":"搜索引擎的几个重要概念","link":"#搜索引擎的几个重要概念","children":[]},{"level":3,"title":"Lucene中的几个概念","slug":"lucene中的几个概念","link":"#lucene中的几个概念","children":[]},{"level":3,"title":"lucene在本网站的使用:","slug":"lucene在本网站的使用","link":"#lucene在本网站的使用","children":[]},{"level":2,"title":"一、搜索","slug":"一、搜索","link":"#一、搜索","children":[]},{"level":2,"title":"二、lucene自动补全","slug":"二、lucene自动补全","link":"#二、lucene自动补全","children":[]}],"git":{"createdTime":1579574285000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":6.82,"words":2046},"filePathRelative":"interesting/个人网站/2.Lucene的使用.md","localizedDate":"2020年1月21日","excerpt":"\\n首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。
","autoDesc":true}');export{p as comp,r as data};
diff --git a/assets/2017.html-DzgcI9cv.js b/assets/2017.html-DzgcI9cv.js
new file mode 100644
index 00000000..52f2bb24
--- /dev/null
+++ b/assets/2017.html-DzgcI9cv.js
@@ -0,0 +1 @@
+import{_ as a,c as i,d as t,o as n}from"./app-ftEjETWs.js";const p={};function r(o,e){return n(),i("div",null,e[0]||(e[0]=[t('2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。 17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?
回到学校,待了几天,那个整天给别人灌毒鸡汤的人还是不着急找工作:该有的时候总会有的啦,然后继续打游戏、那个天天喊着吃麻辣香锅的人,记忆中好像今年都没有吃上,哈哈、厕所还是那样偶尔炸一下,嗯,感觉一切都很熟悉,只是,我有了点伤感,毕竟身边又要换一群不认识的人了。考完试,终于能回广东了,一年没回了,开心不得了,更多的是,为了那个喜欢了好几年没有表白的妹纸,之前从没想过真的能每天跟一个妹纸道晚安,秒回,但是,对她,我还真做到了。1月份的广州,不热不冷,空气很清新,比北京、天津那股泥土味好多了,只是,我被拒了,男闺蜜还是男闺蜜,备胎还是备胎,那会还没想过放弃,直到...
春节期间,把自己的网站 整理了一下,看了看JVM和并发的知识,偶尔刷刷牛客网的题,觉得自己没多大问题了,跟同学出发,去深圳,我并没有一个做马化腾、马云的梦,但是我想,要做出点东西,至少,不是个平庸的人。投了几个,第一个面试,知道是培训兼外包后果断弃了,春招还没开始,再多准备准备,有时间就往深圳图书馆里跑,找个位置,静静的复习,那会,感觉自己一定能去个大公司吧,搞搞分布式、大数据之类的~
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一致性原理这种奇葩的问题。。。。。
没有环境,就自己创造,下班有时间就改改自己的网站http://www.wenzhihuai.com ,GitHub目前有154个star了,感觉也是个小作品吧,把常用的Java技术栈(RabbitMQ、MongoDB等)加了上去,虽然没啥使用场景,但是自己好好努力吧,毕竟高并发、高可用是自己的梦想。今年GitHub自己的提交次数。
决心先好好呆着,学习学习,把公司的产品业务技术专研专研,7、8月份是挺开心的,没怎么加班,虽然下班我都留在公司学习,虽然公司的产品不咋地,但是还是有可学之处的,随后,我没想到的是,公司要实行996,,,9月份至12月,每天都是改bug,开发模块,写业务,全都是增删改查,没有涉及redis、rabbitmq,就真的只有使用Hibernate、spring,而做出的东西,要使用JDK6来运行,至今都能看到sun的类。每天的状态就是累累累,我们组还不是最惨的,隔壁项目组,一周通宵两次,9月到10都是如此,国庆加班,每次经过他们组,我都觉得自己还算是幸福。很厌恶这种不把员工当人看的行为,有同事调侃,明年估计我们这些应届过来的,是不是要走掉2/3的人?疯狂加班的代价是牺牲积极性,我问过那些一周通宵两次的人,敲代码,程序员你喜欢这份工作么?不喜欢!!!有那么一两次,实在是太累了,我都感觉自己有点不行了,想离职,可是,会有公司要我么?会有公司不问那些奇葩的问题么?
双十一,花了500多买了十本书,神书啊,计算机届的圣经啊,然而至今一本都没看完,甚至是都没怎么翻,每天下班回去之后就是9点半了,烧水,洗澡,洗衣服,近11点了,躺床上,一遍看书一遍看鹌鹑直播,一小时才翻几页,996真的太累了,实在看不下书。经过这几个月的加班,感觉自己技术增长为负数,也病了几次,同学见我,都感觉我老了不少,心里不平,可是又没有什么办法。
珠江新城,一年四季都那么美,今晚应该又是万人一起倒计时了吧?已经好久没跟别人一起出去玩过了。今年貌似得了自闭症?社交全靠黄段子。想找人出门走走,然而手机已经没有那种几年的朋友,大学同学一个都不在,哈哈哈,别人说社交软件让人离得更近,我怎么发现我自己一个好朋友都没有了呢,哭笑ing。或许是自己的确不善于跟别人保持联系吧,这个要改,一定要改!!! 远看:
近看:
题外话: 有些时候,遇到不顺,感觉自己不是神,没必要忍住,就开始宣泄自己的情绪,比如疯狂打游戏,只能这样度过了吧。 今年听过最多的一句话,你好厉害,你好牛逼==我感觉也是,可惜,要被业务耽误了不少时间吧。。 《企业IT架构转型之道》是今年最好的架构图书,没有之一。
想起初中,老师让我在黑板写自己的英文作文,好像是信件,描述什么状况来这?最后夸了夸我在文章后面加的一段大概是劝别人不要悲伤要灿烂。也想起一个故事,二战以后,德国满目疮痍,他们处在这样一个凄惨的境地,还能想到在桌上摆设一些花,就一定能在废墟上重建家园。我所看到的是即使在再黑暗的状态下,要永远抱着希望。明年要更加努力的学习,而不是工作,是该挽留一些人了,多运动。说了那么多,其实,我只希望自己的运气不要再差了,再差就没法活了。人在遇到不顺的时候,往往最难过的一关便是自己。哈哈哈,只能学我那个同学给自己灌毒鸡汤了。加油加油↖(^ω^)↗
',35)]))}const h=a(p,[["render",r],["__file","2017.html.vue"]]),m=JSON.parse('{"path":"/life/2017.html","title":"2017","lang":"zh-CN","frontmatter":{"description":"2017 2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。 17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感...","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月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"http://image.wenzhihuai.com/images/20171231044153.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-26T04:53:47.000Z"}],["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\\":[\\"http://image.wenzhihuai.com/images/20171231044153.png\\",\\"http://image.wenzhihuai.com/images/20171231050705.png\\",\\"http://image.wenzhihuai.com/images/20171231073414.png\\",\\"http://image.wenzhihuai.com/images/20171231080129.png\\",\\"http://image.wenzhihuai.com/images/20171231075917.png\\",\\"http://image.wenzhihuai.com/images/20171231082716.png\\",\\"http://image.wenzhihuai.com/images/20171231082725.png\\",\\"http://image.wenzhihuai.com/images/20171231085744.png\\"],\\"dateModified\\":\\"2024-01-26T04:53:47.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1579958290000,"updatedTime":1706244827000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":11.22,"words":3366},"filePathRelative":"life/2017.md","localizedDate":"2020年1月25日","excerpt":"\\n2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。 \\n17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?
","autoDesc":true}');export{h as comp,m as data};
diff --git a/assets/2018.html-UHfvoYE6.js b/assets/2018.html-UHfvoYE6.js
new file mode 100644
index 00000000..623d7497
--- /dev/null
+++ b/assets/2018.html-UHfvoYE6.js
@@ -0,0 +1 @@
+import{_ as t,c as a,d as i,o as n}from"./app-ftEjETWs.js";const o={};function r(p,e){return n(),a("div",null,e[0]||(e[0]=[i('年底老姐结婚,跑回家去了,忙着一直没写,本来想回深圳的时候空余的时候写写,没想到一直加班,嗯,9点半下班那种,偶尔也趁着间隙的时间,一段一段的凑着吧。
想着17年12月31号写的那篇文章https://www.cnblogs.com/w1570631036/p/8158284.html ,感叹18年还算恢复了点。
其实校招过去的那家公司,真的不是很喜欢,996、技术差、产品差,实在受不了,春节前提出了离职,老大也挽留了下,以“来了个阿里的带我们重构,能学不了东西”来挽留,虽然我对技术比较痴迷,但离职去深圳的决心还是没有动摇,嗯,就这么开始了自己的裸辞过程。3月8号拿到离职,回公司的时候跟跟同事吹吹水,吃个饭,某同事还喊:“周末来公司玩玩么,我给你开门”,哈哈哈,泼出去的水,回不去了,偶尔有点伤感。 去深圳面试,第一家随手记,之前超级想去这家公司的,金融这一块,有钱,只可惜,没过,一面面试官一直夸我,我觉得稳了,二面没转过来,就这么挂了,有点不甘心吧,在这,感谢那个内推我的人吧,面经在这 ,之后就是大大小小的面试,联想、恒大、期待金融什么的,都没拿到offer,裸辞真的慌得一比,一天没工作,感觉一年没有工作没人要的样子。。。。没面试就跑去广州图书馆,复习,反思,一天一天的过着,回家就去楼下吃烧烤,打游戏,2点3点才睡觉,boss直聘、拉勾网见一个问一个,迷迷糊糊慌慌张张,那段期间真的想有点把所有书卖掉回家啃老的想法,好在最后联系了一家公司,电商、大小周,知乎上全是差评,不过评价的都不是技术的,更重要的是,岗位是中间件的,嗯,去吧。
and ... 广州拜拜,晚上人少的时候,跟妹纸去珠江新城真的很美好
入职的时候是做日志收集的,就是flume+kafka+es这一套,遇到了不少大佬,嗯,感觉挺好的,打算好好干,一个半月后不知怎么滴,被拉去做容器云了,然后就开始了天天调jenkins、gitlab这些没什么用的api,开始了增删改查的历程,很烦,研究jenkins、gitlab对于自己的技术没什么提升,又不得不做,而且大小周+加班这么做,回到家自己看java、netty、golang的书籍,可是没项目做没实践,过几个月就忘光了,有段时间真的很烦很烦,根本不想工作,天天调api,而且是jenkins、gitlab这些没什么卵用的api,至今也没找到什么办法。。。。 公司发展太快,也实在让人不知所措,一不小心部门被架空了,什么预兆都没有,被分到其他部门,然后发现这个部门领导内斗真的是,“三国争霸”吧,无奈成为炮灰,不同的领导不同的要求,安安静静敲个代码怎么这么难。。。。 去年的学习拉下了不少,文章也写的少了,总写那些入门的文章确实没有什么意思,买的书虽然没有17年的多吧,不过也不少了,也看了挺多本书的,虽然我还是不满意自己的阅读量。 这几年要开始抓准一个框架了,好好专研一下,也要开始学习一下go了,希望能参与一些github的项目,好好努力吧。
平时没事总是宅在家里打游戏,差不多持续到下半年吧,那会打游戏去楼下吃东西的时候老是觉得眼神恍惚,盯着电子产品太多了,然后就跟别人跑步去了,每周去一次人才公园,跑步健身,人才公园真的是深圳跑步最好的一个地方了,桥上总有一群摄影师,好想在深圳湾买一套房子,看了看房价,算了算了,深圳的房,真的贵的离谱。19年也要多多运动,健康第一健康第一。
拿到了深圳户口,全程只花了15天,感谢学妹and家人 买了第一台MacBook Pro,对于Java的我真心不好用 盼了好几年的老姐结婚,18年终于了解了这心事 养了只猫,在经历了好几个月的早起之后,晚上睡觉锁厨房,终于安分了,对不起了哈哈哈 想不起来还有什么要说的了,毕竟程序员,好像每天的生活都一样,就展望一下19年吧。今年,最最重要的是家里人以及身边还有所有人都健健康康的,哈哈哈。然后是安安静静的敲代码~~就酱
',18)]))}const h=t(o,[["render",r],["__file","2018.html.vue"]]),c=JSON.parse('{"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:image","content":"http://image.wenzhihuai.com/images/2019011011294921712062.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-26T04:53:47.000Z"}],["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\\":[\\"http://image.wenzhihuai.com/images/2019011011294921712062.png\\",\\"http://image.wenzhihuai.com/images/201901130418261145369442.png\\",\\"https://upyuncdn.wenzhihuai.com/201901130414532037038633.png\\",\\"https://upyuncdn.wenzhihuai.com/20190113103109865107434.png\\"],\\"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":1579957849000,"updatedTime":1706244827000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":4.35,"words":1306},"filePathRelative":"life/2018.md","localizedDate":"2020年1月25日","excerpt":"\\n年底老姐结婚,跑回家去了,忙着一直没写,本来想回深圳的时候空余的时候写写,没想到一直加班,嗯,9点半下班那种,偶尔也趁着间隙的时间,一段一段的凑着吧。
","autoDesc":true}');export{h as comp,c as data};
diff --git a/assets/2019.html-Df2iUZPh.js b/assets/2019.html-Df2iUZPh.js
new file mode 100644
index 00000000..05b32be2
--- /dev/null
+++ b/assets/2019.html-Df2iUZPh.js
@@ -0,0 +1 @@
+import{_ as t,c as a,d as i,o as n}from"./app-ftEjETWs.js";const p={};function r(h,e){return n(),a("div",null,e[0]||(e[0]=[i('2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。 19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。
从18年底开始吧,大概就知道领导对容器云这么快的完全架构设计错误,就是一个完完全全错误的产品,其他人也觉得有点很有问题,但老板就是固执不听,结果一个跑路,一个被压得懒得反抗,然后我一个人跟老板和项目经理怼了前前后后半年,真是惨啊,还要被骂,各种拉到小黑屋里批斗,一直在对他们强调:没有这么做的!!!然后被以年轻人,不懂事,不要抱怨,长大了以后就领会了怼回来,当时气得真是无语。。。。。自己调研的阿里云、腾讯云、青云,还有其他小公司的容器,发现真的只有我们这么设计,完全错误的方向,,,,直到老板走了之后,才开始决定重构,走上正轨。
之后有了点起色,然后开始着重强调了DevOps的重要性,期初也没人理解,还被骂天天研究技术不干活。。。这东西没技术,但是真的是公司十分需要的公司好么!!可惜公司对这个产品很失望,也不给人,期间还说要暂停项目,唉,这么大的项目就给几个人怎么做,谁都不乐意,就这么过的很憋屈吧,开始了维护的日子。。。
工作上,蛮多人对我挺好的,领导,同事,不过有时候憋屈的时候还是有了点情绪化,有时候有点悲伤的想法,浮躁、暴躁,出去面试了几次,感觉不是自己能力不好,而是市场上的真的需要3+年以上的。。。。不过感觉自己能在这里憋屈的过了这么久,也是很佩服自己的,哈哈,用同事的话来说就是:当做游戏里的练级,锻炼自己哈哈哈
项目的方向错误,导致自己写的代码都是很简单的增删改查,没有技术含量的那种,也最终导致自己浪费了不少时间,上半年算是很气愤吧,不想就这么浪费掉这些时间,虽然期间看了各种各样的东西,比如Netty、Go、操作系统什么的,最终发现,如果不在项目中使用的话,真的会忘,而且很快就忘掉,最后的还是决定学习项目相关度比较大的东西了,比如Go,如果项目不是很大,小项目的话,就用Go来写,这么做感觉提升还是挺大的。 过去一年往南山图书馆借了不少书,省了不少钱,虽然没怎么看,但我至少有个奋斗的心啊,哈哈哈哈哈哈哈哈,文章写得少了,因为感觉写不出好东西,总是入门的那种,不深,不值得学习,想想到时候把别人给坑了,也不好意思。 操作系统感觉还是要好好学学了,加油
Kubernetes就是未来的方向,有时候翻开源码看看,又不敢往下面看了,对底层不熟吧,今年要多多研究下Kubernetes的源码了,至于Spring那一套,也不知道该不该放弃,或者都学习一下?云原生就是趋势。
吵架了,没心思写
过去一年还是把运动算是坚持了下来,每个月必去深圳湾跑一次。还是没怎么睡好,工作感情上都有点不顺,加上自己本身就难以入睡,有时候躺床上就是怎么也睡不着,还长了痘痘,要跑去医院那种,可怕,老了,还是要早点睡觉,多走走多运动,好久没打羽毛球了,自己也不想有空的时候只会打游戏,今年继续加油,多运动吧。
还爬了两次南山
看了周围蛮多同事去了腾讯阿里,有点心动,好想去csig,没到3年真的让人很抓狂。 过去一年过的蛮憋屈的,特别是工作不顺,加上跟女朋友吵架,心态爆炸。。。
每年这个时候,都不敢有太大的期望了,祝大家都健健康康的,工作顺利!!
当然,如果有可能的话,我想去CSIG
',23)]))}const c=t(p,[["render",r],["__file","2019.html.vue"]]),l=JSON.parse('{"path":"/life/2019.html","title":"2019","lang":"zh-CN","frontmatter":{"description":"2019 2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。 19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了...","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年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://upyuncdn.wenzhihuai.com/202001010544131765044792.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-26T04:53:47.000Z"}],["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\\":[\\"https://upyuncdn.wenzhihuai.com/202001010544131765044792.png\\",\\"https://upyuncdn.wenzhihuai.com/202001010516141216483720.png\\",\\"http://image.wenzhihuai.com/images/20200101052650730023760.png\\",\\"http://image.wenzhihuai.com/images/202001010535231861948911.png\\"],\\"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":1579958290000,"updatedTime":1706244827000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":4.43,"words":1329},"filePathRelative":"life/2019.md","localizedDate":"2020年1月25日","excerpt":"\\n2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。 \\n19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。
","autoDesc":true}');export{c as comp,l as data};
diff --git a/assets/2024-07-24.html-9GUkpnJj.js b/assets/2024-07-24.html-9GUkpnJj.js
new file mode 100644
index 00000000..66b78d95
--- /dev/null
+++ b/assets/2024-07-24.html-9GUkpnJj.js
@@ -0,0 +1 @@
+import{_ as t,c as a,d as o,o as i}from"./app-ftEjETWs.js";const r={};function c(p,e){return i(),a("div",null,e[0]||(e[0]=[o('新买了台air m3,午夜色的,心心念念了好久
读写速度
和以前的m1 pro对比了下,感觉差了半截,使用上没有区别吧
非果粉,但好多苹果设备
',9)]))}const n=t(r,[["render",c],["__file","2024-07-24.html.vue"]]),s=JSON.parse('{"path":"/about-the-author/personal-life/2024-07-24.html","title":"2024-07-24","lang":"zh-CN","frontmatter":{"description":"2024-07-24 新买了台air m3,午夜色的,心心念念了好久 IMG_20240723_235443 读写速度 c6c117ff1f5f6371b3ab682621369c1f 和以前的m1 pro对比了下,感觉差了半截,使用上没有区别吧 096e891a0278263d0c790e74f32ef911_720 非果粉,但好多苹果设备 0742...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/about-the-author/personal-life/2024-07-24.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"2024-07-24"}],["meta",{"property":"og:description","content":"2024-07-24 新买了台air m3,午夜色的,心心念念了好久 IMG_20240723_235443 读写速度 c6c117ff1f5f6371b3ab682621369c1f 和以前的m1 pro对比了下,感觉差了半截,使用上没有区别吧 096e891a0278263d0c790e74f32ef911_720 非果粉,但好多苹果设备 0742..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-07-24T15:52:12.000Z"}],["meta",{"property":"article:modified_time","content":"2024-07-24T15:52:12.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2024-07-24\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-07-24T15:52:12.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1721836332000,"updatedTime":1721836332000,"contributors":[{"name":"zhihuaiwen","email":"1570631036@qq.com","commits":1}]},"readingTime":{"minutes":0.34,"words":102},"filePathRelative":"about-the-author/personal-life/2024-07-24.md","localizedDate":"2024年7月24日","excerpt":"\\n新买了台air m3,午夜色的,心心念念了好久
\\n ","autoDesc":true}');export{n as comp,s as data};
diff --git "a/assets/2024-11-09\344\270\212\346\265\267\350\277\252\346\226\257\345\260\274.html-CU80Bk9D.js" "b/assets/2024-11-09\344\270\212\346\265\267\350\277\252\346\226\257\345\260\274.html-CU80Bk9D.js"
new file mode 100644
index 00000000..44ffcc45
--- /dev/null
+++ "b/assets/2024-11-09\344\270\212\346\265\267\350\277\252\346\226\257\345\260\274.html-CU80Bk9D.js"
@@ -0,0 +1 @@
+import{_ as a,c as r,a as e,b as i,o as n,r as c}from"./app-ftEjETWs.js";const p={};function l(m,t){const o=c("BiliBili");return n(),r("div",null,[t[0]||(t[0]=e("h1",{id:"_2024-11-09上海迪斯尼",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2024-11-09上海迪斯尼"},[e("span",null,"2024-11-09上海迪斯尼")])],-1)),i(o,{bvid:"BV1LSmrYqEDw"})])}const h=a(p,[["render",l],["__file","2024-11-09上海迪斯尼.html.vue"]]),d=JSON.parse('{"path":"/about-the-author/personal-life/2024-11-09%E4%B8%8A%E6%B5%B7%E8%BF%AA%E6%96%AF%E5%B0%BC.html","title":"2024-11-09上海迪斯尼","lang":"zh-CN","frontmatter":{"description":"2024-11-09上海迪斯尼","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/about-the-author/personal-life/2024-11-09%E4%B8%8A%E6%B5%B7%E8%BF%AA%E6%96%AF%E5%B0%BC.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"2024-11-09上海迪斯尼"}],["meta",{"property":"og:description","content":"2024-11-09上海迪斯尼"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-11-11T16:10:11.000Z"}],["meta",{"property":"article:modified_time","content":"2024-11-11T16:10:11.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"2024-11-09上海迪斯尼\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-11-11T16:10:11.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1731254136000,"updatedTime":1731341411000,"contributors":[{"name":"zhihuaiwen","email":"1570631036@qq.com","commits":2}]},"readingTime":{"minutes":0.04,"words":12},"filePathRelative":"about-the-author/personal-life/2024-11-09上海迪斯尼.md","localizedDate":"2024年11月10日","excerpt":"\\n","autoDesc":true}');export{h as comp,d as data};
diff --git "a/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-NSgzVWXM.js" "b/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-NSgzVWXM.js"
new file mode 100644
index 00000000..09a2fb62
--- /dev/null
+++ "b/assets/3.\345\256\232\346\227\266\344\273\273\345\212\241.html-NSgzVWXM.js"
@@ -0,0 +1,61 @@
+import{_ as s,c as a,d as n,o as t}from"./app-ftEjETWs.js";const l={};function e(h,i){return t(),a("div",null,i[0]||(i[0]=[n(`先看一下Quartz的架构图:
强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求; 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式; 分布式和集群能力。 JobDetail:需实现该接口定义的人物,其中JobExecutionContext提供了上下文的各种信息。 JobDetail:QUartz的执行任务的类,通过newInstance的反射机制实例化Job。 Trigger: Job的时间触发规则。主要有SimpleTriggerImpl和CronTriggerImpl两个实现类。 Calendar:org.quartz.Calendar和java.util.Calendar不同,它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一个日历时间点,无特殊说明后面的Calendar即指org.quartz.Calendar)。 Scheduler:由上图可以看出,Scheduler是Quartz独立运行的容器。其中,Trigger和JobDetail可以注册到Scheduler中。 ThreadPool:Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。 properties file官网 中表明:quartz中使用了quartz.properties来对quartz进行配置,并保留在其jar包中,如果没有定义则默认使用改文件。 hello world!代码在这 本网站中使用quartz来对数据库进行备份,与Spring结合 (1)导入spring的拓展包,其协助spring集成第三方库:邮件服务、定时任务、缓存等。。。 < dependency >
+ < groupId >org.springframework</ groupId >
+ < artifactId >spring-context-support</ artifactId >
+ < version >4.2.6.RELEASE</ version >
+</ dependency >
(2)导入quartz包
< dependency >
+ < groupId >org.quartz-scheduler</ groupId >
+ < artifactId >quartz</ artifactId >
+ < version >2.3.0</ version >
+</ dependency >
(3)mysql远程备份 使用命令行工具仅仅需要一行:
mysqldump -u [username] -p[password] -h [hostip] database > file
但是java不能直接执行linux的命令,仍旧需要依赖第三方库ganymed
< dependency >
+ < groupId >ch.ethz.ganymed</ groupId >
+ < artifactId >ganymed-ssh2</ artifactId >
+ < version >262</ version >
+</ dependency >
完整代码如下:
@ Component ( "mysqlService" ) //在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 >
(5)java完整文件在这
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.http://blog.csdn.net/oarsman/article/details/52801877 2.http://stackoverflow.com/questions/31199888/spring-task-scheduler-no-qualifying-bean-of-type-org-springframework-scheduli Spring的定时任务调度器会尝试获取一个注册过的 task scheduler来做任务调度,它会尝试通过BeanFactory.getBean的方法来获取一个注册过的scheduler bean,获取的步骤如下:
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
`,36)]))}const p=s(l,[["render",e],["__file","3.定时任务.html.vue"]]),r=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html","title":"3.定时任务","lang":"zh-CN","frontmatter":{"description":"3.定时任务 先看一下Quartz的架构图: 一.特点: 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求; 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式; 分布式和集群能力。 二.主要组成部分 JobDetail:需实现该接口定义的人物,其中JobExecutionContext提供了上下文的各种...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"3.定时任务"}],["meta",{"property":"og:description","content":"3.定时任务 先看一下Quartz的架构图: 一.特点: 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求; 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式; 分布式和集群能力。 二.主要组成部分 JobDetail:需实现该接口定义的人物,其中JobExecutionContext提供了上下文的各种..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/11627468_1438829844Zbz8.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"3.定时任务\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/11627468_1438829844Zbz8.png\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.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":1579574285000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":3.55,"words":1064},"filePathRelative":"interesting/个人网站/3.定时任务.md","localizedDate":"2020年1月21日","excerpt":"\\n先看一下Quartz的架构图:
\\n ","autoDesc":true}');export{p as comp,r as data};
diff --git "a/assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-BH3nB-v9.js" "b/assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-BH3nB-v9.js"
new file mode 100644
index 00000000..eeb64c4d
--- /dev/null
+++ "b/assets/4.\346\227\245\345\277\227\347\263\273\347\273\237.html-BH3nB-v9.js"
@@ -0,0 +1,206 @@
+import{_ as s,c as a,d as n,o as t}from"./app-ftEjETWs.js";const h={};function l(e,i){return t(),a("div",null,i[0]||(i[0]=[n(`欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
建立网站少不了日志系统,用来查看网站的访问次数、停留时间、抓取量、目录抓取统计、页面抓取统计等,其中,最常用的方法还是使用ELK,但是,本网站的服务器配置实在太低了(1GHZ、2G内存),压根就跑不起ELK,所以只能寻求其他方式,目前最常用的有百度统计 和友盟 ,这里,本人使用的是百度统计,提供了API给开发者使用,能够将自己所需要的图表移植到自己的网站上。日志是网站及其重要的文件,通过对日志进行统计、分析、综合,就能有效地掌握网站运行状况,发现和排除错误原因,了解客户访问分布等,更好的加强系统的维护和管理。下面是我的百度统计的概览页面:
企业级的网站日志不能公开,但是我的是个人网站,用来跟大家一起学习的,所以,需要将百度的统计页面展示出来,但是,百度并不提供日志的图像,只提供API给开发者调用,而且还限制访问次数,一天不能超过2000次,这个对于实时统计来说,确实不够,所以只能展示前几天的访问统计。这里的日志系统分为三个步骤:1.API获取数据;2.存储数据;3.展示数据。页面效果如下,也可以点开我的网站的日志系统 :
百度统计提供了Tongji API的Java和Python版本,这两个版本及其复杂,可用性极低,所以,本人用Python写了个及其简单的通用版本,整体只有28行,代码在这,https://github.com/Zephery/baidutongji 。下面是具体过程
先在百度统计 中注册登录之后,进入管理页面,新增网站,然后在代码管理中获取安装代码,大部分人的代码都是类似的,除了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,然后开始使用三个参数来获取数据。
官网的API 详细的记录了接口的参数以及解释, 链接:https://api.baidu.com/json/tongji/v1/ReportService/getData ,详细的官方报告请访问官网TongjiApi 所需参数(必须):
参数名称 参数类型 描述 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" )
至此,python获取百度统计的过程基本就没了,没错,就是那么简简单单的几行,完整代码见https://github.com/Zephery/baidutongji/blob/master/baidu.py ,但是,想要实现获取各种数据,仍需要做很多工作。
(1)需要使用其他参数怎么办
python中提供了个可变参数来解决这一烦恼,详细请看http://www.jianshu.com/p/98f7e34845b5 ,可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple,而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
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 ]))
下面是基本的使用代码,完整的使用代码就不贴了,有兴趣可以去我的github上看看,完整代码 ,希望能给个star哈哈哈,感谢
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)
在将数据存进redis中之后,我们需要在博客中使用这些数据来制作图表。在newblog 中使用方式也很简单,大概就是使用jedis读取数据,然后使用echarts或者highcharts展示。其中折线图以及线型图我都使用了highcharts,确实比echarts好看的多,但是地域图还是选择了echarts,毕竟中国的产品还是对中国的支持较好。 (1)PV、UV折线图 以图表PV、UV为例,由于存储进redis的是一个数组,所以,可以直接从redis中读取然后放到一个attribute里即可:
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': '江苏'}]
地域图目前支持最好的还是百度的echarts,使用方法见echarts的官网吧,这里不再阐述,展示地域图 的时候需要获取下载两个文件,china.js (其提供了js和json,这里使用的js),echarts.js 。 部分代码:
<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>
结果如下:
网上关于日志系统的几乎都是ELK,对于小网站的,隐私不是很重要的还是可以用用百度统计的,这套系统也折磨了我挺久的,特别是它那反人类的返回数据。期初本来是想使用百度统计的,后来考虑了一下ELK,尝试之后发现,服务器配置跑不起来,还是安安稳稳的使用了百度统计,于此做成了这个系统,美观度还是不高,颜色需要优化一下。最后,希望能在GitHub上给我个star吧。 日志系统地址:http://www.wenzhihuai.com/log.html 个人网站网址:http://www.wenzhihuai.com 个人网站代码地址:https://github.com/Zephery/newblog 百度统计python代码地址:https://github.com/Zephery/baidutongji 万分感谢
`,64)]))}const p=s(h,[["render",l],["__file","4.日志系统.html.vue"]]),r=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html","title":"4.日志系统.md","lang":"zh-CN","frontmatter":{"description":"4.日志系统.md 欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。 建立网站少不了日志系统,用来查看网站的访问次数、停留时间、抓取量、目录抓取统计、页面抓取统计等,其中,最常用的方法还是使...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"4.日志系统.md"}],["meta",{"property":"og:description","content":"4.日志系统.md 欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。 建立网站少不了日志系统,用来查看网站的访问次数、停留时间、抓取量、目录抓取统计、页面抓取统计等,其中,最常用的方法还是使..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/300.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"4.日志系统.md\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/300.png\\",\\"https://github-images.wenzhihuai.com/images/20170918090524.png\\",\\"https://github-images.wenzhihuai.com/images/20170918090534.png\\",\\"https://github-images.wenzhihuai.com/images/20170918090546.png\\",\\"https://github-images.wenzhihuai.com/images/20170919090557.png\\",\\"https://github-images.wenzhihuai.com/images/20170919091911.png\\",\\"https://github-images.wenzhihuai.com/images/20170919092505.png\\",\\"https://github-images.wenzhihuai.com/images/20170919012925.png\\",\\"https://github-images.wenzhihuai.com/images/echartsfawe.png\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"1.网站代码安装","slug":"_1-网站代码安装","link":"#_1-网站代码安装","children":[]},{"level":2,"title":"2.根据API获取数据","slug":"_2-根据api获取数据","link":"#_2-根据api获取数据","children":[]},{"level":2,"title":"3.构建请求","slug":"_3-构建请求","link":"#_3-构建请求","children":[]},{"level":2,"title":"4.实际运用","slug":"_4-实际运用","link":"#_4-实际运用","children":[]},{"level":2,"title":"5.基本代码","slug":"_5-基本代码","link":"#_5-基本代码","children":[]},{"level":2,"title":"6.展示数据","slug":"_6-展示数据","link":"#_6-展示数据","children":[]}],"git":{"createdTime":1579574285000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":9.64,"words":2891},"filePathRelative":"interesting/个人网站/4.日志系统.md","localizedDate":"2020年1月21日","excerpt":"\\n欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
","autoDesc":true}');export{p as comp,r as data};
diff --git a/assets/404.html-BMHKR2ag.js b/assets/404.html-BMHKR2ag.js
new file mode 100644
index 00000000..b9e45dea
--- /dev/null
+++ b/assets/404.html-BMHKR2ag.js
@@ -0,0 +1 @@
+import{_ as e,c as o,a as n,o as r}from"./app-ftEjETWs.js";const a={};function p(c,t){return r(),o("div",null,t[0]||(t[0]=[n("p",null,"404 Not Found",-1)]))}const i=e(a,[["render",p],["__file","404.html.vue"]]),l=JSON.parse('{"path":"/404.html","title":"","lang":"zh-CN","frontmatter":{"layout":"NotFound","description":"404 Not Found","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/404.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:description","content":"404 Not Found"}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"zh-CN"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"\\",\\"description\\":\\"404 Not Found\\"}"]]},"headers":[],"git":{},"readingTime":{"minutes":0.01,"words":3},"filePathRelative":null,"excerpt":"404 Not Found
\\n","autoDesc":true}');export{i as comp,l as data};
diff --git "a/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-BN5IQG4o.js" "b/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-BN5IQG4o.js"
new file mode 100644
index 00000000..1aa6f734
--- /dev/null
+++ "b/assets/5.\345\260\217\351\233\206\347\276\244\351\203\250\347\275\262.html-BN5IQG4o.js"
@@ -0,0 +1,96 @@
+import{_ as s,c as a,d as n,o as e}from"./app-ftEjETWs.js";const t={};function l(h,i){return e(),a("div",null,i[0]||(i[0]=[n(`欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com ,个人网站代码地址:https://github.com/Zephery/newblog 。 洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。
一般情况下,当单实例无法支撑起用户的请求时,就需要就行扩容,部署的服务器可以分机房、分地域。而分地域会导致请求分配到太远的地区,比如:深圳的用户却访问到了北京的节点,然后还得从北京返回处理之后的数据,光是来回就至少得30ms。这部分可以通过智能DNS(就近访问)解决。而分机房,需要将请求合理的分配到不同的服务器,这部分就是我们所需要处理的。 通常,负载均衡分为硬件和软件两种,硬件层的比较牛逼,将4-7层负载均衡功能做到一个硬件里面,如F5,梭子鱼等。目前主流的软件负载均衡分为四层和七层,LVS属于四层负载均衡,工作在tcp/ip协议栈上,通过修改网络包的ip地址和端口来转发, 由于效率比七层高,一般放在架构的前端。七层的负载均衡有nginx, haproxy, apache等,虽然nginx自1.9.0版本后也开始支持四层的负载均衡,但是暂不讨论(我木有硬件条件)。下图来自张开涛 的《亿级流量网站架构核心技术》
本站并没有那么多的服务器,目前只有两台,搭建不了那么大型的架构,就简陋的用两台服务器来模拟一下负载均衡的搭建。下图是本站的简单架构:
其中服务器A(119.23.46.71)为深圳节点,服务器B(47.95.10.139)为北京节点,搭建Nginx之后流量是这么走的:user->A->B-A->user或者user->A->user,第一条中A将请求转发给B,然后B返回的是其运行结果的静态资源。因为这里仅仅是用来学习,所以请不要考虑因为地域导致延时的问题。。。。下面是过程。
可以选择tar.gz、yum、rpm安装等,这里,由于编译、nginx配置比较复杂,要是没有把握还是使用rpm来安装吧,比较简单。从https://pkgs.org/download/nginx 可以找到最新的rpm包,然后rpm -ivh 文件,然后在命令行中输入nginx即可启动,可以使用netstat检查一下端口。
启动后页面如下:
记一下常用命令
启动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
Nginx常用的算法有: (1)round-robin:轮询,nginx默认的算法,从词语上可以看出,轮流访问服务器,也可以通过weight来控制访问次数。 (2)ip_hash:根据访客的ip,一个ip地址对应一个服务器。 (3)hash算法:hash算法常用的方式有根据uri、动态指定的consistent_key两种。 使用hash算法的缺点是当添加服务器的时候,只有少部分的uri能够被重新分配到新的服务器。这里,本站使用的是hash uri的算法,将不同的uri分配到不同的服务器,但是由于是不同的服务器,tomcat中的session是不一致,解决办法是tomcat session 的共享。额。。。可惜本站目前没有什么能够涉及到登陆什么session的问题。
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;
+ ...
配置完上流服务器之后,需要配置Http的代理,将请求的端口转发到proxy_pass设定的上流服务器,即当我们访问http://wwww.wenzhihuai.com的时候 ,请求会被转发到backend中配置的服务器,此处为http://47.95.10.139:8080或者http://119.23.46.71:8080 。但是,仔细注意之后,我们会发现,tomcat中的访问日志ip来源都是127.0.0.1,相当于本地访问自己的资源。由于后台中有处理ip的代码,对客户端的ip、访问uri等记录下来,所以需要设置nginx来获取用户的实际ip,参考nginx 配置 。参考文中的一句话:经过反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址”。nginx是可以获得用户的真实ip的,也就是说nginx使用$remote_addr变量时获得的是用户的真实ip,如果我们想要在web端获得用户的真实ip,就必须在nginx这里作一个赋值操作,如下:
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;
X-Forwarded-For:squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,这个不是默认有的,其经过代理转发之后,格式为client1, proxy1, proxy2,如果想通过这个变量来获取用户的ip,那么需要和$proxy_add_x_forwarded_for一起使用。 $proxy_add_x_forwarded_for:现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了“用户的真实ip,第一台nginx的ip”。
HTTPS (全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。一般情况下,能通过服务器的ssh来生成ssl证书,但是如果使用是自己的,一般浏览器(谷歌、360等)都会报证书不安全的错误,正常用户都不敢访问吧==,所以现在使用的是腾讯跟别的机构颁发的:
首先需要下载证书,放在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;
+}
分布式情况下难免会要解决session共享的问题,目前推荐的方法基本上都是使用redis,网上查找的方法目前流行的有下面四种,参考自tomcat 集群中 session 共 : 1.使用 filter 方法存储。(推荐,因为它的服务器使用范围比较多,不仅限于tomcat ,而且实现的原理比较简单容易控制。) 2.使用 tomcat sessionmanager 方法存储。(直接配置即可) 3.使用 terracotta 服务器共享。(不知道,不了解) 4.使用spring-session。(spring的一个小项目,其原理也和第一种基本一致)
本站使用spring-session,毕竟是spring下的子项目,学习下还是挺好的。参考Spring-Session官网 。官方文档提供了spring-boot、spring等例子,可以参考参考。目前最新版本是2.0.0,不同版本使用方式不同,建议看官网的文档吧。
首先,添加相关依赖
< 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查看结果:
访问http://www.wenzhihuai.com tail -f localhost_access_log.2017-11-05.txt查看日志,然后清空一下当前记录
访问技术杂谈页面,此时nginx将请求转发到119.23.46.71服务器,session为28424f91-5bc5-4bba-99ec-f725401d7318。
点击生活笔记页面,转发到的服务器为47.95.10.139,session为28424f91-5bc5-4bba-99ec-f725401d7318,与上面相同。session已保持一致。
值得注意的是:同一个浏览器,在没有关闭的情况下,即使通过域名访问和ip访问得到的session是不同的。 欢迎访问我的个人网站O(∩_∩)O哈哈~希望能给个star 个人网站网址:http://www.wenzhihuai.com 个人网站代码地址:https://github.com/Zephery/newblog
`,56)]))}const r=s(t,[["render",l],["__file","5.小集群部署.html.vue"]]),k=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html","title":"5.小集群部署.md","lang":"zh-CN","frontmatter":{"description":"5.小集群部署.md 欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com,个人网站代码地址:https://github.com/Zephery/newblog。 洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"5.小集群部署.md"}],["meta",{"property":"og:description","content":"5.小集群部署.md 欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com,个人网站代码地址:https://github.com/Zephery/newblog。 洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/20171018044732.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"5.小集群部署.md\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/20171018044732.png\\",\\"https://github-images.wenzhihuai.com/images/20171018051437.png\\",\\"https://github-images.wenzhihuai.com/images/20171103062512.png\\",\\"https://github-images.wenzhihuai.com/images/20171103063022.png\\",\\"https://github-images.wenzhihuai.com/images/20171105024159.png\\",\\"https://github-images.wenzhihuai.com/images/20171105045003.png\\",\\"https://github-images.wenzhihuai.com/images/20171105050714.png\\",\\"https://github-images.wenzhihuai.com/images/20171105050757.png\\",\\"https://github-images.wenzhihuai.com/images/20171105050849.png\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"1.1 Nginx的安装","slug":"_1-1-nginx的安装","link":"#_1-1-nginx的安装","children":[]},{"level":2,"title":"1.2 Nginx的配置","slug":"_1-2-nginx的配置","link":"#_1-2-nginx的配置","children":[]},{"level":2,"title":"测试:","slug":"测试","link":"#测试","children":[]}],"git":{"createdTime":1579574285000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":9.5,"words":2849},"filePathRelative":"interesting/个人网站/5.小集群部署.md","localizedDate":"2020年1月21日","excerpt":"\\n欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com ,个人网站代码地址:https://github.com/Zephery/newblog 。 \\n洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。
","autoDesc":true}');export{r as comp,k as data};
diff --git "a/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-Ca5VIWc1.js" "b/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-Ca5VIWc1.js"
new file mode 100644
index 00000000..b070755c
--- /dev/null
+++ "b/assets/6.\346\225\260\346\215\256\345\272\223\345\244\207\344\273\275.html-Ca5VIWc1.js"
@@ -0,0 +1,61 @@
+import{_ as i,c as a,d as n,o as e}from"./app-ftEjETWs.js";const l={};function t(p,s){return e(),a("div",null,s[0]||(s[0]=[n(`先来回顾一下上一篇的小集群架构,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流)
其中,配置过程如下:https://github.com/alibaba/canal ,可以搭配Zookeeper使用。在ZKUI中能够查看到节点:
一般情况下,还要配合阿里的另一个开源产品使用otter ,相关文档还是找找GitHub吧,个人搭建完了之后,用起来还是不如直接使用mysql的主主复制,而且异地机房同步这种大企业才有的业务。
公司又要996了,实在是忙不过来,感觉自己写的还是急躁了点,困==
`,38)]))}const h=i(l,[["render",t],["__file","6.数据库备份.html.vue"]]),d=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html","title":"6.数据库备份","lang":"zh-CN","frontmatter":{"description":"6.数据库备份 先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地: 由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下: 果然,...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"6.数据库备份"}],["meta",{"property":"og:description","content":"6.数据库备份 先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地: 由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下: 果然,..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/20171018051437-20240126113709561.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"6.数据库备份\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/20171018051437-20240126113709561.png\\",\\"https://github-images.wenzhihuai.com/images/20171118033130.png\\",\\"https://github-images.wenzhihuai.com/images/20171118034129.png\\",\\"https://github-images.wenzhihuai.com/images/20171118035150.png\\",\\"https://github-images.wenzhihuai.com/images/20171118040843.png\\",\\"https://github-images.wenzhihuai.com/images/20171118050128.png\\",\\"https://github-images.wenzhihuai.com/images/20171118051031.png\\",\\"https://github-images.wenzhihuai.com/images/20171120094405.png\\",\\"https://github-images.wenzhihuai.com/images/20171120100237.png\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":3,"title":"2.1 创建所用的复制账号","slug":"_2-1-创建所用的复制账号","link":"#_2-1-创建所用的复制账号","children":[]},{"level":3,"title":"2.2 配置master","slug":"_2-2-配置master","link":"#_2-2-配置master","children":[]},{"level":3,"title":"2.3 配置slave","slug":"_2-3-配置slave","link":"#_2-3-配置slave","children":[]}],"git":{"createdTime":1579574285000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":5.77,"words":1732},"filePathRelative":"interesting/个人网站/6.数据库备份.md","localizedDate":"2020年1月21日","excerpt":"\\n先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地:
","autoDesc":true}');export{h as comp,d as data};
diff --git "a/assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-Br7NfWE4.js" "b/assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-Br7NfWE4.js"
new file mode 100644
index 00000000..7d7c0fbf
--- /dev/null
+++ "b/assets/7.\351\202\243\344\272\233\347\211\233\351\200\274\347\232\204\346\217\222\344\273\266.html-Br7NfWE4.js"
@@ -0,0 +1,13 @@
+import{_ as e,c as a,d as s,o as t}from"./app-ftEjETWs.js";const n={};function r(h,i){return t(),a("div",null,i[0]||(i[0]=[s(`欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。 建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Java的程序员,前端的东西一碰脑子就有“我又不是前端,浪费时间在这合适么?”这种想法,捣鼓来捣鼓去,做出的东西实在是没法看,我就觉得,如果自己的“产品”连自己都看不下去了,那还好意思给别人看?特别是留言板那块,初版的页面简直low的要死。所以,还是踏踏实实的“站在巨人的肩膀上”吧,改用别人的插件。但不要纯粹的使用别人的博客模板了,如hexo,wordpress这些,就算是自己拼凑过来的也比这些强。下面是本博客中所用到的插件,给大家介绍介绍,共同学习学习。 本站主要用到的插件有: 1.wowslider 2.畅言3.Editor.md 4.highchart、echart 5.百度分享 6.waterfall.js 7.心知天气 8.标签云
可能是我这网站中最炫的东西了,图片能够自动像幻灯片一样自动滚动,让网站的首页一看起来就高大上,简直就是建站必备的东西,而且安装也及其简单,有兴趣可以点击官网 看看。GitHub里也开放了源代码 。安装过程:自己选择“幻灯片”切换效果,保存为html就行了,WORDPREESS中好像有集成这个插件的,做的还更好。感兴趣可以点击我的博客首页 看一看。
不过还有个值得注意的问题,就是wowslider里面带有一个googleapis的服务,即https://fonts.googleapis.com/css?family=Arimo&subset=latin,cyrillic,latin-ext,由于一般用户不能访问谷歌,会导致网页加载速度及其缓慢,所以,去掉为妙
作为社交评论的工具,虽然说表示还是想念以前的多说,但是畅言现在做得还是好了,有评论审核,评论导出导入等功能,如果浏览量大的话,还能提供广告服务,让站长也能拿到一丢丢的广告费。本博客中使用了畅言的基本评论、获取某篇文章评论数的功能。可以到我这里留言 哈
一款能将markdown解析为html的插件,国人的作品,博客的文章编辑器一开始想使用的是markdown,想法是:写文章、保存数据库都是markdown格式的,保存在数据库中,读取时有需要解析markdown,这个过程是有点耗时的,但是相比把html式的网页保存在数据库中友好点吧,因为如果一篇文章比较长的话,转成html的格式,光是大小估计也得超过几十kb?所以,还是本人选择的是一切都用源markdown。editor.md ,是一款开源的、可嵌入的 Markdown 在线编辑器(组件),基于 CodeMirror、jQuery 和 Marked 构建。页面看起来还是美观的,相比WORDPRESS的那些牛逼插件还差那么一点点,不过从普通人的眼光来看,应该是可以的了。此处,我用它作为解析网页的利器,还有就是后台编辑也是用的这个。
代码样式,这一点是不如WORDPRESS的插件了,不过已经可以了。
目前最常用的是highcharts跟echart,目前个人博客中的日志系统主要还是采用了highcharts,主要还是颜色什么的格调比较相符吧,其次是因为对echarts印象不太友好,比如下面做这张,打开网页后,缩小浏览器,百度的地域图却不能自适应,出现了越界,而highcharts的全部都能自适应调整。想起有次面试,我说我用的highcharts,面试官一脸嫌弃。。。(网上这么多人鄙视百度是假的?)
不过地图确确实实是echarts的优势,毕竟还是自家的东西了解自家,不过前段时间去看了看echarts的官网,已经不提供下载了。如果有需要,还是去csdn上搜索吧,或者替换为highmap。
作为一个以博客为主的网站,免不了使用一些社会化分享的工具,目前主要是jiathis 和百度分享,这两者的ui都是相似的(丑爆了)。凭我个人的感觉,jiathis加载实在是太过于缓慢,这点是无法让人忍受的,只好投靠百度。百度分享类似于jiathis,安装也很简单,具体见官网http://share.baidu.com/code/advance#tools 。一直点点点,配置完之后,就是下图这种,丑爆了是不是?
好在对它的美观改变不是很难,此处参考了别人的UI设计,原作者我忘记怎么联系他了。其原理主要是使用图片来替换掉原本的东西。完整的源码可以点击此处 。
#share a {
+ width: 34 px ;
+ height: 34 px ;
+ padding: 0 ;
+ margin: 6 px ;
+ border-radius: 25 px ;
+ transition: all .4 s ;
+}
+/*主要的是替换掉backgound的背景图片*/
+#share a .bds_qzone {
+ background: url ( http://image.wenzhihuai.com/t_QQZone.png ) no-repeat ;
+ background-size: 34 px 34 px ;
+}
改完之后的效果。
有段时间,瀑布流特别流行?还有段时间,瀑布流开始遭到各种抵制。。。看看知乎的人怎么说 ,大部分人不喜欢的原因是让人觉得视觉疲劳,不过瀑布流最大的好处还是有的:提高发现好图的效率以及图片列表页极强的视觉感染力。没错,我还是想把自己的网站弄得铉一些==,所以采用了瀑布流(不过效果不是很好,某些浏览器甚至加载出错),这个大bug有时间再改,毕竟花了很多时间做的这个,效果确实不咋地。目前主要的瀑布流有waterfall.js 和masory.js 。这一块目前还不是很完善,希望能得到各位大佬的指点。
此类咨询服务还是网上还是挺多的,这一块不知道是不是所谓的“画蛇添足”这部分,主要是我觉得网站右边这部分老是少了点什么,所以加上了天气插件。目前常用的天气插件有中国天气网 ,心知天气 等。安装方式见各自的官网,这里不再阐述,我使用的是心知天气。注意:心知天气限制流量的,一个小时内只能使用400次,如果超出了会失效,当然也可以付费使用。
标签云,弄得好的话应该说是一个网站的点缀。现在好像比较流行3D的标签云?像下面这种。
从个人的网站风格来看,比较适应PHP形式的,有点颜色而又不绚丽的即可,之前用的跟分类的一样的样式,即双纵列的样式,美观度还行,虽然老是感觉有点怪怪的,如果某个标签的字数过长怎么办,岂不是要顶出div了。所以还是选择换另一种风格,最终偶然一次找到了下面这种,能够自适应宽度,颜色虽然鲜艳了点(以后有空再调一下吧),源码见style.css 。 下图为目前的标签页。
作为一个后端人员,调css和js真是痛苦==,好在坚持下来了,虽然还是很多不足,以后有时间慢慢改。说了那么多,感觉自己还是菜的抠脚。 题外话,搭建一个博客,对于一个新近程序员来说真的是锻炼自己的一个好机会,能够认识到从前端、java后台、linux、jvm等等知识,只是真的有点耗时间(还不如把时间耗在Spring源码),如果不采用别人的框架的话,付出的代价还是蛮大的(所以不要鄙视我啦)。没有什么能够一举两得,看自己的取舍吧。加油💪(ง •_•)ง
欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
`,40)]))}const p=e(n,[["render",r],["__file","7.那些牛逼的插件.html.vue"]]),g=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html","title":"7.那些牛逼的插件","lang":"zh-CN","frontmatter":{"description":"7.那些牛逼的插件 欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。 建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Ja...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"7.那些牛逼的插件"}],["meta",{"property":"og:description","content":"7.那些牛逼的插件 欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。 建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Ja..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/20171121023427.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"7.那些牛逼的插件\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/20171121023427.png\\",\\"https://github-images.wenzhihuai.com/images/20171121024358.png\\",\\"https://github-images.wenzhihuai.com/images/20171122030819.png\\",\\"https://github-images.wenzhihuai.com/images/20171122034349.png\\",\\"https://github-images.wenzhihuai.com/images/20171121023342.png\\",\\"https://github-images.wenzhihuai.com/images/20171125122526.png\\",\\"https://github-images.wenzhihuai.com/images/20171121022116.png\\",\\"https://github-images.wenzhihuai.com/images/20171127034920.png\\",\\"https://github-images.wenzhihuai.com/images/20171125103716.png\\",\\"https://github-images.wenzhihuai.com/images/20171125105127.png\\",\\"https://github-images.wenzhihuai.com/images/20171127033202.png\\",\\"https://github-images.wenzhihuai.com/images/20171127033945.png\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"wowslider","slug":"wowslider","link":"#wowslider","children":[]},{"level":2,"title":"畅言","slug":"畅言","link":"#畅言","children":[]},{"level":2,"title":"Editor.md","slug":"editor-md","link":"#editor-md","children":[]},{"level":2,"title":"图表","slug":"图表","link":"#图表","children":[]},{"level":2,"title":"百度分享","slug":"百度分享","link":"#百度分享","children":[]},{"level":2,"title":"瀑布流","slug":"瀑布流","link":"#瀑布流","children":[]},{"level":2,"title":"天气插件","slug":"天气插件","link":"#天气插件","children":[]},{"level":2,"title":"标签云","slug":"标签云","link":"#标签云","children":[]}],"git":{"createdTime":1579574285000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":7.24,"words":2173},"filePathRelative":"interesting/个人网站/7.那些牛逼的插件.md","localizedDate":"2020年1月21日","excerpt":"\\n欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。 \\n建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Java的程序员,前端的东西一碰脑子就有“我又不是前端,浪费时间在这合适么?”这种想法,捣鼓来捣鼓去,做出的东西实在是没法看,我就觉得,如果自己的“产品”连自己都看不下去了,那还好意思给别人看?特别是留言板那块,初版的页面简直low的要死。所以,还是踏踏实实的“站在巨人的肩膀上”吧,改用别人的插件。但不要纯粹的使用别人的博客模板了,如hexo,wordpress这些,就算是自己拼凑过来的也比这些强。下面是本博客中所用到的插件,给大家介绍介绍,共同学习学习。 \\n本站主要用到的插件有: \\n1.wowslider \\n2.畅言 \\n3.Editor.md \\n4.highchart、echart \\n5.百度分享 \\n6.waterfall.js \\n7.心知天气 \\n8.标签云
","autoDesc":true}');export{p as comp,g as data};
diff --git "a/assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-DopYDuB6.js" "b/assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-DopYDuB6.js"
new file mode 100644
index 00000000..9b468a32
--- /dev/null
+++ "b/assets/8.\345\237\272\344\272\216\350\264\235\345\217\266\346\226\257\347\232\204\346\203\205\346\204\237\345\210\206\346\236\220.html-DopYDuB6.js"
@@ -0,0 +1 @@
+import{_ as n,c as a,a as e,o}from"./app-ftEjETWs.js";const r={};function i(c,t){return o(),a("div",null,t[0]||(t[0]=[e("h1",{id:"_8-基于贝叶斯的情感分析",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_8-基于贝叶斯的情感分析"},[e("span",null,"8.基于贝叶斯的情感分析")])],-1)]))}const m=n(r,[["render",i],["__file","8.基于贝叶斯的情感分析.html.vue"]]),s=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/8.%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%9A%84%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90.html","title":"8.基于贝叶斯的情感分析","lang":"zh-CN","frontmatter":{"description":"8.基于贝叶斯的情感分析","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/8.%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%9A%84%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"8.基于贝叶斯的情感分析"}],["meta",{"property":"og:description","content":"8.基于贝叶斯的情感分析"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"8.基于贝叶斯的情感分析\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1566721640000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":0.04,"words":11},"filePathRelative":"interesting/个人网站/8.基于贝叶斯的情感分析.md","localizedDate":"2019年8月25日","excerpt":"\\n","autoDesc":true}');export{m as comp,s as data};
diff --git "a/assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-8ms_Vznn.js" "b/assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-8ms_Vznn.js"
new file mode 100644
index 00000000..aaa67903
--- /dev/null
+++ "b/assets/9.\347\275\221\347\253\231\346\200\247\350\203\275\344\274\230\345\214\226.html-8ms_Vznn.js"
@@ -0,0 +1 @@
+import{_ as n,c as a,a as e,o}from"./app-ftEjETWs.js";const r={};function i(c,t){return o(),a("div",null,t[0]||(t[0]=[e("h1",{id:"_9-网站性能优化",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_9-网站性能优化"},[e("span",null,"9.网站性能优化")])],-1)]))}const m=n(r,[["render",i],["__file","9.网站性能优化.html.vue"]]),s=JSON.parse('{"path":"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html","title":"9.网站性能优化","lang":"zh-CN","frontmatter":{"description":"9.网站性能优化","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"9.网站性能优化"}],["meta",{"property":"og:description","content":"9.网站性能优化"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"9.网站性能优化\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1566721640000,"updatedTime":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":0.02,"words":7},"filePathRelative":"interesting/个人网站/9.网站性能优化.md","localizedDate":"2019年8月25日","excerpt":"\\n","autoDesc":true}');export{m as comp,s as data};
diff --git "a/assets/IP\343\200\201HTTP\343\200\201HTTPS\343\200\201HTTP2.0.html-DvomVRAD.js" "b/assets/IP\343\200\201HTTP\343\200\201HTTPS\343\200\201HTTP2.0.html-DvomVRAD.js"
new file mode 100644
index 00000000..c5239d9d
--- /dev/null
+++ "b/assets/IP\343\200\201HTTP\343\200\201HTTPS\343\200\201HTTP2.0.html-DvomVRAD.js"
@@ -0,0 +1 @@
+import{_ as t,c as a,d as i,o as r}from"./app-ftEjETWs.js";const n={};function h(p,e){return r(),a("div",null,e[0]||(e[0]=[i('HTTP,全称超文本传输协议(HTTP,HyperText Transfer Protocol),是一个客户端和服务器端请求和应答的标准(TCP),互联网上应用最为广泛的一种网络协议。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求。
HTTPS,即加密后的HTTP。HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全。HTTPS都是用的TLS协议,但是由于SSL出现的时间比较早,并且依旧被现在浏览器所支持,因此SSL依然是HTTPS的代名词,但无论是TLS还是SSL都是上个世纪的事情,SSL最后一个版本是3.0,今后TLS将会继承SSL优良血统继续为我们进行加密服务。目前TLS的版本是1.2,定义在RFC 5246中,暂时还没有被广泛的使用。
HTTP2.0,下一代的HTTP协议。相比于HTTP1.x,大幅度的提升了web性能,进一步减少了网络延时和拥塞。
各自的RFC相关文档自己去搜吧,https://www.rfc-editor.org/ 。
为了了解HTTP,有必要先理解一下TCP/IP。目前,存在两种划分模型的方法,OSI七层模型和TCP/IP模型,具体的区别不在阐述。HTTP是建立在TCP协议之上,所以HTTP协议的瓶颈及其优化技巧都是基于TCP协议本身的特性,例如tcp建立连接的3次握手和断开连接的4次挥手以及每次建立连接带来的RTT延迟时间。
TCP三次握手四次挥手的原理,由于篇幅关系,具体请看TCP协议的三次握手和四次挥手 ,
超文本传输协议(HyperText Transfer Protocol) 是伴随着计算机网络和浏览器而诞生,在浏览器出现之前,人们是怎么使用网络的? ,不管怎么说,那个时代对于现在的我们,有点难以想象。。。之后,网景发布了Netscape Navigator浏览器,才慢慢打开了互联网的幕布。如果根据OSI来划分的话,HTML属于表示层,而HTTP属于应用层。HTTP发展至今,经过了HTTP0.9、HTTP1.0、HTTP1.1、HTTP2.0的时代,虽然2.0很久之前就正式提出标准,大多浏览器也支持了,但是网络支持HTTP2.0的却很少。
报文,是网络中交换和传输的基本单元,即一次性发送的数据块。HTTP的报文是由一行一行组成的,纯文本,而且是明文,即:如果能监听你的网络,那么你发送的所有账号密码都是可以看见的,为了保障数据隐秘性,HTTPS随之而生。
为了形象点,我们把报文标准和实际的结合起来看。
下面是实际报文,以访问自己的网站(http://www.wenzhihuai.com )中的一个链接为例。
请求行由方法字段、URL 字段 和HTTP 协议版本字段 3 个部分组成,他们之间使用空格隔开。常用的 HTTP 请求方法有 GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT,这里我们使用的是GET方法,访问的是/biaoqianyun.do,协议使用的是HTTP/1.1。GET :当客户端要从服务器中读取某个资源时,使用GET 方法。如果需要加传参数的话,需要在URL之后加个"?",然后把参数名字和值用=连接起来,传递参数长度受限制,通常IE8的为4076,Chrome的为7675。例如,/index.jsp?id=100&op=bind。POST :当客户端给服务器提供信息较多时可以使用POST 方法,POST 方法向服务器提交数据,比如完成表单数据的提交,将数据提交给服务器处理。GET 一般用于获取/查询资源信息,POST 会附带用户数据,一般用于更新资源信息。POST 方法将请求参数封装在HTTP 请求数据中,以名称/值的形式出现,可以传输大量数据;
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:User-Agent :产生请求的浏览器类型;Accept :客户端可识别的响应内容类型列表;星号 “ * ” 用于按范围将类型分组,用 “ / ” 指示可接受全部类型,用“ type/* ”指示可接受 type 类型的所有子类型;Accept-Language :客户端可接受的自然语言;Accept-Encoding :客户端可接受的编码压缩格式;Accept-Charset :可接受的应答的字符集;Host :请求的主机名,允许多个域名同处一个IP 地址,即虚拟主机;connection :连接方式(close 或 keepalive),如果是close的话就需要进行TCP四次挥手关闭连接,如果是keepalive,表明还能继续使用,这是HTTP1.1对1.0的新增,加快了网络传输,默认是keepalive;Cookie :存储于客户端扩展字段,向同一域名的服务端发送属于该域的cookie;
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头;
请求包体不在 GET 方法中使用,而是在POST 方法中使用。POST 方法适用于需要客户填写表单的场合。与请求包体相关的最常使用的是包体类型 Content-Type 和包体长度 Content-Length;
同样,先粘贴报文标准。
抓包,以访问(http://www.wenzhihuai.com )为例。
状态行由 HTTP 协议版本字段、状态码和状态码的描述文本 3 个部分组成,他们之间使用空格隔开,描述文本一般不显示;状态码 :由三位数字组成,第一位数字表示响应的类型,常用的状态码有五大类如下所示: 1xx:服务器已接收,但客户端可能仍要继续发送; 2xx:成功; 3xx:重定向; 4xx:请求非法,或者请求不可达; 5xx:服务器内部错误;
Location :Location响应报头域用于重定向接受者到一个新的位置。例如:客户端所请求的页面已不存在原先的位置,为了让客户端重定向到这个页面新的位置,服务器端可以发回Location响应报头后使用重定向语句,让客户端去访问新的域名所对应的服务器上的资源;Server :Server 响应报头域包含了服务器用来处理请求的软件信息及其版本。它和 User-Agent 请求报头域是相对应的,前者发送服务器端软件的信息,后者发送客户端软件(浏览器)和操作系统的信息。Vary :指示不可缓存的请求头列表;Connection :连接方式,这个跟rquest的类似。空行 :最后一个响应头部之后是一个空行,发送回车符和换行符,通知服务器以下不再有响应头部。响应包体 :服务器返回给客户端的文本信息;
HTTP的主要特点主要能概括如下:
即,当客户端访问完一次服务器再次访问的时候,服务器是无法知道这个客户端之前是否已经访问过了。优点是不需要先前的信息,能够更快的应答,缺点是每次连接传送的数据量增大。这种做法不利于信息的交互,随后,Cookie和Session就应运而生,至于它俩有什么区别,可以看看COOKIE和SESSION有什么区别? 。
HTTP1.1 使用持久连接keepalive,所谓持久连接,就是服务器在发送响应后仍然在一段时间内保持这条连接,允许在同一个连接中存在多次数据请求和响应,即在持久连接情况下,服务器在发送完响应后并不关闭TCP连接,客户端可以通过这个连接继续请求其他对象。
支持客户/服务器模式、简单快速(请求方法简单Get和POST)、灵活(数据对象任意)
影响HTTP请求的因素:
带宽 好像只要上网这个因素是一直都有的。。。即使再快的网络,也会有偶尔网络慢的时候。。。 延迟 (1) 浏览器阻塞 一个浏览器对于同一个域名,同时 只能有4个链接(根据不同浏览器),如果超了后面的会被阻塞。 常用浏览器阻塞数量看下图。 (2) DNS查询 浏览器建立连接是需要知道服务器的IP的,DNS用来将域名解析为IP地址,这个可以通过刷新DNS缓存来加快速度。 (3) 建立连接 由之前第一章的就可以看出,HTTP是基于TCP协议的,即使网络、浏览器再快也要进行TCP的三次握手,在高延迟的场景下影响比较明显,慢启动则对文件请求影响较大。
耗时:传输数据每次都要建立连接; 不安全:HTTP是明文传输的,只要在路由器或者交换机上截取,所有东西(账号密码)都是可见的; Header内容过大:通常,客户端的请求header变化较小,但是每次都要携带大量的header信息,导致传输成本增大; keepalive压力过大:持久连接虽然有一点的优点,但同时也会给服务器造成大量的性能压力,特别是传输图片的时候。 BTW:明文传输有多危险,可以去试试,下面是某个政府网站,采用wireshark抓包,身份证、电话号码、住址什么的全暴露出来,所以,,,只要在路由器做点小动作,你的信息是全部能拿得到的,毕竟政府。
由于涉及的隐私太多,打了马赛克
由于HTTP报文的不安全性,网景在1994年就创建了HTTPS,并用在浏览器中。最初HTTPS是和SSL一起使用,然后演化为TLS。SSL/TLS在OSI模型中都是表示层的协议。SSL使 用40 位关键字作为RC4流加密算法,这对于商业信息的加密是合适的。
SSL(Secure Sockets Layer),简称安全套接入层,最初由上世纪90年代由网景公司设计。开启 SSL 会增加内存、CPU、网络带宽的开销,后二者跟你使用的 cipher suite 密切相关,其中参数很多,很难一概而论。开启 SSL 的前提是你的 cert 和 key 必须放在 TCP endpoint,你是否信得过那台设备。 TLS(Transport Layer Security),简称安全传输层协议,该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。较低的层为 TLS 记录协议,位于某个可靠的传输协议(例如 TCP)上面,与具体的应用无关,所以,一般把TLS协议归为传输层安全协议。 由于本人在加密算法上面知识匮乏,就不误人子弟了,有兴趣可以看看百度百科里的资料,SSL ,TLS
2012年google提出了SPDY的方案,大家才开始从正面看待和解决老版本HTTP协议本身的问题,SPDY可以说是综合了HTTPS和HTTP两者有点于一体的传输协议,主要解决:降低延迟 ,针对HTTP高延迟的问题,SPDY优雅的采取了多路复用(multiplexing)。多路复用通过多个请求stream共享一个tcp连接的方式,解决了HOL blocking的问题,降低了延迟同时提高了带宽的利用率。请求优先级(request prioritization) 。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的html内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。header压缩 。前面提到HTTP1.x的header很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。 基于HTTPS的加密协议传输,大大提高了传输数据的可靠性。服务端推送(server push) ,采用了SPDY的网页,例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。SPDY构成图。
跟之前的报文分析一样,我们使用wireshark来抓包分析,以在百度上搜索点东西为例。
192.168.1.103为本地电脑的ip地址,14.215.177.39为百度服务器地址。下面是步骤:
客户端通过发送 Client Hello 报文开始 SSL 通信。报文中包含客户端支持的 SSL 的指定版本、加密组件(Cipher Suite)列表(所使用的加密算法及密钥长度等)。 服务器可进行 SSL 通信时,会以 Server Hello 报文作为应答。和客户端一样,在报文中包含 SSL 版本以及加密组件。服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的。之后服务器发送 Certificate 报文。报文中包含公开密钥证书。最后服务器发送 Server Hello Done 报文通知客户端,最初阶段的SSL握手协商部分结束。 SSL 第一次握手结束之后,客户端以 Client Key Exchange 报文作为回应。接着客户端继续发送 Change Cipher Spec 报文。该报文会提示服务器,在此报文之后的通信会采用 Pre-master secret 密钥加密。客户端发送 Finished 报文。该报文包含连接至今全部报文的整体校验值。 服务器同样发送 Change Cipher Spec 报文。 服务器同样发送 Finished 报文。 服务器和客户端的 Finished 报文交换完毕之后,SSL 连接就算建立完成。当然,通信会受到 SSL 的保护。从此处开始进行应用层协议的通信,即发送 HTTP请求。 应用层协议通信,即发送 HTTP 响应。当然,用一张图更容易解释 简单地说就是下面。 当我们追踪流的数据的时候,可以看到,基本上都是乱码,经过加密,数据是看不到,如果需要在wireshark上看到,则需要在wireshark中配置ssl。
现今,感觉只要和商业利益有关的,就不得不涉及到加密这类东西。淘宝、京东、唯品会这些电商可谓是最早推行全站https的,这类电商是离用户金钱最近的企业。截止今年底,基本所有商业网站也基本实现了HTTPS。。。。至于小站点,比如个人网站,玩玩还是可以的。如果一个网站需要由HTTP全部变为HTTPS,那么需要关注下面几点:
CA证书,大部分证书都是需要收费的,当然,自己在服务器上用openssl也可以,不过浏览器会提示当前私密连接不安全这个警告,普通人看到这种信息是不会继续浏览的,所以,想使用HTTPS,可以使用Let's Encrypt ,由谷歌等公司推行。 HTTPS性能优化,SSL握手,HTTPS 对速度会有一定程度的降低,但是只要经过合理优化和部署,HTTPS 对速度的影响完全可以接受。 CPU计算压力,HTTPS中大量的秘钥算法计算,对CPU的压力可想而知。 至于我自己的个人网站 ,之前实现了https,用的免费证书,但是由于HTTPS下的网站,所有子链都要使用HTTPS,使用了七牛云的CDN,如果要使用HTTPS加速,是要收费的,所以只能放弃。。。 HTTP2.0,相较于HTTP1.x,大幅度的提升了web性能。在与HTTP/1.1完全语义兼容的基础上,进一步减少了网络延迟和传输的安全性。HTTP2.0可以说是SPDY的升级版(基于SPDY设计的),但是依然存在一些不同点:HTTP2.0支持明文传输,而SPDY强制使用HTTPS;HTTP2.0消息头的压缩算法采用HPACK,而非SPDY采用的DEFLATE。
HTTP 2.0在2013年8月进行首次合作共事性测试。在开放互联网上HTTP 2.0将只用于https://网址 ,而 http://网址将继续使用HTTP/1,目的是在开放互联网上增加使用加密技术,以提供强有力的保护去遏制主动攻击。HTTP 2.0是在SPDY(An experimental protocol for a faster web, The Chromium Projects)基础上形成的下一代互联网通信协议。HTTP/2 的目的是通过支持请求与响应的多路复用来较少延迟,通过压缩HTTPS首部字段将协议开销降低,同时增加请求优先级和服务器端推送的支持。
相较于HTTP1.1,HTTP2.0的主要优点有采用二进制帧封装,传输变成多路复用,流量控制算法优化,服务器端推送,首部压缩,优先级等特点。
HTTP1.x的解析是基于文本的,基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多。而HTTP/2会将所有传输的信息分割为更小的消息和帧,然后采用二进制的格式进行编码,HTTP1.x的头部信息会被封装到HEADER frame,而相应的Request Body则封装到DATA frame里面。不改动HTTP的语义,使用二进制编码,实现方便且健壮。
所有的请求都是通过一个 TCP 连接并发完成。HTTP/1.x 虽然通过 pipeline 也能并发请求,但是多个请求之间的响应会被阻塞的,所以 pipeline 至今也没有被普及应用,而 HTTP/2 做到了真正的并发请求。同时,流还支持优先级和流量控制。当流并发时,就会涉及到流的优先级和依赖。即:HTTP2.0对于同一域名下所有请求都是基于流的,不管对于同一域名访问多少文件,也只建立一路连接。优先级高的流会被优先发送。图片请求的优先级要低于 CSS 和 SCRIPT,这个设计可以确保重要的东西可以被优先加载完。
TCP协议通过sliding window的算法来做流量控制。发送方有个sending window,接收方有receive window。http2.0的flow control是类似receive window的做法,数据的接收方通过告知对方自己的flow window大小表明自己还能接收多少数据。只有Data类型的frame才有flow control的功能。对于flow control,如果接收方在flow window为零的情况下依然更多的frame,则会返回block类型的frame,这张场景一般表明http2.0的部署出了问题。
服务器端的推送,就是服务器可以对一个客户端请求发送多个响应。除了对最初请求的响应外,服务器还可以额外向客户端推送资源,而无需客户端明确地请求。当浏览器请求一个html,服务器其实大概知道你是接下来要请求资源了,而不需要等待浏览器得到html后解析页面再发送资源请求。
HTTP 2.0 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;通信期间几乎不会改变的通用键-值对(用户代理、可接受的媒体类型,等等)只 需发送一次。事实上,如果请求中不包含首部(例如对同一资源的轮询请求),那么 首部开销就是零字节。此时所有首部都自动使用之前请求发送的首部。 如果首部发生变化了,那么只需要发送变化了数据在Headers帧里面,新增或修改的首部帧会被追加到“首部表”。首部表在 HTTP 2.0 的连接存续期内始终存在,由客户端和服务器共同渐进地更新 。本质上,当然是为了减少请求啦,通过多个js或css合并成一个文件,多张小图片拼合成Sprite图,可以让多个HTTP请求减少为一个,减少额外的协议开销,而提升性能。当然,一个HTTP的请求的body太大也是不合理的,有个度。文件的合并也会牺牲模块化和缓存粒度,可以把“稳定”的代码or 小图 合并为一个文件or一张Sprite,让其充分地缓存起来,从而区分开迭代快的文件。
以访问https://http2.akamai.com/demo为例。
访问https://http2.akamai.com/demo ,谷歌浏览器的报文没有显示出协议,此处使用火狐浏览器。 响应头部分如下。
请求头如下。
采用淘宝网站为例,淘宝目前采用主站使用HTTP1.1,资源使用HTTP2.0,少些使用SPDY协议。目前也是业界比较流行的做法。
HTTPS那些事 如何搭建一个HTTP2.0的网站 HTTP/2.0 相比1.0有哪些重大改进? HTTP2.0 demo Http、Https、Http2前身 HTTP报文 HTTP、HTTP2.0、SPDY、HTTPS 你应该知道的一些事 HTTPS权威指南 HTTP2.0的奇妙日常 curl 支持 HTTP2 淘宝HTTPS探索 HTTPS完全协议详解 欢迎访问我的个人网站。https://wenzhihuai.com
',103)]))}const o=t(n,[["render",h],["__file","IP、HTTP、HTTPS、HTTP2.0.html.vue"]]),T=JSON.parse('{"path":"/java/%E7%BD%91%E7%BB%9C/IP%E3%80%81HTTP%E3%80%81HTTPS%E3%80%81HTTP2.0.html","title":"TCP/IP、HTTP、HTTPS、HTTP2.0","lang":"zh-CN","frontmatter":{"description":"TCP/IP、HTTP、HTTPS、HTTP2.0 HTTP,全称超文本传输协议(HTTP,HyperText Transfer Protocol),是一个客户端和服务器端请求和应答的标准(TCP),互联网上应用最为广泛的一种网络协议。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/%E7%BD%91%E7%BB%9C/IP%E3%80%81HTTP%E3%80%81HTTPS%E3%80%81HTTP2.0.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"TCP/IP、HTTP、HTTPS、HTTP2.0"}],["meta",{"property":"og:description","content":"TCP/IP、HTTP、HTTPS、HTTP2.0 HTTP,全称超文本传输协议(HTTP,HyperText Transfer Protocol),是一个客户端和服务器端请求和应答的标准(TCP),互联网上应用最为广泛的一种网络协议。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/20171224034237.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-14T17:59:53.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-14T17:59:53.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"TCP/IP、HTTP、HTTPS、HTTP2.0\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/20171224034237.png\\",\\"https://github-images.wenzhihuai.com/images/20171221101751.png\\",\\"https://github-images.wenzhihuai.com/images/20171221111615.png\\",\\"https://github-images.wenzhihuai.com/images/20171221043103.png\\",\\"https://github-images.wenzhihuai.com/images/20171224035755.png\\",\\"https://github-images.wenzhihuai.com/images/20171224035850.png\\",\\"https://github-images.wenzhihuai.com/images/20171226081508.png\\",\\"https://github-images.wenzhihuai.com/images/20171224044825.png\\",\\"https://github-images.wenzhihuai.com/images/20171226042016.png\\",\\"https://github-images.wenzhihuai.com/images/20171226044521.png\\",\\"https://github-images.wenzhihuai.com/images/20171226044137.png\\",\\"https://github-images.wenzhihuai.com/images/20171226045845.png\\",\\"https://github-images.wenzhihuai.com/images/20171226103043.png\\",\\"https://github-images.wenzhihuai.com/images/20171226105514.png\\",\\"https://github-images.wenzhihuai.com/images/20171226051221.png\\",\\"https://github-images.wenzhihuai.com/images/20171226071845.png\\",\\"https://github-images.wenzhihuai.com/images/20171226075106.png\\",\\"https://github-images.wenzhihuai.com/images/20171226065216.png\\"],\\"dateModified\\":\\"2024-02-14T17:59:53.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、TCP/IP","slug":"一、tcp-ip","link":"#一、tcp-ip","children":[]},{"level":2,"title":"二、HTTP","slug":"二、http","link":"#二、http","children":[{"level":3,"title":"2.1 HTTP报文分析","slug":"_2-1-http报文分析","link":"#_2-1-http报文分析","children":[]},{"level":3,"title":"2.2 HTTP特性","slug":"_2-2-http特性","link":"#_2-2-http特性","children":[]},{"level":3,"title":"2.3 影响HTTP的因素","slug":"_2-3-影响http的因素","link":"#_2-3-影响http的因素","children":[]}]},{"level":2,"title":"三、HTTPS","slug":"三、https","link":"#三、https","children":[{"level":3,"title":"3.1 SSL/TLS","slug":"_3-1-ssl-tls","link":"#_3-1-ssl-tls","children":[]},{"level":3,"title":"3.2 SPDY","slug":"_3-2-spdy","link":"#_3-2-spdy","children":[]},{"level":3,"title":"3.3 HTTPS报文分析","slug":"_3-3-https报文分析","link":"#_3-3-https报文分析","children":[]},{"level":3,"title":"3.4 HTTPS全站化","slug":"_3-4-https全站化","link":"#_3-4-https全站化","children":[]}]},{"level":2,"title":"四、HTTP2.0","slug":"四、http2-0","link":"#四、http2-0","children":[{"level":3,"title":"4.1 历史","slug":"_4-1-历史","link":"#_4-1-历史","children":[]},{"level":3,"title":"4.2 HTTP2.0新特性","slug":"_4-2-http2-0新特性","link":"#_4-2-http2-0新特性","children":[]},{"level":3,"title":"4.3 HTTP1.1与HTTP2.0的对比","slug":"_4-3-http1-1与http2-0的对比","link":"#_4-3-http1-1与http2-0的对比","children":[]},{"level":3,"title":"4.4 报文","slug":"_4-4-报文","link":"#_4-4-报文","children":[]}]},{"level":2,"title":"参考","slug":"参考","link":"#参考","children":[]}],"git":{"createdTime":1707203159000,"updatedTime":1707933593000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":3}]},"readingTime":{"minutes":19.51,"words":5852},"filePathRelative":"java/网络/IP、HTTP、HTTPS、HTTP2.0.md","localizedDate":"2024年2月6日","excerpt":"\\nHTTP,全称超文本传输协议(HTTP,HyperText Transfer Protocol),是一个客户端和服务器端请求和应答的标准(TCP),互联网上应用最为广泛的一种网络协议。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求。
","autoDesc":true}');export{o as comp,T as data};
diff --git "a/assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-BtZgPFK4.js" "b/assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-BtZgPFK4.js"
new file mode 100644
index 00000000..8bfbfe3e
--- /dev/null
+++ "b/assets/JVM\350\260\203\344\274\230\345\217\202\346\225\260.html-BtZgPFK4.js"
@@ -0,0 +1,24 @@
+import{_ as i,c as a,d as e,o as n}from"./app-ftEjETWs.js";const l={};function t(r,s){return n(),a("div",null,s[0]||(s[0]=[e(`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后,对年老代进行压缩
`,49)]))}const d=i(l,[["render",t],["__file","JVM调优参数.html.vue"]]),p=JSON.parse('{"path":"/java/JVM/JVM%E8%B0%83%E4%BC%98%E5%8F%82%E6%95%B0.html","title":"JVM调优参数","lang":"zh-CN","frontmatter":{"description":"JVM调优参数 一、堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/JVM/JVM%E8%B0%83%E4%BC%98%E5%8F%82%E6%95%B0.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"JVM调优参数"}],["meta",{"property":"og:description","content":"JVM调优参数 一、堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-16T04:00:26.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-16T04:00:26.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"JVM调优参数\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-16T04:00:26.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、堆大小设置","slug":"一、堆大小设置","link":"#一、堆大小设置","children":[{"level":3,"title":"典型设置:","slug":"典型设置","link":"#典型设置","children":[]}]},{"level":2,"title":"二、回收器选择","slug":"二、回收器选择","link":"#二、回收器选择","children":[{"level":3,"title":"2.1 吞吐量优先的并行收集器","slug":"_2-1-吞吐量优先的并行收集器","link":"#_2-1-吞吐量优先的并行收集器","children":[]},{"level":3,"title":"2.2 响应时间优先的并发收集器","slug":"_2-2-响应时间优先的并发收集器","link":"#_2-2-响应时间优先的并发收集器","children":[]}]},{"level":2,"title":"三、辅助信息","slug":"三、辅助信息","link":"#三、辅助信息","children":[{"level":3,"title":"3.1 堆设置","slug":"_3-1-堆设置","link":"#_3-1-堆设置","children":[]},{"level":3,"title":"3.2 收集器设置","slug":"_3-2-收集器设置","link":"#_3-2-收集器设置","children":[]},{"level":3,"title":"3.3 垃圾回收统计信息","slug":"_3-3-垃圾回收统计信息","link":"#_3-3-垃圾回收统计信息","children":[]},{"level":3,"title":"3.4 并行收集器设置","slug":"_3-4-并行收集器设置","link":"#_3-4-并行收集器设置","children":[]},{"level":3,"title":"3.5 并发收集器设置","slug":"_3-5-并发收集器设置","link":"#_3-5-并发收集器设置","children":[]}]},{"level":2,"title":"四、调优总结","slug":"四、调优总结","link":"#四、调优总结","children":[{"level":3,"title":"4.1 年轻代大小选择","slug":"_4-1-年轻代大小选择","link":"#_4-1-年轻代大小选择","children":[]},{"level":3,"title":"4.2 年老代大小选择","slug":"_4-2-年老代大小选择","link":"#_4-2-年老代大小选择","children":[]},{"level":3,"title":"4.3 较小堆引起的碎片问题","slug":"_4-3-较小堆引起的碎片问题","link":"#_4-3-较小堆引起的碎片问题","children":[]}]}],"git":{"createdTime":1579957849000,"updatedTime":1708056026000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":9.13,"words":2739},"filePathRelative":"java/JVM/JVM调优参数.md","localizedDate":"2020年1月25日","excerpt":"\\n一、堆大小设置 \\nJVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
","autoDesc":true}');export{d as comp,p as data};
diff --git "a/assets/Java\345\206\205\345\255\230\346\250\241\345\236\213.html-Bis3Hglq.js" "b/assets/Java\345\206\205\345\255\230\346\250\241\345\236\213.html-Bis3Hglq.js"
new file mode 100644
index 00000000..afadc5fc
--- /dev/null
+++ "b/assets/Java\345\206\205\345\255\230\346\250\241\345\236\213.html-Bis3Hglq.js"
@@ -0,0 +1,150 @@
+import{_ as s,c as a,d as e,o as n}from"./app-ftEjETWs.js";const l={};function t(h,i){return n(),a("div",null,i[0]||(i[0]=[e(`本文转载自深入理解JVM-内存模型(jmm)和GC
了解jvm内存模型前,了解下cpu和计算机内存的交互情况。【因为Java虚拟机内存模型定义的访问操作与计算机十分相似】
有篇很棒的文章,从cpu讲到内存模型:什么是java内存模型
在计算机中,cpu和内存的交互最为频繁,相比内存,磁盘读写太慢,内存相当于高速的缓冲区。
但是随着cpu的发展,内存的读写速度也远远赶不上cpu。因此cpu厂商在每颗cpu上加上高速缓存,用于缓解这种情况。现在cpu和内存的交互大致如下。
cpu、缓存、内存 cpu上加入了高速缓存这样做解决了处理器和内存的矛盾(一快一慢),但是引来的新的问题 - 缓存一致性
在多核cpu中,每个处理器都有各自的高速缓存(L1,L2,L3),而主内存确只有一个 。 以我的pc为例,因为cpu成本高,缓存区一般也很小。
image-20240216172615735 CPU要读取一个数据时,首先从一级缓存中查找,如果没有找到再从二级缓存中查找,如果还是没有就从三级缓存或内存中查找,每个cpu有且只有一套自己的缓存。
如何保证多个处理器运算涉及到同一个内存区域时,多线程场景下会存在缓存一致性问题,那么运行时保证数据一致性?
为了解决这个问题,各个处理器需遵循一些协议保证一致性。【如MSI,MESI啥啥的协议。。】
大概如下
cpu与内存.png 在CPU层面,内存屏障提供了个充分必要条件
CPU中,每个CPU又有多级缓存【上图统一定义为高速缓存】,一般分为L1,L2,L3,因为这些缓存的出现,提高了数据访问性能,避免每次都向内存索取,但是弊端也很明显,不能实时的和内存发生信息交换,分在不同CPU执行的不同线程对同一个变量的缓存值不同。
硬件层的内存屏障分为两种:Load Barrier
和 Store Barrier
即读屏障和写屏障。【内存屏障是硬件层的】 由于现代操作系统都是多处理器操作系统,每个处理器都会有自己的缓存,可能存再不同处理器缓存不一致的问题,而且由于操作系统可能存在重排序,导致读取到错误的数据,因此,操作系统提供了一些内存屏障以解决这种问题.
+简单来说:
+1. 在不同CPU执行的不同线程对同一个变量的缓存值不同,为了解决这个问题。
+2. 用volatile可以解决上面的问题,不同硬件对内存屏障的实现方式不一样。java屏蔽掉这些差异,通过jvm生成内存屏障的指令。
+对于读屏障:在指令前插入读屏障,可以让高速缓存中的数据失效,强制从主内存取。
cpu执行指令可能是无序的,它有两个比较重要的作用
+1.阻止屏障两侧指令重排序
+2.强制把写缓冲区/高速缓存中的脏数据等写回主内存,让缓存中相应的数据失效。
当我们声明某个变量为volatile修饰时,这个变量就有了线程可见性,volatile通过在读写操作前后添加内存屏障。
用代码可以这么理解
//相当于读写时加锁,保证及时可见性,并发时不被随意修改。
+public class SynchronizedInteger {
+ private long value ;
+
+ public synchronized int get () {
+ return value;
+ }
+
+ public synchronized void set ( long value ) {
+ this . value = value;
+ }
+}
volatile型变量拥有如下特性
可见性,对于一个该变量的读,一定能看到读之前最后的写入。
+防止指令重排序,执行代码时,为了提高执行效率,会在不影响最后结果的前提下对指令进行重新排序,使用volatile可以防止,比如单例模式双重校验锁的创建中有使用到,如(https: //www.jianshu.com/p/b30a4d568be4)
+
+注意的是volatile不具有原子性,如volatile ++ 这样的复合操作,这里感谢大家的指正。
至于volatile底层是怎么实现保证不同线程可见性的,这里涉及到的就是硬件上的,被volatile修饰的变量在进行写操作时,会生成一个特殊的汇编指令,该指令会触发mesi协议,会存在一个总线嗅探机制的东西,简单来说就是这个cpu会不停检测总线中该变量的变化,如果该变量一旦变化了,由于这个嗅探机制,其它cpu会立马将该变量的cpu缓存数据清空掉,重新的去从主内存拿到这个数据。简单画了个图。
img 前提:本文讲的基本都是以Sun HotSpot虚拟机为基础的,Oracle收购了Sun后目前得到了两个【Sun的HotSpot和JRockit(以后可能合并这两个),还有一个是IBM的IBMJVM】
之所以扯了那么多计算机内存模型,是因为java内存模型的设定符合了计算机的规范。
Java程序内存的分配是在JVM虚拟机内存分配机制下完成 。
Java内存模型(Java Memory Model ,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。
简要言之,jmm是jvm的一种规范,定义了jvm的内存模型。它屏蔽了各种硬件和操作系统的访问差异,不像c那样直接访问硬件内存,相对安全很多,它的主要目的是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题。可以保证并发编程场景中的原子性、可见性和有序性。
从下面这张图可以看出来,Java数据区域分为五大数据区域。这些区域各有各的用途,创建及销毁时间。
其中方法区和堆是所有线程共享的,栈,本地方法栈和程序虚拟机则为线程私有的。
根据java虚拟机规范,java虚拟机管理的内存将分为下面五大区域。
jmm 程序计数器是一块很小的内存空间,它是线程私有的,可以认作为当前线程的行号指示器。
为什么需要程序计数器
我们知道对于一个处理器(如果是多核cpu那就是一核),在一个确定的时刻都只会执行一条线程中的指令,一条线程中有多个指令,为了线程切换可以恢复到正确执行位置,每个线程都需有独立的一个程序计数器,不同线程之间的程序计数器互不影响,独立存储。
注意:如果线程执行的是个java方法,那么计数器记录虚拟机字节码指令的地址。如果为native【底层方法】,那么计数器为空。这块内存区域是虚拟机规范中唯一没有OutOfMemoryError的区域 。
同计数器也为线程私有,生命周期与相同,就是我们平时说的栈,栈描述的是Java方法执行的内存模型 。
每个方法被执行的时候都会创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用的过程就对应一个栈帧在虚拟机栈中从入栈到出栈的过程。【栈先进后出,下图栈1先进最后出来】
对于栈帧的解释参考 Java虚拟机运行时栈帧结构
栈帧: 是用来存储数据和部分过程结果的数据结构。
+栈帧的位置: 内存 -> 运行时数据区 -> 某个线程对应的虚拟机栈 -> here [在这里]
+栈帧大小确定时间: 编译期确定,不受运行期数据影响。
通常有人将java内存区分为栈和堆,实际上java内存比这复杂,这么区分可能是因为我们最关注,与对象内存分配关系最密切的是这两个。
平时说的栈一般指局部变量表部分。
局部变量表:一片连续的内存空间,用来存放方法参数,以及方法内定义的局部变量,存放着编译期间已知的数据类型(八大基本类型和对象引用(reference类型),returnAddress类型。它的最小的局部变量表空间单位为Slot,虚拟机没有指明Slot的大小,但在jvm中,long和double类型数据明确规定为64位,这两个类型占2个Slot,其它基本类型固定占用1个Slot。
reference类型:与基本类型不同的是它不等同本身,即使是String,内部也是char数组组成,它可能是指向一个对象起始位置指针,也可能指向一个代表对象的句柄或其他与该对象有关的位置。
returnAddress类型:指向一条字节码指令的地址【深入理解Java虚拟机】怎么理解returnAddress
栈帧 需要注意的是,局部变量表所需要的内存空间在编译期完成分配,当进入一个方法时,这个方法在栈中需要分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表大小。
Java虚拟机栈可能出现两种类型的异常:
线程请求的栈深度大于虚拟机允许的栈深度,将抛出StackOverflowError。 虚拟机栈空间可以动态扩展,当动态扩展是无法申请到足够的空间时,抛出OutOfMemory异常。 本地方法栈是与虚拟机栈发挥的作用十分相似,区别是虚拟机栈执行的是Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的native方法服务,可能底层调用的c或者c++,我们打开jdk安装目录可以看到也有很多用c编写的文件,可能就是native方法所调用的c代码。
对于大多数应用来说,堆是java虚拟机管理内存最大的一块内存区域,因为堆存放的对象是线程共享的,所以多线程的时候也需要同步机制 。因此需要重点了解下。
java虚拟机规范对这块的描述是:所有对象实例及数组都要在堆上分配内存,但随着JIT编译器的发展和逃逸分析技术的成熟,这个说法也不是那么绝对,但是大多数情况都是这样的。
即时编译器:可以把把Java的字节码,包括需要被解释的指令的程序)转换成可以直接发送给处理器的指令的程序)
逃逸分析:通过逃逸分析来决定某些实例或者变量是否要在堆中进行分配,如果开启了逃逸分析,即可将这些变量直接在栈上进行分配,而非堆上进行分配。这些变量的指针可以被全局所引用,或者其其它线程所引用。
参考逃逸分析
注意:它是所有线程共享的,它的目的是存放对象实例。同时它也是GC所管理的主要区域,因此常被称为GC堆,又由于现在收集器常使用分代算法,Java堆中还可以细分为新生代和老年代,再细致点还有Eden(伊甸园)空间之类的不做深究。
根据虚拟机规范,Java堆可以存在物理上不连续的内存空间,就像磁盘空间只要逻辑是连续的即可。它的内存大小可以设为固定大小,也可以扩展。
当前主流的虚拟机如HotPot都能按扩展实现(通过设置 -Xmx和-Xms),如果堆中没有内存内存完成实例分配,而且堆无法扩展将报OOM错误(OutOfMemoryError)
方法区同堆一样,是所有线程共享的内存区域,为了区分堆,又被称为非堆。
用于存储已被虚拟机加载的类信息、常量、静态变量,如static修饰的变量加载类的时候就被加载到方法区中。
运行时常量池
是方法区的一部分,class文件除了有类的字段、接口、方法等描述信息之外,还有常量池用于存放编译期间生成的各种字面量和符号引用。
在老版jdk,方法区也被称为永久代【因为没有强制要求方法区必须实现垃圾回收,HotSpot虚拟机以永久代来实现方法区,从而JVM的垃圾收集器可以像管理堆区一样管理这部分区域,从而不需要专门为这部分设计垃圾回收机制。不过自从JDK7之后,Hotspot虚拟机便将运行时常量池从永久代移除了。】
jdk1 .7开始逐步去永久代。从String .interns( ) 方法可以看出来
+String.interns( )
+native方法:作用是如果字符串常量池已经包含一个等于这个String对象的字符串,则返回代表池中的这个字符串的String对象,在jdk1 .6及以前常量池分配在永久代中。可通过 -XX:PermSize和-XX:MaxPermSize限制方法区大小。
public class StringIntern {
+ //运行如下代码探究运行时常量池的位置
+ public static void main ( String [] args ) throws Throwable {
+ //用list保持着引用 防止full gc回收常量池
+ List < String > list = new ArrayList < String >();
+ int i = 0 ;
+ while ( true ){
+ list . add ( String . valueOf (i++). intern ());
+ }
+ }
+}
+//如果在jdk1.6环境下运行 同时限制方法区大小 将报OOM后面跟着PermGen space说明方法区OOM,即常量池在永久代
+//如果是jdk1.7或1.8环境下运行 同时限制堆的大小 将报heap space 即常量池在堆中
idea设置相关内存大小设置
这边不用全局的方式,设置main方法的vm参数。
做相关设置,比如说这边设定堆大小。(-Xmx5m -Xms5m -XX:-UseGCOverheadLimit)
这边如果不设置UseGCOverheadLimit将报java .lang.OutOfMemoryError : GC overhead limit exceeded,
+这个错是因为GC占用了多余98%(默认值)的CPU时间却只回收了少于2%(默认值)的堆空间。目的是为了让应用终止,给开发者机会去诊断问题。一般是应用程序在有限的内存上创建了大量的临时对象或者弱引用对象,从而导致该异常。虽然加大内存可以暂时解决这个问题,但是还是强烈建议去优化代码,后者更加有效,也可通过UseGCOverheadLimit避免[ 不推荐,这里是因为测试用,并不能解决根本问题 ]
img img jdk8真正开始废弃永久代,而使用元空间(Metaspace)
java虚拟机对方法区比较宽松,除了跟堆一样可以不存在连续的内存空间,定义空间和可扩展空间,还可以选择不实现垃圾收集。
在HotSpot虚拟机中。对象在内存中存储的布局分为
在32位系统下,对象头8字节,64位则是16个字节【未开启压缩指针,开启后12字节】。
markword很像网络协议报文头,划分为多个区间,并且会根据对象的状态复用自己的存储空间。
+为什么这么做:省空间,对象需要存储的数据很多,32bit/64bit是不够的,它被设计成非固定的数据结构以便在极小的空间存储更多的信息,
假设当前为32bit,在对象未被锁定情况下。25bit为存储对象的哈希码、4bit用于存储分代年龄,2bit用于存储锁标志位,1bit固定为0。
不同状态下存放数据
img 这其中锁标识位需要特别关注下。锁标志位与是否为偏向锁对应到唯一的锁状态 。
锁的状态分为四种无锁状态
、偏向锁
、轻量级锁
和重量级锁
不同状态时对象头的区间含义,如图所示。
对象头.jpg HotSpot底层通过markOop实现Mark Word,具体实现位于markOop.hpp
文件。
markOop中提供了大量方法用于查看当前对象头的状态,以及更新对象头的数据,为synchronized锁的实现提供了基础。[比如说我们知道synchronized锁的是对象而不是代码,而锁的状态保存在对象头中,进而实现锁住对象]。
关于对象头和锁之间的转换,网上大神总结
偏向锁轻量级锁重量级锁.png 存放对象程序中各种类型的字段类型,不管是从父类中继承下来的还是在子类中定义的。
+分配策略:相同宽度的字段总是放在一起,比如double和long
这部分没有特殊的含义,仅仅起到占位符的作用满足JVM要求。
由于HotSpot规定对象的大小必须是8的整数倍,对象头刚好是整数倍,如果实例数据不是的话,就需要占位符对齐填充。
java程序需要通过引用(ref)数据来操作堆上面的对象,那么如何通过引用定位、访问到对象的具体位置。
对象的访问方式由虚拟机决定,java虚拟机提供两种主流的方式
+1.句柄访问对象
+2.直接指针访问对象。(Sun HotSpot使用这种方式)
参考Java对象访问定位
简单来说就是java堆划出一块内存作为句柄池,引用中存储对象的句柄地址,句柄中包含对象实例数据、类型数据的地址信息。
访问方式2.jpg 与句柄访问不同的是,ref中直接存储的就是对象的实例数据,但是类型数据跟句柄访问方式一样。
优点:优势很明显,就是速度快,相比于句柄访问少了一次指针定位的开销时间 。【可能是出于Java中对象的访问时十分频繁的,平时我们常用的JVM HotSpot采用此种方式】
访问方式1.jpg 两种内存溢出异常[ 注意内存溢出是error级别的 ]
+1 .StackOverFlowError :当请求的栈深度大于虚拟机所允许的最大深度
+2 .OutOfMemoryError :虚拟机在扩展栈时无法申请到足够的内存空间[ 一般都能设置扩大 ]
java -verbose:class -version 可以查看刚开始加载的类,可以发现这两个类并不是异常出现的时候才去加载,而是jvm启动的时候就已经加载。这么做的原因是在vm启动过程中我们把类加载起来,并创建几个没有堆栈的对象缓存起来,只需要设置下不同的提示信息即可,当需要抛出特定类型的OutOfMemoryError异常的时候,就直接拿出缓存里的这几个对象就可以了。
比如说OutOfMemoryError对象,jvm预留出4个对象【固定常量】,这就为什么最多出现4次有堆栈的OutOfMemoryError异常及大部分情况下都将看到没有堆栈的OutOfMemoryError对象的原因。
参考OutOfMemoryError解读
Snip20180904_8.png 两个基本的例子
public class MemErrorTest {
+ public static void main ( String [] args ) {
+ try {
+ List < Object > list = new ArrayList < Object >();
+ for (;;) {
+ list . add ( new Object ()); //创建对象速度可能高于jvm回收速度
+ }
+ } catch ( OutOfMemoryError e ) {
+ e . printStackTrace ();
+ }
+
+ try {
+ hi (); //递归造成StackOverflowError 这边因为每运行一个方法将创建一个栈帧,栈帧创建太多无法继续申请到内存扩展
+ } catch ( StackOverflowError e ) {
+ e . printStackTrace ();
+ }
+
+ }
+
+ public static void hi () {
+ hi ();
+ }
+}
img GC(Garbage Collection):即垃圾回收器,诞生于1960年MIT的Lisp语言,主要是用来回收,释放垃圾占用的空间。
java GC泛指java的垃圾回收机制,该机制是java与C/C++的主要区别之一,我们在日常写java代码的时候,一般都不需要编写内存回收或者垃圾清理的代码,也不需要像C/C++那样做类似delete/free的操作。
对象的内存分配在java虚拟机的自动内存分配机制下,一般不容易出现内存泄漏问题。但是写代码难免会遇到一些特殊情况,比如OOM神马的。。尽管虚拟机内存的动态分配与内存回收技术很成熟,可万一出现了这样那样的内存溢出问题,那么将难以定位错误的原因所在。
对于本人来说,由于水平有限,而且作为小开发,并没必要深入到GC的底层实现,但至少想要说学会看懂gc及定位一些内存泄漏问题。
从三个角度切入来学习GC
1.哪些内存要回收
2.什么时候回收
3.怎么回收
哪些内存要回收
java内存模型中分为五大区域已经有所了解。我们知道程序计数器
、虚拟机栈
、本地方法栈
,由线程而生,随线程而灭,其中栈中的栈帧随着方法的进入顺序的执行的入栈和出栈的操作,一个栈帧需要分配多少内存取决于具体的虚拟机实现并且在编译期间即确定下来【忽略JIT编译器做的优化,基本当成编译期间可知】,当方法或线程执行完毕后,内存就随着回收,因此无需关心。
而Java堆
、方法区
则不一样。方法区存放着类加载信息,但是一个接口中多个实现类需要的内存可能不太一样,一个方法中多个分支需要的内存也可能不一样【只有在运行期间才可知道这个方法创建了哪些对象没需要多少内存】,这部分内存的分配和回收都是动态的,gc关注的也正是这部分的内存。
Java堆是GC回收的“重点区域”。堆中基本存放着所有对象实例,gc进行回收前,第一件事就是确认哪些对象存活,哪些死去[ 即不可能再被引用 ]
为了高效的回收,jvm将堆分为三个区域
+1 .新生代(Young Generation)NewSize和MaxNewSize分别可以控制年轻代的初始大小和最大的大小
+2 .老年代(Old Generation)
+3 .永久代(Permanent Generation)【1 .8以后采用元空间,就不在堆中了】
GC为什么要分代-R大的回答
关于元空间
1.引用计数算法
+早期判断对象是否存活大多都是以这种算法,这种算法判断很简单,简单来说就是给对象添加一个引用计数器,每当对象被引用一次就加1,引用失效时就减1。当为0的时候就判断对象不会再被引用。
+优点:实现简单效率高,被广泛使用与如python何游戏脚本语言上。
+缺点:难以解决循环引用的问题,就是假如两个对象互相引用已经不会再被其它其它引用,导致一直不会为0就无法进行回收。
+
+2.可达性分析算法
+目前主流的商用语言[如java、c#]采用的是可达性分析算法判断对象是否存活。这个算法有效解决了循环利用的弊端。
+它的基本思路是通过一个称为“GC Roots”的对象为起始点,搜索所经过的路径称为引用链,当一个对象到GC Roots没有任何引用跟它连接则证明对象是不可用的。
gc.png 可作为GC Roots的对象有四种
①虚拟机栈(栈桢中的本地变量表)中的引用的对象。
+②方法区中的类静态属性引用的对象,一般指被static修饰引用的对象,加载类的时候就加载到内存中。
+③方法区中的常量引用的对象 ,
+④本地方法栈中JNI(native方法)引用的对象
即使可达性算法中不可达的对象,也不是一定要马上被回收,还有可能被抢救一下。网上例子很多,基本上和深入理解JVM一书讲的一样对象的生存还是死亡
要真正宣告对象死亡需经过两个过程。
+1 .可达性分析后没有发现引用链
+2 .查看对象是否有finalize方法,如果有重写且在方法内完成自救 [ 比如再建立引用 ],还是可以抢救一下,注意这边一个类的finalize只执行一次,这就会出现一样的代码第一次自救成功第二次失败的情况。[ 如果类重写finalize且还没调用过,会将这个对象放到一个叫做F-Queue的序列里,这边finalize不承诺一定会执行,这么做是因为如果里面死循环的话可能会时F-Queue队列处于等待,严重会导致内存崩溃,这是我们不希望看到的。 ]
HotSpot虚拟机如何实现可达性算法
jvm中,可达性分析算法帮我们解决了哪些对象可以回收的问题,垃圾收集算法则关心怎么回收。
1. 标记 / 清除算法 【 最基础 】
+2. 复制算法
+3. 标记 / 整理算法
+jvm采用 \`分代收集算法\` 对不同区域采用不同的回收算法 。
参考GC算法深度解析
新生代采用复制算法
新生代中因为对象都是"朝生夕死的",【深入理解JVM虚拟机上说98%的对象,不知道是不是这么多,总之就是存活率很低】,适用于复制算法【复制算法比较适合用于存活率低的内存区域】。它优化了标记/清除算法的效率和内存碎片问题,且JVM不以5:5分配内存【由于存活率低,不需要复制保留那么大的区域造成空间上的浪费,因此不需要按1:1【原有区域:保留空间】划分内存区域,而是将内存分为一块Eden空间和From Survivor、To Survivor【保留空间】,三者默认比例为8:1:1,优先使用Eden区,若Eden区满,则将对象复制到第二块内存区上。但是不能保证每次回收都只有不多于10%的对象存货,所以Survivor区不够的话,则会依赖老年代年存进行分配】。
GC开始时,对象只会存于Eden和From Survivor区域,To Survivor【保留空间】为空。
GC进行时,Eden区所有存活的对象都被复制到To Survivor区,而From Survivor区中,仍存活的对象会根据它们的年龄值决定去向,年龄值达到年龄阈值(默认15是因为对象头中年龄战4bit,新生代每熬过一次垃圾回收,年龄+1),则移到老年代,没有达到则复制到To Survivor。
老年代采用标记/清除算法
或标记/整理算法
由于老年代存活率高,没有额外空间给他做担保,必须使用这两种算法。
GC Roots
被虚拟机用来判断对象是否存活
可作为GC Roos的节点主要是在一些全局引用【如常量或静态属性】、执行上下文【如栈帧中本地变量表】中。那么如何在这么多全局变量和本地变量表找到【枚举】根节点将是个问题。
可达性分析算法需考虑
1.如果方法区几百兆,一个个检查里面的引用,将耗费大量资源。
2.在分析时,需保证这个对象引用关系不再变化,否则结果将不准确。【因此GC进行时需停掉其它所有java执行线程(Sun把这种行为称为‘Stop the World’),即使是号称几乎不会停顿的CMS收集器,枚举根节点时也需停掉线程】
解决办法:实际上当系统停下来后JVM不需要一个个检查引用,而是通过OopMap数据结构【HotSpot的叫法】来标记对象引用。
虚拟机先得知哪些地方存放对象的引用,在类加载完时。HotSpot把对象内什么偏移量什么类型的数据算出来,在jit编译过程中,也会在特定位置记录下栈和寄存器哪些位置是引用,这样GC在扫描时就可以知道这些信息。【目前主流JVM使用准确式GC】
OopMap可以帮助HotSpot快速且准确完成GC Roots枚举以及确定相关信息。但是也存在一个问题,可能导致引用关系变化。
这个时候有个safepoint(安全点)的概念。
HotSpot中GC不是在任意位置都可以进入,而只能在safepoint处进入。 GC时对一个Java线程来说,它要么处在safepoint,要么不在safepoint。
safepoint不能太少,否则GC等待的时间会很久
safepoint不能太多,否则将增加运行GC的负担
安全点主要存放的位置
1:循环的末尾
+2:方法临返回前/调用方法的call指令后
+3:可能抛异常的位置
参考:关于安全点safepoint
如果说垃圾回收算法是内存回收的方法论,那么垃圾收集器就是具体实现。jvm会结合针对不同的场景及用户的配置使用不同的收集器。
年轻代收集器
+Serial、ParNew、Parallel Scavenge
+老年代收集器
+Serial Old、Parallel Old、CMS收集器
+特殊收集器
+G1收集器[ 新型,不在年轻、老年代范畴内 ]
img 收集器,连线代表可结合使用
最基本、发展最久的收集器,在jdk3以前是gc收集器的唯一选择,Serial是单线程收集器,Serial收集器只能使用一条线程进行收集工作,在收集的时候必须得停掉其它线程,等待收集工作完成其它线程才可以继续工作。
虽然Serial看起来很坑,需停掉别的线程以完成自己的gc工作,但是也不是完全没用的,比如说Serial在运行在Client模式下优于其它收集器[简单高效, 不过一般都是用Server模式,64bit的jvm甚至没Client模式 ]
JVM的Client模式与Server模式
优点:对于Client模式下的jvm来说是个好的选择。适用于单核CPU【现在基本都是多核了】 缺点:收集时要暂停其它线程,有点浪费资源,多核下显得。
可以认为是Serial的升级版,因为它支持多线程[GC线程],而且收集算法、Stop The World、回收策略和Serial一样,就是可以有多个GC线程并发运行,它是HotSpot第一个真正意义实现并发的收集器。默认开启线程数和当前cpu数量相同【几核就是几个,超线程cpu的话就不清楚了 - -】,如果cpu核数很多不想用那么多,可以通过*-XX:ParallelGCThreads*来控制垃圾收集线程的数量。
优点:
+1.支持多线程,多核CPU下可以充分的利用CPU资源
+2.运行在Server模式下新生代首选的收集器【重点是因为新生代的这几个收集器只有它和Serial可以配合CMS收集器一起使用】
+
+缺点: 在单核下表现不会比Serial好,由于在单核能利用多核的优势,在线程收集过程中可能会出现频繁上下文切换,导致额外的开销。
采用复制算法的收集器,和ParNew一样支持多线程。
但是该收集器重点关心的是吞吐量【吞吐量 = 代码运行时间 / (代码运行时间 + 垃圾收集时间) 如果代码运行100min垃圾收集1min,则为99%】
对于用户界面,适合使用GC停顿时间短,不然因为卡顿导致交互界面卡顿将很影响用户体验。
对于后台
高吞吐量可以高效率的利用cpu尽快完成程序运算任务,适合后台运算
Parallel Scavenge注重吞吐量,所以也成为"吞吐量优先"收集器。
和新生代的Serial一样为单线程,Serial的老年代版本,不过它采用"标记-整理算法",这个模式主要是给Client模式下的JVM使用。
如果是Server模式有两大用途
1.jdk5前和Parallel Scavenge搭配使用,jdk5前也只有这个老年代收集器可以和它搭配。
2.作为CMS收集器的后备。
支持多线程,Parallel Scavenge的老年版本,jdk6开始出现, 采用"标记-整理算法"【老年代的收集器大都采用此算法】
在jdk6以前,新生代的Parallel Scavenge只能和Serial Old配合使用【根据图,没有这个的话只剩Serial Old,而Parallel Scavenge又不能和CMS配合使用】,而且Serial Old为单线程Server模式下会拖后腿【多核cpu下无法充分利用】,这种结合并不能让应用的吞吐量最大化。
Parallel Old的出现结合Parallel Scavenge,真正的形成“吞吐量优先”的收集器组合。
CMS收集器(Concurrent Mark Sweep)是以一种获取最短回收停顿时间为目标的收集器。【重视响应,可以带来好的用户体验,被sun称为并发低停顿收集器】
启用CMS:-XX: + UseConcMarkSweepGC
正如其名,CMS采用的是"标记-清除"(Mark Sweep)算法,而且是支持并发(Concurrent)的
它的运作分为4个阶段
1 .初始标记 :标记一下GC Roots能直接关联到的对象,速度很快
+2 .并发标记 :GC Roots Tarcing过程,即可达性分析
+3 .重新标记 :为了修正因并发标记期间用户程序运作而产生变动的那一部分对象的标记记录,会有些许停顿,时间上一般 初始标记 < 重新标记 < 并发标记
+4 .并发清除
以上初始标记和重新标记需要stw(停掉其它运行java线程)
之所以说CMS的用户体验好,是因为CMS收集器的内存回收工作是可以和用户线程一起并发执行。
总体上CMS是款优秀的收集器,但是它也有些缺点。
1.cms堆cpu特别敏感,cms运行线程和应用程序并发执行需要多核cpu,如果cpu核数多的话可以发挥它并发执行的优势,但是cms默认配置启动的时候垃圾线程数为 (cpu数量+3)/4,它的性能很容易受cpu核数影响,当cpu的数目少的时候比如说为为2核,如果这个时候cpu运算压力比较大,还要分一半给cms运作,这可能会很大程度的影响到计算机性能。
2.cms无法处理浮动垃圾,可能导致Concurrent Mode Failure(并发模式故障)而触发full GC
3.由于cms是采用"标记-清除“算法,因此就会存在垃圾碎片的问题,为了解决这个问题cms提供了 -XX:+UseCMSCompactAtFullCollection 选项,这个选项相当于一个开关【默认开启】,用于CMS顶不住要进行full GC时开启内存碎片合并,内存整理的过程是无法并发的,且开启这个选项会影响性能(比如停顿时间变长)
浮动垃圾:由于cms支持运行的时候用户线程也在运行,程序运行的时候会产生新的垃圾,这里产生的垃圾就是浮动垃圾,cms无法当次处理,得等下次才可以。
G1(garbage first:尽可能多收垃圾,避免full gc)收集器是当前最为前沿的收集器之一(1.7以后才开始有),同cms一样也是关注降低延迟,是用于替代cms功能更为强大的新型收集器,因为它解决了cms产生空间碎片等一系列缺陷。
摘自甲骨文:适用于 Java HotSpot VM 的低暂停、服务器风格的分代式垃圾回收器。G1 GC 使用并发和并行阶段实现其目标暂停时间,并保持良好的吞吐量。当 G1 GC 确定有必要进行垃圾回收时,它会先收集存活数据最少的区域(垃圾优先)
g1的特别之处在于它强化了分区,弱化了分代的概念,是区域化、增量式的收集器,它不属于新生代也不属于老年代收集器。
用到的算法为标记-清理、复制算法
jdk1 .7 , 1 .8的都是默认关闭的,更高版本的还不知道
+开启选项 -XX: + UseG1GC
+比如在tomcat的catania .sh启动参数加上
g1是区域化的,它将java堆内存划分为若干个大小相同的区域【region】,jvm可以设置每个region的大小(1-32m,大小得看堆内存大小,必须是2的幂),它会根据当前的堆内存分配合理的region大小。
jdk7中计算region的源码 ,这边博主看了下也看不怎么懂,也翻了下openjdk8的看了下关于region的处理似乎不太一样。。
g1通过并发(并行)标记阶段查找老年代存活对象,通过并行复制压缩存活对象【这样可以省出连续空间供大对象使用】。
g1将一组或多组区域中存活对象以增量并行的方式复制到不同区域进行压缩,从而减少堆碎片,目标是尽可能多回收堆空间【垃圾优先】,且尽可能不超出暂停目标以达到低延迟的目的。
g1提供三种垃圾回收模式 young gc、mixed gc 和 full gc,不像其它的收集器,根据区域而不是分代,新生代老年代的对象它都能回收。
几个重要的默认值,更多的查看官方文档oracle官方g1中文文档
g1是自适应的回收器,提供了若干个默认值,无需修改就可高效运作
+-XX:G1HeapRegionSize =n 设置g1 region大小,不设置的话自己会根据堆大小算,目标是根据最小堆内存划分2048个区域
+-XX:MaxGCPauseMillis =200 最大停顿时间 默认200毫秒
在年轻代Young space
(包括Eden区和Survivor区)中的垃圾回收称之为 Minor GC,Minor GC只会清理年轻代.
Major GC清理老年代(old GC),但是通常也可以指和Full GC是等价,因为收集老年代的时候往往也会伴随着升级年轻代,收集整个Java堆。所以有人问的时候需问清楚它指的是full GC还是old GC。
full gc是对新生代、老年代、永久代【jdk1.8后没有这个概念了】统一的回收。
【知乎R大的回答:收集整个堆,包括young gen、old gen、perm gen(如果存在的话)、元空间(1.8及以上)等所有部分的模式】
混合GC
收集整个young gen以及部分old gen的GC。只有G1有这个模式
要看得懂并理解GC,需要看懂GC日志。
这边我在idea上试了个小例子,需要在idea配置参数(-XX:+PrintGCDetails)。
img public class GCtest {
+ public static void main ( String [] args ) {
+ for ( int i = 0 ; i < 10000 ; i++) {
+ List < String > list = new ArrayList <>();
+ list . add ( "aaaaaaaaaaaaa" );
+ }
+ System . gc ();
+ }
+}
[GC ( System.gc ()) [PSYoungGen: 3998K->688K(38400K)] 3998K->696K(125952K), 0 . 0016551 secs[本次回收时间]] [Times: user= 0 . 01 sys= 0 . 00 , real= 0 . 00 secs]
+[Full GC ( System.gc ()) [PSYoungGen: 688K->0K(38400K)] [ParOldGen: 8K->603K(87552K)] 696K->603K(125952K), [Metaspace: 3210K->3210K(1056768K)], 0 . 0121034 secs] [Times: user= 0 . 01 sys= 0 . 00 , real= 0 . 01 secs]
+Heap
+ PSYoungGen[年轻代] total 38400K, used 333K [ 0x0000000795580000 , 0x0000000798000000 , 0x00000007c0000000 )
+ eden space 33280K, 1 % used [ 0x0000000795580000 , 0x00000007955d34a8 , 0x0000000797600000 )
+ from space 5120K, 0 % used [ 0x0000000797600000 , 0x0000000797600000 , 0x0000000797b00000 )
+ to space 5120K, 0 % used [ 0x0000000797b00000 , 0x0000000797b00000 , 0x0000000798000000 )
+ ParOldGen[老年代] total 87552K, used 603K [ 0x0000000740000000 , 0x0000000745580000 , 0x0000000795580000 )
+ object space 87552K, 0 % used [ 0x0000000740000000 , 0x0000000740096fe8 , 0x0000000745580000 )
+ Metaspace[元空间] used 3217K, capacity 4496K, committed 4864K, reserved 1056768K
+ class space used 352K, capacity 388K, committed 512K, reserved 1048576K
比如sun的gchisto ,gcviewer 离线分析工具,做个笔记先了解下还没用过,可视化好像很好用的样子。
终端输入jconsole就会出现jdk自带的gui监控工具
jconsole 可以根据内存使用情况间接了解内存使用和gc情况
jconsole jstat命令
比如jstat -gcutil pid查看对应java进程gc情况
jstat s0: 新生代survivor space0简称 就是准备复制的那块 单位为%
+s1:指新生代s1已使用百分比,为0的话说明没有存活对象到这边
+e:新生代eden(伊甸园 ) 区域(% )
+o:老年代(% )
+ygc:新生代 次数
+ygct:minor gc耗时
+fgct:full gc耗时(秒 )
+GCT: ygct + fgct 耗时
通过枚举根节点的方式,通过jvm提供的一种oopMap的数据结构,简单来说就是不要再通过去遍历内存里的东西,而是通过OOPMap的数据结构去记录该记录的信息,比如说它可以不用去遍历整个栈,而是扫描栈上面引用的信息并记录下来。
总结:通过OOPMap把栈上代表引用的位置全部记录下来,避免全栈扫描,加快枚举根节点的速度,除此之外还有一个极为重要的作用,可以帮HotSpot实现准确式GC【这边的准确关键就是类型,可以根据给定位置的某块数据知道它的准确类型,HotSpot是通过oopMap外部记录下这些信息,存成映射表一样的东西】。
简单来说,触发的条件就是GC算法区域满了或将满了。
minor GC(young GC ) :当年轻代中eden区分配满的时候触发[值得一提的是因为young GC后部分存活的对象会已到老年代(比如对象熬过15轮),所以过后old gen的占用量通常会变高 ]
+
+full GC:
+①手动调用System.gc( ) 方法 [增加了full GC频率,不建议使用而是让jvm自己管理内存,可以设置-XX:+ DisableExplicitGC来禁止RMI调用System. gc ]
+②发现perm gen(如果存在永久代的话 ) 需分配空间但已经没有足够空间
+③老年代空间不足,比如说新生代的大对象大数组晋升到老年代就可能导致老年代空间不足。
+④CMS GC时出现Promotion Faield[ pf ]
+⑤统计得到的Minor GC晋升到旧生代的平均大小大于老年代的剩余空间。
+这个比较难理解,这是HotSpot为了避免由于新生代晋升到老年代导致老年代空间不足而触发的FUll GC。
+比如程序第一次触发Minor GC后,有5m的对象晋升到老年代,姑且现在平均算5m,那么下次Minor GC发生时,先判断现在老年代剩余空间大小是否超过5m,如果小于5m,则HotSpot则会触发full GC(这点挺智能的 )
Promotion Faield:minor GC时 survivor space放不下[ 满了或对象太大 ],对象只能放到老年代,而老年代也放不下会导致这个错误。
+Concurrent Model Failure:cms时特有的错误,因为cms时垃圾清理和用户线程可以是并发执行的,如果在清理的过程中
+可能原因:
+1 cms触发太晚,可以把XX:CMSInitiatingOccupancyFraction调小[比如-XX: CMSInitiatingOccupancyFraction = 70 是指设定CMS在对内存占用率达到70%的时候开始GC(因为CMS会有浮动垃圾,所以一般都较早启动GC)]
+2 垃圾产生速度大于清理速度,可能是晋升阈值设置过小,Survivor空间小导致跑到老年代,eden区太小,存在大对象、数组对象等情况
+3 .空间碎片过多,可以开启空间碎片整理并合理设置周期时间
full gc导致了concurrent mode failure,而不是因为concurrent mode failure错误导致触发full gc,真正触发full gc的原因可能是ygc时发生的promotion failure。
会,在初始标记的时候会扫描新生代。
虽然cms是老年代收集器,但是我们知道年轻代的对象是可以晋升为老年代的,为了空间分配担保,还是有必要去扫描年轻代。
在minor gc前,jvm会先检查老年代最大可用空间是否大于新生代所有对象总空间,如果是的话,则minor gc可以确保是安全的,
如果担保失败,会检查一个配置(HandlePromotionFailire),即是否允许担保失败。
如果允许:继续检查老年代最大可用可用的连续空间是否大于之前晋升的平均大小,比如说剩10m,之前每次都有9m左右的新生代到老年代,那么将尝试一次minor gc(大于的情况),这会比较冒险。
如果不允许,而且还小于的情况,则会触发full gc。【为了避免经常full GC 该参数建议打开】
这边为什么说是冒险是因为minor gc过后如果出现大对象,由于新生代采用复制算法,survivor无法容纳将跑到老年代,所以才会去计算之前的平均值作为一种担保的条件与老年代剩余空间比较,这就是分配担保。
这种担保是动态概率的手段,但是也有可能出现之前平均都比较低,突然有一次minor gc对象变得很多远高于以往的平均值,这个时候就会导致担保失败【Handle Promotion Failure】,这就只好再失败后再触发一次FULL GC,
这样做的话效率可能会更高,但是old区一般都是熬过多次可达性分析算法过后的存活的对象,要求比较苛刻且空间有限,而不能直接移过去,这将导致一系列问题(比如老年代容易被撑爆)
分两个Survivor(from/to),自然是为了保证复制算法运行以提高效率。
准确来说,垃圾收集器的使用跟当前jvm也有很大的关系,比如说g1是jdk7以后的版本才开始出现。
并不是所有的垃圾收集器都是默认开启的,有些得通过设置相应的开关参数才会使用。比如说cms,需设置(XX:+UseConcMarkSweepGC)
这边有几个实用的命令,比如说server模式下
#UnlockExperimentalVMOptions UnlockDiagnosticVMOptions解锁获取jvm参数,PrintFlagsFinal用于输出xx相关参数,以Benchmark类测试,这边会有很多结果 大都看不懂- - 在这边查(usexxxxxxgc会看到jvm不同收集器的开关情况)
+java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark
+
+#后面跟| grep ":"获取已赋值的参数[加:代表被赋值过]
+java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark | grep ":"
+
+#获得用户自定义的设置或者jvm设置的详细的xx参数和值
+java -server -XX:+PrintCommandLineFlags Benchmark
img 本人用的jdk8,这边UseParallelGC为true,参考深入理解jvm那本书说这个是Parallel Scavenge+Serial old搭配组合的开关,但是网上又说8默认是Parallel Scavenge+Parallel Old,我还是信书的吧 - -。
更多相关参数来源
img 常用参数
据说更高版本的jvm默认使用g1
stop the world简单来说就是gc的时候,停掉除gc外的java线程。
无论什么gc都难以避免停顿,即使是g1也会在初始标记阶段发生,stw并不可怕,可以尽可能的减少停顿时间。
对象优先分配在eden区,eden区满时会触发一次minor GC
对象晋升规则 1 长期存活的对象进入老年代,对象每熬过一次GC年龄+1(默认年龄阈值15,可配置)。 2 对象太大新生代无法容纳则会分配到老年代 3 eden区满了,进行minor gc后,eden和一个survivor区仍然存活的对象无法放到(to survivor区)则会通过分配担保机制放到老年代,这种情况一般是minor gc后新生代存活的对象太多。 4 动态年龄判定,为了使内存分配更灵活,jvm不一定要求对象年龄达到MaxTenuringThreshold(15)才晋升为老年代,若survior区相同年龄对象总大小大于survior区空间的一半,则大于等于这个年龄的对象将会在minor gc时移到老年代
G1 GC 是区域化、并行-并发、增量式垃圾回收器,相比其他 HotSpot 垃圾回收器,可提供更多可预测的暂停。增量的特性使 G1 GC 适用于更大的堆,在最坏的情况下仍能提供不错的响应。G1 GC 的自适应特性使 JVM 命令行只需要软实时暂停时间目标的最大值以及 Java 堆大小的最大值和最小值,即可开始工作。
g1不再区分老年代、年轻代这样的内存空间,这是较以往收集器很大的差异,所有的内存空间就是一块划分为不同子区域,每个区域大小为1m-32m,最多支持的内存为64g左右,且由于它为了的特性适用于大内存机器。
g1回收时堆内存情况 适用场景:
1.像cms能与应用程序并发执行,GC停顿短【短而且可控】,用户体验好的场景。
2.面向服务端,大内存,高cpu的应用机器。【网上说差不多是6g或更大】
3.应用在运行过程中经常会产生大量内存碎片,需要压缩空间【比cms好的地方之一,g1具备压缩功能】。
深入理解Java虚拟机
JVM内存模型、指令重排、内存屏障概念解析
Java对象头
GC收集器
Major GC和Full GC的区别
JVM 垃圾回收 Minor gc vs Major gc vs Full gc
关于准确式GC、保守式GC
关于CMS垃圾收集算法的一些疑惑
图解cms
G1垃圾收集器介绍
详解cms回收机制
JMM 是一种规范,是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题,而且写java代码的时候难免会经常和内存打交道,遇到各种内存溢出问题,有时候又难以定位问题,因此是一定要学习jmm以及GC的。
`,308)]))}const r=s(l,[["render",t],["__file","Java内存模型.html.vue"]]),k=JSON.parse('{"path":"/java/JVM/Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B.html","title":"Java内存模型(JMM)","lang":"zh-CN","frontmatter":{"description":"Java内存模型(JMM) 本文转载自深入理解JVM-内存模型(jmm)和GC 1 CPU和内存的交互 了解jvm内存模型前,了解下cpu和计算机内存的交互情况。【因为Java虚拟机内存模型定义的访问操作与计算机十分相似】 有篇很棒的文章,从cpu讲到内存模型:什么是java内存模型 在计算机中,cpu和内存的交互最为频繁,相比内存,磁盘读写太慢,内存...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/JVM/Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"Java内存模型(JMM)"}],["meta",{"property":"og:description","content":"Java内存模型(JMM) 本文转载自深入理解JVM-内存模型(jmm)和GC 1 CPU和内存的交互 了解jvm内存模型前,了解下cpu和计算机内存的交互情况。【因为Java虚拟机内存模型定义的访问操作与计算机十分相似】 有篇很棒的文章,从cpu讲到内存模型:什么是java内存模型 在计算机中,cpu和内存的交互最为频繁,相比内存,磁盘读写太慢,内存..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/10006199-d3fc8462f127a2c7-20240216171550523.jpg"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-16T09:55:09.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-16T09:55:09.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Java内存模型(JMM)\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/10006199-d3fc8462f127a2c7-20240216171550523.jpg\\",\\"https://github-images.wenzhihuai.com/images/image-20240216172615735.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-0a3299bca20f13ad.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-61e3c01d0b265732.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-a4108d8fb7810a71.jpeg\\",\\"https://github-images.wenzhihuai.com/images/10006199-728567b81e7abff5.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-b55cc68293d1807d.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-76054110706ff110.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-b0fd456c33c09fce.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-9b3fe05daab42136.jpg\\",\\"https://github-images.wenzhihuai.com/images/10006199-318ad80ccb29abe4.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-27ef5c978077ed1c.jpg\\",\\"https://github-images.wenzhihuai.com/images/10006199-6cefc46d23c2d549.jpg\\",\\"https://github-images.wenzhihuai.com/images/10006199-07496d628d676815.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-04a7ea1247b98809.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-854e1de91f66764b.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-975ca350889de014.jpg\\",\\"https://github-images.wenzhihuai.com/images/10006199-239c6e3a1d84a447.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-d409f452f8364937.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-c0eb6418cf4bade9.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-6ed3ee78469592e8.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-a3524986c654e356.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-324780351133d59a.png\\",\\"https://github-images.wenzhihuai.com/images/10006199-8c124d281e0c6dd1.png\\"],\\"dateModified\\":\\"2024-02-16T09:55:09.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"1 CPU和内存的交互","slug":"_1-cpu和内存的交互","link":"#_1-cpu和内存的交互","children":[{"level":3,"title":"1.1.1 内存屏障(Memory Barrier)","slug":"_1-1-1-内存屏障-memory-barrier","link":"#_1-1-1-内存屏障-memory-barrier","children":[]}]},{"level":2,"title":"2. Java内存区域","slug":"_2-java内存区域","link":"#_2-java内存区域","children":[{"level":3,"title":"2.1 五大内存区域","slug":"_2-1-五大内存区域","link":"#_2-1-五大内存区域","children":[]}]},{"level":2,"title":"3.内存溢出","slug":"_3-内存溢出","link":"#_3-内存溢出","children":[]},{"level":2,"title":"4.GC简介","slug":"_4-gc简介","link":"#_4-gc简介","children":[]},{"level":2,"title":"4.1.为什么需要学习GC","slug":"_4-1-为什么需要学习gc","link":"#_4-1-为什么需要学习gc","children":[]},{"level":2,"title":"4.2 堆的回收区域","slug":"_4-2-堆的回收区域","link":"#_4-2-堆的回收区域","children":[]},{"level":2,"title":"5 判断对象是否存活算法","slug":"_5-判断对象是否存活算法","link":"#_5-判断对象是否存活算法","children":[]},{"level":2,"title":"5 垃圾收集算法","slug":"_5-垃圾收集算法","link":"#_5-垃圾收集算法","children":[{"level":3,"title":"5.1 三大垃圾收集算法","slug":"_5-1-三大垃圾收集算法","link":"#_5-1-三大垃圾收集算法","children":[]},{"level":3,"title":"5.2 枚举根节点算法","slug":"_5-2-枚举根节点算法","link":"#_5-2-枚举根节点算法","children":[]}]},{"level":2,"title":"6.垃圾收集器","slug":"_6-垃圾收集器","link":"#_6-垃圾收集器","children":[{"level":3,"title":"新生代收集器","slug":"新生代收集器","link":"#新生代收集器","children":[]},{"level":3,"title":"6.1 Serial","slug":"_6-1-serial","link":"#_6-1-serial","children":[]},{"level":3,"title":"6.2 ParNew收集器","slug":"_6-2-parnew收集器","link":"#_6-2-parnew收集器","children":[]},{"level":3,"title":"6.3 Parallel Scavenge","slug":"_6-3-parallel-scavenge","link":"#_6-3-parallel-scavenge","children":[]},{"level":3,"title":"老年代收集器","slug":"老年代收集器","link":"#老年代收集器","children":[]}]},{"level":2,"title":"6.4 Serial Old","slug":"_6-4-serial-old","link":"#_6-4-serial-old","children":[]},{"level":2,"title":"6.5 Parallel Old","slug":"_6-5-parallel-old","link":"#_6-5-parallel-old","children":[{"level":3,"title":"6.6 CMS","slug":"_6-6-cms","link":"#_6-6-cms","children":[]},{"level":3,"title":"6.7 G1收集器","slug":"_6-7-g1收集器","link":"#_6-7-g1收集器","children":[]}]},{"level":2,"title":"7 Minor GC、Major GC、FULL GC、mixed gc","slug":"_7-minor-gc、major-gc、full-gc、mixed-gc","link":"#_7-minor-gc、major-gc、full-gc、mixed-gc","children":[{"level":3,"title":"7.1 Minor GC","slug":"_7-1-minor-gc","link":"#_7-1-minor-gc","children":[]},{"level":3,"title":"7.2 Major GC","slug":"_7-2-major-gc","link":"#_7-2-major-gc","children":[]},{"level":3,"title":"7.3 Full GC","slug":"_7-3-full-gc","link":"#_7-3-full-gc","children":[]},{"level":3,"title":"7.4 mixed GC【g1特有】","slug":"_7-4-mixed-gc【g1特有】","link":"#_7-4-mixed-gc【g1特有】","children":[]}]},{"level":2,"title":"8 查看GC日志","slug":"_8-查看gc日志","link":"#_8-查看gc日志","children":[{"level":3,"title":"8.3 自带的jconsole工具、jstat命令","slug":"_8-3-自带的jconsole工具、jstat命令","link":"#_8-3-自带的jconsole工具、jstat命令","children":[]}]},{"level":2,"title":"几个疑问","slug":"几个疑问","link":"#几个疑问","children":[{"level":3,"title":"1.GC是怎么判断对象是被标记的","slug":"_1-gc是怎么判断对象是被标记的","link":"#_1-gc是怎么判断对象是被标记的","children":[]},{"level":3,"title":"2.什么时候触发GC","slug":"_2-什么时候触发gc","link":"#_2-什么时候触发gc","children":[]},{"level":3,"title":"3.cms收集器是否会扫描年轻代","slug":"_3-cms收集器是否会扫描年轻代","link":"#_3-cms收集器是否会扫描年轻代","children":[]},{"level":3,"title":"4.什么是空间分配担保","slug":"_4-什么是空间分配担保","link":"#_4-什么是空间分配担保","children":[]},{"level":3,"title":"5.为什么复制算法要分两个Survivor,而不直接移到老年代","slug":"_5-为什么复制算法要分两个survivor-而不直接移到老年代","link":"#_5-为什么复制算法要分两个survivor-而不直接移到老年代","children":[]},{"level":3,"title":"6.各个版本的JVM使用的垃圾收集器是怎么样的","slug":"_6-各个版本的jvm使用的垃圾收集器是怎么样的","link":"#_6-各个版本的jvm使用的垃圾收集器是怎么样的","children":[]},{"level":3,"title":"7 stop the world具体是什么,有没有办法避免","slug":"_7-stop-the-world具体是什么-有没有办法避免","link":"#_7-stop-the-world具体是什么-有没有办法避免","children":[]},{"level":3,"title":"8 新生代什么样的情况会晋升为老年代","slug":"_8-新生代什么样的情况会晋升为老年代","link":"#_8-新生代什么样的情况会晋升为老年代","children":[]},{"level":3,"title":"8.怎么理解g1,适用于什么场景","slug":"_8-怎么理解g1-适用于什么场景","link":"#_8-怎么理解g1-适用于什么场景","children":[]}]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1708075355000,"updatedTime":1708077309000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":3}]},"readingTime":{"minutes":46.11,"words":13833},"filePathRelative":"java/JVM/Java内存模型.md","localizedDate":"2024年2月16日","excerpt":"\\n本文转载自深入理解JVM-内存模型(jmm)和GC
","autoDesc":true}');export{r as comp,k as data};
diff --git "a/assets/Jenkins\347\232\204\344\270\200\344\272\233\347\254\224\350\256\260.html--8cnUWGp.js" "b/assets/Jenkins\347\232\204\344\270\200\344\272\233\347\254\224\350\256\260.html--8cnUWGp.js"
new file mode 100644
index 00000000..cc0397d1
--- /dev/null
+++ "b/assets/Jenkins\347\232\204\344\270\200\344\272\233\347\254\224\350\256\260.html--8cnUWGp.js"
@@ -0,0 +1,16 @@
+import{_ as s,c as a,d as n,o as e}from"./app-ftEjETWs.js";const t={};function h(l,i){return e(),a("div",null,i[0]||(i[0]=[n(`公司主要要开发自己的paas平台,集成了Jenkins,真的是遇到了很多很多困难,特别是在api调用的权限这一块,这里,把自己遇到的一些坑的解决方法做一下笔记吧。当然,首先要讲的,就是如何在开启安全的情况下进行API调用。
如果勾选不对,那么Jenkins有可能崩溃掉,亲身经历,之前一直没有勾选安全域,然后授权策略为登录用户可以做任何事,之后权限这一块就彻底崩溃了,重装了又重装,才知道,需要勾选安全域。
同时开启跨站请求伪造保护,Jenkins的一些API需要用到的。
Jenkins的用户token可以在用户的设置下面获得,但是这种方式如果需要重装Jenkins的话,就得重新修改一次配置文件
经过对Jenkins-client 的抓包分析,token可以由username+":"+password,然后进行base64加密组成,之后在token前面加上"Basic "即可,代码如下:
在远程API调用的时候,Jenkins对于某些接口的要求不仅限于Authorization,还必须要有Jenkins-Crumb,这个东西之前在进行获取的时候,有时候会变来变去,比如用curl命令和f12查看的时候发现不一致,实在受不了,感觉毫无规律可言,之后才发现上面的Authorization来直接调用接口获取的才是正确的,再然后想想,可能是之前调用api的时候,没有开启启用安全,再或者是有没有勾选上使用碎片算法。
另,附上curl查询Jenkins-Crumb的命令:
curl -s 'http://admin:yourtoken@jenkins-url/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'
替换掉yourtoken和jenkins-url即可。
Jenkins的API设计可谓是独领风骚,能把一个提交设计成这样真实佩服测试之后才发现只要提交个表单,key为json,value为值即可,其他的都不需要,这个设计我也不知道怎么来的,感觉超级坑。
由于我们是将Jenkins集成在我们自己的平台里面,并不暴露Jenkins给用户,所以,创建一个job的时候,必须由我们平台的参数往Jenkins里面提交,这一提交,发现的问题不少。 一是Jenkins的整个job的提交是由两步组成的,先是创建job,再提交配置。即:/createItem?name=xxx接口。 二是提交的配置参数,提交的是整个xml,而不是由一个一个参数组成的。对于java来说,就得使用xstream或者其他来转化,甚是折腾,如图这种转化。
在点击立即构建的时候,Jenkins是没有返回任何信息,但是在Jenkins的内部,它是通过放到队列里等待的,如果有空闲,就开始构建,否则等待,这个队列是可以获取得到的,我们从里面可以获取上一次构建的信息,是成功还是失败。这种情况下,假设我们多个人同时点击,这下子就有点慌了,如何获取到具体某个人的构建结果,有点虐心。想了半天,最终得出的事:代码相同,意味着每次构建的结果相同,为什么要允许多个人同时点击?就这么解决了:从一个job的构建队列中获取最后一次构建的信息,如果是正在构建,那么不允许构建了,直到构建结果出来。
需要将Jenkins中的构建进度移植到我们自有的平台,Jenkins的构建进度时通过ajax轮询实现的,获取文本的规则主要从response header里面的两个字段获取 (1)X-More-Data:是否有更多的数据 (2)X-Text-Size:从开始到该次调用的文本大小 我们是通过websocket来将文本内容推送到前端,使用的stomp协议,部分代码如下:
while ( true ) {
+ ...
+ String string = response . body (). string ();
+ String header = response . header ( "X-More-Data" );
+ if ( ! Strings . isNullOrEmpty (header) || start == 0 ) {
+ template . convertAndSend ( "/topic/" + uuid, string);
+ String textSize = response . header ( "X-Text-Size" );
+ if ( ! Strings . isNullOrEmpty (textSize) ) {
+ start = Integer . parseInt (textSize);
+ }
+ TimeUnit . SECONDS . sleep ( 5 );
+ } else {
+ template . convertAndSend ( "/topic/" + uuid, string);
+ return ;
+ }
+ }
参考: 1.通过jenkins API去build一个job 2.Jenkins Remote API
`,34)]))}const k=s(t,[["render",h],["__file","Jenkins的一些笔记.html.vue"]]),r=JSON.parse('{"path":"/kubernetes/Jenkins%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AC%94%E8%AE%B0.html","title":"Jenkins的一些笔记","lang":"zh-CN","frontmatter":{"description":"Jenkins的一些笔记 公司主要要开发自己的paas平台,集成了Jenkins,真的是遇到了很多很多困难,特别是在api调用的权限这一块,这里,把自己遇到的一些坑的解决方法做一下笔记吧。当然,首先要讲的,就是如何在开启安全的情况下进行API调用。 一、在全局安全配置中 1.1 启用安全 如果勾选不对,那么Jenkins有可能崩溃掉,亲身经历,之前一直...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/kubernetes/Jenkins%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AC%94%E8%AE%B0.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"Jenkins的一些笔记"}],["meta",{"property":"og:description","content":"Jenkins的一些笔记 公司主要要开发自己的paas平台,集成了Jenkins,真的是遇到了很多很多困难,特别是在api调用的权限这一块,这里,把自己遇到的一些坑的解决方法做一下笔记吧。当然,首先要讲的,就是如何在开启安全的情况下进行API调用。 一、在全局安全配置中 1.1 启用安全 如果勾选不对,那么Jenkins有可能崩溃掉,亲身经历,之前一直..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/20181027023132911846860.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-24T05:12:56.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-24T05:12:56.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Jenkins的一些笔记\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/20181027023132911846860.png\\",\\"https://github-images.wenzhihuai.com/images/201810270231471528136147.png\\",\\"https://github-images.wenzhihuai.com/images/20181027023526539361439.png\\",\\"https://github-images.wenzhihuai.com/images/20181027024305570167743.png\\",\\"https://github-images.wenzhihuai.com/images/201810270251031329488332.png\\",\\"https://github-images.wenzhihuai.com/images/20181027030059348201424.png\\",\\"https://github-images.wenzhihuai.com/images/20181029112422597829257.png\\"],\\"dateModified\\":\\"2024-02-24T05:12:56.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、在全局安全配置中","slug":"一、在全局安全配置中","link":"#一、在全局安全配置中","children":[]},{"level":2,"title":"二、获取TOKEN","slug":"二、获取token","link":"#二、获取token","children":[]},{"level":2,"title":"三、获取Jenkins-Crumb","slug":"三、获取jenkins-crumb","link":"#三、获取jenkins-crumb","children":[]},{"level":2,"title":"四、值得注意的事","slug":"四、值得注意的事","link":"#四、值得注意的事","children":[]}],"git":{"createdTime":1708751576000,"updatedTime":1708751576000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":3.98,"words":1195},"filePathRelative":"kubernetes/Jenkins的一些笔记.md","localizedDate":"2024年2月24日","excerpt":"\\n公司主要要开发自己的paas平台,集成了Jenkins,真的是遇到了很多很多困难,特别是在api调用的权限这一块,这里,把自己遇到的一些坑的解决方法做一下笔记吧。当然,首先要讲的,就是如何在开启安全的情况下进行API调用。
","autoDesc":true}');export{k as comp,r as data};
diff --git "a/assets/Kubernetes\345\256\271\345\231\250\346\227\245\345\277\227\346\224\266\351\233\206.html-SN4rN7dm.js" "b/assets/Kubernetes\345\256\271\345\231\250\346\227\245\345\277\227\346\224\266\351\233\206.html-SN4rN7dm.js"
new file mode 100644
index 00000000..ea30bd8c
--- /dev/null
+++ "b/assets/Kubernetes\345\256\271\345\231\250\346\227\245\345\277\227\346\224\266\351\233\206.html-SN4rN7dm.js"
@@ -0,0 +1,161 @@
+import{_ as i,c as a,d as n,o as e}from"./app-ftEjETWs.js";const l={};function t(h,s){return e(),a("div",null,s[0]||(s[0]=[n(`日志从传统方式演进到容器方式的过程就不详细讲了,可以参考一下这篇文章Docker日志收集最佳实践 ,由于容器的漂移、自动伸缩等特性,日志收集也就必须使用新的方式来实现,Kubernetes官方给出的方式基本是这三种:原生方式、DaemonSet方式和Sidecar方式。
1.原生方式 使用 kubectl logs 直接在查看本地保留的日志,或者通过docker engine的 log driver 把日志重定向到文件、syslog、fluentd等系统中。2.DaemonSet方式 在K8S的每个node上部署日志agent,由agent采集所有容器的日志到服务端。3.Sidecar方式 一个POD中运行一个sidecar的日志agent容器,用于采集该POD主容器产生的日志。 三种方式都有利有弊,没有哪种方式能够完美的解决100%问题的,所以要根据场景来贴合。
简单的说,原生方式就是直接使用kubectl logs来查看日志,或者将docker的日志通过日志驱动来打到syslog、journal等去,然后再通过命令来排查,这种方式最好的优势就是简单、资源占用率低等,但是,在多容器、弹性伸缩情况下,日志的排查会十分困难,仅仅适用于刚开始研究Kubernetes的公司吧。不过,原生方式确实其他两种方式的基础,因为它的两种最基础的理念,daemonset和sidecar模式都是基于这两种方式而来的。
这种方式是daemonset方式的基础。将日志全部输出到控制台,然后docker开启journal,然后就能在/var/log/journal下面看到二进制的journal日志,如果要查看二进制的日志的话,可以使用journalctl来查看日志:journalctl -u docker.service -n 1 --no-pager -o json -o json-pretty
{
+ "__CURSOR" : "s=113d7df2f5ff4d0985b08222b365c27a;i=1a5744e3;b=05e0fdf6d1814557939e52c0ac7ea76c;m=5cffae4cd4;t=58a452ca82da8;x=29bef852bcd70ae2" ,
+ "__REALTIME_TIMESTAMP" : "1559404590149032" ,
+ "__MONOTONIC_TIMESTAMP" : "399426604244" ,
+ "_BOOT_ID" : "05e0fdf6d1814557939e52c0ac7ea76c" ,
+ "PRIORITY" : "6" ,
+ "CONTAINER_ID_FULL" : "f2108df841b1f72684713998c976db72665f353a3b4ea17cd06b5fc5f0b8ae27" ,
+ "CONTAINER_NAME" : "k8s_controllers_master-controllers-dev4.gcloud.set_kube-system_dcab37be702c9ab6c2b17122c867c74a_1" ,
+ "CONTAINER_TAG" : "f2108df841b1" ,
+ "CONTAINER_ID" : "f2108df841b1" ,
+ "_TRANSPORT" : "journal" ,
+ "_PID" : "6418" ,
+ "_UID" : "0" ,
+ "_GID" : "0" ,
+ "_COMM" : "dockerd-current" ,
+ "_EXE" : "/usr/bin/dockerd-current" ,
+ "_CMDLINE" : "/usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --init-path=/usr/libexec/docker/docker-init-current --seccomp-profile=/etc/docker/seccomp.json --selinux-enabled=false --log-driver=journald --insecure-registry hub.paas.kjtyun.com --insecure-registry hub.gcloud.lab --insecure-registry 172.30.0.0/16 --log-level=warn --signature-verification=false --max-concurrent-downloads=20 --max-concurrent-uploads=20 --storage-driver devicemapper --storage-opt dm.fs=xfs --storage-opt dm.thinpooldev=/dev/mapper/docker--vg-docker--pool --storage-opt dm.use_deferred_removal=true --storage-opt dm.use_deferred_deletion=true --mtu=1450" ,
+ "_CAP_EFFECTIVE" : "1fffffffff" ,
+ "_SYSTEMD_CGROUP" : "/system.slice/docker.service" ,
+ "_SYSTEMD_UNIT" : "docker.service" ,
+ "_SYSTEMD_SLICE" : "system.slice" ,
+ "_MACHINE_ID" : "225adcce13bd233a56ab481df7413e0b" ,
+ "_HOSTNAME" : "dev4.gcloud.set" ,
+ "MESSAGE" : "I0601 23:56:30.148153 1 event.go:221] Event(v1.ObjectReference{Kind: \\" DaemonSet \\" , Namespace: \\" openshift-monitoring \\" , Name: \\" node-exporter \\" , UID: \\" f6d2bdc1-6658-11e9-aca2-fa163e938959 \\" , APIVersion: \\" apps/v1 \\" , ResourceVersion: \\" 15378688 \\" , FieldPath: \\"\\" }): type: 'Normal' reason: 'SuccessfulCreate' Created pod: node-exporter-hvrpf" ,
+ "_SOURCE_REALTIME_TIMESTAMP" : "1559404590148488"
+}
在上面的json中,_CMDLINE以及其他字段占用量比较大,而且这些没有什么意义,会导致一条简短的日志却被封装成多了几十倍的量,所以的在日志量特别大的情况下,最好进行一下字段的定制,能够减少就减少。 我们一般需要的字段是CONTAINER_NAME以及MESSAGE,通过CONTAINER_NAME可以获取到Kubernetes的namespace和podName,比如CONTAINER_NAME为k8s_controllers_master-controllers-dev4.gcloud.set_kube-system_dcab37be702c9ab6c2b17122c867c74a_1的时候container name in pod: controllers **pod name: **master-controllers-dev4.gcloud.setnamespace: kube-system **pod uid: **dcab37be702c9ab6c2b17122c867c74a_1
journal方式算是比较标准的方式,如果采用hostPath方式,能够直接将日志输出这里。这种方式唯一的缺点就是在旧Kubernetes中无法获取到podName,但是最新版的Kubernetes1.14的一些特性subPathExpr,就是可以将目录挂载的时候同时将podName写进目录里,但是这个特性仍旧是alpha版本,谨慎使用。 简单说下实现原理:容器中填写的日志目录,挂载到宿主机的/data/logs/namespace/service_name/$(PodName)/xxx.log里面,如果是sidecar模式,则将改目录挂载到sidecar的收集目录里面进行推送。如果是宿主机安装fluentd模式,则需要匹配编写代码实现识别namespace、service_name、PodName等,然后发送到日志系统。
可参考:https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/20181029-volume-subpath-env-expansion.md 日志落盘参考细节:
env :
+ - name : POD_NAME
+ valueFrom :
+ fieldRef :
+ apiVersion : v1
+ fieldPath : metadata.name
+ ...
+ volumeMounts :
+ - name : workdir1
+ mountPath : /logs
+ subPathExpr : $(POD_NAME)
我们主要使用了在Pod里的主容器挂载了一个fluent-agent的收集器,来将日志进行收集,其中我们修改了Kubernetes-Client的源码使之支持subPathExpr,然后发送到日志系统的kafka。这种方式能够处理多种日志的收集,比如业务方的日志打到控制台了,但是jvm的日志不能同时打到控制台,否则会发生错乱,所以,如果能够将业务日志挂载到宿主机上,同时将一些其他的日志比如jvm的日志挂载到容器上,就可以使用该种方式。
{
+ "_fileName" : "/data/work/logs/epaas_2019-05-22-0.log" ,
+ "_sortedId" : "660c2ce8-aacc-42c4-80d1-d3f6d4c071ea" ,
+ "_collectTime" : "2019-05-22 17:23:58" ,
+ "_log" : "[33m2019-05-22 17:23:58[0;39m |[34mINFO [0;39m |[34mmain[0;39m |[34mSpringApplication.java:679[0;39m |[32mcom.hqyg.epaas.EpaasPortalApplication[0;39m | The following profiles are active: dev" ,
+ "_domain" : "rongqiyun-dev" ,
+ "_podName" : "aofjweojo-5679849765-gncbf" ,
+ "_hostName" : "dev4.gcloud.set"
+}
daemonset方式也是基于journal,日志使用journal的log-driver,变成二进制的日志,然后在每个node节点上部署一个日志收集的agent,挂载/var/log/journal的日志进行解析,然后发送到kafka或者es,如果节点或者日志量比较大的话,对es的压力实在太大,所以,我们选择将日志推送到kafka。容器日志收集普遍使用fluentd,资源要求较少,性能高,是目前最成熟的日志收集方案,可惜是使用了ruby来写的,普通人根本没时间去话时间学习这个然后进行定制,好在openshift中提供了origin-aggregated-logging 方案。 我们可以通过fluent.conf来看origin-aggregated-logging做了哪些工作,把注释,空白的一些东西去掉,然后我稍微根据自己的情况修改了下,结果如下:
@include configs.d/openshift/system.conf
+设置fluent的日志级别
+@include configs.d/openshift/input-pre-*.conf
+最主要的地方,读取journal的日志
+@include configs.d/dynamic/input-syslog-*.conf
+读取syslog,即操作日志
+<label @INGRESS>
+ @include configs.d/openshift/filter-retag-journal.conf
+ 进行匹配
+ @include configs.d/openshift/filter-k8s-meta.conf
+ 获取Kubernetes的相关信息
+ @include configs.d/openshift/filter-viaq-data-model.conf
+ 进行模型的定义
+ @include configs.d/openshift/filter-post-*.conf
+ 生成es的索引id
+ @include configs.d/openshift/filter-k8s-record-transform.conf
+ 修改日志记录,我们在这里进行了字段的定制,移除了不需要的字段
+ @include configs.d/openshift/output-applications.conf
+ 输出,默认是es,如果想使用其他的比如kafka,需要自己定制
+</label>
当然,细节上并没有那么好理解,换成一步步理解如下:
1. 解析journal日志 origin-aggregated-logging会将二进制的journal日志中的CONTAINER_NAME进行解析,根据匹配规则将字段进行拆解
"kubernetes" : {
+ "container_name" : "fas-dataservice-dev-new" ,
+ "namespace_name" : "fas-cost-dev" ,
+ "pod_name" : "fas-dataservice-dev-new-5c48d7c967-kb79l" ,
+ "pod_id" : "4ad125bb7558f52e30dceb3c5e88dc7bc160980527356f791f78ffcaa6d1611c" ,
+ "namespace_id" : "f95238a6-3a67-11e9-a211-20040fe7b690"
+ }
2. es封装 主要用的是elasticsearch_genid_ext插件,写在了filter-post-genid.conf上。
3. 日志分类 通过origin-aggregated-logging来收集journal的日志,然后推送至es,origin-aggregated-logging在推送过程中做了不少优化,即适应高ops的、带有等待队列的、推送重试等,详情可以具体查看一下。
还有就是对日志进行了分类,分为三种:(1).操作日志 (在es中以.operations匹配的),记录了对Kubernetes的操作(2).项目日志 (在es中以project 匹配的),业务日志,日志收集中最重要的(3).孤儿日志 (在es中以.orphaned.*匹配的),没有namespace的日志都会打到这里
4. 日志字段定制 经过origin-aggregated-logging推送至后采集的一条日志如下:
{
+ "CONTAINER_TAG" : "4ad125bb7558" ,
+ "docker" : {
+ "container_id" : "4ad125bb7558f52e30dceb3c5e88dc7bc160980527356f791f78ffcaa6d1611c"
+ },
+ "kubernetes" : {
+ "container_name" : "fas-dataservice-dev-new" ,
+ "namespace_name" : "fas-cost-dev" ,
+ "pod_name" : "fas-dataservice-dev-new-5c48d7c967-kb79l" ,
+ "pod_id" : "4ad125bb7558f52e30dceb3c5e88dc7bc160980527356f791f78ffcaa6d1611c" ,
+ "namespace_id" : "f95238a6-3a67-11e9-a211-20040fe7b690"
+ },
+ "systemd" : {
+ "t" : {
+ "BOOT_ID" : "6246327d7ea441339d6d14b44498b177" ,
+ "CAP_EFFECTIVE" : "1fffffffff" ,
+ "CMDLINE" : "/usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --init-path=/usr/libexec/docker/docker-init-current --seccomp-profile=/etc/docker/seccomp.json --selinux-enabled=false --log-driver=journald --insecure-registry hub.paas.kjtyun.com --insecure-registry 10.77.0.0/16 --log-level=warn --signature-verification=false --bridge=none --max-concurrent-downloads=20 --max-concurrent-uploads=20 --storage-driver devicemapper --storage-opt dm.fs=xfs --storage-opt dm.thinpooldev=/dev/mapper/docker--vg-docker--pool --storage-opt dm.use_deferred_removal=true --storage-opt dm.use_deferred_deletion=true --mtu=1450" ,
+ "COMM" : "dockerd-current" ,
+ "EXE" : "/usr/bin/dockerd-current" ,
+ "GID" : "0" ,
+ "MACHINE_ID" : "0096083eb4204215a24efd202176f3ec" ,
+ "PID" : "17181" ,
+ "SYSTEMD_CGROUP" : "/system.slice/docker.service" ,
+ "SYSTEMD_SLICE" : "system.slice" ,
+ "SYSTEMD_UNIT" : "docker.service" ,
+ "TRANSPORT" : "journal" ,
+ "UID" : "0"
+ }
+ },
+ "level" : "info" ,
+ "message" : " \\t at com.sun.proxy.$Proxy242.execute(Unknown Source)" ,
+ "hostname" : "host11.rqy.kx" ,
+ "pipeline_metadata" : {
+ "collector" : {
+ "ipaddr4" : "10.76.232.16" ,
+ "ipaddr6" : "fe80::a813:abff:fe66:3b0c" ,
+ "inputname" : "fluent-plugin-systemd" ,
+ "name" : "fluentd" ,
+ "received_at" : "2019-05-15T09:22:39.297151+00:00" ,
+ "version" : "0.12.43 1.6.0"
+ }
+ },
+ "@timestamp" : "2019-05-06T01:41:01.960000+00:00" ,
+ "viaq_msg_id" : "NjllNmI1ZWQtZGUyMi00NDdkLWEyNzEtMTY3MDQ0ZjEyZjZh"
+ }
可以看出,跟原生的journal日志类似,增加了几个字段为了写进es中而已,总体而言,其他字段并没有那么重要,所以我们对其中的字段进行了定制,以减少日志的大小,定制化字段之后,一段日志的输出变为(不是同一段,只是举个例子):
{
+ "hostname" : "dev18.gcloud.set" ,
+ "@timestamp" : "2019-05-17T04:22:33.139608+00:00" ,
+ "pod_name" : "istio-pilot-8588fcb99f-rqtkd" ,
+ "appName" : "discovery" ,
+ "container_name" : "epaas-discovery" ,
+ "domain" : "istio-system" ,
+ "sortedId" : "NjA3ODVhODMtZDMyYy00ZWMyLWE4NjktZjcwZDMwMjNkYjQ3" ,
+ "log" : "spiffluster.local/ns/istio-system/sa/istio-galley-service-account"
+}
5.部署 最后,在node节点上添加logging-infra-fluentd: "true"的标签,就可以在namespace为openshift-logging中看到节点的收集器了。
logging-fluentd-29p8z 1/1 Running 0 6d
+logging-fluentd-bpkjt 1/1 Running 0 6d
+logging-fluentd-br9z5 1/1 Running 0 6d
+logging-fluentd-dkb24 1/1 Running 1 5d
+logging-fluentd-lbvbw 1/1 Running 0 6d
+logging-fluentd-nxmk9 1/1 Running 1 5d
6.关于ip 业务方不仅仅想要podName,同时还有对ip的需求,控制台方式正常上是没有记录ip的,所以这算是一个难点中的难点,我们在kubernetes_metadata_common.rb的kubernetes_metadata中添加了 'pod_ip' => pod_object['status']['podIP'],最终是有些有ip,有些没有ip,这个问题我们继续排查。
这种方式的好处是能够获取日志的文件名、容器的ip地址等,并且配置性比较高,能够很好的进行一系列定制化的操作,比如使用log-pilot或者filebeat或者其他的收集器,还能定制一些特定的字段,比如文件名、ip地址等。 sidecar模式用来解决日志收集的问题的话,需要将日志目录挂载到宿主机的目录上,然后再mount到收集agent的目录里面,以达到文件共享的目的,默认情况下,使用emptydir来实现文件共享的目的,这里简单介绍下emptyDir的作用。 EmptyDir类型的volume创建于pod被调度到某个宿主机上的时候,而同一个pod内的容器都能读写EmptyDir中的同一个文件。一旦这个pod离开了这个宿主机,EmptyDir中的数据就会被永久删除。所以目前EmptyDir类型的volume主要用作临时空间,比如Web服务器写日志或者tmp文件需要的临时目录。 日志如果丢失的话,会对业务造成的影响不可估量,所以,我们使用了尚未成熟的subPathExpr来实现,即挂载到宿主的固定目录/data/logs下,然后是namespace,deploymentName,podName,再然后是日志文件,合成一块便是/data/logs/\${namespace}/\${deploymentName}/\${podName}/xxx.log。 具体的做法就不在演示了,这里只贴一下yaml文件。
apiVersion : extensions/v1beta1
+kind : Deployment
+metadata :
+ name : xxxx
+ namespace : element-dev
+spec :
+ template :
+ spec :
+ volumes :
+ - name : host-log-path-0
+ hostPath :
+ path : /data/logs/element-dev/xxxx
+ type : DirectoryOrCreate
+ containers :
+ - name : xxxx
+ image : 'xxxxxxx'
+ volumeMounts :
+ - name : host-log-path-0
+ mountPath : /data/work/logs/
+ subPathExpr : $(POD_NAME)
+ - name : xxxx-elog-agent
+ image : 'agent'
+ volumeMounts :
+ - name : host-log-path-0
+ mountPath : /data/work/logs/
+ subPathExpr : $(POD_NAME)
fluent.conf的配置文件由于保密关系就不贴了,收集后的一条数据如下:
{
+ "_fileName" : "/data/work/logs/xxx_2019-05-22-0.log" ,
+ "_sortedId" : "660c2ce8-aacc-42c4-80d1-d3f6d4c071ea" ,
+ "_collectTime" : "2019-05-22 17:23:58" ,
+ "_log" : "[33m2019-05-22 17:23:58[0;39m |[34mINFO [0;39m |[34mmain[0;39m |[34mSpringApplication.java:679[0;39m |[32mcom.hqyg.epaas.EpaasPortalApplication[0;39m | The following profiles are active: dev" ,
+ "_domain" : "namespace" ,
+ "_ip" : "10.128.93.31" ,
+ "_podName" : "xxxx-5679849765-gncbf" ,
+ "_hostName" : "dev4.gcloud.set"
+}
总的来说,daemonset方式比较简单,而且适合更加适合微服务化,当然,不是完美的,比如业务方想把业务日志打到控制台上,但是同时也想知道jvm的日志,这种情况下或许sidecar模式更好。但是sidecar也有不完美的地方,每个pod里都要存在一个日志收集的agent实在是太消耗资源了,而且很多问题也难以解决,比如:主容器挂了,agent还没收集完,就把它给kill掉,这个时候日志怎么处理,业务会不会受到要杀掉才能启动新的这一短暂过程的影响等。所以,我们实际使用中首选daemonset方式,但是提供了sidecar模式让用户选择。
参考: 1.Kubernetes日志官方文档 2.Kubernetes日志采集Sidecar模式介绍 3.Docker日志收集最佳实践
`,41)]))}const k=i(l,[["render",t],["__file","Kubernetes容器日志收集.html.vue"]]),d=JSON.parse('{"path":"/kubernetes/Kubernetes%E5%AE%B9%E5%99%A8%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86.html","title":"Kubernetes容器日志收集","lang":"zh-CN","frontmatter":{"description":"Kubernetes容器日志收集 日志采集方式 日志从传统方式演进到容器方式的过程就不详细讲了,可以参考一下这篇文章Docker日志收集最佳实践,由于容器的漂移、自动伸缩等特性,日志收集也就必须使用新的方式来实现,Kubernetes官方给出的方式基本是这三种:原生方式、DaemonSet方式和Sidecar方式。 1.原生方式 使用 kubectl ...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/kubernetes/Kubernetes%E5%AE%B9%E5%99%A8%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"Kubernetes容器日志收集"}],["meta",{"property":"og:description","content":"Kubernetes容器日志收集 日志采集方式 日志从传统方式演进到容器方式的过程就不详细讲了,可以参考一下这篇文章Docker日志收集最佳实践,由于容器的漂移、自动伸缩等特性,日志收集也就必须使用新的方式来实现,Kubernetes官方给出的方式基本是这三种:原生方式、DaemonSet方式和Sidecar方式。 1.原生方式 使用 kubectl ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://upyuncdn.wenzhihuai.com/201906020557591917511053.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-24T05:35:53.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-24T05:35:53.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Kubernetes容器日志收集\\",\\"image\\":[\\"https://upyuncdn.wenzhihuai.com/201906020557591917511053.png\\",\\"https://upyuncdn.wenzhihuai.com/201906020558431636899655.png\\",\\"https://upyuncdn.wenzhihuai.com/201906020559061972119021.png\\"],\\"dateModified\\":\\"2024-02-24T05:35:53.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":3,"title":"1.1 控制台stdout方式","slug":"_1-1-控制台stdout方式","link":"#_1-1-控制台stdout方式","children":[]},{"level":3,"title":"1.2 新版本的subPathExpr","slug":"_1-2-新版本的subpathexpr","link":"#_1-2-新版本的subpathexpr","children":[]}]},{"level":2,"title":"二、Daemonset方式","slug":"二、daemonset方式","link":"#二、daemonset方式","children":[]},{"level":2,"title":"三、Sidecar模式","slug":"三、sidecar模式","link":"#三、sidecar模式","children":[]},{"level":2,"title":"四、总结","slug":"四、总结","link":"#四、总结","children":[]}],"git":{"createdTime":1708751576000,"updatedTime":1708752953000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":10.62,"words":3187},"filePathRelative":"kubernetes/Kubernetes容器日志收集.md","localizedDate":"2024年2月24日","excerpt":"\\n日志采集方式 \\n日志从传统方式演进到容器方式的过程就不详细讲了,可以参考一下这篇文章Docker日志收集最佳实践 ,由于容器的漂移、自动伸缩等特性,日志收集也就必须使用新的方式来实现,Kubernetes官方给出的方式基本是这三种:原生方式、DaemonSet方式和Sidecar方式。
","autoDesc":true}');export{k as comp,d as data};
diff --git "a/assets/RedissonLock\345\210\206\345\270\203\345\274\217\351\224\201\346\272\220\347\240\201\345\210\206\346\236\220.html-DBlO1MVO.js" "b/assets/RedissonLock\345\210\206\345\270\203\345\274\217\351\224\201\346\272\220\347\240\201\345\210\206\346\236\220.html-DBlO1MVO.js"
new file mode 100644
index 00000000..f21b831c
--- /dev/null
+++ "b/assets/RedissonLock\345\210\206\345\270\203\345\274\217\351\224\201\346\272\220\347\240\201\345\210\206\346\236\220.html-DBlO1MVO.js"
@@ -0,0 +1,199 @@
+import{_ as i,c as a,d as n,o as l}from"./app-ftEjETWs.js";const h={};function k(t,s){return l(),a("div",null,s[0]||(s[0]=[n(`最近碰到的一个问题,Java代码中写了一个定时器,分布式部署的时候,多台同时执行的话就会出现重复的数据,为了避免这种情况,之前是通过在配置文件里写上可以执行这段代码的IP,代码中判断如果跟这个IP相等,则执行,否则不执行,想想也是一种比较简单的方式吧,但是感觉很low很low,所以改用分布式锁。 目前分布式锁常用的三种方式:1.数据库的锁;2.基于Redis的分布式锁;3.基于ZooKeeper的分布式锁。其中数据库中的锁有共享锁和排他锁,这两种都无法直接解决数据库的单点和可重入的问题,所以,本章还是来讲讲基于Redis的分布式锁,也可以用其他缓存(Memcache、Tair等)来实现。
互斥性。在任何时候,当且仅有一个客户端能够持有锁。 不能有死锁。持有锁的客户端崩溃后,后续客户端能够加锁。 容错性。大部分Redis或者ZooKeeper节点能够正常运行。 加锁解锁相同。加锁的客户端和解锁的客户端必须为同一个客户端,不能让其他的解锁了。 1.SETNX key val 当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。2.expire key timeout 为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。3.delete key 删除key,此处用来解锁使用。4.HEXISTS key field 当key 中存储着field的时候返回1,如果key或者field至少有一个不存在返回0。5.HINCRBY key field increment 将存储在 key 中的哈希(Hash)对象中的指定字段 field 的值加上增量 increment。如果键 key 不存在,一个保存了哈希对象的新建将被创建。如果字段 field 不存在,在进行当前操作前,其将被创建,且对应的值被置为 0。返回值是增量之后的值。
由上面三个命令,我们可以很快的写一个分布式锁出来:
if ( conn . setnx ( "lock" , "1" ). equals ( 1L ) ) {
+ //do something
+ return true ;
+}
+return false ;
但是这样也会存在问题,如果获取该锁的客户端挂掉了怎么办?一般而言,我们可以通过设置expire的过期时间来防止客户端挂掉所带来的影响,可以降低应用挂掉所带来的影响,不过当时间失效的时候,要保证其他客户端只有一台能够获取。
Redisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在Java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。——摘自百度百科
先在pom引入Redssion
< dependency >
+ < groupId >org.redisson</ groupId >
+ < artifactId >redisson</ artifactId >
+ < version >3.6.1</ version >
+</ dependency >
起100个线程,同时对count进行操作,每次操作减1,加锁的时候能够保持顺序输出,不加的话为随机。
public class RedissonTest implements Runnable {
+ private static RedissonClient redisson ;
+ private static int count = 10000 ;
+
+ private static void init () {
+ Config config = new Config ();
+ config . useSingleServer ()
+ . setAddress ( "redis://119.23.46.71:6340" )
+ . setPassword ( "root" )
+ . setDatabase ( 10 );
+ redisson = Redisson . create (config);
+ }
+
+ @ Override
+ public void run () {
+ RLock lock = redisson . getLock ( "anyLock" );
+ lock . lock ();
+ count--;
+ System . out . println (count);
+ lock . unlock ();
+ }
+
+ public static void main ( String [] args ) {
+ init ();
+ for ( int i = 0 ; i < 100 ; i++) {
+ new Thread ( new RedissonTest ()). start ();
+ }
+ }
+}
输出结果(部分结果):
...
+9930
+9929
+9928
+9927
+9926
+9925
+9924
+9923
+9922
+9921
+
+...
去掉lock.lock()和lock.unlock()之后(部分结果):
...
+9930
+9931
+9933
+9935
+9938
+9937
+9940
+9941
+9942
+9944
+9947
+9946
+9914
+...
最新版的Redisson要求redis能够支持eval的命令,否则无法实现,即Redis要求2.6版本以上。在lua脚本中可以调用大部分的Redis命令,使用脚本的好处如下:(1)减少网络开销 :在Redis操作需求需要向Redis发送5次请求,而使用脚本功能完成同样的操作只需要发送一个请求即可,减少了网络往返时延。(2)原子操作 :Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说在编写脚本的过程中无需担心会出现竞态条件,也就无需使用事务。事务可以完成的所有功能都可以用脚本来实现。(3)复用 :客户端发送的脚本会永久存储在Redis中,这就意味着其他客户端(可以是其他语言开发的项目)可以复用这一脚本而不需要使用代码完成同样的逻辑。
全局变量:expirationRenewalMap :存储entryName和其过期时间,底层用的netty的PlatformDependent.newConcurrentHashMap()internalLockLeaseTime :锁默认释放的时间:30 * 1000,即30秒id :UUID,用作客户端的唯一标识PUBSUB :订阅者模式,当释放锁的时候,其他客户端能够知道锁已经被释放的消息,并让队列中的第一个消费者获取锁。使用PUB/SUB消息机制的优点:减少申请锁时的等待时间、安全、 锁带有超时时间、锁的标识唯一,防止死锁 锁设计为可重入,避免死锁。commandExecutor :命令执行器,异步执行器
以lock.lock()为例,调用lock之后,底层使用的是lockInterruptibly,之后调用lockInterruptibly(-1, null);
(1)我们来看一下lockInterruptibly的源码,如果别的客户端没有加锁,则当前客户端进行加锁并且订阅,其他客户端尝试加锁,并且获取ttl,然后等待已经加了锁的客户端解锁。
//leaseTime默认为-1
+public void lockInterruptibly ( long leaseTime , TimeUnit unit) throws InterruptedException {
+ long threadId = Thread . currentThread (). getId (); //获取当前线程ID
+ Long ttl = tryAcquire (leaseTime , unit , threadId) ; //尝试加锁
+ // 如果为空,当前线程获取锁成功,否则已经被其他客户端加锁
+ if (ttl == null ) {
+ return ;
+ }
+ //等待释放,并订阅锁
+ RFuture < RedissonLockEntry > future = subscribe (threadId) ;
+ commandExecutor . syncSubscription (future);
+ try {
+ while ( true ) {
+ // 重新尝试获取锁
+ ttl = tryAcquire (leaseTime , unit , threadId) ;
+ // 成功获取锁
+ if (ttl == null ) {
+ break ;
+ }
+ // 等待锁释放
+ if (ttl >= 0 ) {
+ getEntry (threadId) . getLatch (). tryAcquire (ttl, TimeUnit . MILLISECONDS );
+ } else {
+ getEntry (threadId) . getLatch (). acquire ();
+ }
+ }
+ } finally {
+ // 取消订阅
+ unsubscribe (future , threadId) ;
+ }
+}
(2)下面是tryAcquire的实现,调用的是tryAcquireAsync
private Long tryAcquire ( long leaseTime , TimeUnit unit , long threadId) {
+ return get ( tryAcquireAsync (leaseTime , unit , threadId)) ;
+ }
(3)下面是tryAcquireAsync的实现,异步尝试进行加锁,尝试加锁的时候leaseTime为-1。通常如果客户端没有加锁成功,则会进行阻塞,leaseTime为锁释放的时间。
private < T > RFuture < Long > tryAcquireAsync ( long leaseTime , TimeUnit unit , final long threadId) {
+ if (leaseTime != - 1 ) { //在lock.lock()的时候,已经声明了leaseTime为-1,尝试加锁
+ return tryLockInnerAsync (leaseTime , unit , threadId , RedisCommands . EVAL_LONG ) ;
+ }
+ RFuture < Long > ttlRemainingFuture = tryLockInnerAsync ( commandExecutor . getConnectionManager (). getCfg (). getLockWatchdogTimeout (), TimeUnit . MILLISECONDS , threadId , RedisCommands . EVAL_LONG ) ;
+ //监听事件,订阅消息
+ ttlRemainingFuture . addListener ( new FutureListener < Long >() {
+ @ Override
+ public void operationComplete ( Future < Long > future ) throws Exception {
+ if ( ! future . isSuccess ()) {
+ return ;
+ }
+ Long ttlRemaining = future . getNow ();
+ // lock acquired
+ if (ttlRemaining == null ) {
+ //获取新的超时时间
+ scheduleExpirationRenewal (threadId);
+ }
+ }
+ });
+ return ttlRemainingFuture ; //返回ttl时间
+}
(4)下面是tryLockInnerAsyncy异步加锁,使用lua能够保证操作是原子性的
< T > RFuture < T > tryLockInnerAsync ( long leaseTime , TimeUnit unit , long threadId , RedisStrictCommand < T > command) {
+ internalLockLeaseTime = unit . toMillis (leaseTime);
+ return commandExecutor . evalWriteAsync ( getName (), LongCodec . INSTANCE , command,
+ "if (redis.call('exists', KEYS[1]) == 0) then " +
+ "redis.call('hset', KEYS[1], ARGV[2], 1); " +
+ "redis.call('pexpire', KEYS[1], ARGV[1]); " +
+ "return nil; " +
+ "end; " +
+ "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
+ "redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
+ "redis.call('pexpire', KEYS[1], ARGV[1]); " +
+ "return nil; " +
+ "end; " +
+ "return redis.call('pttl', KEYS[1]);" ,
+ Collections. < Object > singletonList ( getName ()), internalLockLeaseTime, getLockName (threadId));
+}
参数KEYS[1] (getName()) :需要加锁的key,这里需要是字符串类型。ARGV[1] (internalLockLeaseTime) :锁的超时时间,防止死锁ARGV[2] (getLockName(threadId)) :锁的唯一标识,也就是刚才介绍的 id(UUID.randomUUID()) + “:” + threadId lua脚本解释
--检查key是否被占用了,如果没有则设置超时时间和唯一标识,初始化value=1
+if ( redis . call ( 'exists' , KEYS [ 1 ]) == 0 ) then
+ redis . call ( 'hset' , KEYS [ 1 ], ARGV [ 2 ], 1 );
+ redis . call ( 'pexpire' , KEYS [ 1 ], ARGV [ 1 ]);
+ return nil ;
+end ;
+--如果锁重入,需要判断锁的key field 都一致情况下 value 加一
+if ( redis . call ( 'hexists' , KEYS [ 1 ], ARGV [ 2 ]) == 1 ) then
+ redis . call ( 'hincrby' , KEYS [ 1 ], ARGV [ 2 ], 1 );
+ --锁重入重新设置超时时间
+ redis . call ( 'pexpire' , KEYS [ 1 ], ARGV [ 1 ]);
+ return nil ;
+end ;
+--返回剩余的过期时间
+return redis . call ( 'pttl' , KEYS [ 1 ]);
(5)流程图
解锁的代码很简单,大意是将该节点删除,并发布消息。 (1)unlock源码
public void unlock () {
+ Boolean opStatus = get ( unlockInnerAsync ( Thread . currentThread (). getId () )) ;
+ if (opStatus == null ) {
+ throw new IllegalMonitorStateException ( "attempt to unlock lock, not locked by current thread by node id: "
+ + id + " thread-id: " + Thread . currentThread (). getId () ) ;
+ }
+ if (opStatus) {
+ cancelExpirationRenewal () ;
+ }
(2)异步解锁,并返回是否成功
protected RFuture < Boolean > unlockInnerAsync ( long threadId) {
+ return commandExecutor . evalWriteAsync ( getName (), LongCodec . INSTANCE , RedisCommands . EVAL_BOOLEAN ,
+ "if (redis.call('exists', KEYS[1]) == 0) then " +
+ "redis.call('publish', KEYS[2], ARGV[1]); " +
+ "return 1; " +
+ "end;" +
+ "if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then " +
+ "return nil;" +
+ "end; " +
+ "local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); " +
+ "if (counter > 0) then " +
+ "redis.call('pexpire', KEYS[1], ARGV[2]); " +
+ "return 0; " +
+ "else " +
+ "redis.call('del', KEYS[1]); " +
+ "redis.call('publish', KEYS[2], ARGV[1]); " +
+ "return 1; " +
+ "end; " +
+ "return nil;" ,
+ Arrays. < Object > asList ( getName (), getChannelName ()), LockPubSub . unlockMessage , internalLockLeaseTime, getLockName (threadId));
+
+ }
输入的参数有: 参数:KEYS[1] (getName()):需要加锁的key,这里需要是字符串类型。KEYS[2] (getChannelName()):redis消息的ChannelName,一个分布式锁对应唯一的一个 channelName:“redisson_lock__channel__{” + getName() + “}”ARGV[1] (LockPubSub.unlockMessage):redis消息体,这里只需要一个字节的标记就可以,主要标记redis的key已经解锁,再结合redis的Subscribe,能唤醒其他订阅解锁消息的客户端线程申请锁。ARGV[2] (internalLockLeaseTime):锁的超时时间,防止死锁ARGV[3] (getLockName(threadId)) :锁的唯一标识,也就是刚才介绍的 id(UUID.randomUUID()) + “:” + threadId
此处lua脚本的作用:
--如果keys[1]不存在,则发布消息,说明已经被解锁了
+if ( redis . call ( 'exists' , KEYS [ 1 ]) == 0 ) then
+ redis . call ( 'publish' , KEYS [ 2 ], ARGV [ 1 ]);
+ return 1 ;
+end ;
+--key和field不匹配,说明当前客户端线程没有持有锁,不能主动解锁。
+if ( redis . call ( 'hexists' , KEYS [ 1 ], ARGV [ 3 ]) == 0 ) then
+ return nil ;
+end ;
+--将value减1,这里主要用在重入锁
+local counter = redis . call ( 'hincrby' , KEYS [ 1 ], ARGV [ 3 ], - 1 );
+if ( counter > 0 ) then
+ redis . call ( 'pexpire' , KEYS [ 1 ], ARGV [ 2 ]);
+ return 0 ;
+else
+--删除key并消息
+ redis . call ( 'del' , KEYS [ 1 ]);
+ redis . call ( 'publish' , KEYS [ 2 ], ARGV [ 1 ]);
+ return 1 ;
+end ;
+return nil ;
(3)删除过期信息
void cancelExpirationRenewal () {
+ Timeout task = expirationRenewalMap . remove ( getEntryName ());
+ if (task != null ) {
+ task . cancel ();
+ }
+}
Redis2.6版本之后引入了eval,能够支持lua脚本,更好的保证了redis的原子性,而且redisson采用了大量异步的写法来避免性能所带来的影响。本文只是讲解了下redisson的重入锁,其还有公平锁、联锁、红锁、读写锁等,有兴趣的可以看下。感觉这篇文章写得也不是很好,毕竟netty还没开始学,有些api也不太清楚,希望各位大佬能够建议建议~~
参考: 1.redisson 2.Redis分布式锁的正确实现方式 3.分布式锁的多种实现方式 4.用Redis构建分布式锁 5.基于Redis的分布式锁实现 6.基于Redis实现分布式锁,Redisson使用及源码分析
`,53)]))}const p=i(h,[["render",k],["__file","RedissonLock分布式锁源码分析.html.vue"]]),d=JSON.parse('{"path":"/database/redis/RedissonLock%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.html","title":"RedissonLock分布式锁源码分析","lang":"zh-CN","frontmatter":{"description":"RedissonLock分布式锁源码分析 最近碰到的一个问题,Java代码中写了一个定时器,分布式部署的时候,多台同时执行的话就会出现重复的数据,为了避免这种情况,之前是通过在配置文件里写上可以执行这段代码的IP,代码中判断如果跟这个IP相等,则执行,否则不执行,想想也是一种比较简单的方式吧,但是感觉很low很low,所以改用分布式锁。 目前分布式锁常...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/database/redis/RedissonLock%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"RedissonLock分布式锁源码分析"}],["meta",{"property":"og:description","content":"RedissonLock分布式锁源码分析 最近碰到的一个问题,Java代码中写了一个定时器,分布式部署的时候,多台同时执行的话就会出现重复的数据,为了避免这种情况,之前是通过在配置文件里写上可以执行这段代码的IP,代码中判断如果跟这个IP相等,则执行,否则不执行,想想也是一种比较简单的方式吧,但是感觉很low很low,所以改用分布式锁。 目前分布式锁常..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://upyuncdn.wenzhihuai.com/20180316081203383746214.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-06T07:22:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-06T07:22:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"RedissonLock分布式锁源码分析\\",\\"image\\":[\\"https://upyuncdn.wenzhihuai.com/20180316081203383746214.png\\",\\"https://upyuncdn.wenzhihuai.com/20180320010140455516380.png\\"],\\"dateModified\\":\\"2024-02-06T07:22:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"一、实现分布式锁的要求","slug":"一、实现分布式锁的要求","link":"#一、实现分布式锁的要求","children":[]},{"level":2,"title":"二、Redis实现分布式锁的常用命令","slug":"二、redis实现分布式锁的常用命令","link":"#二、redis实现分布式锁的常用命令","children":[]},{"level":2,"title":"三、常见写法","slug":"三、常见写法","link":"#三、常见写法","children":[]},{"level":2,"title":"四、Redisson","slug":"四、redisson","link":"#四、redisson","children":[{"level":3,"title":"4.1 测试例子","slug":"_4-1-测试例子","link":"#_4-1-测试例子","children":[]}]},{"level":2,"title":"五、RedissonLock源码分析","slug":"五、redissonlock源码分析","link":"#五、redissonlock源码分析","children":[{"level":3,"title":"5.1 使用到的全局变量","slug":"_5-1-使用到的全局变量","link":"#_5-1-使用到的全局变量","children":[]},{"level":3,"title":"5.2 加锁","slug":"_5-2-加锁","link":"#_5-2-加锁","children":[]},{"level":3,"title":"5.3 解锁","slug":"_5-3-解锁","link":"#_5-3-解锁","children":[]}]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1707204155000,"updatedTime":1707204155000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":9.66,"words":2897},"filePathRelative":"database/redis/RedissonLock分布式锁源码分析.md","localizedDate":"2024年2月6日","excerpt":"\\n最近碰到的一个问题,Java代码中写了一个定时器,分布式部署的时候,多台同时执行的话就会出现重复的数据,为了避免这种情况,之前是通过在配置文件里写上可以执行这段代码的IP,代码中判断如果跟这个IP相等,则执行,否则不执行,想想也是一种比较简单的方式吧,但是感觉很low很low,所以改用分布式锁。 \\n目前分布式锁常用的三种方式:1.数据库的锁;2.基于Redis的分布式锁;3.基于ZooKeeper的分布式锁。其中数据库中的锁有共享锁和排他锁,这两种都无法直接解决数据库的单点和可重入的问题,所以,本章还是来讲讲基于Redis的分布式锁,也可以用其他缓存(Memcache、Tair等)来实现。
","autoDesc":true}');export{p as comp,d as data};
diff --git "a/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-CvPEGSZS.js" "b/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-CvPEGSZS.js"
new file mode 100644
index 00000000..a2d9a54c
--- /dev/null
+++ "b/assets/Spring Boot Prometheus\344\275\277\347\224\250.html-CvPEGSZS.js"
@@ -0,0 +1,49 @@
+import{_ as s,c as a,d as e,o as n}from"./app-ftEjETWs.js";const t={};function l(h,i){return n(),a("div",null,i[0]||(i[0]=[e(`Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。
image-20240127202704612 Prometheus Daemon负责定时去目标上抓取metrics(指标)数据,每个抓取目标需要暴露一个http服务的接口给它定时抓取。Prometheus支持通过配置文件、文本文件、Zookeeper、Consul、DNS SRV Lookup等方式指定抓取目标。Prometheus采用PULL的方式进行监控,即服务器可以直接通过目标PULL数据或者间接地通过中间网关来Push数据。 Prometheus在本地存储抓取的所有数据,并通过一定规则进行清理和整理数据,并把得到的结果存储到新的时间序列中。 Prometheus通过PromQL和其他API可视化地展示收集的数据。Prometheus支持很多方式的图表可视化,例如Grafana、自带的Promdash以及自身提供的模版引擎等等。Prometheus还提供HTTP API的查询方式,自定义所需要的输出。 PushGateway支持Client主动推送metrics到PushGateway,而Prometheus只是定时去Gateway上抓取数据。 Alertmanager是独立于Prometheus的一个组件,可以支持Prometheus的查询语句,提供十分灵活的报警方式。 <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-actuator</artifactId>
+</dependency>
+<dependency>
+ <groupId>io.micrometer</groupId>
+ <artifactId>micrometer-registry-prometheus</artifactId>
+</dependency>
management :
+ endpoints :
+ web :
+ exposure :
+ include : prometheus
+ metrics :
+ tags :
+ application : \${spring.application.name}
之后查看/actuator/prometheus就可以看到
image-20240127202722776 腾讯云上面有个prometheus的服务,接入云原生监控还要配置一个Servicemonitor、PodMonitor等,详细的可以访问腾讯云的官方文档(https://cloud.tencent.com/document/product/1416/56031)
大部分现实场景中,如果每增加一个服务,都需要开发去配置的话,不仅沟通成本高,也导致因配错而起的运维成本很高,采用主动上报方式比较简单,方便规避一些问题。
主动上报除了需要引入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
image-20240127202830908 大致看了下 simpleclient_pushgateway和spring-boot-starter-actuator的源码,并没有对http的请求发起日志,调试的时候都不知道是不是正常上报过去了,只能采取抓包来研究下。
image-20240127202853218 image-20240127202944264 平均间隔5s左右,符合配置文件里的设置。
image-20240127203001776 对于java来说,常用的dashboard是https://grafana.com/grafana/dashboards/4701,也可以用spring boot的https://grafana.com/grafana/dashboards/6756
image-20240127203024477 除了通用的封装好的指标之外,也可以自定义prometheus的监控。对于Spring Boot来说,只要如下代码即可实现:
@ Resource
+ private MeterRegistry meterRegistry ;
+
+ public void report () {
+ meterRegistry . counter ( "指标" , "tag的名称" , "tag的值" ). increment ();
+ }
也可以通过抓包来查看,以及在push-gateway上看到。
`,35)]))}const r=s(t,[["render",l],["__file","Spring Boot Prometheus使用.html.vue"]]),k=JSON.parse('{"path":"/java/SpringBoot/Spring%20Boot%20Prometheus%E4%BD%BF%E7%94%A8.html","title":"Spring Boot Prometheus使用","lang":"zh-CN","frontmatter":{"description":"Spring Boot Prometheus使用 一、基本原理 Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exp...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/SpringBoot/Spring%20Boot%20Prometheus%E4%BD%BF%E7%94%A8.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"Spring Boot Prometheus使用"}],["meta",{"property":"og:description","content":"Spring Boot Prometheus使用 一、基本原理 Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exp..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/image-20240127202704612.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-27T13:52:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-27T13:52:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Spring Boot Prometheus使用\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/image-20240127202704612.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240127202722776.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240127202830908.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240127202853218.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240127202944264.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240127203001776.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240127203024477.png\\"],\\"dateModified\\":\\"2024-01-27T13:52:01.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"(1)引入库","slug":"_1-引入库","link":"#_1-引入库","children":[]},{"level":2,"title":"(2)修改配置文件","slug":"_2-修改配置文件","link":"#_2-修改配置文件","children":[]},{"level":2,"title":"(3)抓包看一下metrics(可跳过)","slug":"_3-抓包看一下metrics-可跳过","link":"#_3-抓包看一下metrics-可跳过","children":[]}],"git":{"createdTime":1706363521000,"updatedTime":1706363521000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":3.49,"words":1046},"filePathRelative":"java/SpringBoot/Spring Boot Prometheus使用.md","localizedDate":"2024年1月27日","excerpt":"\\n一、基本原理 \\nPrometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。
","autoDesc":true}');export{r as comp,k as data};
diff --git a/assets/aop.html-C7ud1qex.js b/assets/aop.html-C7ud1qex.js
new file mode 100644
index 00000000..72fd0dc5
--- /dev/null
+++ b/assets/aop.html-C7ud1qex.js
@@ -0,0 +1,51 @@
+import{_ as e,c as s,d as a,o as n}from"./app-ftEjETWs.js";const l={};function t(r,i){return n(),s("div",null,i[0]||(i[0]=[a(`在通常的开发过程中,我们调用的顺序通常是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容器来负责生成、管理的。其创建的方式有两种:
默认使用Java动态代理来创建AOP代理; 当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB。高版本的Spring会自动选择是使用动态代理还是CGLIB生成代理内容,当然我们也可以强制使用CGLIB生成代理,那就是aop:config 里面有一个"proxy-target-class"属性,这个属性值如果被设置为true,那么基于类的代理将起作用。 [1] Before:前置通知,在方法执行之前执行 [2] After:后置通知,在方法执行之后执行 [3] AfterRunning:返回通知,在方法返回结果之后执行 [4] AfterThrowing:异常通知,在方法抛出异常之后执行 [5] Around:环绕通知,围绕着方法执行 其中,环绕通知是最常见的一种通知注解,特别是在缓存的使用中,例如:Spring-Cache中的使用,在service的方法中添加一个cache的注解,通过AOP来拦截,如果缓存中已经存在,则直接返回结果,如果没有,再进行service的访问。
经典的基于代理的AOP @AspectJ注解驱动的切面 纯POJO切面 注入式AspectJ切面 Spring AOP的实现原理是基于动态织入的动态代理技术,而AspectJ则是静态织入,而动态代理技术又分为Java JDK动态代理和CGLIB动态代理,前者是基于反射技术的实现,后者是基于继承的机制实现。Spring AOP 在使用时机上也进行自动化调整,当有接口时会自动选择JDK动态代理技术,如果没有则选择CGLIB技术,当然Spring AOP的底层实现并没有这么简单,为更简便生成代理对象,Spring AOP 内部实现了一个专注于生成代理对象的工厂类,这样就避免了大量的手动编码,这点也是十分人性化的,但最核心的还是动态代理技术。从性能上来说,Spring AOP 虽然无需特殊编译器协助,但性能上并不优于AspectJ的静态织入,这点了解一下即可。
具体的原理请看Spring AOP
网上看别人写了很多入门的例子,自己就不再阐述了,毕竟自己还是菜,下面是关于AOP入门的资料:我们为什么要使用AOP? Spring中AOP的实现 关于AOP
下面是自己在个人网站 中的使用,主要是用来统计一个方法的执行消耗了多少时间,需要引入aopalliance.jar、aspectj.weaver.jar 和 spring-aspects.jar的包。
<!--自动扫描自定义切面-->
+ < 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,算是客观吧,如果太大则要对其进行优化。
主要的源码在这:
TimeInterceptor
也可以下载我的博客源码参考参考:newblog
Spring学习总结——Spring实现AOP的多种方式 Spring AOP基础入门总结一 Spring AOP官方 `,48)]))}const h=e(l,[["render",t],["__file","aop.html.vue"]]),o=JSON.parse('{"path":"/java/SpringBoot/aop.html","title":"AOP","lang":"zh-CN","frontmatter":{"description":"AOP 一、概述 在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会...","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来查看执行该函数的耗时,过多的使用此类方式会..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/20180118085015.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T06:53:42.000Z"}],["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\\":[\\"https://github-images.wenzhihuai.com/images/20180118085015.png\\",\\"https://github-images.wenzhihuai.com/images/20180204060518.png\\"],\\"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":"\\n一、概述 \\n在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了。AOP关注的是横向的,而OOP的是纵向。
","autoDesc":true}');export{h as comp,o as data};
diff --git a/assets/app-ftEjETWs.js b/assets/app-ftEjETWs.js
new file mode 100644
index 00000000..f2025531
--- /dev/null
+++ b/assets/app-ftEjETWs.js
@@ -0,0 +1,330 @@
+var Xh=Object.defineProperty;var ep=(e,t,n)=>t in e?Xh(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var ui=(e,t,n)=>ep(e,typeof t!="symbol"?t+"":t,n);/**
+* @vue/shared v3.5.13
+* (c) 2018-present Yuxi (Evan) You and Vue contributors
+* @license MIT
+**//*! #__NO_SIDE_EFFECTS__ */function wa(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const xe={},Un=[],$t=()=>{},tp=()=>!1,ql=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Ba=e=>e.startsWith("onUpdate:"),Me=Object.assign,Ca=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},np=Object.prototype.hasOwnProperty,_e=(e,t)=>np.call(e,t),re=Array.isArray,Al=e=>Ur(e)==="[object Map]",lp=e=>Ur(e)==="[object Set]",ie=e=>typeof e=="function",ze=e=>typeof e=="string",ol=e=>typeof e=="symbol",De=e=>e!==null&&typeof e=="object",iu=e=>(De(e)||ie(e))&&ie(e.then)&&ie(e.catch),rp=Object.prototype.toString,Ur=e=>rp.call(e),ip=e=>Ur(e).slice(8,-1),ap=e=>Ur(e)==="[object Object]",xa=e=>ze(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Gn=wa(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Gr=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},op=/-(\w)/g,at=Gr(e=>e.replace(op,(t,n)=>n?n.toUpperCase():"")),sp=/\B([A-Z])/g,Pn=Gr(e=>e.replace(sp,"-$1").toLowerCase()),Wl=Gr(e=>e.charAt(0).toUpperCase()+e.slice(1)),di=Gr(e=>e?`on${Wl(e)}`:""),dn=(e,t)=>!Object.is(e,t),fi=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:l,value:n})},cp=e=>{const t=parseFloat(e);return isNaN(t)?e:t},up=e=>{const t=ze(e)?Number(e):NaN;return isNaN(t)?e:t};let Po;const Kr=()=>Po||(Po=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Sa(e){if(re(e)){const t={};for(let n=0;n{if(n){const l=n.split(fp);l.length>1&&(t[l[0].trim()]=l[1].trim())}}),t}function Ta(e){let t="";if(ze(e))t=e;else if(re(e))for(let n=0;n0)return;if(wl){let t=wl;for(wl=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;kl;){let t=kl;for(kl=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(l){e||(e=l)}t=n}}if(e)throw e}function fu(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function hu(e){let t,n=e.depsTail,l=n;for(;l;){const r=l.prevDep;l.version===-1?(l===n&&(n=r),Da(l),_p(l)):t=l,l.dep.activeLink=l.prevActiveLink,l.prevActiveLink=void 0,l=r}e.deps=t,e.depsTail=n}function Ni(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(pu(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function pu(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Pl))return;e.globalVersion=Pl;const t=e.dep;if(e.flags|=2,t.version>0&&!e.isSSR&&e.deps&&!Ni(e)){e.flags&=-3;return}const n=Ce,l=Tt;Ce=e,Tt=!0;try{fu(e);const r=e.fn(e._value);(t.version===0||dn(r,e._value))&&(e._value=r,t.version++)}catch(r){throw t.version++,r}finally{Ce=n,Tt=l,hu(e),e.flags&=-3}}function Da(e,t=!1){const{dep:n,prevSub:l,nextSub:r}=e;if(l&&(l.nextSub=r,e.prevSub=void 0),r&&(r.prevSub=l,e.nextSub=void 0),n.subs===e&&(n.subs=l,!l&&n.computed)){n.computed.flags&=-5;for(let i=n.computed.deps;i;i=i.nextDep)Da(i,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function _p(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}let Tt=!0;const vu=[];function vn(){vu.push(Tt),Tt=!1}function mn(){const e=vu.pop();Tt=e===void 0?!0:e}function Io(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=Ce;Ce=void 0;try{t()}finally{Ce=n}}}let Pl=0;class bp{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class qr{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0}track(t){if(!Ce||!Tt||Ce===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==Ce)n=this.activeLink=new bp(Ce,this),Ce.deps?(n.prevDep=Ce.depsTail,Ce.depsTail.nextDep=n,Ce.depsTail=n):Ce.deps=Ce.depsTail=n,mu(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const l=n.nextDep;l.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=l),n.prevDep=Ce.depsTail,n.nextDep=void 0,Ce.depsTail.nextDep=n,Ce.depsTail=n,Ce.deps===n&&(Ce.deps=l)}return n}trigger(t){this.version++,Pl++,this.notify(t)}notify(t){La();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Oa()}}}function mu(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let l=t.deps;l;l=l.nextDep)mu(l)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const Dr=new WeakMap,Sn=Symbol(""),ji=Symbol(""),Il=Symbol("");function Ye(e,t,n){if(Tt&&Ce){let l=Dr.get(e);l||Dr.set(e,l=new Map);let r=l.get(n);r||(l.set(n,r=new qr),r.map=l,r.key=n),r.track()}}function Yt(e,t,n,l,r,i){const a=Dr.get(e);if(!a){Pl++;return}const o=c=>{c&&c.trigger()};if(La(),t==="clear")a.forEach(o);else{const c=re(e),u=c&&xa(n);if(c&&n==="length"){const d=Number(l);a.forEach((f,h)=>{(h==="length"||h===Il||!ol(h)&&h>=d)&&o(f)})}else switch((n!==void 0||a.has(void 0))&&o(a.get(n)),u&&o(a.get(Il)),t){case"add":c?u&&o(a.get("length")):(o(a.get(Sn)),Al(e)&&o(a.get(ji)));break;case"delete":c||(o(a.get(Sn)),Al(e)&&o(a.get(ji)));break;case"set":Al(e)&&o(a.get(Sn));break}}Oa()}function yp(e,t){const n=Dr.get(e);return n&&n.get(t)}function Mn(e){const t=de(e);return t===e?t:(Ye(t,"iterate",Il),Lt(e)?t:t.map(tt))}function Pa(e){return Ye(e=de(e),"iterate",Il),e}const Ap={__proto__:null,[Symbol.iterator](){return pi(this,Symbol.iterator,tt)},concat(...e){return Mn(this).concat(...e.map(t=>re(t)?Mn(t):t))},entries(){return pi(this,"entries",e=>(e[1]=tt(e[1]),e))},every(e,t){return Gt(this,"every",e,t,void 0,arguments)},filter(e,t){return Gt(this,"filter",e,t,n=>n.map(tt),arguments)},find(e,t){return Gt(this,"find",e,t,tt,arguments)},findIndex(e,t){return Gt(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Gt(this,"findLast",e,t,tt,arguments)},findLastIndex(e,t){return Gt(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Gt(this,"forEach",e,t,void 0,arguments)},includes(...e){return vi(this,"includes",e)},indexOf(...e){return vi(this,"indexOf",e)},join(e){return Mn(this).join(e)},lastIndexOf(...e){return vi(this,"lastIndexOf",e)},map(e,t){return Gt(this,"map",e,t,void 0,arguments)},pop(){return vl(this,"pop")},push(...e){return vl(this,"push",e)},reduce(e,...t){return Fo(this,"reduce",e,t)},reduceRight(e,...t){return Fo(this,"reduceRight",e,t)},shift(){return vl(this,"shift")},some(e,t){return Gt(this,"some",e,t,void 0,arguments)},splice(...e){return vl(this,"splice",e)},toReversed(){return Mn(this).toReversed()},toSorted(e){return Mn(this).toSorted(e)},toSpliced(...e){return Mn(this).toSpliced(...e)},unshift(...e){return vl(this,"unshift",e)},values(){return pi(this,"values",tt)}};function pi(e,t,n){const l=Pa(e),r=l[t]();return l!==e&&!Lt(e)&&(r._next=r.next,r.next=()=>{const i=r._next();return i.value&&(i.value=n(i.value)),i}),r}const kp=Array.prototype;function Gt(e,t,n,l,r,i){const a=Pa(e),o=a!==e&&!Lt(e),c=a[t];if(c!==kp[t]){const f=c.apply(e,i);return o?tt(f):f}let u=n;a!==e&&(o?u=function(f,h){return n.call(this,tt(f),h,e)}:n.length>2&&(u=function(f,h){return n.call(this,f,h,e)}));const d=c.call(a,u,l);return o&&r?r(d):d}function Fo(e,t,n,l){const r=Pa(e);let i=n;return r!==e&&(Lt(e)?n.length>3&&(i=function(a,o,c){return n.call(this,a,o,c,e)}):i=function(a,o,c){return n.call(this,a,tt(o),c,e)}),r[t](i,...l)}function vi(e,t,n){const l=de(e);Ye(l,"iterate",Il);const r=l[t](...n);return(r===-1||r===!1)&&Ra(n[0])?(n[0]=de(n[0]),l[t](...n)):r}function vl(e,t,n=[]){vn(),La();const l=de(e)[t].apply(e,n);return Oa(),mn(),l}const wp=wa("__proto__,__v_isRef,__isVue"),gu=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(ol));function Bp(e){ol(e)||(e=String(e));const t=de(this);return Ye(t,"has",e),t.hasOwnProperty(e)}class Eu{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,l){if(n==="__v_skip")return t.__v_skip;const r=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!r;if(n==="__v_isReadonly")return r;if(n==="__v_isShallow")return i;if(n==="__v_raw")return l===(r?i?Fp:Au:i?yu:bu).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(l)?t:void 0;const a=re(t);if(!r){let c;if(a&&(c=Ap[n]))return c;if(n==="hasOwnProperty")return Bp}const o=Reflect.get(t,n,Re(t)?t:l);return(ol(n)?gu.has(n):wp(n))||(r||Ye(t,"get",n),i)?o:Re(o)?a&&xa(n)?o:o.value:De(o)?r?In(o):Jl(o):o}}class _u extends Eu{constructor(t=!1){super(!1,t)}set(t,n,l,r){let i=t[n];if(!this._isShallow){const c=Ln(i);if(!Lt(l)&&!Ln(l)&&(i=de(i),l=de(l)),!re(t)&&Re(i)&&!Re(l))return c?!1:(i.value=l,!0)}const a=re(t)&&xa(n)?Number(n)e,mr=e=>Reflect.getPrototypeOf(e);function Lp(e,t,n){return function(...l){const r=this.__v_raw,i=de(r),a=Al(i),o=e==="entries"||e===Symbol.iterator&&a,c=e==="keys"&&a,u=r[e](...l),d=n?Hi:t?zi:tt;return!t&&Ye(i,"iterate",c?ji:Sn),{next(){const{value:f,done:h}=u.next();return h?{value:f,done:h}:{value:o?[d(f[0]),d(f[1])]:d(f),done:h}},[Symbol.iterator](){return this}}}}function gr(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Op(e,t){const n={get(r){const i=this.__v_raw,a=de(i),o=de(r);e||(dn(r,o)&&Ye(a,"get",r),Ye(a,"get",o));const{has:c}=mr(a),u=t?Hi:e?zi:tt;if(c.call(a,r))return u(i.get(r));if(c.call(a,o))return u(i.get(o));i!==a&&i.get(r)},get size(){const r=this.__v_raw;return!e&&Ye(de(r),"iterate",Sn),Reflect.get(r,"size",r)},has(r){const i=this.__v_raw,a=de(i),o=de(r);return e||(dn(r,o)&&Ye(a,"has",r),Ye(a,"has",o)),r===o?i.has(r):i.has(r)||i.has(o)},forEach(r,i){const a=this,o=a.__v_raw,c=de(o),u=t?Hi:e?zi:tt;return!e&&Ye(c,"iterate",Sn),o.forEach((d,f)=>r.call(i,u(d),u(f),a))}};return Me(n,e?{add:gr("add"),set:gr("set"),delete:gr("delete"),clear:gr("clear")}:{add(r){!t&&!Lt(r)&&!Ln(r)&&(r=de(r));const i=de(this);return mr(i).has.call(i,r)||(i.add(r),Yt(i,"add",r,r)),this},set(r,i){!t&&!Lt(i)&&!Ln(i)&&(i=de(i));const a=de(this),{has:o,get:c}=mr(a);let u=o.call(a,r);u||(r=de(r),u=o.call(a,r));const d=c.call(a,r);return a.set(r,i),u?dn(i,d)&&Yt(a,"set",r,i):Yt(a,"add",r,i),this},delete(r){const i=de(this),{has:a,get:o}=mr(i);let c=a.call(i,r);c||(r=de(r),c=a.call(i,r)),o&&o.call(i,r);const u=i.delete(r);return c&&Yt(i,"delete",r,void 0),u},clear(){const r=de(this),i=r.size!==0,a=r.clear();return i&&Yt(r,"clear",void 0,void 0),a}}),["keys","values","entries",Symbol.iterator].forEach(r=>{n[r]=Lp(r,e,t)}),n}function Ia(e,t){const n=Op(e,t);return(l,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?l:Reflect.get(_e(n,r)&&r in l?n:l,r,i)}const Dp={get:Ia(!1,!1)},Pp={get:Ia(!1,!0)},Ip={get:Ia(!0,!1)};const bu=new WeakMap,yu=new WeakMap,Au=new WeakMap,Fp=new WeakMap;function Rp(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Mp(e){return e.__v_skip||!Object.isExtensible(e)?0:Rp(ip(e))}function Jl(e){return Ln(e)?e:Fa(e,!1,xp,Dp,bu)}function ku(e){return Fa(e,!1,Tp,Pp,yu)}function In(e){return Fa(e,!0,Sp,Ip,Au)}function Fa(e,t,n,l,r){if(!De(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=r.get(e);if(i)return i;const a=Mp(e);if(a===0)return e;const o=new Proxy(e,a===2?l:n);return r.set(e,o),o}function Kn(e){return Ln(e)?Kn(e.__v_raw):!!(e&&e.__v_isReactive)}function Ln(e){return!!(e&&e.__v_isReadonly)}function Lt(e){return!!(e&&e.__v_isShallow)}function Ra(e){return e?!!e.__v_raw:!1}function de(e){const t=e&&e.__v_raw;return t?de(t):e}function Vp(e){return!_e(e,"__v_skip")&&Object.isExtensible(e)&&au(e,"__v_skip",!0),e}const tt=e=>De(e)?Jl(e):e,zi=e=>De(e)?In(e):e;function Re(e){return e?e.__v_isRef===!0:!1}function ee(e){return wu(e,!1)}function $e(e){return wu(e,!0)}function wu(e,t){return Re(e)?e:new Np(e,t)}class Np{constructor(t,n){this.dep=new qr,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:de(t),this._value=n?t:tt(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,l=this.__v_isShallow||Lt(t)||Ln(t);t=l?t:de(t),dn(t,n)&&(this._rawValue=t,this._value=l?t:tt(t),this.dep.trigger())}}function St(e){return Re(e)?e.value:e}const jp={get:(e,t,n)=>t==="__v_raw"?e:St(Reflect.get(e,t,n)),set:(e,t,n,l)=>{const r=e[t];return Re(r)&&!Re(n)?(r.value=n,!0):Reflect.set(e,t,n,l)}};function Bu(e){return Kn(e)?e:new Proxy(e,jp)}class Hp{constructor(t){this.__v_isRef=!0,this._value=void 0;const n=this.dep=new qr,{get:l,set:r}=t(n.track.bind(n),n.trigger.bind(n));this._get=l,this._set=r}get value(){return this._value=this._get()}set value(t){this._set(t)}}function Cu(e){return new Hp(e)}function zp(e){const t=re(e)?new Array(e.length):{};for(const n in e)t[n]=xu(e,n);return t}class $p{constructor(t,n,l){this._object=t,this._key=n,this._defaultValue=l,this.__v_isRef=!0,this._value=void 0}get value(){const t=this._object[this._key];return this._value=t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return yp(de(this._object),this._key)}}class Up{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function sl(e,t,n){return Re(e)?e:ie(e)?new Up(e):De(e)&&arguments.length>1?xu(e,t,n):ee(e)}function xu(e,t,n){const l=e[t];return Re(l)?l:new $p(e,t,n)}class Gp{constructor(t,n,l){this.fn=t,this.setter=n,this._value=void 0,this.dep=new qr(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Pl-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=l}notify(){if(this.flags|=16,!(this.flags&8)&&Ce!==this)return du(this,!0),!0}get value(){const t=this.dep.track();return pu(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function Kp(e,t,n=!1){let l,r;return ie(e)?l=e:(l=e.get,r=e.set),new Gp(l,r,n)}const Er={},Pr=new WeakMap;let wn;function qp(e,t=!1,n=wn){if(n){let l=Pr.get(n);l||Pr.set(n,l=[]),l.push(e)}}function Wp(e,t,n=xe){const{immediate:l,deep:r,once:i,scheduler:a,augmentJob:o,call:c}=n,u=w=>r?w:Lt(w)||r===!1||r===0?un(w,1):un(w);let d,f,h,p,g=!1,v=!1;if(Re(e)?(f=()=>e.value,g=Lt(e)):Kn(e)?(f=()=>u(e),g=!0):re(e)?(v=!0,g=e.some(w=>Kn(w)||Lt(w)),f=()=>e.map(w=>{if(Re(w))return w.value;if(Kn(w))return u(w);if(ie(w))return c?c(w,2):w()})):ie(e)?t?f=c?()=>c(e,2):e:f=()=>{if(h){vn();try{h()}finally{mn()}}const w=wn;wn=d;try{return c?c(e,3,[p]):e(p)}finally{wn=w}}:f=$t,t&&r){const w=f,F=r===!0?1/0:r;f=()=>un(w(),F)}const y=su(),_=()=>{d.stop(),y&&y.active&&Ca(y.effects,d)};if(i&&t){const w=t;t=(...F)=>{w(...F),_()}}let A=v?new Array(e.length).fill(Er):Er;const m=w=>{if(!(!(d.flags&1)||!d.dirty&&!w))if(t){const F=d.run();if(r||g||(v?F.some((V,R)=>dn(V,A[R])):dn(F,A))){h&&h();const V=wn;wn=d;try{const R=[F,A===Er?void 0:v&&A[0]===Er?[]:A,p];c?c(t,3,R):t(...R),A=F}finally{wn=V}}}else d.run()};return o&&o(m),d=new cu(f),d.scheduler=a?()=>a(m,!1):m,p=w=>qp(w,!1,d),h=d.onStop=()=>{const w=Pr.get(d);if(w){if(c)c(w,4);else for(const F of w)F();Pr.delete(d)}},t?l?m(!0):A=d.run():a?a(m.bind(null,!0),!0):d.run(),_.pause=d.pause.bind(d),_.resume=d.resume.bind(d),_.stop=_,_}function un(e,t=1/0,n){if(t<=0||!De(e)||e.__v_skip||(n=n||new Set,n.has(e)))return e;if(n.add(e),t--,Re(e))un(e.value,t,n);else if(re(e))for(let l=0;l{un(l,t,n)});else if(ap(e)){for(const l in e)un(e[l],t,n);for(const l of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,l)&&un(e[l],t,n)}return e}/**
+* @vue/runtime-core v3.5.13
+* (c) 2018-present Yuxi (Evan) You and Vue contributors
+* @license MIT
+**/function Yl(e,t,n,l){try{return l?e(...l):e()}catch(r){Zl(r,t,n)}}function Dt(e,t,n,l){if(ie(e)){const r=Yl(e,t,n,l);return r&&iu(r)&&r.catch(i=>{Zl(i,t,n)}),r}if(re(e)){const r=[];for(let i=0;i>>1,r=nt[l],i=Fl(r);i=Fl(n)?nt.push(e):nt.splice(Yp(t),0,e),e.flags|=1,Tu()}}function Tu(){Ir||(Ir=Su.then(Lu))}function Zp(e){re(e)?qn.push(...e):an&&e.id===-1?an.splice(Nn+1,0,e):e.flags&1||(qn.push(e),e.flags|=1),Tu()}function Ro(e,t,n=Ht+1){for(;nFl(n)-Fl(l));if(qn.length=0,an){an.push(...t);return}for(an=t,Nn=0;Nne.id==null?e.flags&2?-1:1/0:e.id;function Lu(e){try{for(Ht=0;Ht{l._d&&Wo(-1);const i=Rr(t);let a;try{a=e(...r)}finally{Rr(i),l._d&&Wo(1)}return a};return l._n=!0,l._c=!0,l._d=!0,l}function zt(e,t,n,l){const r=e.dirs,i=t&&t.dirs;for(let a=0;ae.__isTeleport,on=Symbol("_leaveCb"),_r=Symbol("_enterCb");function Pu(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return we(()=>{e.isMounted=!0}),Jr(()=>{e.isUnmounting=!0}),e}const Et=[Function,Array],Iu={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Et,onEnter:Et,onAfterEnter:Et,onEnterCancelled:Et,onBeforeLeave:Et,onLeave:Et,onAfterLeave:Et,onLeaveCancelled:Et,onBeforeAppear:Et,onAppear:Et,onAfterAppear:Et,onAppearCancelled:Et},Fu=e=>{const t=e.subTree;return t.component?Fu(t.component):t},Xp={name:"BaseTransition",props:Iu,setup(e,{slots:t}){const n=Xl(),l=Pu();return()=>{const r=t.default&&Va(t.default(),!0);if(!r||!r.length)return;const i=Ru(r),a=de(e),{mode:o}=a;if(l.isLeaving)return mi(i);const c=Mo(i);if(!c)return mi(i);let u=Rl(c,a,l,n,f=>u=f);c.type!==pt&&On(c,u);let d=n.subTree&&Mo(n.subTree);if(d&&d.type!==pt&&!Bn(c,d)&&Fu(n).type!==pt){let f=Rl(d,a,l,n);if(On(d,f),o==="out-in"&&c.type!==pt)return l.isLeaving=!0,f.afterLeave=()=>{l.isLeaving=!1,n.job.flags&8||n.update(),delete f.afterLeave,d=void 0},mi(i);o==="in-out"&&c.type!==pt?f.delayLeave=(h,p,g)=>{const v=Mu(l,d);v[String(d.key)]=d,h[on]=()=>{p(),h[on]=void 0,delete u.delayedLeave,d=void 0},u.delayedLeave=()=>{g(),delete u.delayedLeave,d=void 0}}:d=void 0}else d&&(d=void 0);return i}}};function Ru(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==pt){t=n;break}}return t}const e1=Xp;function Mu(e,t){const{leavingVNodes:n}=e;let l=n.get(t.type);return l||(l=Object.create(null),n.set(t.type,l)),l}function Rl(e,t,n,l,r){const{appear:i,mode:a,persisted:o=!1,onBeforeEnter:c,onEnter:u,onAfterEnter:d,onEnterCancelled:f,onBeforeLeave:h,onLeave:p,onAfterLeave:g,onLeaveCancelled:v,onBeforeAppear:y,onAppear:_,onAfterAppear:A,onAppearCancelled:m}=t,w=String(e.key),F=Mu(n,e),V=(M,T)=>{M&&Dt(M,l,9,T)},R=(M,T)=>{const $=T[1];V(M,T),re(M)?M.every(O=>O.length<=1)&&$():M.length<=1&&$()},Z={mode:a,persisted:o,beforeEnter(M){let T=c;if(!n.isMounted)if(i)T=y||c;else return;M[on]&&M[on](!0);const $=F[w];$&&Bn(e,$)&&$.el[on]&&$.el[on](),V(T,[M])},enter(M){let T=u,$=d,O=f;if(!n.isMounted)if(i)T=_||u,$=A||d,O=m||f;else return;let X=!1;const se=M[_r]=he=>{X||(X=!0,he?V(O,[M]):V($,[M]),Z.delayedLeave&&Z.delayedLeave(),M[_r]=void 0)};T?R(T,[M,se]):se()},leave(M,T){const $=String(e.key);if(M[_r]&&M[_r](!0),n.isUnmounting)return T();V(h,[M]);let O=!1;const X=M[on]=se=>{O||(O=!0,T(),se?V(v,[M]):V(g,[M]),M[on]=void 0,F[$]===e&&delete F[$])};F[$]=e,p?R(p,[M,X]):X()},clone(M){const T=Rl(M,t,n,l,r);return r&&r(T),T}};return Z}function mi(e){if(Ql(e))return e=fn(e),e.children=null,e}function Mo(e){if(!Ql(e))return Du(e.type)&&e.children?Ru(e.children):e;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&ie(n.default))return n.default()}}function On(e,t){e.shapeFlag&6&&e.component?(e.transition=t,On(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Va(e,t=!1,n){let l=[],r=0;for(let i=0;i1)for(let i=0;iMl(g,t&&(re(t)?t[v]:t),n,l,r));return}if(Wn(l)&&!r){l.shapeFlag&512&&l.type.__asyncResolved&&l.component.subTree.component&&Ml(e,t,n,l.component.subTree);return}const i=l.shapeFlag&4?Ga(l.component):l.el,a=r?null:i,{i:o,r:c}=e,u=t&&t.r,d=o.refs===xe?o.refs={}:o.refs,f=o.setupState,h=de(f),p=f===xe?()=>!1:g=>_e(h,g);if(u!=null&&u!==c&&(ze(u)?(d[u]=null,p(u)&&(f[u]=null)):Re(u)&&(u.value=null)),ie(c))Yl(c,o,12,[a,d]);else{const g=ze(c),v=Re(c);if(g||v){const y=()=>{if(e.f){const _=g?p(c)?f[c]:d[c]:c.value;r?re(_)&&Ca(_,i):re(_)?_.includes(i)||_.push(i):g?(d[c]=[i],p(c)&&(f[c]=d[c])):(c.value=[i],e.k&&(d[e.k]=c.value))}else g?(d[c]=a,p(c)&&(f[c]=a)):v&&(c.value=a,e.k&&(d[e.k]=a))};a?(y.id=-1,dt(y,n)):y()}}}let Vo=!1;const Vn=()=>{Vo||(console.error("Hydration completed but contains mismatches."),Vo=!0)},t1=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",n1=e=>e.namespaceURI.includes("MathML"),br=e=>{if(e.nodeType===1){if(t1(e))return"svg";if(n1(e))return"mathml"}},Hn=e=>e.nodeType===8;function l1(e){const{mt:t,p:n,o:{patchProp:l,createText:r,nextSibling:i,parentNode:a,remove:o,insert:c,createComment:u}}=e,d=(m,w)=>{if(!w.hasChildNodes()){n(null,m,w),Fr(),w._vnode=m;return}f(w.firstChild,m,null,null,null),Fr(),w._vnode=m},f=(m,w,F,V,R,Z=!1)=>{Z=Z||!!w.dynamicChildren;const M=Hn(m)&&m.data==="[",T=()=>v(m,w,F,V,R,M),{type:$,ref:O,shapeFlag:X,patchFlag:se}=w;let he=m.nodeType;w.el=m,se===-2&&(Z=!1,w.dynamicChildren=null);let K=null;switch($){case Tn:he!==3?w.children===""?(c(w.el=r(""),a(m),m),K=m):K=T():(m.data!==w.children&&(Vn(),m.data=w.children),K=i(m));break;case pt:A(m)?(K=i(m),_(w.el=m.content.firstChild,m,F)):he!==8||M?K=T():K=i(m);break;case Cl:if(M&&(m=i(m),he=m.nodeType),he===1||he===3){K=m;const N=!w.children.length;for(let J=0;J{Z=Z||!!w.dynamicChildren;const{type:M,props:T,patchFlag:$,shapeFlag:O,dirs:X,transition:se}=w,he=M==="input"||M==="option";if(he||$!==-1){X&&zt(w,null,F,"created");let K=!1;if(A(m)){K=Zu(null,se)&&F&&F.vnode.props&&F.vnode.props.appear;const J=m.content.firstChild;K&&se.beforeEnter(J),_(J,m,F),w.el=m=J}if(O&16&&!(T&&(T.innerHTML||T.textContent))){let J=p(m.firstChild,w,m,F,V,R,Z);for(;J;){yr(m,1)||Vn();const ae=J;J=J.nextSibling,o(ae)}}else if(O&8){let J=w.children;J[0]===`
+`&&(m.tagName==="PRE"||m.tagName==="TEXTAREA")&&(J=J.slice(1)),m.textContent!==J&&(yr(m,0)||Vn(),m.textContent=w.children)}if(T){if(he||!Z||$&48){const J=m.tagName.includes("-");for(const ae in T)(he&&(ae.endsWith("value")||ae==="indeterminate")||ql(ae)&&!Gn(ae)||ae[0]==="."||J)&&l(m,ae,null,T[ae],void 0,F)}else if(T.onClick)l(m,"onClick",null,T.onClick,void 0,F);else if($&4&&Kn(T.style))for(const J in T.style)T.style[J]}let N;(N=T&&T.onVnodeBeforeMount)&&_t(N,F,w),X&&zt(w,null,F,"beforeMount"),((N=T&&T.onVnodeMounted)||X||K)&&rd(()=>{N&&_t(N,F,w),K&&se.enter(m),X&&zt(w,null,F,"mounted")},V)}return m.nextSibling},p=(m,w,F,V,R,Z,M)=>{M=M||!!w.dynamicChildren;const T=w.children,$=T.length;for(let O=0;O<$;O++){const X=M?T[O]:T[O]=yt(T[O]),se=X.type===Tn;m?(se&&!M&&O+1<$&&yt(T[O+1]).type===Tn&&(c(r(m.data.slice(X.children.length)),F,i(m)),m.data=X.children),m=f(m,X,V,R,Z,M)):se&&!X.children?c(X.el=r(""),F):(yr(F,1)||Vn(),n(null,X,F,null,V,R,br(F),Z))}return m},g=(m,w,F,V,R,Z)=>{const{slotScopeIds:M}=w;M&&(R=R?R.concat(M):M);const T=a(m),$=p(i(m),w,T,F,V,R,Z);return $&&Hn($)&&$.data==="]"?i(w.anchor=$):(Vn(),c(w.anchor=u("]"),T,$),$)},v=(m,w,F,V,R,Z)=>{if(yr(m.parentElement,1)||Vn(),w.el=null,Z){const $=y(m);for(;;){const O=i(m);if(O&&O!==$)o(O);else break}}const M=i(m),T=a(m);return o(m),n(null,w,T,M,F,V,br(T),R),F&&(F.vnode.el=w.el,nd(F,w.el)),M},y=(m,w="[",F="]")=>{let V=0;for(;m;)if(m=i(m),m&&Hn(m)&&(m.data===w&&V++,m.data===F)){if(V===0)return i(m);V--}return m},_=(m,w,F)=>{const V=w.parentNode;V&&V.replaceChild(m,w);let R=F;for(;R;)R.vnode.el===w&&(R.vnode.el=R.subTree.el=m),R=R.parent},A=m=>m.nodeType===1&&m.tagName==="TEMPLATE";return[d,f]}const No="data-allow-mismatch",r1={0:"text",1:"children",2:"class",3:"style",4:"attribute"};function yr(e,t){if(t===0||t===1)for(;e&&!e.hasAttribute(No);)e=e.parentElement;const n=e&&e.getAttribute(No);if(n==null)return!1;if(n==="")return!0;{const l=n.split(",");return t===0&&l.includes("children")?!0:n.split(",").includes(r1[t])}}Kr().requestIdleCallback;Kr().cancelIdleCallback;function i1(e,t){if(Hn(e)&&e.data==="["){let n=1,l=e.nextSibling;for(;l;){if(l.nodeType===1){if(t(l)===!1)break}else if(Hn(l))if(l.data==="]"){if(--n===0)break}else l.data==="["&&n++;l=l.nextSibling}}else t(e)}const Wn=e=>!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function a1(e){ie(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:l,delay:r=200,hydrate:i,timeout:a,suspensible:o=!0,onError:c}=e;let u=null,d,f=0;const h=()=>(f++,u=null,p()),p=()=>{let g;return u||(g=u=t().catch(v=>{if(v=v instanceof Error?v:new Error(String(v)),c)return new Promise((y,_)=>{c(v,()=>y(h()),()=>_(v),f+1)});throw v}).then(v=>g!==u&&u?u:(v&&(v.__esModule||v[Symbol.toStringTag]==="Module")&&(v=v.default),d=v,v)))};return H({name:"AsyncComponentWrapper",__asyncLoader:p,__asyncHydrate(g,v,y){const _=i?()=>{const A=i(y,m=>i1(g,m));A&&(v.bum||(v.bum=[])).push(A)}:y;d?_():p().then(()=>!v.isUnmounted&&_())},get __asyncResolved(){return d},setup(){const g=Ue;if(Na(g),d)return()=>gi(d,g);const v=m=>{u=null,Zl(m,g,13,!l)};if(o&&g.suspense||Qn)return p().then(m=>()=>gi(m,g)).catch(m=>(v(m),()=>l?Ve(l,{error:m}):null));const y=ee(!1),_=ee(),A=ee(!!r);return r&&setTimeout(()=>{A.value=!1},r),a!=null&&setTimeout(()=>{if(!y.value&&!_.value){const m=new Error(`Async component timed out after ${a}ms.`);v(m),_.value=m}},a),p().then(()=>{y.value=!0,g.parent&&Ql(g.parent.vnode)&&g.parent.update()}).catch(m=>{v(m),_.value=m}),()=>{if(y.value&&d)return gi(d,g);if(_.value&&l)return Ve(l,{error:_.value});if(n&&!A.value)return Ve(n)}}})}function gi(e,t){const{ref:n,props:l,children:r,ce:i}=t.vnode,a=Ve(e,l,r);return a.ref=n,a.ce=i,delete t.vnode.ce,a}const Ql=e=>e.type.__isKeepAlive;function o1(e,t){Vu(e,"a",t)}function s1(e,t){Vu(e,"da",t)}function Vu(e,t,n=Ue){const l=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(Wr(t,l,n),n){let r=n.parent;for(;r&&r.parent;)Ql(r.parent.vnode)&&c1(l,t,n,r),r=r.parent}}function c1(e,t,n,l){const r=Wr(t,e,l,!0);cl(()=>{Ca(l[t],r)},n)}function Wr(e,t,n=Ue,l=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...a)=>{vn();const o=er(n),c=Dt(t,n,e,a);return o(),mn(),c});return l?r.unshift(i):r.push(i),i}}const Xt=e=>(t,n=Ue)=>{(!Qn||e==="sp")&&Wr(e,(...l)=>t(...l),n)},u1=Xt("bm"),we=Xt("m"),d1=Xt("bu"),Nu=Xt("u"),Jr=Xt("bum"),cl=Xt("um"),f1=Xt("sp"),h1=Xt("rtg"),p1=Xt("rtc");function v1(e,t=Ue){Wr("ec",e,t)}const m1="components";function kt(e,t){return E1(m1,e,!0,t)||e}const g1=Symbol.for("v-ndc");function E1(e,t,n=!0,l=!1){const r=At||Ue;if(r){const i=r.type;{const o=l0(i,!1);if(o&&(o===t||o===at(t)||o===Wl(at(t))))return i}const a=jo(r[e]||i[e],t)||jo(r.appContext[e],t);return!a&&l?i:a}}function jo(e,t){return e&&(e[t]||e[at(t)]||e[Wl(at(t))])}const Ui=e=>e?sd(e)?Ga(e):Ui(e.parent):null,Bl=Me(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Ui(e.parent),$root:e=>Ui(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>ja(e),$forceUpdate:e=>e.f||(e.f=()=>{Ma(e.update)}),$nextTick:e=>e.n||(e.n=Qt.bind(e.proxy)),$watch:e=>V1.bind(e)}),Ei=(e,t)=>e!==xe&&!e.__isScriptSetup&&_e(e,t),_1={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:l,data:r,props:i,accessCache:a,type:o,appContext:c}=e;let u;if(t[0]!=="$"){const p=a[t];if(p!==void 0)switch(p){case 1:return l[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if(Ei(l,t))return a[t]=1,l[t];if(r!==xe&&_e(r,t))return a[t]=2,r[t];if((u=e.propsOptions[0])&&_e(u,t))return a[t]=3,i[t];if(n!==xe&&_e(n,t))return a[t]=4,n[t];Gi&&(a[t]=0)}}const d=Bl[t];let f,h;if(d)return t==="$attrs"&&Ye(e.attrs,"get",""),d(e);if((f=o.__cssModules)&&(f=f[t]))return f;if(n!==xe&&_e(n,t))return a[t]=4,n[t];if(h=c.config.globalProperties,_e(h,t))return h[t]},set({_:e},t,n){const{data:l,setupState:r,ctx:i}=e;return Ei(r,t)?(r[t]=n,!0):l!==xe&&_e(l,t)?(l[t]=n,!0):_e(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:l,appContext:r,propsOptions:i}},a){let o;return!!n[a]||e!==xe&&_e(e,a)||Ei(t,a)||(o=i[0])&&_e(o,a)||_e(l,a)||_e(Bl,a)||_e(r.config.globalProperties,a)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:_e(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function Ho(e){return re(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Gi=!0;function b1(e){const t=ja(e),n=e.proxy,l=e.ctx;Gi=!1,t.beforeCreate&&zo(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:a,watch:o,provide:c,inject:u,created:d,beforeMount:f,mounted:h,beforeUpdate:p,updated:g,activated:v,deactivated:y,beforeDestroy:_,beforeUnmount:A,destroyed:m,unmounted:w,render:F,renderTracked:V,renderTriggered:R,errorCaptured:Z,serverPrefetch:M,expose:T,inheritAttrs:$,components:O,directives:X,filters:se}=t;if(u&&y1(u,l,null),a)for(const N in a){const J=a[N];ie(J)&&(l[N]=J.bind(n))}if(r){const N=r.call(n,n);De(N)&&(e.data=Jl(N))}if(Gi=!0,i)for(const N in i){const J=i[N],ae=ie(J)?J.bind(n,n):ie(J.get)?J.get.bind(n,n):$t,Ge=!ie(J)&&ie(J.set)?J.set.bind(n):$t,Fe=k({get:ae,set:Ge});Object.defineProperty(l,N,{enumerable:!0,configurable:!0,get:()=>Fe.value,set:ge=>Fe.value=ge})}if(o)for(const N in o)ju(o[N],l,n,N);if(c){const N=ie(c)?c.call(n):c;Reflect.ownKeys(N).forEach(J=>{Ot(J,N[J])})}d&&zo(d,e,"c");function K(N,J){re(J)?J.forEach(ae=>N(ae.bind(n))):J&&N(J.bind(n))}if(K(u1,f),K(we,h),K(d1,p),K(Nu,g),K(o1,v),K(s1,y),K(v1,Z),K(p1,V),K(h1,R),K(Jr,A),K(cl,w),K(f1,M),re(T))if(T.length){const N=e.exposed||(e.exposed={});T.forEach(J=>{Object.defineProperty(N,J,{get:()=>n[J],set:ae=>n[J]=ae})})}else e.exposed||(e.exposed={});F&&e.render===$t&&(e.render=F),$!=null&&(e.inheritAttrs=$),O&&(e.components=O),X&&(e.directives=X),M&&Na(e)}function y1(e,t,n=$t){re(e)&&(e=Ki(e));for(const l in e){const r=e[l];let i;De(r)?"default"in r?i=Se(r.from||l,r.default,!0):i=Se(r.from||l):i=Se(r),Re(i)?Object.defineProperty(t,l,{enumerable:!0,configurable:!0,get:()=>i.value,set:a=>i.value=a}):t[l]=i}}function zo(e,t,n){Dt(re(e)?e.map(l=>l.bind(t.proxy)):e.bind(t.proxy),t,n)}function ju(e,t,n,l){let r=l.includes(".")?ed(n,l):()=>n[l];if(ze(e)){const i=t[e];ie(i)&&pe(r,i)}else if(ie(e))pe(r,e.bind(n));else if(De(e))if(re(e))e.forEach(i=>ju(i,t,n,l));else{const i=ie(e.handler)?e.handler.bind(n):t[e.handler];ie(i)&&pe(r,i,e)}}function ja(e){const t=e.type,{mixins:n,extends:l}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:a}}=e.appContext,o=i.get(t);let c;return o?c=o:!r.length&&!n&&!l?c=t:(c={},r.length&&r.forEach(u=>Mr(c,u,a,!0)),Mr(c,t,a)),De(t)&&i.set(t,c),c}function Mr(e,t,n,l=!1){const{mixins:r,extends:i}=t;i&&Mr(e,i,n,!0),r&&r.forEach(a=>Mr(e,a,n,!0));for(const a in t)if(!(l&&a==="expose")){const o=A1[a]||n&&n[a];e[a]=o?o(e[a],t[a]):t[a]}return e}const A1={data:$o,props:Uo,emits:Uo,methods:_l,computed:_l,beforeCreate:Xe,created:Xe,beforeMount:Xe,mounted:Xe,beforeUpdate:Xe,updated:Xe,beforeDestroy:Xe,beforeUnmount:Xe,destroyed:Xe,unmounted:Xe,activated:Xe,deactivated:Xe,errorCaptured:Xe,serverPrefetch:Xe,components:_l,directives:_l,watch:w1,provide:$o,inject:k1};function $o(e,t){return t?e?function(){return Me(ie(e)?e.call(this,this):e,ie(t)?t.call(this,this):t)}:t:e}function k1(e,t){return _l(Ki(e),Ki(t))}function Ki(e){if(re(e)){const t={};for(let n=0;n1)return n&&ie(t)?t.call(l&&l.proxy):t}}const zu={},$u=()=>Object.create(zu),Uu=e=>Object.getPrototypeOf(e)===zu;function x1(e,t,n,l=!1){const r={},i=$u();e.propsDefaults=Object.create(null),Gu(e,t,r,i);for(const a in e.propsOptions[0])a in r||(r[a]=void 0);n?e.props=l?r:ku(r):e.type.props?e.props=r:e.props=i,e.attrs=i}function S1(e,t,n,l){const{props:r,attrs:i,vnode:{patchFlag:a}}=e,o=de(r),[c]=e.propsOptions;let u=!1;if((l||a>0)&&!(a&16)){if(a&8){const d=e.vnode.dynamicProps;for(let f=0;f{c=!0;const[h,p]=Ku(f,t,!0);Me(a,h),p&&o.push(...p)};!n&&t.mixins.length&&t.mixins.forEach(d),e.extends&&d(e.extends),e.mixins&&e.mixins.forEach(d)}if(!i&&!c)return De(e)&&l.set(e,Un),Un;if(re(i))for(let d=0;de[0]==="_"||e==="$stable",Ha=e=>re(e)?e.map(yt):[yt(e)],L1=(e,t,n)=>{if(t._n)return t;const l=$i((...r)=>Ha(t(...r)),n);return l._c=!1,l},Wu=(e,t,n)=>{const l=e._ctx;for(const r in e){if(qu(r))continue;const i=e[r];if(ie(i))t[r]=L1(r,i,l);else if(i!=null){const a=Ha(i);t[r]=()=>a}}},Ju=(e,t)=>{const n=Ha(t);e.slots.default=()=>n},Yu=(e,t,n)=>{for(const l in t)(n||l!=="_")&&(e[l]=t[l])},O1=(e,t,n)=>{const l=e.slots=$u();if(e.vnode.shapeFlag&32){const r=t._;r?(Yu(l,t,n),n&&au(l,"_",r,!0)):Wu(t,l)}else t&&Ju(e,t)},D1=(e,t,n)=>{const{vnode:l,slots:r}=e;let i=!0,a=xe;if(l.shapeFlag&32){const o=t._;o?n&&o===1?i=!1:Yu(r,t,n):(i=!t.$stable,Wu(t,r)),a=t}else t&&(Ju(e,t),a={default:1});if(i)for(const o in r)!qu(o)&&a[o]==null&&delete r[o]},dt=rd;function P1(e){return I1(e,l1)}function I1(e,t){const n=Kr();n.__VUE__=!0;const{insert:l,remove:r,patchProp:i,createElement:a,createText:o,createComment:c,setText:u,setElementText:d,parentNode:f,nextSibling:h,setScopeId:p=$t,insertStaticContent:g}=e,v=(E,b,B,D=null,S=null,P=null,G=void 0,z=null,j=!!b.dynamicChildren)=>{if(E===b)return;E&&!Bn(E,b)&&(D=x(E),ge(E,S,P,!0),E=null),b.patchFlag===-2&&(j=!1,b.dynamicChildren=null);const{type:I,ref:ne,shapeFlag:W}=b;switch(I){case Tn:y(E,b,B,D);break;case pt:_(E,b,B,D);break;case Cl:E==null&&A(b,B,D,G);break;case ht:O(E,b,B,D,S,P,G,z,j);break;default:W&1?F(E,b,B,D,S,P,G,z,j):W&6?X(E,b,B,D,S,P,G,z,j):(W&64||W&128)&&I.process(E,b,B,D,S,P,G,z,j,Q)}ne!=null&&S&&Ml(ne,E&&E.ref,P,b||E,!b)},y=(E,b,B,D)=>{if(E==null)l(b.el=o(b.children),B,D);else{const S=b.el=E.el;b.children!==E.children&&u(S,b.children)}},_=(E,b,B,D)=>{E==null?l(b.el=c(b.children||""),B,D):b.el=E.el},A=(E,b,B,D)=>{[E.el,E.anchor]=g(E.children,b,B,D,E.el,E.anchor)},m=({el:E,anchor:b},B,D)=>{let S;for(;E&&E!==b;)S=h(E),l(E,B,D),E=S;l(b,B,D)},w=({el:E,anchor:b})=>{let B;for(;E&&E!==b;)B=h(E),r(E),E=B;r(b)},F=(E,b,B,D,S,P,G,z,j)=>{b.type==="svg"?G="svg":b.type==="math"&&(G="mathml"),E==null?V(b,B,D,S,P,G,z,j):M(E,b,S,P,G,z,j)},V=(E,b,B,D,S,P,G,z)=>{let j,I;const{props:ne,shapeFlag:W,transition:te,dirs:le}=E;if(j=E.el=a(E.type,P,ne&&ne.is,ne),W&8?d(j,E.children):W&16&&Z(E.children,j,null,D,S,_i(E,P),G,z),le&&zt(E,null,D,"created"),R(j,E,E.scopeId,G,D),ne){for(const Be in ne)Be!=="value"&&!Gn(Be)&&i(j,Be,null,ne[Be],P,D);"value"in ne&&i(j,"value",null,ne.value,P),(I=ne.onVnodeBeforeMount)&&_t(I,D,E)}le&&zt(E,null,D,"beforeMount");const ue=Zu(S,te);ue&&te.beforeEnter(j),l(j,b,B),((I=ne&&ne.onVnodeMounted)||ue||le)&&dt(()=>{I&&_t(I,D,E),ue&&te.enter(j),le&&zt(E,null,D,"mounted")},S)},R=(E,b,B,D,S)=>{if(B&&p(E,B),D)for(let P=0;P{for(let I=j;I{const z=b.el=E.el;let{patchFlag:j,dynamicChildren:I,dirs:ne}=b;j|=E.patchFlag&16;const W=E.props||xe,te=b.props||xe;let le;if(B&&yn(B,!1),(le=te.onVnodeBeforeUpdate)&&_t(le,B,b,E),ne&&zt(b,E,B,"beforeUpdate"),B&&yn(B,!0),(W.innerHTML&&te.innerHTML==null||W.textContent&&te.textContent==null)&&d(z,""),I?T(E.dynamicChildren,I,z,B,D,_i(b,S),P):G||J(E,b,z,null,B,D,_i(b,S),P,!1),j>0){if(j&16)$(z,W,te,B,S);else if(j&2&&W.class!==te.class&&i(z,"class",null,te.class,S),j&4&&i(z,"style",W.style,te.style,S),j&8){const ue=b.dynamicProps;for(let Be=0;Be{le&&_t(le,B,b,E),ne&&zt(b,E,B,"updated")},D)},T=(E,b,B,D,S,P,G)=>{for(let z=0;z{if(b!==B){if(b!==xe)for(const P in b)!Gn(P)&&!(P in B)&&i(E,P,b[P],null,S,D);for(const P in B){if(Gn(P))continue;const G=B[P],z=b[P];G!==z&&P!=="value"&&i(E,P,z,G,S,D)}"value"in B&&i(E,"value",b.value,B.value,S)}},O=(E,b,B,D,S,P,G,z,j)=>{const I=b.el=E?E.el:o(""),ne=b.anchor=E?E.anchor:o("");let{patchFlag:W,dynamicChildren:te,slotScopeIds:le}=b;le&&(z=z?z.concat(le):le),E==null?(l(I,B,D),l(ne,B,D),Z(b.children||[],B,ne,S,P,G,z,j)):W>0&&W&64&&te&&E.dynamicChildren?(T(E.dynamicChildren,te,B,S,P,G,z),(b.key!=null||S&&b===S.subTree)&&Qu(E,b,!0)):J(E,b,B,ne,S,P,G,z,j)},X=(E,b,B,D,S,P,G,z,j)=>{b.slotScopeIds=z,E==null?b.shapeFlag&512?S.ctx.activate(b,B,D,G,j):se(b,B,D,S,P,G,j):he(E,b,j)},se=(E,b,B,D,S,P,G)=>{const z=E.component=Q1(E,D,S);if(Ql(E)&&(z.ctx.renderer=Q),X1(z,!1,G),z.asyncDep){if(S&&S.registerDep(z,K,G),!E.el){const j=z.subTree=Ve(pt);_(null,j,b,B)}}else K(z,E,b,B,S,P,G)},he=(E,b,B)=>{const D=b.component=E.component;if($1(E,b,B))if(D.asyncDep&&!D.asyncResolved){N(D,b,B);return}else D.next=b,D.update();else b.el=E.el,D.vnode=b},K=(E,b,B,D,S,P,G)=>{const z=()=>{if(E.isMounted){let{next:W,bu:te,u:le,parent:ue,vnode:Be}=E;{const ct=Xu(E);if(ct){W&&(W.el=Be.el,N(E,W,G)),ct.asyncDep.then(()=>{E.isUnmounted||z()});return}}let be=W,st;yn(E,!1),W?(W.el=Be.el,N(E,W,G)):W=Be,te&&fi(te),(st=W.props&&W.props.onVnodeBeforeUpdate)&&_t(st,ue,W,Be),yn(E,!0);const Je=bi(E),Ct=E.subTree;E.subTree=Je,v(Ct,Je,f(Ct.el),x(Ct),E,S,P),W.el=Je.el,be===null&&nd(E,Je.el),le&&dt(le,S),(st=W.props&&W.props.onVnodeUpdated)&&dt(()=>_t(st,ue,W,Be),S)}else{let W;const{el:te,props:le}=b,{bm:ue,m:Be,parent:be,root:st,type:Je}=E,Ct=Wn(b);if(yn(E,!1),ue&&fi(ue),!Ct&&(W=le&&le.onVnodeBeforeMount)&&_t(W,be,b),yn(E,!0),te&&ye){const ct=()=>{E.subTree=bi(E),ye(te,E.subTree,E,S,null)};Ct&&Je.__asyncHydrate?Je.__asyncHydrate(te,E,ct):ct()}else{st.ce&&st.ce._injectChildStyle(Je);const ct=E.subTree=bi(E);v(null,ct,B,D,E,S,P),b.el=ct.el}if(Be&&dt(Be,S),!Ct&&(W=le&&le.onVnodeMounted)){const ct=b;dt(()=>_t(W,be,ct),S)}(b.shapeFlag&256||be&&Wn(be.vnode)&&be.vnode.shapeFlag&256)&&E.a&&dt(E.a,S),E.isMounted=!0,b=B=D=null}};E.scope.on();const j=E.effect=new cu(z);E.scope.off();const I=E.update=j.run.bind(j),ne=E.job=j.runIfDirty.bind(j);ne.i=E,ne.id=E.uid,j.scheduler=()=>Ma(ne),yn(E,!0),I()},N=(E,b,B)=>{b.component=E;const D=E.vnode.props;E.vnode=b,E.next=null,S1(E,b.props,D,B),D1(E,b.children,B),vn(),Ro(E),mn()},J=(E,b,B,D,S,P,G,z,j=!1)=>{const I=E&&E.children,ne=E?E.shapeFlag:0,W=b.children,{patchFlag:te,shapeFlag:le}=b;if(te>0){if(te&128){Ge(I,W,B,D,S,P,G,z,j);return}else if(te&256){ae(I,W,B,D,S,P,G,z,j);return}}le&8?(ne&16&&We(I,S,P),W!==I&&d(B,W)):ne&16?le&16?Ge(I,W,B,D,S,P,G,z,j):We(I,S,P,!0):(ne&8&&d(B,""),le&16&&Z(W,B,D,S,P,G,z,j))},ae=(E,b,B,D,S,P,G,z,j)=>{E=E||Un,b=b||Un;const I=E.length,ne=b.length,W=Math.min(I,ne);let te;for(te=0;tene?We(E,S,P,!0,!1,W):Z(b,B,D,S,P,G,z,j,W)},Ge=(E,b,B,D,S,P,G,z,j)=>{let I=0;const ne=b.length;let W=E.length-1,te=ne-1;for(;I<=W&&I<=te;){const le=E[I],ue=b[I]=j?sn(b[I]):yt(b[I]);if(Bn(le,ue))v(le,ue,B,null,S,P,G,z,j);else break;I++}for(;I<=W&&I<=te;){const le=E[W],ue=b[te]=j?sn(b[te]):yt(b[te]);if(Bn(le,ue))v(le,ue,B,null,S,P,G,z,j);else break;W--,te--}if(I>W){if(I<=te){const le=te+1,ue=lete)for(;I<=W;)ge(E[I],S,P,!0),I++;else{const le=I,ue=I,Be=new Map;for(I=ue;I<=te;I++){const ut=b[I]=j?sn(b[I]):yt(b[I]);ut.key!=null&&Be.set(ut.key,I)}let be,st=0;const Je=te-ue+1;let Ct=!1,ct=0;const pl=new Array(Je);for(I=0;I=Je){ge(ut,S,P,!0);continue}let Vt;if(ut.key!=null)Vt=Be.get(ut.key);else for(be=ue;be<=te;be++)if(pl[be-ue]===0&&Bn(ut,b[be])){Vt=be;break}Vt===void 0?ge(ut,S,P,!0):(pl[Vt-ue]=I+1,Vt>=ct?ct=Vt:Ct=!0,v(ut,b[Vt],B,null,S,P,G,z,j),st++)}const Oo=Ct?F1(pl):Un;for(be=Oo.length-1,I=Je-1;I>=0;I--){const ut=ue+I,Vt=b[ut],Do=ut+1{const{el:P,type:G,transition:z,children:j,shapeFlag:I}=E;if(I&6){Fe(E.component.subTree,b,B,D);return}if(I&128){E.suspense.move(b,B,D);return}if(I&64){G.move(E,b,B,Q);return}if(G===ht){l(P,b,B);for(let W=0;Wz.enter(P),S);else{const{leave:W,delayLeave:te,afterLeave:le}=z,ue=()=>l(P,b,B),Be=()=>{W(P,()=>{ue(),le&&le()})};te?te(P,ue,Be):Be()}else l(P,b,B)},ge=(E,b,B,D=!1,S=!1)=>{const{type:P,props:G,ref:z,children:j,dynamicChildren:I,shapeFlag:ne,patchFlag:W,dirs:te,cacheIndex:le}=E;if(W===-2&&(S=!1),z!=null&&Ml(z,null,B,E,!0),le!=null&&(b.renderCache[le]=void 0),ne&256){b.ctx.deactivate(E);return}const ue=ne&1&&te,Be=!Wn(E);let be;if(Be&&(be=G&&G.onVnodeBeforeUnmount)&&_t(be,b,E),ne&6)rt(E.component,B,D);else{if(ne&128){E.suspense.unmount(B,D);return}ue&&zt(E,null,b,"beforeUnmount"),ne&64?E.type.remove(E,b,B,Q,D):I&&!I.hasOnce&&(P!==ht||W>0&&W&64)?We(I,b,B,!1,!0):(P===ht&&W&384||!S&&ne&16)&&We(j,b,B),D&&Ne(E)}(Be&&(be=G&&G.onVnodeUnmounted)||ue)&&dt(()=>{be&&_t(be,b,E),ue&&zt(E,null,b,"unmounted")},B)},Ne=E=>{const{type:b,el:B,anchor:D,transition:S}=E;if(b===ht){gt(B,D);return}if(b===Cl){w(E);return}const P=()=>{r(B),S&&!S.persisted&&S.afterLeave&&S.afterLeave()};if(E.shapeFlag&1&&S&&!S.persisted){const{leave:G,delayLeave:z}=S,j=()=>G(B,P);z?z(E.el,P,j):j()}else P()},gt=(E,b)=>{let B;for(;E!==b;)B=h(E),r(E),E=B;r(b)},rt=(E,b,B)=>{const{bum:D,scope:S,job:P,subTree:G,um:z,m:j,a:I}=E;Ko(j),Ko(I),D&&fi(D),S.stop(),P&&(P.flags|=8,ge(G,E,b,B)),z&&dt(z,b),dt(()=>{E.isUnmounted=!0},b),b&&b.pendingBranch&&!b.isUnmounted&&E.asyncDep&&!E.asyncResolved&&E.suspenseId===b.pendingId&&(b.deps--,b.deps===0&&b.resolve())},We=(E,b,B,D=!1,S=!1,P=0)=>{for(let G=P;G{if(E.shapeFlag&6)return x(E.component.subTree);if(E.shapeFlag&128)return E.suspense.next();const b=h(E.anchor||E.el),B=b&&b[Qp];return B?h(B):b};let q=!1;const U=(E,b,B)=>{E==null?b._vnode&&ge(b._vnode,null,null,!0):v(b._vnode||null,E,b,null,null,null,B),b._vnode=E,q||(q=!0,Ro(),Fr(),q=!1)},Q={p:v,um:ge,m:Fe,r:Ne,mt:se,mc:Z,pc:J,pbc:T,n:x,o:e};let fe,ye;return t&&([fe,ye]=t(Q)),{render:U,hydrate:fe,createApp:C1(U,fe)}}function _i({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 yn({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Zu(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Qu(e,t,n=!1){const l=e.children,r=t.children;if(re(l)&&re(r))for(let i=0;i>1,e[n[o]]0&&(t[l]=n[i-1]),n[i]=l)}}for(i=n.length,a=n[i-1];i-- >0;)n[i]=a,a=t[a];return n}function Xu(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Xu(t)}function Ko(e){if(e)for(let t=0;tSe(R1);function za(e,t){return $a(e,null,t)}function pe(e,t,n){return $a(e,t,n)}function $a(e,t,n=xe){const{immediate:l,deep:r,flush:i,once:a}=n,o=Me({},n),c=t&&l||!t&&i!=="post";let u;if(Qn){if(i==="sync"){const p=M1();u=p.__watcherHandles||(p.__watcherHandles=[])}else if(!c){const p=()=>{};return p.stop=$t,p.resume=$t,p.pause=$t,p}}const d=Ue;o.call=(p,g,v)=>Dt(p,d,g,v);let f=!1;i==="post"?o.scheduler=p=>{dt(p,d&&d.suspense)}:i!=="sync"&&(f=!0,o.scheduler=(p,g)=>{g?p():Ma(p)}),o.augmentJob=p=>{t&&(p.flags|=4),f&&(p.flags|=2,d&&(p.id=d.uid,p.i=d))};const h=Wp(e,t,o);return Qn&&(u?u.push(h):c&&h()),h}function V1(e,t,n){const l=this.proxy,r=ze(e)?e.includes(".")?ed(l,e):()=>l[e]:e.bind(l,l);let i;ie(t)?i=t:(i=t.handler,n=t);const a=er(this),o=$a(r,i.bind(l),n);return a(),o}function ed(e,t){const n=t.split(".");return()=>{let l=e;for(let r=0;rt==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${at(t)}Modifiers`]||e[`${Pn(t)}Modifiers`];function j1(e,t,...n){if(e.isUnmounted)return;const l=e.vnode.props||xe;let r=n;const i=t.startsWith("update:"),a=i&&N1(l,t.slice(7));a&&(a.trim&&(r=n.map(d=>ze(d)?d.trim():d)),a.number&&(r=n.map(cp)));let o,c=l[o=di(t)]||l[o=di(at(t))];!c&&i&&(c=l[o=di(Pn(t))]),c&&Dt(c,e,6,r);const u=l[o+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[o])return;e.emitted[o]=!0,Dt(u,e,6,r)}}function td(e,t,n=!1){const l=t.emitsCache,r=l.get(e);if(r!==void 0)return r;const i=e.emits;let a={},o=!1;if(!ie(e)){const c=u=>{const d=td(u,t,!0);d&&(o=!0,Me(a,d))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!i&&!o?(De(e)&&l.set(e,null),null):(re(i)?i.forEach(c=>a[c]=null):Me(a,i),De(e)&&l.set(e,a),a)}function Yr(e,t){return!e||!ql(t)?!1:(t=t.slice(2).replace(/Once$/,""),_e(e,t[0].toLowerCase()+t.slice(1))||_e(e,Pn(t))||_e(e,t))}function bi(e){const{type:t,vnode:n,proxy:l,withProxy:r,propsOptions:[i],slots:a,attrs:o,emit:c,render:u,renderCache:d,props:f,data:h,setupState:p,ctx:g,inheritAttrs:v}=e,y=Rr(e);let _,A;try{if(n.shapeFlag&4){const w=r||l,F=w;_=yt(u.call(F,w,d,f,p,h,g)),A=o}else{const w=t;_=yt(w.length>1?w(f,{attrs:o,slots:a,emit:c}):w(f,null)),A=t.props?o:H1(o)}}catch(w){xl.length=0,Zl(w,e,1),_=Ve(pt)}let m=_;if(A&&v!==!1){const w=Object.keys(A),{shapeFlag:F}=m;w.length&&F&7&&(i&&w.some(Ba)&&(A=z1(A,i)),m=fn(m,A,!1,!0))}return n.dirs&&(m=fn(m,null,!1,!0),m.dirs=m.dirs?m.dirs.concat(n.dirs):n.dirs),n.transition&&On(m,n.transition),_=m,Rr(y),_}const H1=e=>{let t;for(const n in e)(n==="class"||n==="style"||ql(n))&&((t||(t={}))[n]=e[n]);return t},z1=(e,t)=>{const n={};for(const l in e)(!Ba(l)||!(l.slice(9)in t))&&(n[l]=e[l]);return n};function $1(e,t,n){const{props:l,children:r,component:i}=e,{props:a,children:o,patchFlag:c}=t,u=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return l?qo(l,a,u):!!a;if(c&8){const d=t.dynamicProps;for(let f=0;fe.__isSuspense;function rd(e,t){t&&t.pendingBranch?re(e)?t.effects.push(...e):t.effects.push(e):Zp(e)}const ht=Symbol.for("v-fgt"),Tn=Symbol.for("v-txt"),pt=Symbol.for("v-cmt"),Cl=Symbol.for("v-stc"),xl=[];let mt=null;function U1(e=!1){xl.push(mt=e?null:[])}function G1(){xl.pop(),mt=xl[xl.length-1]||null}let Vl=1;function Wo(e,t=!1){Vl+=e,e<0&&mt&&t&&(mt.hasOnce=!0)}function id(e){return e.dynamicChildren=Vl>0?mt||Un:null,G1(),Vl>0&&mt&&mt.push(e),e}function AE(e,t,n,l,r,i){return id(Sl(e,t,n,l,r,i,!0))}function K1(e,t,n,l,r){return id(Ve(e,t,n,l,r,!0))}function Vr(e){return e?e.__v_isVNode===!0:!1}function Bn(e,t){return e.type===t.type&&e.key===t.key}const ad=({key:e})=>e??null,xr=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?ze(e)||Re(e)||ie(e)?{i:At,r:e,k:t,f:!!n}:e:null);function Sl(e,t=null,n=null,l=0,r=null,i=e===ht?0:1,a=!1,o=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ad(t),ref:t&&xr(t),scopeId:Ou,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:l,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:At};return o?(Ua(c,n),i&128&&e.normalize(c)):n&&(c.shapeFlag|=ze(n)?8:16),Vl>0&&!a&&mt&&(c.patchFlag>0||i&6)&&c.patchFlag!==32&&mt.push(c),c}const Ve=q1;function q1(e,t=null,n=null,l=0,r=null,i=!1){if((!e||e===g1)&&(e=pt),Vr(e)){const o=fn(e,t,!0);return n&&Ua(o,n),Vl>0&&!i&&mt&&(o.shapeFlag&6?mt[mt.indexOf(e)]=o:mt.push(o)),o.patchFlag=-2,o}if(r0(e)&&(e=e.__vccOpts),t){t=W1(t);let{class:o,style:c}=t;o&&!ze(o)&&(t.class=Ta(o)),De(c)&&(Ra(c)&&!re(c)&&(c=Me({},c)),t.style=Sa(c))}const a=ze(e)?1:ld(e)?128:Du(e)?64:De(e)?4:ie(e)?2:0;return Sl(e,t,n,l,r,a,i,!0)}function W1(e){return e?Ra(e)||Uu(e)?Me({},e):e:null}function fn(e,t,n=!1,l=!1){const{props:r,ref:i,patchFlag:a,children:o,transition:c}=e,u=t?J1(r||{},t):r,d={__v_isVNode:!0,__v_skip:!0,type:e.type,props:u,key:u&&ad(u),ref:t&&t.ref?n&&i?re(i)?i.concat(xr(t)):[i,xr(t)]:xr(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:o,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ht?a===-1?16:a|16:a,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&fn(e.ssContent),ssFallback:e.ssFallback&&fn(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&l&&On(d,c.clone(d)),d}function od(e=" ",t=0){return Ve(Tn,null,e,t)}function kE(e,t){const n=Ve(Cl,null,e);return n.staticCount=t,n}function yt(e){return e==null||typeof e=="boolean"?Ve(pt):re(e)?Ve(ht,null,e.slice()):Vr(e)?sn(e):Ve(Tn,null,String(e))}function sn(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:fn(e)}function Ua(e,t){let n=0;const{shapeFlag:l}=e;if(t==null)t=null;else if(re(t))n=16;else if(typeof t=="object")if(l&65){const r=t.default;r&&(r._c&&(r._d=!1),Ua(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!Uu(t)?t._ctx=At:r===3&&At&&(At.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else ie(t)?(t={default:t,_ctx:At},n=32):(t=String(t),l&64?(n=16,t=[od(t)]):n=8);e.children=t,e.shapeFlag|=n}function J1(...e){const t={};for(let n=0;nUe||At;let Nr,Wi;{const e=Kr(),t=(n,l)=>{let r;return(r=e[n])||(r=e[n]=[]),r.push(l),i=>{r.length>1?r.forEach(a=>a(i)):r[0](i)}};Nr=t("__VUE_INSTANCE_SETTERS__",n=>Ue=n),Wi=t("__VUE_SSR_SETTERS__",n=>Qn=n)}const er=e=>{const t=Ue;return Nr(e),e.scope.on(),()=>{e.scope.off(),Nr(t)}},Jo=()=>{Ue&&Ue.scope.off(),Nr(null)};function sd(e){return e.vnode.shapeFlag&4}let Qn=!1;function X1(e,t=!1,n=!1){t&&Wi(t);const{props:l,children:r}=e.vnode,i=sd(e);x1(e,l,i,t),O1(e,r,n);const a=i?e0(e,t):void 0;return t&&Wi(!1),a}function e0(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,_1);const{setup:l}=n;if(l){vn();const r=e.setupContext=l.length>1?n0(e):null,i=er(e),a=Yl(l,e,0,[e.props,r]),o=iu(a);if(mn(),i(),(o||e.sp)&&!Wn(e)&&Na(e),o){if(a.then(Jo,Jo),t)return a.then(c=>{Yo(e,c,t)}).catch(c=>{Zl(c,e,0)});e.asyncDep=a}else Yo(e,a,t)}else cd(e,t)}function Yo(e,t,n){ie(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:De(t)&&(e.setupState=Bu(t)),cd(e,n)}let Zo;function cd(e,t,n){const l=e.type;if(!e.render){if(!t&&Zo&&!l.render){const r=l.template||ja(e).template;if(r){const{isCustomElement:i,compilerOptions:a}=e.appContext.config,{delimiters:o,compilerOptions:c}=l,u=Me(Me({isCustomElement:i,delimiters:o},a),c);l.render=Zo(r,u)}}e.render=l.render||$t}{const r=er(e);vn();try{b1(e)}finally{mn(),r()}}}const t0={get(e,t){return Ye(e,"get",""),e[t]}};function n0(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,t0),slots:e.slots,emit:e.emit,expose:t}}function Ga(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Bu(Vp(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Bl)return Bl[n](e)},has(t,n){return n in t||n in Bl}})):e.proxy}function l0(e,t=!0){return ie(e)?e.displayName||e.name:e.name||t&&e.__name}function r0(e){return ie(e)&&"__vccOpts"in e}const k=(e,t)=>Kp(e,t,Qn);function s(e,t,n){const l=arguments.length;return l===2?De(t)&&!re(t)?Vr(t)?Ve(e,null,[t]):Ve(e,t):Ve(e,null,t):(l>3?n=Array.prototype.slice.call(arguments,2):l===3&&Vr(n)&&(n=[n]),Ve(e,t,n))}const i0="3.5.13";/**
+* @vue/runtime-dom v3.5.13
+* (c) 2018-present Yuxi (Evan) You and Vue contributors
+* @license MIT
+**/let Ji;const Qo=typeof window<"u"&&window.trustedTypes;if(Qo)try{Ji=Qo.createPolicy("vue",{createHTML:e=>e})}catch{}const ud=Ji?e=>Ji.createHTML(e):e=>e,a0="http://www.w3.org/2000/svg",o0="http://www.w3.org/1998/Math/MathML",Jt=typeof document<"u"?document:null,Xo=Jt&&Jt.createElement("template"),s0={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,l)=>{const r=t==="svg"?Jt.createElementNS(a0,e):t==="mathml"?Jt.createElementNS(o0,e):n?Jt.createElement(e,{is:n}):Jt.createElement(e);return e==="select"&&l&&l.multiple!=null&&r.setAttribute("multiple",l.multiple),r},createText:e=>Jt.createTextNode(e),createComment:e=>Jt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Jt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,l,r,i){const a=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{Xo.innerHTML=ud(l==="svg"?`${e} `:l==="mathml"?`${e} `:e);const o=Xo.content;if(l==="svg"||l==="mathml"){const c=o.firstChild;for(;c.firstChild;)o.appendChild(c.firstChild);o.removeChild(c)}t.insertBefore(o,n)}return[a?a.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},nn="transition",ml="animation",Xn=Symbol("_vtc"),dd={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},fd=Me({},Iu,dd),c0=e=>(e.displayName="Transition",e.props=fd,e),el=c0((e,{slots:t})=>s(e1,hd(e),t)),An=(e,t=[])=>{re(e)?e.forEach(n=>n(...t)):e&&e(...t)},es=e=>e?re(e)?e.some(t=>t.length>1):e.length>1:!1;function hd(e){const t={};for(const O in e)O in dd||(t[O]=e[O]);if(e.css===!1)return t;const{name:n="v",type:l,duration:r,enterFromClass:i=`${n}-enter-from`,enterActiveClass:a=`${n}-enter-active`,enterToClass:o=`${n}-enter-to`,appearFromClass:c=i,appearActiveClass:u=a,appearToClass:d=o,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:h=`${n}-leave-active`,leaveToClass:p=`${n}-leave-to`}=e,g=u0(r),v=g&&g[0],y=g&&g[1],{onBeforeEnter:_,onEnter:A,onEnterCancelled:m,onLeave:w,onLeaveCancelled:F,onBeforeAppear:V=_,onAppear:R=A,onAppearCancelled:Z=m}=t,M=(O,X,se,he)=>{O._enterCancelled=he,rn(O,X?d:o),rn(O,X?u:a),se&&se()},T=(O,X)=>{O._isLeaving=!1,rn(O,f),rn(O,p),rn(O,h),X&&X()},$=O=>(X,se)=>{const he=O?R:A,K=()=>M(X,O,se);An(he,[X,K]),ts(()=>{rn(X,O?c:i),jt(X,O?d:o),es(he)||ns(X,l,v,K)})};return Me(t,{onBeforeEnter(O){An(_,[O]),jt(O,i),jt(O,a)},onBeforeAppear(O){An(V,[O]),jt(O,c),jt(O,u)},onEnter:$(!1),onAppear:$(!0),onLeave(O,X){O._isLeaving=!0;const se=()=>T(O,X);jt(O,f),O._enterCancelled?(jt(O,h),Yi()):(Yi(),jt(O,h)),ts(()=>{O._isLeaving&&(rn(O,f),jt(O,p),es(w)||ns(O,l,y,se))}),An(w,[O,se])},onEnterCancelled(O){M(O,!1,void 0,!0),An(m,[O])},onAppearCancelled(O){M(O,!0,void 0,!0),An(Z,[O])},onLeaveCancelled(O){T(O),An(F,[O])}})}function u0(e){if(e==null)return null;if(De(e))return[yi(e.enter),yi(e.leave)];{const t=yi(e);return[t,t]}}function yi(e){return up(e)}function jt(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Xn]||(e[Xn]=new Set)).add(t)}function rn(e,t){t.split(/\s+/).forEach(l=>l&&e.classList.remove(l));const n=e[Xn];n&&(n.delete(t),n.size||(e[Xn]=void 0))}function ts(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let d0=0;function ns(e,t,n,l){const r=e._endId=++d0,i=()=>{r===e._endId&&l()};if(n!=null)return setTimeout(i,n);const{type:a,timeout:o,propCount:c}=pd(e,t);if(!a)return l();const u=a+"end";let d=0;const f=()=>{e.removeEventListener(u,h),i()},h=p=>{p.target===e&&++d>=c&&f()};setTimeout(()=>{d(n[g]||"").split(", "),r=l(`${nn}Delay`),i=l(`${nn}Duration`),a=ls(r,i),o=l(`${ml}Delay`),c=l(`${ml}Duration`),u=ls(o,c);let d=null,f=0,h=0;t===nn?a>0&&(d=nn,f=a,h=i.length):t===ml?u>0&&(d=ml,f=u,h=c.length):(f=Math.max(a,u),d=f>0?a>u?nn:ml:null,h=d?d===nn?i.length:c.length:0);const p=d===nn&&/\b(transform|all)(,|$)/.test(l(`${nn}Property`).toString());return{type:d,timeout:f,propCount:h,hasTransform:p}}function ls(e,t){for(;e.lengthrs(n)+rs(e[l])))}function rs(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Yi(){return document.body.offsetHeight}function f0(e,t,n){const l=e[Xn];l&&(t=(t?[t,...l]:[...l]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const is=Symbol("_vod"),h0=Symbol("_vsh"),p0=Symbol(""),v0=/(^|;)\s*display\s*:/;function m0(e,t,n){const l=e.style,r=ze(n);let i=!1;if(n&&!r){if(t)if(ze(t))for(const a of t.split(";")){const o=a.slice(0,a.indexOf(":")).trim();n[o]==null&&Sr(l,o,"")}else for(const a in t)n[a]==null&&Sr(l,a,"");for(const a in n)a==="display"&&(i=!0),Sr(l,a,n[a])}else if(r){if(t!==n){const a=l[p0];a&&(n+=";"+a),l.cssText=n,i=v0.test(n)}}else t&&e.removeAttribute("style");is in e&&(e[is]=i?l.display:"",e[h0]&&(l.display="none"))}const as=/\s*!important$/;function Sr(e,t,n){if(re(n))n.forEach(l=>Sr(e,t,l));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const l=g0(e,t);as.test(n)?e.setProperty(Pn(l),n.replace(as,""),"important"):e[l]=n}}const os=["Webkit","Moz","ms"],Ai={};function g0(e,t){const n=Ai[t];if(n)return n;let l=at(t);if(l!=="filter"&&l in e)return Ai[t]=l;l=Wl(l);for(let r=0;rki||(A0.then(()=>ki=0),ki=Date.now());function w0(e,t){const n=l=>{if(!l._vts)l._vts=Date.now();else if(l._vts<=n.attached)return;Dt(B0(l,n.value),t,5,[l])};return n.value=e,n.attached=k0(),n}function B0(e,t){if(re(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(l=>r=>!r._stopped&&l&&l(r))}else return t}const hs=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,C0=(e,t,n,l,r,i)=>{const a=r==="svg";t==="class"?f0(e,l,a):t==="style"?m0(e,n,l):ql(t)?Ba(t)||b0(e,t,n,l,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):x0(e,t,l,a))?(us(e,t,l),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&cs(e,t,l,a,i,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!ze(l))?us(e,at(t),l,i,t):(t==="true-value"?e._trueValue=l:t==="false-value"&&(e._falseValue=l),cs(e,t,l,a))};function x0(e,t,n,l){if(l)return!!(t==="innerHTML"||t==="textContent"||t in e&&hs(t)&&ie(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 r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return hs(t)&&ze(n)?!1:t in e}const vd=new WeakMap,md=new WeakMap,jr=Symbol("_moveCb"),ps=Symbol("_enterCb"),S0=e=>(delete e.props.mode,e),T0=S0({name:"TransitionGroup",props:Me({},fd,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=Xl(),l=Pu();let r,i;return Nu(()=>{if(!r.length)return;const a=e.moveClass||`${e.name||"v"}-move`;if(!P0(r[0].el,n.vnode.el,a))return;r.forEach(L0),r.forEach(O0);const o=r.filter(D0);Yi(),o.forEach(c=>{const u=c.el,d=u.style;jt(u,a),d.transform=d.webkitTransform=d.transitionDuration="";const f=u[jr]=h=>{h&&h.target!==u||(!h||/transform$/.test(h.propertyName))&&(u.removeEventListener("transitionend",f),u[jr]=null,rn(u,a))};u.addEventListener("transitionend",f)})}),()=>{const a=de(e),o=hd(a);let c=a.tag||ht;if(r=[],i)for(let u=0;u{o.split(/\s+/).forEach(c=>c&&l.classList.remove(c))}),n.split(/\s+/).forEach(o=>o&&l.classList.add(o)),l.style.display="none";const i=t.nodeType===1?t:t.parentNode;i.appendChild(l);const{hasTransform:a}=pd(l);return i.removeChild(l),a}const I0=Me({patchProp:C0},s0);let wi,vs=!1;function F0(){return wi=vs?wi:P1(I0),vs=!0,wi}const R0=(...e)=>{const t=F0().createApp(...e),{mount:n}=t;return t.mount=l=>{const r=V0(l);if(r)return n(r,!0,M0(r))},t};function M0(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function V0(e){return ze(e)?document.querySelector(e):e}var tr=e=>/^[a-z][a-z0-9+.-]*:/.test(e)||e.startsWith("//"),N0=/.md((\?|#).*)?$/,Ka=(e,t="/")=>tr(e)||e.startsWith("/")&&!e.startsWith(t)&&!N0.test(e),gn=e=>/^(https?:)?\/\//.test(e),ms=e=>{if(!e||e.endsWith("/"))return e;let t=e.replace(/(^|\/)README.md$/i,"$1index.html");return t.endsWith(".md")?t=t.substring(0,t.length-3)+".html":t.endsWith(".html")||(t=t+".html"),t.endsWith("/index.html")&&(t=t.substring(0,t.length-10)),t},j0="http://.",H0=(e,t)=>{if(!e.startsWith("/")&&t){const n=t.slice(0,t.lastIndexOf("/"));return ms(new URL(`${n}/${e}`,j0).pathname)}return ms(e)},z0=(e,t)=>{const n=Object.keys(e).sort((l,r)=>{const i=r.split("/").length-l.split("/").length;return i!==0?i:r.length-l.length});for(const l of n)if(t.startsWith(l))return l;return"/"},$0=/(#|\?)/,Ed=e=>{const[t,...n]=e.split($0);return{pathname:t,hashAndQueries:n.join("")}},U0=["link","meta","script","style","noscript","template"],G0=["title","base"],K0=([e,t,n])=>G0.includes(e)?e:U0.includes(e)?e==="meta"&&t.name?`${e}.${t.name}`:e==="template"&&t.id?`${e}.${t.id}`:JSON.stringify([e,Object.entries(t).map(([l,r])=>typeof r=="boolean"?r?[l,""]:null:[l,r]).filter(l=>l!=null).sort(([l],[r])=>l.localeCompare(r)),n]):null,q0=e=>{const t=new Set,n=[];return e.forEach(l=>{const r=K0(l);r&&!t.has(r)&&(t.add(r),n.push(l))}),n},W0=e=>e[0]==="/"?e:`/${e}`,_d=e=>e[e.length-1]==="/"||e.endsWith(".html")?e:`${e}/`,Zr=e=>e[e.length-1]==="/"?e.slice(0,-1):e,bd=e=>e[0]==="/"?e.slice(1):e,nr=e=>Object.prototype.toString.call(e)==="[object Object]",ke=e=>typeof e=="string";const J0="modulepreload",Y0=function(e){return"/"+e},gs={},C=function(t,n,l){let r=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),a=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));r=Promise.all(n.map(o=>{if(o=Y0(o),o in gs)return;gs[o]=!0;const c=o.endsWith(".css"),u=c?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${u}`))return;const d=document.createElement("link");if(d.rel=c?"stylesheet":J0,c||(d.as="script",d.crossOrigin=""),d.href=o,a&&d.setAttribute("nonce",a),document.head.appendChild(d),c)return new Promise((f,h)=>{d.addEventListener("load",f),d.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${o}`)))})}))}return r.then(()=>t()).catch(i=>{const a=new Event("vite:preloadError",{cancelable:!0});if(a.payload=i,window.dispatchEvent(a),!a.defaultPrevented)throw i})},Z0=JSON.parse("{}"),Q0=Object.fromEntries([["/",{loader:()=>C(()=>import("./index.html-By-pQ7Wl.js"),[]),meta:{t:"首页",i:"home"}}],["/about-the-author/",{loader:()=>C(()=>import("./index.html-DqVhfNm4.js"),[]),meta:{d:1706204085e3,e:`
+留空
+`,r:{minutes:.02,words:5},t:"关于我",y:"a"}}],["/bigdata/",{loader:()=>C(()=>import("./index.html-D1R9zQcp.js"),[]),meta:{d:156672164e4,e:`
+`,r:{minutes:0,words:1},t:"Spark",y:"a"}}],["/cloudnative/",{loader:()=>C(()=>import("./index.html-DlwW5Vje.js"),[]),meta:{d:156672164e4,t:"",y:"a"}}],["/database/",{loader:()=>C(()=>import("./index.html-DWXiwN5o.js"),[]),meta:{d:1706182936e3,e:`
+目录留空
+`,r:{minutes:.02,words:5},t:"Database",y:"a"}}],["/donate/",{loader:()=>C(()=>import("./index.html-D4WG7yPk.js"),[]),meta:{d:1706169851e3,e:`
+微信支付 `,r:{minutes:.04,words:12},t:"微信支付",y:"a"}}],["/interesting/",{loader:()=>C(()=>import("./index.html-B1Akg086.js"),[]),meta:{d:171606205e4,e:`
+`,r:{minutes:.02,words:6},t:"好玩的",y:"a"}}],["/interesting/chatgpt.html",{loader:()=>C(()=>import("./chatgpt.html-BgeRWiYw.js"),[]),meta:{d:1706186538e3,e:`
+想体验的可以去微信上搜索【旅行的树】公众号。
+一、ChatGPT注册 `,r:{minutes:9.96,words:2987},t:"微信公众号-chatgpt智能客服搭建",y:"a"}}],["/interesting/idea%E8%AE%BE%E7%BD%AE.html",{loader:()=>C(()=>import("./idea设置.html-BThIkzaw.js"),[]),meta:{d:1715445447e3,e:`
+一、类注释
+想要在生成类的时候,自动带上author和时间,效果如下:
`,r:{minutes:1.33,words:399},t:"Jetbrains Idea设置",y:"a"}}],["/interesting/starcraft-ai.html",{loader:()=>C(()=>import("./starcraft-ai.html-C018rwGF.js"),[]),meta:{d:1706288023e3,e:`
+非深度学习人士,仅仅是兴趣驱动,可能有很多不对的地方,也欢迎大家指正。这里主要讲解如何将AI运行起来、机器人对战、人机对战、天梯上分等等,希望能对大家的人工智能工程道路上有所帮助。
`,r:{minutes:2.72,words:817},t:"StarCraft Ⅱ 人工智能教程",y:"a"}}],["/interesting/tesla.html",{loader:()=>C(()=>import("./tesla.html-K0riacrL.js"),[]),meta:{d:1706186538e3,e:`
+一、特斯拉应用申请
+1.1 创建 Tesla 账户
+如果您还没有 Tesla 账户,请创建账户。验证您的电子邮件并设置多重身份验证。
`,r:{minutes:4.5,words:1351},t:"Tesla api",y:"a"}}],["/interesting/%E4%B8%80%E4%BA%9B%E4%B8%8D%E5%B8%B8%E7%94%A8%E4%BD%86%E5%BE%88%E5%AE%9E%E7%94%A8%E7%9A%84%E5%91%BD%E4%BB%A4.html",{loader:()=>C(()=>import("./一些不常用但很实用的命令.html-BtEABYaE.js"),[]),meta:{d:1708752707e3,e:`
+https连接耗时检测
+curl -w "TCP handshake: %{time_connect}, SSL handshake: %{time_appconnect}\\n" -so /dev/null https://zhls.qq.com/test-nginx
+
`,r:{minutes:.16,words:47},t:"一些不常用但很实用的命令",y:"a"}}],["/interesting/%E5%9F%BA%E4%BA%8EOLAP%E5%81%9A%E4%B8%9A%E5%8A%A1%E7%9B%91%E6%8E%A7.html",{loader:()=>C(()=>import("./基于OLAP做业务监控.html-BNdB--VB.js"),[]),meta:{d:1715617566e3,e:`
+在监控领域,Prometheus 与 Grafana 常被认为是无敌组合。然而,随着成本的增加,不少人开始审慎考虑其他替代方案。本文将深入探讨 Prometheus 的特点,并讨论 Grafana 中关键参数 interval
和 for
的意义及其影响。此外,还将分析 OLAP 数据库作为监控数据持久性存储的优势。
`,r:{minutes:1.95,words:586},t:"基于OLAP做业务监控",y:"a"}}],["/interesting/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%8F%8D%E7%BC%96%E8%AF%91.html",{loader:()=>C(()=>import("./小程序反编译.html-BNnmGgbc.js"),[]),meta:{d:171008157e4,e:`
+第一步:电脑端提取
+先找到小程序保存的地址,一般先找到微信的文件管理下
`,r:{minutes:.82,words:246},t:"小程序反编译",y:"a"}}],["/interesting/%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",{loader:()=>C(()=>import("./广州图书馆借阅抓取.html-CPwBtyqR.js"),[]),meta:{d:1706596625e3,e:`
+欢迎访问我的个人网站 ,要是能在GitHub上对网站源码 给个star就更好了。
`,r:{minutes:6.83,words:2049},t:"广州图书馆借阅抓取",y:"a"}}],["/interesting/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E6%95%B4%E7%90%86.html",{loader:()=>C(()=>import("./开发工具整理.html-BKoUISo4.js"),[]),meta:{d:171008157e4,e:`
+ShadowsocksX
+mac端:https://github.com/shadowsocks/ShadowsocksX-NG
+win端:https://github.com/shadowsocks/shadowsocks-windows
+安卓:https://github.com/shadowsocks/shadowsocks-android
`,r:{minutes:.12,words:36},t:"开发工具整理",y:"a"}}],["/interesting/%E7%A8%8B%E5%BA%8F%E5%91%98%E5%89%AF%E4%B8%9A%E6%8E%A2%E7%B4%A2%E4%B9%8B%E7%94%B5%E5%95%86.html",{loader:()=>C(()=>import("./程序员副业探索之电商.html-CwtUep3k.js"),[]),meta:{d:1722783109e3,e:`
+在腾讯广告工作期间,我主要负责小程序电商与广告业务,见证了互联网电商行业的剧变,特别是众多电商公司纷纷拥抱私域流量,直播带货成为新风尚,广告投入也在持续增加。通过这些经历,我积累了不少关于互联网电商的经验,并萌生了尝试电商副业的想法。
`,r:{minutes:10.01,words:3002},t:"程序员副业探索之电商",y:"a"}}],["/interview/tiktok2023.html",{loader:()=>C(()=>import("./tiktok2023.html-BxK5gJWF.js"),[]),meta:{d:1680437706e3,e:`tt一面:
+1.全程项目
+2.lc3,最长无重复子串,滑动窗口解决
+tt二面:
+全程基础,一直追问
+1.java内存模型介绍一下
+2.volatile原理
+3.内存屏障,使用场景?(我提了在gc中有使用)
+4.gc中具体是怎么使用内存屏障的,详细介绍
+5.cms和g1介绍一下,g1能取代cms吗?g1和cms各自的使用场景是什么
+6.线程内存分配方式,tlab相关
+7.happens-before介绍一下
+8.总线风暴是什么,怎么解决
+9.网络相关,time_wait,close_wait产生原因,带来的影响,怎么解决
+10.算法题,给你一个数字n,求用这个n的各位上的数字组合出最大的小于n的数字m,注意边界case,如2222
+11.场景题,设计一个微信朋友圈,功能包含feed流拉取,评论,转发,点赞等操作
`,r:{minutes:1.15,words:344},t:"",y:"a"}}],["/java/",{loader:()=>C(()=>import("./index.html-jGjDZXTI.js"),[]),meta:{d:156672164e4,e:`
+`,r:{minutes:.01,words:4},t:"Java",y:"a"}}],["/java/serverlog.html",{loader:()=>C(()=>import("./serverlog.html-bICZU0Nm.js"),[]),meta:{d:1579957849e3,e:`
+服务器被黑,进程占用率高达99%,查看了一下,是/usr/sbin/bashd的原因,怎么删也删不掉,使用ps查看:
+
+stratum+tcp://get.bi-chi.com:3333 -u 47EAoaBc5TWDZKVaAYvQ7Y4ZfoJMFathAR882gabJ43wHEfxEp81vfJ3J3j6FQGJxJNQTAwvmJYS2Ei8dbkKcwfPFst8FhG
`,r:{minutes:.57,words:172},t:"被挖矿攻击",y:"a"}}],["/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",{loader:()=>C(()=>import("./在 Spring 6 中使用虚拟线程.html-DsVzFk6c.js"),[]),meta:{d:1706186538e3,e:`
+一、简介
+在这个简短的教程中,我们将了解如何在 Spring Boot 应用程序中利用虚拟线程的强大功能。
`,r:{minutes:4.83,words:1448},t:"在 Spring 6 中使用虚拟线程",y:"a"}}],["/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",{loader:()=>C(()=>import("./基于kubernetes的分布式限流.html-B1ZIsZdu.js"),[]),meta:{d:1649482551e3,e:`
+做为一个数据上报系统,随着接入量越来越大,由于 API 接口无法控制调用方的行为,因此当遇到瞬时请求量激增时,会导致接口占用过多服务器资源,使得其他请求响应速度降低或是超时,更有甚者可能导致服务器宕机。
`,r:{minutes:7.18,words:2155},t:"基于kubernetes的分布式限流",y:"a"}}],["/java/%E6%B5%81%E7%A8%8B%E7%BC%96%E6%8E%92LiteFlow.html",{loader:()=>C(()=>import("./流程编排LiteFlow.html-CvCVGQll.js"),[]),meta:{d:1725814553e3,e:`
+LiteFlow真的是相见恨晚啊,之前做过的很多系统,都会用各种if else,switch这些来解决不同业务方提出的问题,有时候还要“切一个分支”来搞这些额外的事情,把代码搞得一团糟,毫无可读性而言。如何打破僵局?LiteFlow为解耦逻辑而生,为编排而生,在使用LiteFlow之后,你会发现打造一个低耦合,灵活的系统会变得易如反掌!
`,r:{minutes:7.11,words:2134},t:"流程编排LiteFlow",y:"a"}}],["/java/%E9%AB%98%E5%8F%AF%E7%94%A8.html",{loader:()=>C(()=>import("./高可用.html-DjOPo7tP.js"),[]),meta:{d:171008157e4,e:`
+4个9(99.99)
+
+
+
+
+Sentinel
+Hystrix(维护状态)
+Resilience4j(Spring推荐)
+
+
+
+
+隔离策略
+信号量隔离(并发线程数限流)
+线程池隔离/信号量隔离
+信号量隔离
+
+
+熔断降级策略
+基于响应时间、异常比率、异常数
+基于异常比率
+基于异常比率、响应时间
+
+
+实时统计实现
+滑动窗口
+滑动窗口
+Ring Bit Buffer
+
+
+动态规则配置
+支持多种数据源
+支持多种数据源
+有限支持
+
+
+扩展性
+支持多种数据源
+支持多种数据源
+有限支持
+
+
+限流
+基于 QPS,支持基于调用关系的限流
+有限的支持
+Rate Limiter
+
+
+流量整形
+支持预热模式、匀速器模式、预热排队模式
+不支持
+简单的 Rate Limiter 模式
+
+
+系统的自适应保护
+支持
+不支持
+不支持
+
+
+控制台
+提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等
+简单的监控查看
+不提供控制台,可对接其他监控系统
+
+
+
`,r:{minutes:4.27,words:1281},t:"高可用",y:"a"}}],["/java/%E9%AB%98%E5%B9%B6%E5%8F%91.html",{loader:()=>C(()=>import("./高并发.html-B4hi1h21.js"),[]),meta:{d:171008157e4,e:`
+QPS
+高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求 。 高并发相关常用的一些指标有响应时间 (Response Time),吞吐量 (Throughput),每秒查询率 QPS(Query Per Second),并发用户数 等。
`,r:{minutes:4.28,words:1285},t:"高并发",y:"a"}}],["/java/%E9%AB%98%E6%80%A7%E8%83%BD.html",{loader:()=>C(()=>import("./高性能.html-CN7rmRWu.js"),[]),meta:{d:171008157e4,e:`
+响应时间
+性能直接影响用户的感官体验,访问一个系统,如果超过5秒没有响应,绝大数用户会选择离开。
`,r:{minutes:3.03,words:909},t:"高性能",y:"a"}}],["/java/%E9%AB%98%E6%80%A7%E8%83%BD%E9%AB%98%E5%B9%B6%E5%8F%91%E9%AB%98%E5%8F%AF%E7%94%A8%E7%9A%84%E4%B8%80%E4%BA%9B%E6%80%9D%E8%80%83.html",{loader:()=>C(()=>import("./高性能高并发高可用的一些思考.html-DLPHuyVJ.js"),[]),meta:{d:1706983034e3,e:`
+TODO待补充
+异步
+Jmeter `,r:{minutes:.36,words:109},t:"高性能高并发高可用的一些思考",y:"a"}}],["/kubernetes/Jenkins%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AC%94%E8%AE%B0.html",{loader:()=>C(()=>import("./Jenkins的一些笔记.html--8cnUWGp.js"),[]),meta:{d:1708751576e3,e:`
+公司主要要开发自己的paas平台,集成了Jenkins,真的是遇到了很多很多困难,特别是在api调用的权限这一块,这里,把自己遇到的一些坑的解决方法做一下笔记吧。当然,首先要讲的,就是如何在开启安全的情况下进行API调用。
`,r:{minutes:3.98,words:1195},t:"Jenkins的一些笔记",y:"a"}}],["/kubernetes/Kubernetes%E5%AE%B9%E5%99%A8%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86.html",{loader:()=>C(()=>import("./Kubernetes容器日志收集.html-SN4rN7dm.js"),[]),meta:{d:1708751576e3,e:`
+日志采集方式
+日志从传统方式演进到容器方式的过程就不详细讲了,可以参考一下这篇文章Docker日志收集最佳实践 ,由于容器的漂移、自动伸缩等特性,日志收集也就必须使用新的方式来实现,Kubernetes官方给出的方式基本是这三种:原生方式、DaemonSet方式和Sidecar方式。
`,r:{minutes:10.62,words:3187},t:"Kubernetes容器日志收集",y:"a"}}],["/kubernetes/",{loader:()=>C(()=>import("./index.html-BEv74XKv.js"),[]),meta:{d:156672164e4,e:`
+包含CICD、Kubernetes
+`,r:{minutes:.03,words:8},t:"目录",y:"a"}}],["/kubernetes/request_limit.html",{loader:()=>C(()=>import("./request_limit.html-CBNYeI2L.js"),[]),meta:{d:1708083988e3,e:`
+我们都知道 Kubernetes 中最小的原子调度单位是Pod,那么就意味着资源管理和资源调度相关的属性都应该Pod对象的字段,其中我们最常见的就是 Pod 的 CPU 和内存配置,而为了实现 Kubernetes 集群中资源的有效调度和充分利用,Kubernetes采用 requests 和 limits 两种限制类型来对CPU和内存资源进行容器粒度的分配。
`,r:{minutes:2.21,words:663},t:"Kubernetes之request 和 limit详解",y:"a"}}],["/kubernetes/spark%20on%20k8s%20operator.html",{loader:()=>C(()=>import("./spark on k8s operator.html-D9Tpznzk.js"),[]),meta:{d:1655036363e3,e:`
+Spark operator是一个管理Kubernetes上的Apache Spark应用程序生命周期的operator,旨在像在Kubernetes上运行其他工作负载一样简单的指定和运行spark应用程序。
`,r:{minutes:3.51,words:1054},t:"spark on k8s operator",y:"a"}}],["/life/2017.html",{loader:()=>C(()=>import("./2017.html-DzgcI9cv.js"),[]),meta:{d:157995829e4,e:`
+2016年6月,大三,考完最后一科,默默的看着大四那群人一个一个的走了,想着想着,明年毕业的时候,自己将会失去你所拥有的一切,大学那群认识的人,可能这辈子都不会见到了——致远离家乡出省读书的娃。然而,我并没有想到,自己失去的,不仅仅是那群人,几乎是一切。。。。
+17年1月,因为受不了北京雾霾(其实是次因),从实习的公司跑路了,很不舍,只是,感觉自己还有很多事要做,很多梦想要去实现,毕竟,看着身边的人,去了美团,拿着15k的月薪,有点不平衡,感觉他也不是很厉害吧,我努力努力10k应该没问题吧?
`,r:{minutes:11.22,words:3366},t:"2017",y:"a"}}],["/life/2018.html",{loader:()=>C(()=>import("./2018.html-UHfvoYE6.js"),[]),meta:{d:1579957849e3,e:`
+年底老姐结婚,跑回家去了,忙着一直没写,本来想回深圳的时候空余的时候写写,没想到一直加班,嗯,9点半下班那种,偶尔也趁着间隙的时间,一段一段的凑着吧。
`,r:{minutes:4.35,words:1306},t:"2018",y:"a"}}],["/life/2019.html",{loader:()=>C(()=>import("./2019.html-Df2iUZPh.js"),[]),meta:{d:157995829e4,e:`
+2019,本命年,1字头开头的年份,就这么过去了,迎来了2开头的十年,12月过的不是很好,每隔几天就吵架,都没怎么想起写自己的年终总结了,对这个跨年也不是很重视,貌似有点浑浑噩噩的样子。今天1号,就继续来公司学习学习,就写写文章吧。
+19年一月,没发生什么事,对老板也算是失望,打算过完春节就出去外面试试,完全的架构错误啊,怎么守得了,然后开了个年会,没什么好看的,唯一的例外就是看见漂漂亮亮的她,可惜不敢搭话,就这么的呗。2月以奇奇怪怪的方式走到了一起,开心,又有点伤心,然后就开始了这个欢喜而又悲剧的本命年。
`,r:{minutes:4.43,words:1329},t:"2019",y:"a"}}],["/link/main.html",{loader:()=>C(()=>import("./main.html-B2OQipck.js"),[]),meta:{d:1706846339e3,e:`
+`,r:{minutes:.28,words:83},t:"友链地址",y:"a"}}],["/middleware/",{loader:()=>C(()=>import("./index.html-0EEVTum5.js"),[]),meta:{d:170606734e4,e:`
+`,r:{minutes:.01,words:3},t:"中间件",y:"a"}}],["/open-source-project/",{loader:()=>C(()=>import("./index.html-BcZZ4qCt.js"),[]),meta:{d:1706092222e3,e:`jfaowejfoewj
+`,r:{minutes:0,words:1},t:"",y:"a"}}],["/stock/",{loader:()=>C(()=>import("./index.html-nZcQpO1z.js"),[]),meta:{d:1719930789e3,e:`
+`,r:{minutes:3.15,words:946},t:"股票预测",y:"a"}}],["/stock/%E8%B5%9B%E5%8A%9B%E6%96%AF.html",{loader:()=>C(()=>import("./赛力斯.html-BrY99iGU.js"),[]),meta:{d:1719930789e3,e:`
+update
+`,r:{minutes:.01,words:4},t:"赛力斯",y:"a"}}],["/system-design/feed.html",{loader:()=>C(()=>import("./feed.html-BcapapFL.js"),[]),meta:{d:171008157e4,e:`
+https://blog.csdn.net/weixin_45583158/article/details/128195940
`,r:{minutes:.02,words:7},t:"Feed系统设计",y:"a"}}],["/about-the-author/personal-life/2024-07-24.html",{loader:()=>C(()=>import("./2024-07-24.html-9GUkpnJj.js"),[]),meta:{d:1721836332e3,e:`
+新买了台air m3,午夜色的,心心念念了好久
+ `,r:{minutes:.34,words:102},t:"2024-07-24",y:"a"}}],["/about-the-author/personal-life/2024-11-09%E4%B8%8A%E6%B5%B7%E8%BF%AA%E6%96%AF%E5%B0%BC.html",{loader:()=>C(()=>import("./2024-11-09上海迪斯尼.html-CU80Bk9D.js"),[]),meta:{d:1731254136e3,e:`
+`,r:{minutes:.04,words:12},t:"2024-11-09上海迪斯尼",y:"a"}}],["/about-the-author/personal-life/wewe.html",{loader:()=>C(()=>import("./wewe.html-BLY5_jfL.js"),[]),meta:{d:1706244827e3,e:`
+安安静静的开发,搞点好玩的。
+硅谷 `,r:{minutes:.07,words:21},t:"自我介绍",y:"a"}}],["/about-the-author/works/%E4%B8%AA%E4%BA%BA%E4%BD%9C%E5%93%81.html",{loader:()=>C(()=>import("./个人作品.html-DDpX9I3v.js"),[]),meta:{d:1706349103e3,e:`
+助眠风扇 `,r:{minutes:.05,words:14},t:"小程序",y:"a"}}],["/bigdata/spark/elastic-spark.html",{loader:()=>C(()=>import("./elastic-spark.html-Cz2jVT52.js"),[]),meta:{d:165157815e4,e:`
+Hadoop允许Elasticsearch在Spark中以两种方式使用:通过自2.1以来的原生RDD支持,或者通过自2.0以来的Map/Reduce桥接器。从5.0版本开始,elasticsearch-hadoop就支持Spark 2.0。目前spark支持的数据源有:
+(1)文件系统:LocalFS、HDFS、Hive、text、parquet、orc、json、csv
+(2)数据RDBMS:mysql、oracle、mssql
+(3)NOSQL数据库:HBase、ES、Redis
+(4)消息对象:Redis
`,r:{minutes:1.71,words:514},t:"elastic spark",y:"a"}}],["/database/elasticsearch/elasticsearch%E6%BA%90%E7%A0%81debug.html",{loader:()=>C(()=>import("./elasticsearch源码debug.html-Bo6HcrbI.js"),[]),meta:{d:1706186538e3,e:`
+一、下载源代码
+直接用idea下载代码https://github.com/elastic/elasticsearch.git
+
`,r:{minutes:.52,words:157},t:"【elasticsearch】源码debug",y:"a"}}],["/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",{loader:()=>C(()=>import("./【elasticsearch】搜索过程详解.html-Dg8HV8OO.js"),[]),meta:{d:164778928e4,e:`
+本文基于elasticsearch8.1。在es搜索中,经常会使用索引+星号,采用时间戳来进行搜索,比如aaaa-*在es中是怎么处理这类请求的呢?是对匹配的进行搜索呢还是仅仅根据时间找出索引,然后才遍历索引进行搜索。在了解其原理前先了解一些基本知识。
`,r:{minutes:8.92,words:2677},t:"【elasticsearch】搜索过程详解",y:"a"}}],["/database/elasticsearch/%E5%9F%BA%E7%A1%80.html",{loader:()=>C(()=>import("./基础.html-Bsofr9G8.js"),[]),meta:{d:1708786978e3,e:`
+一、ElasticSearch基础
+1、什么是Elasticsearch:
+Elasticsearch 是基于 Lucene 的 Restful 的分布式实时全文搜索引擎,每个字段都被索引并可被搜索,可以快速存储、搜索、分析海量的数据。
+全文检索是指对每一个词建立一个索引,指明该词在文章中出现的次数和位置。当查询时,根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
`,r:{minutes:14.53,words:4360},t:"基础",O:100,y:"a"}}],["/database/mysql/1mysql.html",{loader:()=>C(()=>import("./1mysql.html-CW43wjS_.js"),[]),meta:{d:1679834663e3,e:`
+img `,r:{minutes:.02,words:5},t:"Mysql",y:"a"}}],["/database/mysql/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%BC%93%E5%AD%98.html",{loader:()=>C(()=>import("./数据库缓存.html-DNuD8_hU.js"),[]),meta:{d:1679834663e3,e:`
+在MySQL 5.6开始,就已经默认禁用查询缓存了。在MySQL 8.0,就已经删除查询缓存功能了。
`,r:{minutes:.34,words:101},t:"数据库缓存",y:"a"}}],["/database/mysql/%E8%A1%8C%E9%94%81%EF%BC%8C%E8%A1%A8%E9%94%81%EF%BC%8C%E6%84%8F%E5%90%91%E9%94%81.html",{loader:()=>C(()=>import("./行锁,表锁,意向锁.html-DwU2qcUM.js"),[]),meta:{d:171008157e4,e:`
+`,r:{minutes:.03,words:9},t:"行锁,表锁,意向锁",I:!1,y:"a"}}],["/database/redis/RedissonLock%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.html",{loader:()=>C(()=>import("./RedissonLock分布式锁源码分析.html-DBlO1MVO.js"),[]),meta:{d:1707204155e3,e:`
+最近碰到的一个问题,Java代码中写了一个定时器,分布式部署的时候,多台同时执行的话就会出现重复的数据,为了避免这种情况,之前是通过在配置文件里写上可以执行这段代码的IP,代码中判断如果跟这个IP相等,则执行,否则不执行,想想也是一种比较简单的方式吧,但是感觉很low很low,所以改用分布式锁。
+目前分布式锁常用的三种方式:1.数据库的锁;2.基于Redis的分布式锁;3.基于ZooKeeper的分布式锁。其中数据库中的锁有共享锁和排他锁,这两种都无法直接解决数据库的单点和可重入的问题,所以,本章还是来讲讲基于Redis的分布式锁,也可以用其他缓存(Memcache、Tair等)来实现。
`,r:{minutes:9.66,words:2897},t:"RedissonLock分布式锁源码分析",y:"a"}}],["/database/redis/redis%E7%BC%93%E5%AD%98.html",{loader:()=>C(()=>import("./redis缓存.html-H1xCPktw.js"),[]),meta:{d:1579957849e3,e:`
+一、概述
+1.1 缓存介绍
+系统的性能指标一般包括响应时间、延迟时间、吞吐量,并发用户数和资源利用率等。在应用运行过程中,我们有可能在一次数据库会话中,执行多次查询条件完全相同的SQL,MyBatis提供了一级缓存的方案优化这部分场景,如果是相同的SQL语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能。
+缓存常用语:
+数据不一致性、缓存更新机制、缓存可用性、缓存服务降级、缓存预热、缓存穿透
+可查看Redis实战(一) 使用缓存合理性
`,r:{minutes:12.08,words:3623},t:"Redis缓存",y:"a"}}],["/database/redis/%E4%B8%80%E8%87%B4%E6%80%A7hash%E7%AE%97%E6%B3%95%E5%92%8C%E5%93%88%E5%B8%8C%E6%A7%BD.html",{loader:()=>C(()=>import("./一致性hash算法和哈希槽.html-a1P2YWrj.js"),[]),meta:{d:171008157e4,e:`
+`,r:{minutes:.04,words:12},t:"一致性hash算法和哈希槽",I:!1,y:"a"}}],["/interesting/mini%E4%B8%BB%E6%9C%BA/",{loader:()=>C(()=>import("./index.html-wU0YCmBl.js"),[]),meta:{d:1708056026e3,r:{minutes:.04,words:13},t:"mini主机",i:"pen",O:2,y:"a"}}],["/interesting/mini%E4%B8%BB%E6%9C%BA/mac%E8%BF%9E%E6%8E%A5%E4%B8%BB%E6%9C%BA.html",{loader:()=>C(()=>import("./mac连接主机.html-BbWWw_2k.js"),[]),meta:{d:173290591e4,e:`
+一、mac端
+mac是typec的,用了个转接头+网线直连主机,初始化的时候跟下面一致,默认都是自动的
`,r:{minutes:1.72,words:515},t:"mac通过网线连接主机(fnOS)",y:"a"}}],["/interesting/mini%E4%B8%BB%E6%9C%BA/%E4%B9%B0%E4%BA%86%E4%B8%AAmini%E4%B8%BB%E6%9C%BA.html",{loader:()=>C(()=>import("./买了个mini主机.html-DMCiuYMs.js"),[]),meta:{d:1730035985e3,e:`
+虽然有苹果的电脑,但是在安装一些软件的时候,总想着能不能有一个小型的服务器,免得各种设置导致 Mac 出现异常。整体上看了一些小型主机,也看过苹果的 Mac mini,但是发现它太贵了,大概要 3000 多,特别是如果要更高配置的话,价格会更高,甚至更贵。所以,我就考虑一些别的小型主机。也看了一些像 NUC 这些服务器,但是觉得还是太贵了。于是我自己去淘宝搜索,找到了这一款 N100 版的主机。
`,r:{minutes:5.88,words:1763},t:"买了个mini主机",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html",{loader:()=>C(()=>import("./1.历史与架构.html-B9tl8qmz.js"),[]),meta:{d:1579574285e3,e:`
+各位大佬瞄一眼我的个人网站 呗 。如果觉得不错,希望能在GitHub上麻烦给个star,GitHub地址https://github.com/Zephery/newblog 。
+大学的时候萌生的一个想法,就是建立一个个人网站,前前后后全部推翻重构了4、5遍,现在终于能看了,下面是目前的首页。
`,r:{minutes:6.79,words:2038},t:"1.历史与架构",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/10.%E5%8E%86%E6%97%B68%E5%B9%B4%E6%9C%80%E7%BB%88%E6%94%B9%E7%89%88.html",{loader:()=>C(()=>import("./10.历时8年最终改版.html-BVYNR54w.js"),[]),meta:{d:1706165044e3,e:`
+不知不觉,自建站https://www.wenzhihuai.com 已经接近8年了,大二的时候开启使用ssh+jsp框架来做了一个自己的网站,完全自写前后端,过程中不断进化,改用ssm,整合es做文章搜索,加kafka,加redis缓存,整体上对个人来说还是学习到了不少东西。但是随之而来的问题也不少,被挖矿攻击、服务器被黑等等。有时候因为要用服务器搞一些别的东西,直接没有备份数据库就重装,导致不少文章丢失,虽然别的平台可能零散分布。
`,r:{minutes:5.78,words:1733},t:"10.历时8年最终改版",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html",{loader:()=>C(()=>import("./2.Lucene的使用.html-9FjHGi9W.js"),[]),meta:{d:1579574285e3,e:`
+首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。
`,r:{minutes:6.82,words:2046},t:"2.Lucene的使用",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html",{loader:()=>C(()=>import("./3.定时任务.html-NSgzVWXM.js"),[]),meta:{d:1579574285e3,e:`
+先看一下Quartz的架构图:
+ `,r:{minutes:3.55,words:1064},t:"3.定时任务",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html",{loader:()=>C(()=>import("./4.日志系统.html-BH3nB-v9.js"),[]),meta:{d:1579574285e3,e:`
+欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
`,r:{minutes:9.64,words:2891},t:"4.日志系统.md",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html",{loader:()=>C(()=>import("./5.小集群部署.html-BN5IQG4o.js"),[]),meta:{d:1579574285e3,e:`
+欢迎访问我的个人网站O(∩_∩)O哈哈~希望大佬们能给个star,个人网站网址:http://www.wenzhihuai.com ,个人网站代码地址:https://github.com/Zephery/newblog 。
+洋洋洒洒的买了两个服务器,用来学习分布式、集群之类的东西,整来整去,感觉分布式这种东西没人指导一下真的是太抽象了,先从网站的分布式部署一步一步学起来吧,虽然网站本身的访问量不大==。
`,r:{minutes:9.5,words:2849},t:"5.小集群部署.md",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html",{loader:()=>C(()=>import("./6.数据库备份.html-Ca5VIWc1.js"),[]),meta:{d:1579574285e3,e:`
+先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地:
`,r:{minutes:5.77,words:1732},t:"6.数据库备份",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html",{loader:()=>C(()=>import("./7.那些牛逼的插件.html-Br7NfWE4.js"),[]),meta:{d:1579574285e3,e:`
+欢迎访问我的网站http://www.wenzhihuai.com/ 。感谢,如果可以,希望能在GitHub上给个star,GitHub地址https://github.com/Zephery/newblog 。
+建站的一开始,我也想自己全部实现,各种布局,各种炫丽的效果,想做点能让大家佩服的UI出来,但是,事实上,自己作为专注Java的程序员,前端的东西一碰脑子就有“我又不是前端,浪费时间在这合适么?”这种想法,捣鼓来捣鼓去,做出的东西实在是没法看,我就觉得,如果自己的“产品”连自己都看不下去了,那还好意思给别人看?特别是留言板那块,初版的页面简直low的要死。所以,还是踏踏实实的“站在巨人的肩膀上”吧,改用别人的插件。但不要纯粹的使用别人的博客模板了,如hexo,wordpress这些,就算是自己拼凑过来的也比这些强。下面是本博客中所用到的插件,给大家介绍介绍,共同学习学习。
+本站主要用到的插件有:
+1.wowslider
+2.畅言
+3.Editor.md
+4.highchart、echart
+5.百度分享
+6.waterfall.js
+7.心知天气
+8.标签云
`,r:{minutes:7.24,words:2173},t:"7.那些牛逼的插件",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/8.%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%9A%84%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90.html",{loader:()=>C(()=>import("./8.基于贝叶斯的情感分析.html-DopYDuB6.js"),[]),meta:{d:156672164e4,e:`
+`,r:{minutes:.04,words:11},t:"8.基于贝叶斯的情感分析",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html",{loader:()=>C(()=>import("./9.网站性能优化.html-8ms_Vznn.js"),[]),meta:{d:156672164e4,e:`
+`,r:{minutes:.02,words:7},t:"9.网站性能优化",y:"a"}}],["/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/",{loader:()=>C(()=>import("./index.html-BXiz75su.js"),[]),meta:{d:1708056026e3,e:`jofjweoiaejof
+`,r:{minutes:.05,words:15},t:"个人网站",i:"pen",O:1,y:"a"}}],["/java/JVM/JVM%E8%B0%83%E4%BC%98%E5%8F%82%E6%95%B0.html",{loader:()=>C(()=>import("./JVM调优参数.html-BtZgPFK4.js"),[]),meta:{d:1579957849e3,e:`
+一、堆大小设置
+JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
`,r:{minutes:9.13,words:2739},t:"JVM调优参数",y:"a"}}],["/java/JVM/Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B.html",{loader:()=>C(()=>import("./Java内存模型.html-Bis3Hglq.js"),[]),meta:{d:1708075355e3,e:`
+本文转载自深入理解JVM-内存模型(jmm)和GC
`,r:{minutes:46.11,words:13833},t:"Java内存模型(JMM)",y:"a"}}],["/java/JVM/",{loader:()=>C(()=>import("./index.html-B9smc87Y.js"),[]),meta:{d:1708056026e3,r:{minutes:.04,words:11},t:"JVM",i:"pen",O:100,y:"a"}}],["/java/JVM/cms.html",{loader:()=>C(()=>import("./cms.html-Dfw5I__q.js"),[]),meta:{d:1708056026e3,e:`
+JDK14已经将CMS回收器完全移除,这里只需要记住它的缺点即可。
+CPU资源消耗 :CMS垃圾回收器在运行过程中会与应用线程并发执行,这可能会导致较高的CPU资源消耗。
`,r:{minutes:.73,words:218},t:"CMS",y:"a"}}],["/java/JVM/g1.html",{loader:()=>C(()=>import("./g1.html-CcgAHdWl.js"),[]),meta:{d:1708056026e3,e:`
+本文转载自增量式垃圾回收器——带你深入理解G1垃圾回收器
`,r:{minutes:39.5,words:11851},t:"G1",y:"a"}}],["/java/JVM/jvm(java%E8%99%9A%E6%8B%9F%E6%9C%BA).html",{loader:()=>C(()=>import("./jvm(java虚拟机).html-CpFuSPpy.js"),[]),meta:{d:171008157e4,e:`一、了解JVM
+1、什么是JVM
+JVM是Java Virtual Machine(Java虚拟机)的缩写,是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟计算机功能来实现的,JVM屏蔽了与具体操作系统平台相关的信息,Java程序只需生成在Java虚拟机上运行的字节码,就可以在多种平台上不加修改的运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。
`,r:{minutes:12.39,words:3717},t:"JVM(java虚拟机)",i:"pen",I:!1,y:"a"}}],["/java/JVM/zgc.html",{loader:()=>C(()=>import("./zgc.html-Cj33F57G.js"),[]),meta:{d:1708056026e3,e:`
+本文转载自12 张图带你彻底理解 ZGC
`,r:{minutes:11.65,words:3494},t:"ZGC",y:"a"}}],["/java/JVM/%E4%B8%80%E6%AC%A1jvm%E8%B0%83%E4%BC%98%E8%BF%87%E7%A8%8B.html",{loader:()=>C(()=>import("./一次jvm调优过程.html-zaM0dK5_.js"),[]),meta:{d:1579573736e3,e:`
+前端时间把公司的一个分布式定时调度的系统弄上了容器云,部署在kubernetes,在容器运行的动不动就出现问题,特别容易jvm溢出,导致程序不可用,终端无法进入,日志一直在刷错误,kubernetes也没有将该容器自动重启。业务方基本每天都在反馈task不稳定,后续就协助接手看了下,先主要讲下该程序的架构吧。
+该程序task主要分为三个模块:
+console进行一些cron的配置(表达式、任务名称、任务组等);
+schedule主要从数据库中读取配置然后装载到quartz再然后进行命令下发;
+client接收任务执行,然后向schedule返回运行的信息(成功、失败原因等)。
+整体架构跟github上开源的xxl-job类似,也可以参考一下。
`,r:{minutes:6.28,words:1884},t:"一次jvm调优过程",y:"a"}}],["/java/JVM/%E5%B8%B8%E7%94%A8GC%E5%9B%9E%E6%94%B6%E5%99%A8.html",{loader:()=>C(()=>import("./常用GC回收器.html-Br8UVQp8.js"),[]),meta:{d:1708077309e3,e:`
+
+
+
+垃圾回收器
+采用的GC算法
+代次
+
+
+
+
+Serial
+复制
+新生代
+
+
+Parallel
+复制
+新生代
+
+
+ParNew
+复制
+新生代
+
+
+CMS (Concurrent Mark-Sweep)
+标记-清除
+老年代
+
+
+G1 (Garbage-First)
+标记-整理
+老年代
+
+
+ZGC (Z Garbage Collector)
+标记-整理
+老年代
+
+
+Shenandoah
+标记-复制(独立的全局复制阶段)
+老年代
+
+
+
`,r:{minutes:2.95,words:886},t:"主流GC收集器采用的算法",y:"a"}}],["/java/JVM/%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0%E5%92%8C%E6%A0%B9%E5%8F%AF%E8%BE%BE%E7%AE%97%E6%B3%95.html",{loader:()=>C(()=>import("./引用计数和根可达算法.html-BVqGPH4F.js"),[]),meta:{d:1708075355e3,e:`
+本文从JVM是如何寻找垃圾的?——引用计数和根可达算法 转载
`,r:{minutes:11.61,words:3483},t:"引用计数和根可达算法",y:"a"}}],["/java/JVM/%E8%B0%83%E4%BC%98%E6%80%9D%E8%B7%AF.html",{loader:()=>C(()=>import("./调优思路.html-DzuQiit4.js"),[]),meta:{d:1708083988e3,e:`
+在项目开发过程中、生产环境中,任何问题的解决、性能的调优总结下来都是三个步骤,即发现问题、定位问题、解决问题,本文将从这个步骤入手,详细阐述内存溢出(OOM、OutOfMemeory)、CPU飙高、GC频繁等JVM问题的排查、定位,以及调优。
`,r:{minutes:.7,words:210},t:"JVM调优思路",I:!1,y:"a"}}],["/java/SpringBoot/",{loader:()=>C(()=>import("./index.html-DGy09Ap4.js"),[]),meta:{d:1708056026e3,r:{minutes:.04,words:11},t:"SpringBoot",i:"pen",O:100,y:"a"}}],["/java/SpringBoot/Spring%20Boot%20Prometheus%E4%BD%BF%E7%94%A8.html",{loader:()=>C(()=>import("./Spring Boot Prometheus使用.html-CvPEGSZS.js"),[]),meta:{d:1706363521e3,e:`
+一、基本原理
+Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。
`,r:{minutes:3.49,words:1046},t:"Spring Boot Prometheus使用",y:"a"}}],["/java/SpringBoot/aop.html",{loader:()=>C(()=>import("./aop.html-C7ud1qex.js"),[]),meta:{d:1706596625e3,e:`
+一、概述
+在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了。AOP关注的是横向的,而OOP的是纵向。
`,r:{minutes:7.17,words:2150},t:"AOP",y:"a"}}],["/java/SpringBoot/webflux.html",{loader:()=>C(()=>import("./webflux.html-KjGFiVkN.js"),[]),meta:{d:1706349103e3,e:`
+1.Servlet 3.1就已经支持异步非阻塞,为什么要用webflux?
+ChatGpt:
+Servlet 3.1 和 WebFlux 虽然底层都使用了 Java 的 NIO(非阻塞 IO),但是他们的编程模型和如何使用 NIO 是不同的,这也是导致他们性能差异的原因。
`,r:{minutes:3.07,words:921},t:"Webflux",y:"a"}}],["/java/io/",{loader:()=>C(()=>import("./index.html-CpCz4LWW.js"),[]),meta:{d:1708056026e3,r:{minutes:.04,words:11},t:"I/O",i:"pen",O:100,y:"a"}}],["/java/io/nio.html",{loader:()=>C(()=>import("./nio.html-DVcQhX_V.js"),[]),meta:{d:171008157e4,e:`
+一、简介
+1)Java BIO : 同步并阻塞(传统阻塞型),服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销。
`,r:{minutes:1.96,words:587},t:"JAVA NIO",y:"a"}}],["/java/%E7%BA%BF%E7%A8%8B/",{loader:()=>C(()=>import("./index.html-CMe--mJk.js"),[]),meta:{d:1708056026e3,r:{minutes:.04,words:12},t:"线程",i:"pen",O:100,y:"a"}}],["/java/%E7%BA%BF%E7%A8%8B/synchronized.html",{loader:()=>C(()=>import("./synchronized.html-B2MTfSju.js"),[]),meta:{d:1708075355e3,e:`
+偏向锁在JDK 15后已经废弃
+一、什么是synchronized `,r:{minutes:16.38,words:4915},t:"synchronized",y:"a"}}],["/java/%E7%BA%BF%E7%A8%8B/volatile.html",{loader:()=>C(()=>import("./volatile.html-C-UWQAjc.js"),[]),meta:{d:1708056026e3,e:`
+Volatile是Java中的一种轻量级同步机制 ,用于保证变量的可见性和禁止指令重排 。当一个变量被声明为Volatile类型时,任何修改该变量的操作都会立即被所有线程看到。也就是说,Volatile修饰的变量在每次修改时都会强制将修改刷新到主内存中,具有很好的可见性和线程安全性。
`,r:{minutes:.54,words:161},t:"volatile",y:"a"}}],["/java/%E7%BD%91%E7%BB%9C/IP%E3%80%81HTTP%E3%80%81HTTPS%E3%80%81HTTP2.0.html",{loader:()=>C(()=>import("./IP、HTTP、HTTPS、HTTP2.0.html-DvomVRAD.js"),[]),meta:{d:1707203159e3,e:`
+HTTP,全称超文本传输协议(HTTP,HyperText Transfer Protocol),是一个客户端和服务器端请求和应答的标准(TCP),互联网上应用最为广泛的一种网络协议。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求。
`,r:{minutes:19.51,words:5852},t:"TCP/IP、HTTP、HTTPS、HTTP2.0",y:"a"}}],["/java/%E7%BD%91%E7%BB%9C/",{loader:()=>C(()=>import("./index.html-DaAoZU-K.js"),[]),meta:{d:1708056026e3,r:{minutes:.04,words:12},t:"网络",i:"pen",O:100,y:"a"}}],["/kubernetes/devops/",{loader:()=>C(()=>import("./index.html-muK9iEFv.js"),[]),meta:{d:1708056026e3,e:`jofjweoiaejof
+`,r:{minutes:.04,words:12},t:"DevOps",i:"pen",O:1,y:"a"}}],["/kubernetes/devops/devops-ping-tai.html",{loader:()=>C(()=>import("./devops-ping-tai.html-CjTXGrBr.js"),[]),meta:{d:1566437746e3,e:`
+DevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
`,r:{minutes:11.96,words:3589},t:"DevOps平台.md",y:"a"}}],["/middleware/canal/%E4%B8%AD%E9%97%B4%E4%BB%B6%E2%80%94%E2%80%94canal%E5%B0%8F%E8%AE%B0.html",{loader:()=>C(()=>import("./中间件——canal小记.html-Bb5S9Lg5.js"),[]),meta:{d:1707204155e3,e:`
+接到个小需求,将mysql的部分数据增量同步到es,但是不仅仅是使用canal而已,整体的流程是mysql>>canal>>flume>>kafka>>es,说难倒也不难,只是做起来碰到的坑实在太多,特别是中间套了那么多中间件,出了故障找起来真的特别麻烦。
`,r:{minutes:5.37,words:1610},t:"canal小记",y:"a"}}],["/middleware/kafka/kafka.html",{loader:()=>C(()=>import("./kafka.html-tMeeu2BM.js"),[]),meta:{d:164778928e4,e:`
+1、请说明什么是Apache Kafka?
+Apache Kafka是由Apache开发的一种发布订阅消息系统,它是一个分布式的、分区的和可复制的提交日志服务。
`,r:{minutes:17.01,words:5103},t:"kafka面试题",y:"a"}}],["/middleware/sentinel/springcloud_sentinel.html",{loader:()=>C(()=>import("./springcloud_sentinel.html-CFCKUB71.js"),[]),meta:{d:171008157e4,e:`
+参考
+1.超详细springcloud sentinel教程~
`,r:{minutes:.06,words:17},t:"Spring Cloud Sentinel",I:!1,y:"a"}}],["/middleware/sentinel/%E5%85%A5%E9%97%A8%E4%BD%BF%E7%94%A8.html",{loader:()=>C(()=>import("./入门使用.html-DfOcEEjE.js"),[]),meta:{d:171008157e4,e:`
+参考
+1.Sentinel入门(干货版)
`,r:{minutes:.06,words:17},t:"入门使用",I:!1,y:"a"}}],["/middleware/zookeeper/zookeeper.html",{loader:()=>C(()=>import("./zookeeper.html-Dd8HToeq.js"),[]),meta:{d:1706204085e3,e:`
+留空
+`,r:{minutes:.01,words:3},t:"Zookeeper",y:"a"}}],["/middleware/zookeeper/%E5%9F%BA%E4%BA%8EZooKeeper%E7%9A%84%E9%98%9F%E5%88%97%E7%88%AC%E8%99%AB.html",{loader:()=>C(()=>import("./基于ZooKeeper的队列爬虫.html-D6Y4vXXb.js"),[]),meta:{d:1707204155e3,e:`
+一直琢磨着分布式的东西怎么搞,公司也没有相关的项目能够参与,所以还是回归自己的专长来吧——基于ZooKeeper的分布式队列爬虫,由于没什么人能够一起沟通分布式的相关知识,下面的小项目纯属“胡编乱造”。
+简单介绍下ZooKeeper :ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
+基本的知识就不过多介绍了,可以参考参考下面这些人的:
+ZooKeeper官网
+http://www.cnblogs.com/wuxl360/p/5817471.html
`,r:{minutes:9.55,words:2864},t:"基于ZooKeeper的队列爬虫",y:"a"}}],["/system-design/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/%E6%8E%A8%E8%8D%90%E5%B7%A5%E7%A8%8B-%E6%A6%82%E8%BF%B0.html",{loader:()=>C(()=>import("./推荐工程-概述.html-CyDH_f4g.js"),[]),meta:{d:173290591e4,e:`
+随着移动互联网的飞速发展,人们已经处于信息过载的时代。在这个时代,信息的生产者很难将信息呈现在对其感兴趣的消费者面前,而信息消费者也难以从海量信息中找到自己感兴趣的内容。推荐系统充当了将信息生产者和信息消费者连接起来的桥梁,平台通常作为推荐系统的载体,实现信息生产者和消费者之间的匹配。
`,r:{minutes:6.19,words:1856},t:"推荐工程-概述",O:1,y:"a"}}],["/system-design/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F%E5%85%A5%E9%97%A8.html",{loader:()=>C(()=>import("./推荐系统入门.html-DF2q_M-N.js"),[]),meta:{d:1725198884e3,e:`
+转载自:https://www.cnblogs.com/cgli/p/17225189.html
`,r:{minutes:16.79,words:5036},t:"推荐系统入门",y:"a"}}],["/system-design/%E8%AE%A1%E7%AE%97%E5%B9%BF%E5%91%8A/%E8%AE%A1%E7%AE%97%E5%B9%BF%E5%91%8A%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%E5%85%A5%E9%97%A8%E6%80%BB%E7%BB%93.html",{loader:()=>C(()=>import("./计算广告基本概念入门总结.html-Zcj8usmP.js"),[]),meta:{d:1725198884e3,e:`
+广告业务是各大互联网公司主要的商业化变现营收来源,近年来随着互联网和移动端技术的普及,使得广告的用户触达成本大大降低,而广告的形态和内涵也逐渐变得复杂,广告不再是单纯的展示和计费,而是结合了推荐、大数据等各类计算技术,以达到广告的精准受众定向,计算广告概念由此诞生。本文基于《计算广告》及互联网内容,整理了计算广告核心概念及入门知识,希望对入行广告行业的RD和非技术同学有所帮助。
`,r:{minutes:12.31,words:3692},t:"计算广告基本概念入门总结",y:"a"}}],["/404.html",{loader:()=>C(()=>import("./404.html-BMHKR2ag.js"),[]),meta:{t:""}}],["/interview/",{loader:()=>C(()=>import("./index.html-DQFfT5fQ.js"),[]),meta:{t:"Interview"}}],["/life/",{loader:()=>C(()=>import("./index.html-DJHdkCFZ.js"),[]),meta:{t:"Life"}}],["/link/",{loader:()=>C(()=>import("./index.html-7tsgb-dC.js"),[]),meta:{t:"Link"}}],["/system-design/",{loader:()=>C(()=>import("./index.html-KwQlr7R4.js"),[]),meta:{t:"System Design"}}],["/about-the-author/personal-life/",{loader:()=>C(()=>import("./index.html-DtDo2qGn.js"),[]),meta:{t:"Personal Life"}}],["/about-the-author/works/",{loader:()=>C(()=>import("./index.html-TDa4J3OS.js"),[]),meta:{t:"Works"}}],["/bigdata/spark/",{loader:()=>C(()=>import("./index.html-BAbeWXfD.js"),[]),meta:{t:"Spark"}}],["/database/elasticsearch/",{loader:()=>C(()=>import("./index.html-BTDM2Wpl.js"),[]),meta:{t:"Elasticsearch"}}],["/database/mysql/",{loader:()=>C(()=>import("./index.html-Uqis1PLJ.js"),[]),meta:{t:"Mysql"}}],["/database/redis/",{loader:()=>C(()=>import("./index.html-B2fh3Mku.js"),[]),meta:{t:"Redis"}}],["/middleware/canal/",{loader:()=>C(()=>import("./index.html-DRyhNgG6.js"),[]),meta:{t:"Canal"}}],["/middleware/kafka/",{loader:()=>C(()=>import("./index.html-CY6pLx2d.js"),[]),meta:{t:"Kafka"}}],["/middleware/sentinel/",{loader:()=>C(()=>import("./index.html-BwVnwmVL.js"),[]),meta:{t:"Sentinel"}}],["/middleware/zookeeper/",{loader:()=>C(()=>import("./index.html-5ZTxzR_p.js"),[]),meta:{t:"Zookeeper"}}],["/system-design/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/",{loader:()=>C(()=>import("./index.html-C9P5ouBn.js"),[]),meta:{t:"推荐系统"}}],["/system-design/%E8%AE%A1%E7%AE%97%E5%B9%BF%E5%91%8A/",{loader:()=>C(()=>import("./index.html-SdCcjUz-.js"),[]),meta:{t:"计算广告"}}],["/category/",{loader:()=>C(()=>import("./index.html-DYmvtxA9.js"),[]),meta:{t:"分类",I:!1}}],["/tag/",{loader:()=>C(()=>import("./index.html-BKAyyte1.js"),[]),meta:{t:"标签",I:!1}}],["/article/",{loader:()=>C(()=>import("./index.html-CD6aFyf5.js"),[]),meta:{t:"文章",I:!1}}],["/star/",{loader:()=>C(()=>import("./index.html-B8Qu0Pmr.js"),[]),meta:{t:"星标",I:!1}}],["/timeline/",{loader:()=>C(()=>import("./index.html-CdxL9VtY.js"),[]),meta:{t:"时间轴",I:!1}}],["/slide/",{loader:()=>C(()=>import("./index.html-DJZmVM8a.js"),[]),meta:{t:""}}]]);/*!
+ * vue-router v4.5.0
+ * (c) 2024 Eduardo San Martin Morote
+ * @license MIT
+ */const jn=typeof document<"u";function yd(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function X0(e){return e.__esModule||e[Symbol.toStringTag]==="Module"||e.default&&yd(e.default)}const Ee=Object.assign;function Bi(e,t){const n={};for(const l in t){const r=t[l];n[l]=Pt(r)?r.map(e):e(r)}return n}const Tl=()=>{},Pt=Array.isArray,Ad=/#/g,e2=/&/g,t2=/\//g,n2=/=/g,l2=/\?/g,kd=/\+/g,r2=/%5B/g,i2=/%5D/g,wd=/%5E/g,a2=/%60/g,Bd=/%7B/g,o2=/%7C/g,Cd=/%7D/g,s2=/%20/g;function qa(e){return encodeURI(""+e).replace(o2,"|").replace(r2,"[").replace(i2,"]")}function c2(e){return qa(e).replace(Bd,"{").replace(Cd,"}").replace(wd,"^")}function Zi(e){return qa(e).replace(kd,"%2B").replace(s2,"+").replace(Ad,"%23").replace(e2,"%26").replace(a2,"`").replace(Bd,"{").replace(Cd,"}").replace(wd,"^")}function u2(e){return Zi(e).replace(n2,"%3D")}function d2(e){return qa(e).replace(Ad,"%23").replace(l2,"%3F")}function f2(e){return e==null?"":d2(e).replace(t2,"%2F")}function Nl(e){try{return decodeURIComponent(""+e)}catch{}return""+e}const h2=/\/$/,p2=e=>e.replace(h2,"");function Ci(e,t,n="/"){let l,r={},i="",a="";const o=t.indexOf("#");let c=t.indexOf("?");return o=0&&(c=-1),c>-1&&(l=t.slice(0,c),i=t.slice(c+1,o>-1?o:t.length),r=e(i)),o>-1&&(l=l||t.slice(0,o),a=t.slice(o,t.length)),l=E2(l??t,n),{fullPath:l+(i&&"?")+i+a,path:l,query:r,hash:Nl(a)}}function v2(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function Es(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function m2(e,t,n){const l=t.matched.length-1,r=n.matched.length-1;return l>-1&&l===r&&tl(t.matched[l],n.matched[r])&&xd(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function tl(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function xd(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!g2(e[n],t[n]))return!1;return!0}function g2(e,t){return Pt(e)?_s(e,t):Pt(t)?_s(t,e):e===t}function _s(e,t){return Pt(t)?e.length===t.length&&e.every((n,l)=>n===t[l]):e.length===1&&e[0]===t}function E2(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),l=e.split("/"),r=l[l.length-1];(r===".."||r===".")&&l.push("");let i=n.length-1,a,o;for(a=0;a1&&i--;else break;return n.slice(0,i).join("/")+"/"+l.slice(a).join("/")}const Wt={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};var jl;(function(e){e.pop="pop",e.push="push"})(jl||(jl={}));var Ll;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Ll||(Ll={}));function _2(e){if(!e)if(jn){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),p2(e)}const b2=/^[^#]+#/;function y2(e,t){return e.replace(b2,"#")+t}function A2(e,t){const n=document.documentElement.getBoundingClientRect(),l=e.getBoundingClientRect();return{behavior:t.behavior,left:l.left-n.left-(t.left||0),top:l.top-n.top-(t.top||0)}}const Qr=()=>({left:window.scrollX,top:window.scrollY});function k2(e){let t;if("el"in e){const n=e.el,l=typeof n=="string"&&n.startsWith("#"),r=typeof n=="string"?l?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!r)return;t=A2(r,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function bs(e,t){return(history.state?history.state.position-t:-1)+e}const Qi=new Map;function w2(e,t){Qi.set(e,t)}function B2(e){const t=Qi.get(e);return Qi.delete(e),t}let C2=()=>location.protocol+"//"+location.host;function Sd(e,t){const{pathname:n,search:l,hash:r}=t,i=e.indexOf("#");if(i>-1){let o=r.includes(e.slice(i))?e.slice(i).length:1,c=r.slice(o);return c[0]!=="/"&&(c="/"+c),Es(c,"")}return Es(n,e)+l+r}function x2(e,t,n,l){let r=[],i=[],a=null;const o=({state:h})=>{const p=Sd(e,location),g=n.value,v=t.value;let y=0;if(h){if(n.value=p,t.value=h,a&&a===g){a=null;return}y=v?h.position-v.position:0}else l(p);r.forEach(_=>{_(n.value,g,{delta:y,type:jl.pop,direction:y?y>0?Ll.forward:Ll.back:Ll.unknown})})};function c(){a=n.value}function u(h){r.push(h);const p=()=>{const g=r.indexOf(h);g>-1&&r.splice(g,1)};return i.push(p),p}function d(){const{history:h}=window;h.state&&h.replaceState(Ee({},h.state,{scroll:Qr()}),"")}function f(){for(const h of i)h();i=[],window.removeEventListener("popstate",o),window.removeEventListener("beforeunload",d)}return window.addEventListener("popstate",o),window.addEventListener("beforeunload",d,{passive:!0}),{pauseListeners:c,listen:u,destroy:f}}function ys(e,t,n,l=!1,r=!1){return{back:e,current:t,forward:n,replaced:l,position:window.history.length,scroll:r?Qr():null}}function S2(e){const{history:t,location:n}=window,l={value:Sd(e,n)},r={value:t.state};r.value||i(l.value,{back:null,current:l.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function i(c,u,d){const f=e.indexOf("#"),h=f>-1?(n.host&&document.querySelector("base")?e:e.slice(f))+c:C2()+e+c;try{t[d?"replaceState":"pushState"](u,"",h),r.value=u}catch(p){console.error(p),n[d?"replace":"assign"](h)}}function a(c,u){const d=Ee({},t.state,ys(r.value.back,c,r.value.forward,!0),u,{position:r.value.position});i(c,d,!0),l.value=c}function o(c,u){const d=Ee({},r.value,t.state,{forward:c,scroll:Qr()});i(d.current,d,!0);const f=Ee({},ys(l.value,c,null),{position:d.position+1},u);i(c,f,!1),l.value=c}return{location:l,state:r,push:o,replace:a}}function T2(e){e=_2(e);const t=S2(e),n=x2(e,t.state,t.location,t.replace);function l(i,a=!0){a||n.pauseListeners(),history.go(i)}const r=Ee({location:"",base:e,go:l,createHref:y2.bind(null,e)},t,n);return Object.defineProperty(r,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(r,"state",{enumerable:!0,get:()=>t.state.value}),r}function L2(e){return typeof e=="string"||e&&typeof e=="object"}function Td(e){return typeof e=="string"||typeof e=="symbol"}const Ld=Symbol("");var As;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(As||(As={}));function nl(e,t){return Ee(new Error,{type:e,[Ld]:!0},t)}function Kt(e,t){return e instanceof Error&&Ld in e&&(t==null||!!(e.type&t))}const ks="[^/]+?",O2={sensitive:!1,strict:!1,start:!0,end:!0},D2=/[.+*?^${}()[\]/\\]/g;function P2(e,t){const n=Ee({},O2,t),l=[];let r=n.start?"^":"";const i=[];for(const u of e){const d=u.length?[]:[90];n.strict&&!u.length&&(r+="/");for(let f=0;ft.length?t.length===1&&t[0]===80?1:-1:0}function Od(e,t){let n=0;const l=e.score,r=t.score;for(;n0&&t[t.length-1]<0}const F2={type:0,value:""},R2=/[a-zA-Z0-9_]/;function M2(e){if(!e)return[[]];if(e==="/")return[[F2]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(p){throw new Error(`ERR (${n})/"${u}": ${p}`)}let n=0,l=n;const r=[];let i;function a(){i&&r.push(i),i=[]}let o=0,c,u="",d="";function f(){u&&(n===0?i.push({type:0,value:u}):n===1||n===2||n===3?(i.length>1&&(c==="*"||c==="+")&&t(`A repeatable param (${u}) must be alone in its segment. eg: '/:ids+.`),i.push({type:1,value:u,regexp:d,repeatable:c==="*"||c==="+",optional:c==="*"||c==="?"})):t("Invalid state to consume buffer"),u="")}function h(){u+=c}for(;o{a(m)}:Tl}function a(f){if(Td(f)){const h=l.get(f);h&&(l.delete(f),n.splice(n.indexOf(h),1),h.children.forEach(a),h.alias.forEach(a))}else{const h=n.indexOf(f);h>-1&&(n.splice(h,1),f.record.name&&l.delete(f.record.name),f.children.forEach(a),f.alias.forEach(a))}}function o(){return n}function c(f){const h=z2(f,n);n.splice(h,0,f),f.record.name&&!xs(f)&&l.set(f.record.name,f)}function u(f,h){let p,g={},v,y;if("name"in f&&f.name){if(p=l.get(f.name),!p)throw nl(1,{location:f});y=p.record.name,g=Ee(Bs(h.params,p.keys.filter(m=>!m.optional).concat(p.parent?p.parent.keys.filter(m=>m.optional):[]).map(m=>m.name)),f.params&&Bs(f.params,p.keys.map(m=>m.name))),v=p.stringify(g)}else if(f.path!=null)v=f.path,p=n.find(m=>m.re.test(v)),p&&(g=p.parse(v),y=p.record.name);else{if(p=h.name?l.get(h.name):n.find(m=>m.re.test(h.path)),!p)throw nl(1,{location:f,currentLocation:h});y=p.record.name,g=Ee({},h.params,f.params),v=p.stringify(g)}const _=[];let A=p;for(;A;)_.unshift(A.record),A=A.parent;return{name:y,path:v,params:g,matched:_,meta:H2(_)}}e.forEach(f=>i(f));function d(){n.length=0,l.clear()}return{addRoute:i,resolve:u,removeRoute:a,clearRoutes:d,getRoutes:o,getRecordMatcher:r}}function Bs(e,t){const n={};for(const l of t)l in e&&(n[l]=e[l]);return n}function Cs(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:j2(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function j2(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const l in e.components)t[l]=typeof n=="object"?n[l]:n;return t}function xs(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function H2(e){return e.reduce((t,n)=>Ee(t,n.meta),{})}function Ss(e,t){const n={};for(const l in e)n[l]=l in t?t[l]:e[l];return n}function z2(e,t){let n=0,l=t.length;for(;n!==l;){const i=n+l>>1;Od(e,t[i])<0?l=i:n=i+1}const r=$2(e);return r&&(l=t.lastIndexOf(r,l-1)),l}function $2(e){let t=e;for(;t=t.parent;)if(Dd(t)&&Od(e,t)===0)return t}function Dd({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function U2(e){const t={};if(e===""||e==="?")return t;const l=(e[0]==="?"?e.slice(1):e).split("&");for(let r=0;ri&&Zi(i)):[l&&Zi(l)]).forEach(i=>{i!==void 0&&(t+=(t.length?"&":"")+n,i!=null&&(t+="="+i))})}return t}function G2(e){const t={};for(const n in e){const l=e[n];l!==void 0&&(t[n]=Pt(l)?l.map(r=>r==null?null:""+r):l==null?l:""+l)}return t}const K2=Symbol(""),Ls=Symbol(""),Xr=Symbol(""),Wa=Symbol(""),Xi=Symbol("");function gl(){let e=[];function t(l){return e.push(l),()=>{const r=e.indexOf(l);r>-1&&e.splice(r,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function cn(e,t,n,l,r,i=a=>a()){const a=l&&(l.enterCallbacks[r]=l.enterCallbacks[r]||[]);return()=>new Promise((o,c)=>{const u=h=>{h===!1?c(nl(4,{from:n,to:t})):h instanceof Error?c(h):L2(h)?c(nl(2,{from:t,to:h})):(a&&l.enterCallbacks[r]===a&&typeof h=="function"&&a.push(h),o())},d=i(()=>e.call(l&&l.instances[r],t,n,u));let f=Promise.resolve(d);e.length<3&&(f=f.then(u)),f.catch(h=>c(h))})}function xi(e,t,n,l,r=i=>i()){const i=[];for(const a of e)for(const o in a.components){let c=a.components[o];if(!(t!=="beforeRouteEnter"&&!a.instances[o]))if(yd(c)){const d=(c.__vccOpts||c)[t];d&&i.push(cn(d,n,l,a,o,r))}else{let u=c();i.push(()=>u.then(d=>{if(!d)throw new Error(`Couldn't resolve component "${o}" at "${a.path}"`);const f=X0(d)?d.default:d;a.mods[o]=d,a.components[o]=f;const p=(f.__vccOpts||f)[t];return p&&cn(p,n,l,a,o,r)()}))}}return i}function Os(e){const t=Se(Xr),n=Se(Wa),l=k(()=>{const c=St(e.to);return t.resolve(c)}),r=k(()=>{const{matched:c}=l.value,{length:u}=c,d=c[u-1],f=n.matched;if(!d||!f.length)return-1;const h=f.findIndex(tl.bind(null,d));if(h>-1)return h;const p=Ds(c[u-2]);return u>1&&Ds(d)===p&&f[f.length-1].path!==p?f.findIndex(tl.bind(null,c[u-2])):h}),i=k(()=>r.value>-1&&Z2(n.params,l.value.params)),a=k(()=>r.value>-1&&r.value===n.matched.length-1&&xd(n.params,l.value.params));function o(c={}){if(Y2(c)){const u=t[St(e.replace)?"replace":"push"](St(e.to)).catch(Tl);return e.viewTransition&&typeof document<"u"&&"startViewTransition"in document&&document.startViewTransition(()=>u),u}return Promise.resolve()}return{route:l,href:k(()=>l.value.href),isActive:i,isExactActive:a,navigate:o}}function q2(e){return e.length===1?e[0]:e}const W2=H({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:Os,setup(e,{slots:t}){const n=Jl(Os(e)),{options:l}=Se(Xr),r=k(()=>({[Ps(e.activeClass,l.linkActiveClass,"router-link-active")]:n.isActive,[Ps(e.exactActiveClass,l.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const i=t.default&&q2(t.default(n));return e.custom?i:s("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:r.value},i)}}}),J2=W2;function Y2(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 Z2(e,t){for(const n in t){const l=t[n],r=e[n];if(typeof l=="string"){if(l!==r)return!1}else if(!Pt(r)||r.length!==l.length||l.some((i,a)=>i!==r[a]))return!1}return!0}function Ds(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const Ps=(e,t,n)=>e??t??n,Q2=H({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const l=Se(Xi),r=k(()=>e.route||l.value),i=Se(Ls,0),a=k(()=>{let u=St(i);const{matched:d}=r.value;let f;for(;(f=d[u])&&!f.components;)u++;return u}),o=k(()=>r.value.matched[a.value]);Ot(Ls,k(()=>a.value+1)),Ot(K2,o),Ot(Xi,r);const c=ee();return pe(()=>[c.value,o.value,e.name],([u,d,f],[h,p,g])=>{d&&(d.instances[f]=u,p&&p!==d&&u&&u===h&&(d.leaveGuards.size||(d.leaveGuards=p.leaveGuards),d.updateGuards.size||(d.updateGuards=p.updateGuards))),u&&d&&(!p||!tl(d,p)||!h)&&(d.enterCallbacks[f]||[]).forEach(v=>v(u))},{flush:"post"}),()=>{const u=r.value,d=e.name,f=o.value,h=f&&f.components[d];if(!h)return Is(n.default,{Component:h,route:u});const p=f.props[d],g=p?p===!0?u.params:typeof p=="function"?p(u):p:null,y=s(h,Ee({},g,t,{onVnodeUnmounted:_=>{_.component.isUnmounted&&(f.instances[d]=null)},ref:c}));return Is(n.default,{Component:y,route:u})||y}}});function Is(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const X2=Q2;function ev(e){const t=N2(e.routes,e),n=e.parseQuery||U2,l=e.stringifyQuery||Ts,r=e.history,i=gl(),a=gl(),o=gl(),c=$e(Wt);let u=Wt;jn&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const d=Bi.bind(null,x=>""+x),f=Bi.bind(null,f2),h=Bi.bind(null,Nl);function p(x,q){let U,Q;return Td(x)?(U=t.getRecordMatcher(x),Q=q):Q=x,t.addRoute(Q,U)}function g(x){const q=t.getRecordMatcher(x);q&&t.removeRoute(q)}function v(){return t.getRoutes().map(x=>x.record)}function y(x){return!!t.getRecordMatcher(x)}function _(x,q){if(q=Ee({},q||c.value),typeof x=="string"){const b=Ci(n,x,q.path),B=t.resolve({path:b.path},q),D=r.createHref(b.fullPath);return Ee(b,B,{params:h(B.params),hash:Nl(b.hash),redirectedFrom:void 0,href:D})}let U;if(x.path!=null)U=Ee({},x,{path:Ci(n,x.path,q.path).path});else{const b=Ee({},x.params);for(const B in b)b[B]==null&&delete b[B];U=Ee({},x,{params:f(b)}),q.params=f(q.params)}const Q=t.resolve(U,q),fe=x.hash||"";Q.params=d(h(Q.params));const ye=v2(l,Ee({},x,{hash:c2(fe),path:Q.path})),E=r.createHref(ye);return Ee({fullPath:ye,hash:fe,query:l===Ts?G2(x.query):x.query||{}},Q,{redirectedFrom:void 0,href:E})}function A(x){return typeof x=="string"?Ci(n,x,c.value.path):Ee({},x)}function m(x,q){if(u!==x)return nl(8,{from:q,to:x})}function w(x){return R(x)}function F(x){return w(Ee(A(x),{replace:!0}))}function V(x){const q=x.matched[x.matched.length-1];if(q&&q.redirect){const{redirect:U}=q;let Q=typeof U=="function"?U(x):U;return typeof Q=="string"&&(Q=Q.includes("?")||Q.includes("#")?Q=A(Q):{path:Q},Q.params={}),Ee({query:x.query,hash:x.hash,params:Q.path!=null?{}:x.params},Q)}}function R(x,q){const U=u=_(x),Q=c.value,fe=x.state,ye=x.force,E=x.replace===!0,b=V(U);if(b)return R(Ee(A(b),{state:typeof b=="object"?Ee({},fe,b.state):fe,force:ye,replace:E}),q||U);const B=U;B.redirectedFrom=q;let D;return!ye&&m2(l,Q,U)&&(D=nl(16,{to:B,from:Q}),Fe(Q,Q,!0,!1)),(D?Promise.resolve(D):T(B,Q)).catch(S=>Kt(S)?Kt(S,2)?S:Ge(S):J(S,B,Q)).then(S=>{if(S){if(Kt(S,2))return R(Ee({replace:E},A(S.to),{state:typeof S.to=="object"?Ee({},fe,S.to.state):fe,force:ye}),q||B)}else S=O(B,Q,!0,E,fe);return $(B,Q,S),S})}function Z(x,q){const U=m(x,q);return U?Promise.reject(U):Promise.resolve()}function M(x){const q=gt.values().next().value;return q&&typeof q.runWithContext=="function"?q.runWithContext(x):x()}function T(x,q){let U;const[Q,fe,ye]=tv(x,q);U=xi(Q.reverse(),"beforeRouteLeave",x,q);for(const b of Q)b.leaveGuards.forEach(B=>{U.push(cn(B,x,q))});const E=Z.bind(null,x,q);return U.push(E),We(U).then(()=>{U=[];for(const b of i.list())U.push(cn(b,x,q));return U.push(E),We(U)}).then(()=>{U=xi(fe,"beforeRouteUpdate",x,q);for(const b of fe)b.updateGuards.forEach(B=>{U.push(cn(B,x,q))});return U.push(E),We(U)}).then(()=>{U=[];for(const b of ye)if(b.beforeEnter)if(Pt(b.beforeEnter))for(const B of b.beforeEnter)U.push(cn(B,x,q));else U.push(cn(b.beforeEnter,x,q));return U.push(E),We(U)}).then(()=>(x.matched.forEach(b=>b.enterCallbacks={}),U=xi(ye,"beforeRouteEnter",x,q,M),U.push(E),We(U))).then(()=>{U=[];for(const b of a.list())U.push(cn(b,x,q));return U.push(E),We(U)}).catch(b=>Kt(b,8)?b:Promise.reject(b))}function $(x,q,U){o.list().forEach(Q=>M(()=>Q(x,q,U)))}function O(x,q,U,Q,fe){const ye=m(x,q);if(ye)return ye;const E=q===Wt,b=jn?history.state:{};U&&(Q||E?r.replace(x.fullPath,Ee({scroll:E&&b&&b.scroll},fe)):r.push(x.fullPath,fe)),c.value=x,Fe(x,q,U,E),Ge()}let X;function se(){X||(X=r.listen((x,q,U)=>{if(!rt.listening)return;const Q=_(x),fe=V(Q);if(fe){R(Ee(fe,{replace:!0,force:!0}),Q).catch(Tl);return}u=Q;const ye=c.value;jn&&w2(bs(ye.fullPath,U.delta),Qr()),T(Q,ye).catch(E=>Kt(E,12)?E:Kt(E,2)?(R(Ee(A(E.to),{force:!0}),Q).then(b=>{Kt(b,20)&&!U.delta&&U.type===jl.pop&&r.go(-1,!1)}).catch(Tl),Promise.reject()):(U.delta&&r.go(-U.delta,!1),J(E,Q,ye))).then(E=>{E=E||O(Q,ye,!1),E&&(U.delta&&!Kt(E,8)?r.go(-U.delta,!1):U.type===jl.pop&&Kt(E,20)&&r.go(-1,!1)),$(Q,ye,E)}).catch(Tl)}))}let he=gl(),K=gl(),N;function J(x,q,U){Ge(x);const Q=K.list();return Q.length?Q.forEach(fe=>fe(x,q,U)):console.error(x),Promise.reject(x)}function ae(){return N&&c.value!==Wt?Promise.resolve():new Promise((x,q)=>{he.add([x,q])})}function Ge(x){return N||(N=!x,se(),he.list().forEach(([q,U])=>x?U(x):q()),he.reset()),x}function Fe(x,q,U,Q){const{scrollBehavior:fe}=e;if(!jn||!fe)return Promise.resolve();const ye=!U&&B2(bs(x.fullPath,0))||(Q||!U)&&history.state&&history.state.scroll||null;return Qt().then(()=>fe(x,q,ye)).then(E=>E&&k2(E)).catch(E=>J(E,x,q))}const ge=x=>r.go(x);let Ne;const gt=new Set,rt={currentRoute:c,listening:!0,addRoute:p,removeRoute:g,clearRoutes:t.clearRoutes,hasRoute:y,getRoutes:v,resolve:_,options:e,push:w,replace:F,go:ge,back:()=>ge(-1),forward:()=>ge(1),beforeEach:i.add,beforeResolve:a.add,afterEach:o.add,onError:K.add,isReady:ae,install(x){const q=this;x.component("RouterLink",J2),x.component("RouterView",X2),x.config.globalProperties.$router=q,Object.defineProperty(x.config.globalProperties,"$route",{enumerable:!0,get:()=>St(c)}),jn&&!Ne&&c.value===Wt&&(Ne=!0,w(r.location).catch(fe=>{}));const U={};for(const fe in Wt)Object.defineProperty(U,fe,{get:()=>c.value[fe],enumerable:!0});x.provide(Xr,q),x.provide(Wa,ku(U)),x.provide(Xi,c);const Q=x.unmount;gt.add(x),x.unmount=function(){gt.delete(x),gt.size<1&&(u=Wt,X&&X(),X=null,c.value=Wt,Ne=!1,N=!1),Q()}}};function We(x){return x.reduce((q,U)=>q.then(()=>M(U)),Promise.resolve())}return rt}function tv(e,t){const n=[],l=[],r=[],i=Math.max(t.matched.length,e.matched.length);for(let a=0;atl(u,o))?l.push(o):n.push(o));const c=e.matched[a];c&&(t.matched.find(u=>tl(u,c))||r.push(c))}return[n,l,r]}function en(){return Se(Xr)}function Ut(e){return Se(Wa)}var Ja=Symbol(""),Rt=()=>{const e=Se(Ja);if(!e)throw new Error("useClientData() is called without provider.");return e},nv=()=>Rt().pageComponent,Oe=()=>Rt().pageData,ve=()=>Rt().pageFrontmatter,lv=()=>Rt().pageHead,ei=()=>Rt().pageLang,rv=()=>Rt().pageLayout,Mt=()=>Rt().routeLocale,Pd=()=>Rt().routePath,iv=()=>Rt().routes,Id=()=>Rt().siteData,lr=()=>Rt().siteLocaleData,av=Symbol(""),ea=$e(Z0),Yn=$e(Q0),Fd=(e,t)=>{const n=H0(e,t);if(Yn.value[n])return n;const l=encodeURI(n);if(Yn.value[l])return l;const r=ea.value[n]||ea.value[l];return r||n},wt=(e,t)=>{const{pathname:n,hashAndQueries:l}=Ed(e),r=Fd(n,t),i=r+l;return Yn.value[r]?{...Yn.value[r],path:i,notFound:!1}:{...Yn.value["/404.html"],path:i,notFound:!0}},ov=(e,t)=>{const{pathname:n,hashAndQueries:l}=Ed(e);return Fd(n,t)+l},sv=e=>{if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget){const t=e.currentTarget.getAttribute("target");if(t!=null&&t.match(/\b_blank\b/i))return}return e.preventDefault(),!0}},He=H({name:"RouteLink",props:{to:{type:String,required:!0},active:Boolean,activeClass:{type:String,default:"route-link-active"}},slots:Object,setup(e,{slots:t}){const n=en(),l=Ut(),r=k(()=>e.to.startsWith("#")||e.to.startsWith("?")?e.to:`/${ov(e.to,l.path).substring(1)}`);return()=>{var i;return s("a",{class:["route-link",{[e.activeClass]:e.active}],href:r.value,onClick:(a={})=>{sv(a)&&n.push(e.to).catch()}},(i=t.default)==null?void 0:i.call(t))}}}),cv=H({name:"AutoLink",props:{config:{type:Object,required:!0}},slots:Object,setup(e,{slots:t}){const n=sl(e,"config"),l=Ut(),r=Id(),i=k(()=>tr(n.value.link)),a=k(()=>n.value.target||(i.value?"_blank":void 0)),o=k(()=>a.value==="_blank"),c=k(()=>!i.value&&!o.value),u=k(()=>n.value.rel||(o.value?"noopener noreferrer":null)),d=k(()=>n.value.ariaLabel??n.value.text),f=k(()=>{if(n.value.exact)return!1;const p=Object.keys(r.value.locales);return p.length?p.every(g=>g!==n.value.link):n.value.link!=="/"}),h=k(()=>c.value?n.value.activeMatch?(n.value.activeMatch instanceof RegExp?n.value.activeMatch:new RegExp(n.value.activeMatch,"u")).test(l.path):f.value?l.path.startsWith(n.value.link):l.path===n.value.link:!1);return()=>{const{before:p,after:g,default:v}=t,y=(v==null?void 0:v(n.value))||[p==null?void 0:p(n.value),n.value.text,g==null?void 0:g(n.value)];return c.value?s(He,{class:"auto-link",to:n.value.link,active:h.value,"aria-label":d.value},()=>y):s("a",{class:"auto-link external-link",href:n.value.link,"aria-label":d.value,rel:u.value,target:a.value},y)}}}),Rd=H({name:"ClientOnly",setup(e,t){const n=ee(!1);return we(()=>{n.value=!0}),()=>{var l,r;return n.value?(r=(l=t.slots).default)==null?void 0:r.call(l):null}}}),Md=H({name:"Content",props:{path:{type:String,required:!1,default:""}},setup(e){const t=nv(),n=k(()=>{if(!e.path)return t.value;const l=wt(e.path);return a1(()=>l.loader().then(({comp:r})=>r))});return()=>s(n.value)}}),uv="Layout",dv="en-US",kn=Jl({resolveLayouts:e=>e.reduce((t,n)=>({...t,...n.layouts}),{}),resolvePageHead:(e,t,n)=>{const l=ke(t.description)?t.description:n.description,r=[...Array.isArray(t.head)?t.head:[],...n.head,["title",{},e],["meta",{name:"description",content:l}]];return q0(r)},resolvePageHeadTitle:(e,t)=>[e.title,t.title].filter(n=>!!n).join(" | "),resolvePageLang:(e,t)=>e.lang||t.lang||dv,resolvePageLayout:(e,t)=>{const n=ke(e.frontmatter.layout)?e.frontmatter.layout:uv;if(!t[n])throw new Error(`[vuepress] Cannot resolve layout: ${n}`);return t[n]},resolveRouteLocale:(e,t)=>z0(e,decodeURI(t)),resolveSiteLocaleData:({base:e,locales:t,...n},l)=>{var r;return{...n,...t[l],head:[...((r=t[l])==null?void 0:r.head)??[],...n.head??[]]}}}),Bt=(e={})=>e,Ae=e=>gn(e)?e:`/${bd(e)}`;const fv=Object.freeze(Object.defineProperty({__proto__:null},Symbol.toStringTag,{value:"Module"})),hv=Object.freeze(Object.defineProperty({__proto__:null},Symbol.toStringTag,{value:"Module"}));function ul(e){return su()?(Ep(e),!0):!1}function lt(e){return typeof e=="function"?e():St(e)}const rr=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const pv=Object.prototype.toString,vv=e=>pv.call(e)==="[object Object]",ll=()=>{},Fs=mv();function mv(){var e,t;return rr&&((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 Ya(e,t){function n(...l){return new Promise((r,i)=>{Promise.resolve(e(()=>t.apply(this,l),{fn:t,thisArg:this,args:l})).then(r).catch(i)})}return n}const Vd=e=>e();function gv(e,t={}){let n,l,r=ll;const i=o=>{clearTimeout(o),r(),r=ll};return o=>{const c=lt(e),u=lt(t.maxWait);return n&&i(n),c<=0||u!==void 0&&u<=0?(l&&(i(l),l=null),Promise.resolve(o())):new Promise((d,f)=>{r=t.rejectOnCancel?f:d,u&&!l&&(l=setTimeout(()=>{n&&i(n),l=null,d(o())},u)),n=setTimeout(()=>{l&&i(l),l=null,d(o())},c)})}}function Ev(...e){let t=0,n,l=!0,r=ll,i,a,o,c,u;!Re(e[0])&&typeof e[0]=="object"?{delay:a,trailing:o=!0,leading:c=!0,rejectOnCancel:u=!1}=e[0]:[a,o=!0,c=!0,u=!1]=e;const d=()=>{n&&(clearTimeout(n),n=void 0,r(),r=ll)};return h=>{const p=lt(a),g=Date.now()-t,v=()=>i=h();return d(),p<=0?(t=Date.now(),v()):(g>p&&(c||!l)?(t=Date.now(),v()):o&&(i=new Promise((y,_)=>{r=u?_:y,n=setTimeout(()=>{t=Date.now(),l=!0,y(v()),d()},Math.max(0,p-g))})),!c&&!n&&(n=setTimeout(()=>l=!0,p)),l=!1,i)}}function _v(e=Vd){const t=ee(!0);function n(){t.value=!1}function l(){t.value=!0}const r=(...i)=>{t.value&&e(...i)};return{isActive:In(t),pause:n,resume:l,eventFilter:r}}function bv(e){let t;function n(){return t||(t=e()),t}return n.reset=async()=>{const l=t;t=void 0,l&&await l},n}function yv(e){return Xl()}function Av(...e){if(e.length!==1)return sl(...e);const t=e[0];return typeof t=="function"?In(Cu(()=>({get:t,set:ll}))):ee(t)}function Nd(e,t=200,n={}){return Ya(gv(t,n),e)}function kv(e,t=200,n=!1,l=!0,r=!1){return Ya(Ev(t,n,l,r),e)}function wv(e,t,n={}){const{eventFilter:l=Vd,...r}=n;return pe(e,Ya(l,t),r)}function Bv(e,t,n={}){const{eventFilter:l,...r}=n,{eventFilter:i,pause:a,resume:o,isActive:c}=_v(l);return{stop:wv(e,t,{...r,eventFilter:i}),pause:a,resume:o,isActive:c}}function Za(e,t=!0,n){yv()?we(e,n):t?e():Qt(e)}function Cv(e,t,n={}){const{immediate:l=!0}=n,r=ee(!1);let i=null;function a(){i&&(clearTimeout(i),i=null)}function o(){r.value=!1,a()}function c(...u){a(),r.value=!0,i=setTimeout(()=>{r.value=!1,i=null,e(...u)},lt(t))}return l&&(r.value=!0,rr&&c()),ul(o),{isPending:In(r),start:c,stop:o}}function ta(e=!1,t={}){const{truthyValue:n=!0,falsyValue:l=!1}=t,r=Re(e),i=ee(e);function a(o){if(arguments.length)return i.value=o,i.value;{const c=lt(n);return i.value=i.value===c?lt(l):c,i.value}}return r?a:[i,a]}const It=rr?window:void 0,xv=rr?window.document:void 0,jd=rr?window.navigator:void 0;function Zt(e){var t;const n=lt(e);return(t=n==null?void 0:n.$el)!=null?t:n}function Ie(...e){let t,n,l,r;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,l,r]=e,t=It):[t,n,l,r]=e,!t)return ll;Array.isArray(n)||(n=[n]),Array.isArray(l)||(l=[l]);const i=[],a=()=>{i.forEach(d=>d()),i.length=0},o=(d,f,h,p)=>(d.addEventListener(f,h,p),()=>d.removeEventListener(f,h,p)),c=pe(()=>[Zt(t),lt(r)],([d,f])=>{if(a(),!d)return;const h=vv(f)?{...f}:f;i.push(...n.flatMap(p=>l.map(g=>o(d,p,g,h))))},{immediate:!0,flush:"post"}),u=()=>{c(),a()};return ul(u),u}function Sv(){const e=ee(!1),t=Xl();return t&&we(()=>{e.value=!0},t),e}function ir(e){const t=Sv();return k(()=>(t.value,!!e()))}function Qa(e,t={}){const{window:n=It}=t,l=ir(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let r;const i=ee(!1),a=u=>{i.value=u.matches},o=()=>{r&&("removeEventListener"in r?r.removeEventListener("change",a):r.removeListener(a))},c=za(()=>{l.value&&(o(),r=n.matchMedia(lt(e)),"addEventListener"in r?r.addEventListener("change",a):r.addListener(a),i.value=r.matches)});return ul(()=>{c(),o(),r=void 0}),i}function Rs(e,t={}){const{controls:n=!1,navigator:l=jd}=t,r=ir(()=>l&&"permissions"in l),i=$e(),a=typeof e=="string"?{name:e}:e,o=$e(),c=()=>{var d,f;o.value=(f=(d=i.value)==null?void 0:d.state)!=null?f:"prompt"};Ie(i,"change",c);const u=bv(async()=>{if(r.value){if(!i.value)try{i.value=await l.permissions.query(a)}catch{i.value=void 0}finally{c()}if(n)return de(i.value)}});return u(),n?{state:o,isSupported:r,query:u}:o}function Tv(e={}){const{navigator:t=jd,read:n=!1,source:l,copiedDuring:r=1500,legacy:i=!1}=e,a=ir(()=>t&&"clipboard"in t),o=Rs("clipboard-read"),c=Rs("clipboard-write"),u=k(()=>a.value||i),d=ee(""),f=ee(!1),h=Cv(()=>f.value=!1,r);function p(){a.value&&_(o.value)?t.clipboard.readText().then(A=>{d.value=A}):d.value=y()}u.value&&n&&Ie(["copy","cut"],p);async function g(A=lt(l)){u.value&&A!=null&&(a.value&&_(c.value)?await t.clipboard.writeText(A):v(A),d.value=A,f.value=!0,h.start())}function v(A){const m=document.createElement("textarea");m.value=A??"",m.style.position="absolute",m.style.opacity="0",document.body.appendChild(m),m.select(),document.execCommand("copy"),m.remove()}function y(){var A,m,w;return(w=(m=(A=document==null?void 0:document.getSelection)==null?void 0:A.call(document))==null?void 0:m.toString())!=null?w:""}function _(A){return A==="granted"||A==="prompt"}return{isSupported:u,text:d,copied:f,copy:g}}const Ar=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},kr="__vueuse_ssr_handlers__",Lv=Ov();function Ov(){return kr in Ar||(Ar[kr]=Ar[kr]||{}),Ar[kr]}function Dv(e,t){return Lv[e]||t}function Pv(e){return Qa("(prefers-color-scheme: dark)",e)}function Iv(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 Fv={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()}},Ms="vueuse-storage";function Xa(e,t,n,l={}){var r;const{flush:i="pre",deep:a=!0,listenToStorageChanges:o=!0,writeDefaults:c=!0,mergeDefaults:u=!1,shallow:d,window:f=It,eventFilter:h,onError:p=T=>{console.error(T)},initOnMounted:g}=l,v=(d?$e:ee)(typeof t=="function"?t():t);if(!n)try{n=Dv("getDefaultStorage",()=>{var T;return(T=It)==null?void 0:T.localStorage})()}catch(T){p(T)}if(!n)return v;const y=lt(t),_=Iv(y),A=(r=l.serializer)!=null?r:Fv[_],{pause:m,resume:w}=Bv(v,()=>V(v.value),{flush:i,deep:a,eventFilter:h});f&&o&&Za(()=>{n instanceof Storage?Ie(f,"storage",Z):Ie(f,Ms,M),g&&Z()}),g||Z();function F(T,$){if(f){const O={key:e,oldValue:T,newValue:$,storageArea:n};f.dispatchEvent(n instanceof Storage?new StorageEvent("storage",O):new CustomEvent(Ms,{detail:O}))}}function V(T){try{const $=n.getItem(e);if(T==null)F($,null),n.removeItem(e);else{const O=A.write(T);$!==O&&(n.setItem(e,O),F($,O))}}catch($){p($)}}function R(T){const $=T?T.newValue:n.getItem(e);if($==null)return c&&y!=null&&n.setItem(e,A.write(y)),y;if(!T&&u){const O=A.read($);return typeof u=="function"?u(O,y):_==="object"&&!Array.isArray(O)?{...y,...O}:O}else return typeof $!="string"?$:A.read($)}function Z(T){if(!(T&&T.storageArea!==n)){if(T&&T.key==null){v.value=y;return}if(!(T&&T.key!==e)){m();try{(T==null?void 0:T.newValue)!==A.write(v.value)&&(v.value=R(T))}catch($){p($)}finally{T?Qt(w):w()}}}}function M(T){Z(T.detail)}return v}function Rv(e,t,n={}){const{window:l=It,...r}=n;let i;const a=ir(()=>l&&"ResizeObserver"in l),o=()=>{i&&(i.disconnect(),i=void 0)},c=k(()=>{const f=lt(e);return Array.isArray(f)?f.map(h=>Zt(h)):[Zt(f)]}),u=pe(c,f=>{if(o(),a.value&&l){i=new ResizeObserver(t);for(const h of f)h&&i.observe(h,r)}},{immediate:!0,flush:"post"}),d=()=>{o(),u()};return ul(d),{isSupported:a,stop:d}}function Mv(e,t={width:0,height:0},n={}){const{window:l=It,box:r="content-box"}=n,i=k(()=>{var f,h;return(h=(f=Zt(e))==null?void 0:f.namespaceURI)==null?void 0:h.includes("svg")}),a=ee(t.width),o=ee(t.height),{stop:c}=Rv(e,([f])=>{const h=r==="border-box"?f.borderBoxSize:r==="content-box"?f.contentBoxSize:f.devicePixelContentBoxSize;if(l&&i.value){const p=Zt(e);if(p){const g=p.getBoundingClientRect();a.value=g.width,o.value=g.height}}else if(h){const p=Array.isArray(h)?h:[h];a.value=p.reduce((g,{inlineSize:v})=>g+v,0),o.value=p.reduce((g,{blockSize:v})=>g+v,0)}else a.value=f.contentRect.width,o.value=f.contentRect.height},n);Za(()=>{const f=Zt(e);f&&(a.value="offsetWidth"in f?f.offsetWidth:t.width,o.value="offsetHeight"in f?f.offsetHeight:t.height)});const u=pe(()=>Zt(e),f=>{a.value=f?t.width:0,o.value=f?t.height:0});function d(){c(),u()}return{width:a,height:o,stop:d}}const Vs=["fullscreenchange","webkitfullscreenchange","webkitendfullscreen","mozfullscreenchange","MSFullscreenChange"];function ti(e,t={}){const{document:n=xv,autoExit:l=!1}=t,r=k(()=>{var _;return(_=Zt(e))!=null?_:n==null?void 0:n.querySelector("html")}),i=ee(!1),a=k(()=>["requestFullscreen","webkitRequestFullscreen","webkitEnterFullscreen","webkitEnterFullScreen","webkitRequestFullScreen","mozRequestFullScreen","msRequestFullscreen"].find(_=>n&&_ in n||r.value&&_ in r.value)),o=k(()=>["exitFullscreen","webkitExitFullscreen","webkitExitFullScreen","webkitCancelFullScreen","mozCancelFullScreen","msExitFullscreen"].find(_=>n&&_ in n||r.value&&_ in r.value)),c=k(()=>["fullScreen","webkitIsFullScreen","webkitDisplayingFullscreen","mozFullScreen","msFullscreenElement"].find(_=>n&&_ in n||r.value&&_ in r.value)),u=["fullscreenElement","webkitFullscreenElement","mozFullScreenElement","msFullscreenElement"].find(_=>n&&_ in n),d=ir(()=>r.value&&n&&a.value!==void 0&&o.value!==void 0&&c.value!==void 0),f=()=>u?(n==null?void 0:n[u])===r.value:!1,h=()=>{if(c.value){if(n&&n[c.value]!=null)return n[c.value];{const _=r.value;if((_==null?void 0:_[c.value])!=null)return!!_[c.value]}}return!1};async function p(){if(!(!d.value||!i.value)){if(o.value)if((n==null?void 0:n[o.value])!=null)await n[o.value]();else{const _=r.value;(_==null?void 0:_[o.value])!=null&&await _[o.value]()}i.value=!1}}async function g(){if(!d.value||i.value)return;h()&&await p();const _=r.value;a.value&&(_==null?void 0:_[a.value])!=null&&(await _[a.value](),i.value=!0)}async function v(){await(i.value?p():g())}const y=()=>{const _=h();(!_||_&&f())&&(i.value=_)};return Ie(n,Vs,y,!1),Ie(()=>Zt(r),Vs,y,!1),l&&ul(p),{isSupported:d,isFullscreen:i,enter:g,exit:p,toggle:v}}function Si(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function Vv(e,t,n={}){const{window:l=It}=n;return Xa(e,t,l==null?void 0:l.localStorage,n)}function Nv(e={}){const{window:t=It}=e;if(!t)return ee(["en"]);const n=t.navigator,l=ee(n.languages);return Ie(t,"languagechange",()=>{l.value=n.languages}),l}function Hd(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const Ti=new WeakMap;function eo(e,t=!1){const n=ee(t);let l=null,r="";pe(Av(e),o=>{const c=Si(lt(o));if(c){const u=c;if(Ti.get(u)||Ti.set(u,u.style.overflow),u.style.overflow!=="hidden"&&(r=u.style.overflow),u.style.overflow==="hidden")return n.value=!0;if(n.value)return u.style.overflow="hidden"}},{immediate:!0});const i=()=>{const o=Si(lt(e));!o||n.value||(Fs&&(l=Ie(o,"touchmove",c=>{jv(c)},{passive:!1})),o.style.overflow="hidden",n.value=!0)},a=()=>{const o=Si(lt(e));!o||!n.value||(Fs&&(l==null||l()),o.style.overflow=r,Ti.delete(o),n.value=!1)};return ul(a),k({get(){return n.value},set(o){o?i():a()}})}function Hv(e,t,n={}){const{window:l=It}=n;return Xa(e,t,l==null?void 0:l.sessionStorage,n)}function zv(e={}){const{window:t=It,behavior:n="auto"}=e;if(!t)return{x:ee(0),y:ee(0)};const l=ee(t.scrollX),r=ee(t.scrollY),i=k({get(){return l.value},set(o){scrollTo({left:o,behavior:n})}}),a=k({get(){return r.value},set(o){scrollTo({top:o,behavior:n})}});return Ie(t,"scroll",()=>{l.value=t.scrollX,r.value=t.scrollY},{capture:!1,passive:!0}),{x:i,y:a}}function $v(e={}){const{window:t=It,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:l=Number.POSITIVE_INFINITY,listenOrientation:r=!0,includeScrollbar:i=!0,type:a="inner"}=e,o=ee(n),c=ee(l),u=()=>{t&&(a==="outer"?(o.value=t.outerWidth,c.value=t.outerHeight):i?(o.value=t.innerWidth,c.value=t.innerHeight):(o.value=t.document.documentElement.clientWidth,c.value=t.document.documentElement.clientHeight))};if(u(),Za(u),Ie("resize",u,{passive:!0}),r){const d=Qa("(orientation: portrait)");pe(d,()=>u())}return{width:o,height:c}}const Ns=async(e,t)=>{const{path:n,query:l}=e.currentRoute.value,{scrollBehavior:r}=e.options;e.options.scrollBehavior=void 0,await e.replace({path:n,query:l,hash:t}),e.options.scrollBehavior=r},Uv=({headerLinkSelector:e,headerAnchorSelector:t,delay:n,offset:l=5})=>{const r=en();Ie("scroll",Nd(()=>{var g,v;const a=Math.max(window.scrollY,document.documentElement.scrollTop,document.body.scrollTop);if(Math.abs(a-0)f.some(_=>_.hash===y.hash));for(let y=0;y=(((g=_.parentElement)==null?void 0:g.offsetTop)??0)-l,w=!A||a<(((v=A.parentElement)==null?void 0:v.offsetTop)??0)-l;if(!(m&&w))continue;const V=decodeURIComponent(r.currentRoute.value.hash),R=decodeURIComponent(_.hash);if(V===R)return;if(d){for(let Z=y+1;Z{const r=s("svg",{xmlns:"http://www.w3.org/2000/svg",width:e,height:e,preserveAspectRatio:"xMidYMid",viewBox:"25 25 50 50"},[s("animateTransform",{attributeName:"transform",type:"rotate",dur:"2s",keyTimes:"0;1",repeatCount:"indefinite",values:"0;360"}),s("circle",{cx:"50",cy:"50",r:"20",fill:"none",stroke:"currentColor","stroke-width":t,"stroke-linecap":"round"},[s("animate",{attributeName:"stroke-dasharray",dur:"1.5s",keyTimes:"0;0.5;1",repeatCount:"indefinite",values:"1,200;90,200;1,200"}),s("animate",{attributeName:"stroke-dashoffset",dur:"1.5s",keyTimes:"0;0.5;1",repeatCount:"indefinite",values:"0;-35px;-125px"})])]);return n?s("div",{class:"loading-icon-wrapper",style:`display:flex;align-items:center;justify-content:center;height:${l}px`},r):r};to.displayName="LoadingIcon";var vt=Uint8Array,zn=Uint16Array,Zv=Int32Array,zd=new vt([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),$d=new vt([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Qv=new vt([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Ud=function(e,t){for(var n=new zn(31),l=0;l<31;++l)n[l]=t+=1<>1|(Le&21845)<<1;ln=(ln&52428)>>2|(ln&13107)<<2,ln=(ln&61680)>>4|(ln&3855)<<4,na[Le]=((ln&65280)>>8|(ln&255)<<8)>>1}var Ol=function(e,t,n){for(var l=e.length,r=0,i=new zn(t);r>c]=u}else for(o=new zn(l),r=0;r>15-e[r]);return o},ar=new vt(288);for(var Le=0;Le<144;++Le)ar[Le]=8;for(var Le=144;Le<256;++Le)ar[Le]=9;for(var Le=256;Le<280;++Le)ar[Le]=7;for(var Le=280;Le<288;++Le)ar[Le]=8;var qd=new vt(32);for(var Le=0;Le<32;++Le)qd[Le]=5;var nm=Ol(ar,9,1),lm=Ol(qd,5,1),Li=function(e){for(var t=e[0],n=1;nt&&(t=e[n]);return t},xt=function(e,t,n){var l=t/8|0;return(e[l]|e[l+1]<<8)>>(t&7)&n},Oi=function(e,t){var n=t/8|0;return(e[n]|e[n+1]<<8|e[n+2]<<16)>>(t&7)},rm=function(e){return(e+7)/8|0},Wd=function(e,t,n){return(t==null||t<0)&&(t=0),(n==null||n>e.length)&&(n=e.length),new vt(e.subarray(t,n))},im=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],bt=function(e,t,n){var l=new Error(t||im[e]);if(l.code=e,Error.captureStackTrace&&Error.captureStackTrace(l,bt),!n)throw l;return l},am=function(e,t,n,l){var r=e.length,i=0;if(!r||t.f&&!t.l)return n||new vt(0);var a=!n,o=a||t.i!=2,c=t.i;a&&(n=new vt(r*3));var u=function(fe){var ye=n.length;if(fe>ye){var E=new vt(Math.max(ye*2,fe));E.set(n),n=E}},d=t.f||0,f=t.p||0,h=t.b||0,p=t.l,g=t.d,v=t.m,y=t.n,_=r*8;do{if(!p){d=xt(e,f,1);var A=xt(e,f+1,3);if(f+=3,A)if(A==1)p=nm,g=lm,v=9,y=5;else if(A==2){var V=xt(e,f,31)+257,R=xt(e,f+10,15)+4,Z=V+xt(e,f+5,31)+1;f+=14;for(var M=new vt(Z),T=new vt(19),$=0;$>4;if(m<16)M[$++]=m;else{var K=0,N=0;for(m==16?(N=3+xt(e,f,3),f+=2,K=M[$-1]):m==17?(N=3+xt(e,f,7),f+=3):m==18&&(N=11+xt(e,f,127),f+=7);N--;)M[$++]=K}}var J=M.subarray(0,V),ae=M.subarray(V);v=Li(J),y=Li(ae),p=Ol(J,v,1),g=Ol(ae,y,1)}else bt(1);else{var m=rm(f)+4,w=e[m-4]|e[m-3]<<8,F=m+w;if(F>r){c&&bt(0);break}o&&u(h+w),n.set(e.subarray(m,F),h),t.b=h+=w,t.p=f=F*8,t.f=d;continue}if(f>_){c&&bt(0);break}}o&&u(h+131072);for(var Ge=(1<>4;if(f+=K&15,f>_){c&&bt(0);break}if(K||bt(2),Ne<256)n[h++]=Ne;else if(Ne==256){ge=f,p=null;break}else{var gt=Ne-254;if(Ne>264){var $=Ne-257,rt=zd[$];gt=xt(e,f,(1<>4;We||bt(3),f+=We&15;var ae=tm[x];if(x>3){var rt=$d[x];ae+=Oi(e,f)&(1<_){c&&bt(0);break}o&&u(h+131072);var q=h+gt;if(h>4>7||(e[0]<<8|e[1])%31)&&bt(6,"invalid zlib data"),(e[1]>>5&1)==+!t&&bt(6,"invalid zlib data: "+(e[1]&32?"need":"unexpected")+" dictionary"),(e[1]>>3&4)+2};function cm(e,t){return am(e.subarray(sm(e,t),-4),{i:2},t,t)}var la=typeof TextDecoder<"u"&&new TextDecoder,um=0;try{la.decode(om,{stream:!0}),um=1}catch{}var dm=function(e){for(var t="",n=0;;){var l=e[n++],r=(l>127)+(l>223)+(l>239);if(n+r>e.length)return{s:t,r:Wd(e,n-1)};r?r==3?(l=((l&15)<<18|(e[n++]&63)<<12|(e[n++]&63)<<6|e[n++]&63)-65536,t+=String.fromCharCode(55296|l>>10,56320|l&1023)):r&1?t+=String.fromCharCode((l&31)<<6|e[n++]&63):t+=String.fromCharCode((l&15)<<12|(e[n++]&63)<<6|e[n++]&63):t+=String.fromCharCode(l)}};function fm(e,t){{for(var n=new vt(e.length),l=0;l{const t=atob(e);return hm(cm(fm(t)))},Ft=(e,t)=>{var l;const n=(l=(t==null?void 0:t._instance)??Xl())==null?void 0:l.appContext.components;return n?e in n||at(e)in n||Wl(at(e))in n:!1},no=e=>new Promise(t=>{setTimeout(t,e)}),Fn=e=>{const t=Mt();return k(()=>e[t.value]??{})},Jd=e=>typeof e<"u",Di=e=>typeof e=="number",{isArray:ra}=Array,Hr=(e,t)=>ke(e)&&e.startsWith(t),vm=(e,t)=>ke(e)&&e.endsWith(t),{entries:En}=Object,{fromEntries:mm}=Object,{keys:hn}=Object,lo=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},ni=e=>Hr(e,"/");let Yd=e=>ke(e.title)?{title:e.title}:null;const Zd=Symbol(""),gm=e=>{Yd=e},Em=()=>Se(Zd),_m=e=>{e.provide(Zd,Yd)};var bm={"/":{title:"目录",empty:"暂无目录"}},ym=H({name:"Catalog",props:{base:{type:String,default:""},level:{type:Number,default:3},index:Boolean,hideHeading:Boolean},setup(e){const t=Em(),n=Fn(bm),l=Oe(),r=iv(),i=Id(),a=$e(En(r.value).map(([c,{meta:u}])=>{const d=t(u);if(!d)return null;const f=c.split("/").length;return{level:vm(c,"/")?f-2:f-1,base:c.replace(/\/[^/]+\/?$/,"/"),path:c,...d}}).filter(c=>nr(c)&&ke(c.title))),o=k(()=>{const c=e.base?W0(_d(e.base)):l.value.path.replace(/\/[^/]+$/,"/"),u=c.split("/").length-2,d=[];return a.value.filter(({level:f,path:h})=>{if(!Hr(h,c)||h===c)return!1;if(c==="/"){const p=hn(i.value.locales).filter(g=>g!=="/");if(h==="/404.html"||p.some(g=>Hr(h,g)))return!1}return f-u<=e.level}).sort(({title:f,level:h,order:p},{title:g,level:v,order:y})=>h-v||(Di(p)?Di(y)?p>0?y>0?p-y:-1:y<0?p-y:1:p:Di(y)?y:f.localeCompare(g))).forEach(f=>{var g;const{base:h,level:p}=f;switch(p-u){case 1:{d.push(f);break}case 2:{const v=d.find(y=>y.path===h);v&&(v.children??(v.children=[])).push(f);break}default:{const v=d.find(y=>y.path===h.replace(/\/[^/]+\/$/,"/"));if(v){const y=(g=v.children)==null?void 0:g.find(_=>_.path===h);y&&(y.children??(y.children=[])).push(f)}}}}),d});return()=>{const c=o.value.some(u=>u.children);return s("div",{class:["vp-catalog",{index:e.index}]},[e.hideHeading?null:s("h2",{class:"vp-catalog-main-title"},n.value.title),o.value.length?s(e.index?"ol":"ul",{class:["vp-catalog-list",{deep:c}]},o.value.map(({children:u=[],title:d,path:f,content:h})=>{const p=s(He,{class:"vp-catalog-title",to:f},()=>h?s(h):d);return s("li",{class:"vp-catalog-item"},c?[s("h3",{id:d,class:["vp-catalog-child-title",{"has-children":u.length}]},[s("a",{href:`#${d}`,class:"vp-catalog-header-anchor","aria-hidden":!0},"#"),p]),u.length?s(e.index?"ol":"ul",{class:"vp-child-catalogs"},u.map(({children:g=[],content:v,path:y,title:_})=>s("li",{class:"vp-child-catalog"},[s("div",{class:["vp-catalog-sub-title",{"has-children":g.length}]},[s("a",{href:`#${_}`,class:"vp-catalog-header-anchor"},"#"),s(He,{class:"vp-catalog-title",to:y},()=>v?s(v):_)]),g.length?s(e.index?"ol":"div",{class:e.index?"vp-sub-catalogs":"vp-sub-catalogs-wrapper"},g.map(({content:A,path:m,title:w})=>e.index?s("li",{class:"vp-sub-catalog"},s(He,{to:m},()=>A?s(A):w)):s(He,{class:"vp-sub-catalog-link",to:m},()=>A?s(A):w))):null]))):null]:s("div",{class:"vp-catalog-child-title"},p))})):s("p",{class:"vp-empty-catalog"},n.value.empty)])}}}),Am=Bt({enhance:({app:e})=>{_m(e),Ft("Catalog",e)||e.component("Catalog",ym)}});const km=Object.freeze(Object.defineProperty({__proto__:null,default:Am},Symbol.toStringTag,{value:"Module"}));var wm={"/":{backToTop:"返回顶部"}};const Bm=H({name:"BackToTop",setup(){const e=ve(),t=Fn(wm),n=$e(),{height:l}=Mv(n),{height:r}=$v(),{y:i}=zv(),a=k(()=>e.value.backToTop!==!1&&i.value>100),o=k(()=>i.value/(l.value-r.value)*100);return we(()=>{n.value=document.body}),()=>s(el,{name:"back-to-top"},()=>a.value?s("button",{type:"button",class:"vp-back-to-top-button","aria-label":t.value.backToTop,onClick:()=>{window.scrollTo({top:0,behavior:"smooth"})}},[s("span",{class:"vp-scroll-progress",role:"progressbar","aria-labelledby":"loadinglabel","aria-valuenow":o.value},s("svg",s("circle",{cx:"26",cy:"26",r:"24",fill:"none",stroke:"currentColor","stroke-width":"4","stroke-dasharray":`${Math.PI*o.value*.48} ${Math.PI*(100-o.value)*.48}`}))),s("div",{class:"back-to-top-icon"})]):null)}}),Cm=Bt({rootComponents:[Bm]}),xm=Object.freeze(Object.defineProperty({__proto__:null,default:Cm},Symbol.toStringTag,{value:"Module"}));/**
+ * NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
+ * @license MIT
+ */const js=(e,t)=>{e.classList.add(t)},Hs=(e,t)=>{e.classList.remove(t)},Sm=e=>{var t;(t=e==null?void 0:e.parentNode)==null||t.removeChild(e)},Pi=(e,t,n)=>en?n:e,zs=e=>(-1+e)*100,Tm=(()=>{const e=[],t=()=>{const n=e.shift();n&&n(t)};return n=>{e.push(n),e.length===1&&t()}})(),Lm=e=>e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(t,n)=>n.toUpperCase()),wr=(()=>{const e=["Webkit","O","Moz","ms"],t={},n=i=>{const{style:a}=document.body;if(i in a)return i;const o=i.charAt(0).toUpperCase()+i.slice(1);let c=e.length;for(;c--;){const u=`${e[c]}${o}`;if(u in a)return u}return i},l=i=>{const a=Lm(i);return t[a]??(t[a]=n(a))},r=(i,a,o)=>{i.style[l(a)]=o};return(i,a)=>{for(const o in a){const c=a[o];Object.hasOwn(a,o)&&Jd(c)&&r(i,o,c)}}})(),qt={minimum:.08,easing:"ease",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,barSelector:'[role="bar"]',parent:"body",template:'
'},Pe={percent:null,isRendered:()=>!!document.getElementById("nprogress"),set:e=>{const{speed:t,easing:n}=qt,l=Pe.isStarted(),r=Pi(e,qt.minimum,1);Pe.percent=r===1?null:r;const i=Pe.render(!l),a=i.querySelector(qt.barSelector);return i.offsetWidth,Tm(o=>{wr(a,{transform:`translate3d(${zs(r)}%,0,0)`,transition:`all ${t}ms ${n}`}),r===1?(wr(i,{transition:"none",opacity:"1"}),i.offsetWidth,setTimeout(()=>{wr(i,{transition:`all ${t}ms linear`,opacity:"0"}),setTimeout(()=>{Pe.remove(),o()},t)},t)):setTimeout(()=>{o()},t)}),Pe},isStarted:()=>typeof Pe.percent=="number",start:()=>{Pe.percent||Pe.set(0);const e=()=>{setTimeout(()=>{Pe.percent&&(Pe.trickle(),e())},qt.trickleSpeed)};return e(),Pe},done:e=>!e&&!Pe.percent?Pe:Pe.increase(.3+.5*Math.random()).set(1),increase:e=>{let{percent:t}=Pe;return t?(t=Pi(t+(typeof e=="number"?e:(1-t)*Pi(Math.random()*t,.1,.95)),0,.994),Pe.set(t)):Pe.start()},trickle:()=>Pe.increase(Math.random()*qt.trickleRate),render:e=>{if(Pe.isRendered())return document.getElementById("nprogress");js(document.documentElement,"nprogress-busy");const t=document.createElement("div");t.id="nprogress",t.innerHTML=qt.template;const n=t.querySelector(qt.barSelector),l=document.querySelector(qt.parent),r=e?"-100":zs(Pe.percent??0);return wr(n,{transition:"all 0 linear",transform:`translate3d(${r}%,0,0)`}),l&&(l!==document.body&&js(l,"nprogress-custom-parent"),l.appendChild(t)),t},remove:()=>{Hs(document.documentElement,"nprogress-busy"),Hs(document.querySelector(qt.parent),"nprogress-custom-parent"),Sm(document.getElementById("nprogress"))}},Om=()=>{we(()=>{const e=en(),t=new Set;t.add(e.currentRoute.value.path),e.beforeEach(n=>{t.has(n.path)||Pe.start()}),e.afterEach(n=>{t.add(n.path),Pe.done()})})},Dm=Bt({setup(){Om()}}),Pm=Object.freeze(Object.defineProperty({__proto__:null,default:Dm},Symbol.toStringTag,{value:"Module"}));var Im=Object.create,Qd=Object.defineProperty,Fm=Object.getOwnPropertyDescriptor,ro=Object.getOwnPropertyNames,Rm=Object.getPrototypeOf,Mm=Object.prototype.hasOwnProperty,Vm=(e,t)=>function(){return e&&(t=(0,e[ro(e)[0]])(e=0)),t},Nm=(e,t)=>function(){return t||(0,e[ro(e)[0]])((t={exports:{}}).exports,t),t.exports},jm=(e,t,n,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ro(t))!Mm.call(e,r)&&r!==n&&Qd(e,r,{get:()=>t[r],enumerable:!(l=Fm(t,r))||l.enumerable});return e},Hm=(e,t,n)=>(n=e!=null?Im(Rm(e)):{},jm(Qd(n,"default",{value:e,enumerable:!0}),e)),or=Vm({"../../node_modules/.pnpm/tsup@8.3.5_@microsoft+api-extractor@7.48.0_@types+node@22.10.1__@swc+core@1.5.29_jiti@2.0.0_p_swvvp2d4pgn6xuiiec4l4x2i7a/node_modules/tsup/assets/esm_shims.js"(){}}),zm=Nm({"../../node_modules/.pnpm/rfdc@1.4.1/node_modules/rfdc/index.js"(e,t){or(),t.exports=l;function n(i){return i instanceof Buffer?Buffer.from(i):new i.constructor(i.buffer.slice(),i.byteOffset,i.length)}function l(i){if(i=i||{},i.circles)return r(i);const a=new Map;if(a.set(Date,f=>new Date(f)),a.set(Map,(f,h)=>new Map(c(Array.from(f),h))),a.set(Set,(f,h)=>new Set(c(Array.from(f),h))),i.constructorHandlers)for(const f of i.constructorHandlers)a.set(f[0],f[1]);let o=null;return i.proto?d:u;function c(f,h){const p=Object.keys(f),g=new Array(p.length);for(let v=0;vnew Date(p)),c.set(Map,(p,g)=>new Map(d(Array.from(p),g))),c.set(Set,(p,g)=>new Set(d(Array.from(p),g))),i.constructorHandlers)for(const p of i.constructorHandlers)c.set(p[0],p[1]);let u=null;return i.proto?h:f;function d(p,g){const v=Object.keys(p),y=new Array(v.length);for(let _=0;_(a=Jm(e,u,d),a.finally(()=>{if(a=null,n.trailing&&o&&!r){const f=c(u,o);return o=null,f}}),a);return function(...u){return a?(n.trailing&&(o=u),a):new Promise(d=>{const f=!r&&n.leading;clearTimeout(r),r=setTimeout(()=>{r=null;const h=n.leading?l:c(this,u);for(const p of i)p(h);i=[]},t),f?(l=c(this,u),d(l)):i.push(d)})}}async function Jm(e,t,n){return await e.apply(t,n)}function ia(e,t={},n){for(const l in e){const r=e[l],i=n?`${n}:${l}`:l;typeof r=="object"&&r!==null?ia(r,t,i):typeof r=="function"&&(t[i]=r)}return t}const Ym={run:e=>e()},Zm=()=>Ym,ef=typeof console.createTask<"u"?console.createTask:Zm;function Qm(e,t){const n=t.shift(),l=ef(n);return e.reduce((r,i)=>r.then(()=>l.run(()=>i(...t))),Promise.resolve())}function Xm(e,t){const n=t.shift(),l=ef(n);return Promise.all(e.map(r=>l.run(()=>r(...t))))}function Ii(e,t){for(const n of[...e])n(t)}class eg{constructor(){this._hooks={},this._before=void 0,this._after=void 0,this._deprecatedMessages=void 0,this._deprecatedHooks={},this.hook=this.hook.bind(this),this.callHook=this.callHook.bind(this),this.callHookWith=this.callHookWith.bind(this)}hook(t,n,l={}){if(!t||typeof n!="function")return()=>{};const r=t;let i;for(;this._deprecatedHooks[t];)i=this._deprecatedHooks[t],t=i.to;if(i&&!l.allowDeprecated){let a=i.message;a||(a=`${r} hook has been deprecated`+(i.to?`, please use ${i.to}`:"")),this._deprecatedMessages||(this._deprecatedMessages=new Set),this._deprecatedMessages.has(a)||(console.warn(a),this._deprecatedMessages.add(a))}if(!n.name)try{Object.defineProperty(n,"name",{get:()=>"_"+t.replace(/\W+/g,"_")+"_hook_cb",configurable:!0})}catch{}return this._hooks[t]=this._hooks[t]||[],this._hooks[t].push(n),()=>{n&&(this.removeHook(t,n),n=void 0)}}hookOnce(t,n){let l,r=(...i)=>(typeof l=="function"&&l(),l=void 0,r=void 0,n(...i));return l=this.hook(t,r),l}removeHook(t,n){if(this._hooks[t]){const l=this._hooks[t].indexOf(n);l!==-1&&this._hooks[t].splice(l,1),this._hooks[t].length===0&&delete this._hooks[t]}}deprecateHook(t,n){this._deprecatedHooks[t]=typeof n=="string"?{to:n}:n;const l=this._hooks[t]||[];delete this._hooks[t];for(const r of l)this.hook(t,r)}deprecateHooks(t){Object.assign(this._deprecatedHooks,t);for(const n in t)this.deprecateHook(n,t[n])}addHooks(t){const n=ia(t),l=Object.keys(n).map(r=>this.hook(r,n[r]));return()=>{for(const r of l.splice(0,l.length))r()}}removeHooks(t){const n=ia(t);for(const l in n)this.removeHook(l,n[l])}removeAllHooks(){for(const t in this._hooks)delete this._hooks[t]}callHook(t,...n){return n.unshift(t),this.callHookWith(Qm,t,...n)}callHookParallel(t,...n){return n.unshift(t),this.callHookWith(Xm,t,...n)}callHookWith(t,n,...l){const r=this._before||this._after?{name:n,args:l,context:{}}:void 0;this._before&&Ii(this._before,r);const i=t(n in this._hooks?[...this._hooks[n]]:[],l);return i instanceof Promise?i.finally(()=>{this._after&&r&&Ii(this._after,r)}):(this._after&&r&&Ii(this._after,r),i)}beforeEach(t){return this._before=this._before||[],this._before.push(t),()=>{if(this._before!==void 0){const n=this._before.indexOf(t);n!==-1&&this._before.splice(n,1)}}}afterEach(t){return this._after=this._after||[],this._after.push(t),()=>{if(this._after!==void 0){const n=this._after.indexOf(t);n!==-1&&this._after.splice(n,1)}}}}function tf(){return new eg}var tg=Object.create,nf=Object.defineProperty,ng=Object.getOwnPropertyDescriptor,io=Object.getOwnPropertyNames,lg=Object.getPrototypeOf,rg=Object.prototype.hasOwnProperty,ig=(e,t)=>function(){return e&&(t=(0,e[io(e)[0]])(e=0)),t},lf=(e,t)=>function(){return t||(0,e[io(e)[0]])((t={exports:{}}).exports,t),t.exports},ag=(e,t,n,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of io(t))!rg.call(e,r)&&r!==n&&nf(e,r,{get:()=>t[r],enumerable:!(l=ng(t,r))||l.enumerable});return e},og=(e,t,n)=>(n=e!=null?tg(lg(e)):{},ag(nf(n,"default",{value:e,enumerable:!0}),e)),L=ig({"../../node_modules/.pnpm/tsup@8.3.5_@microsoft+api-extractor@7.48.0_@types+node@22.10.1__@swc+core@1.5.29_jiti@2.0.0_p_swvvp2d4pgn6xuiiec4l4x2i7a/node_modules/tsup/assets/esm_shims.js"(){}}),sg=lf({"../../node_modules/.pnpm/speakingurl@14.0.1/node_modules/speakingurl/lib/speakingurl.js"(e,t){L(),function(n){var l={À:"A",Á:"A",Â:"A",Ã:"A",Ä:"Ae",Å:"A",Æ:"AE",Ç:"C",È:"E",É:"E",Ê:"E",Ë:"E",Ì:"I",Í:"I",Î:"I",Ï:"I",Ð:"D",Ñ:"N",Ò:"O",Ó:"O",Ô:"O",Õ:"O",Ö:"Oe",Ő:"O",Ø:"O",Ù:"U",Ú:"U",Û:"U",Ü:"Ue",Ű:"U",Ý:"Y",Þ:"TH",ß:"ss",à:"a",á:"a",â:"a",ã:"a",ä:"ae",å:"a",æ:"ae",ç:"c",è:"e",é:"e",ê:"e",ë:"e",ì:"i",í:"i",î:"i",ï:"i",ð:"d",ñ:"n",ò:"o",ó:"o",ô:"o",õ:"o",ö:"oe",ő:"o",ø:"o",ù:"u",ú:"u",û:"u",ü:"ue",ű:"u",ý:"y",þ:"th",ÿ:"y","ẞ":"SS",ا:"a",أ:"a",إ:"i",آ:"aa",ؤ:"u",ئ:"e",ء:"a",ب:"b",ت:"t",ث:"th",ج:"j",ح:"h",خ:"kh",د:"d",ذ:"th",ر:"r",ز:"z",س:"s",ش:"sh",ص:"s",ض:"dh",ط:"t",ظ:"z",ع:"a",غ:"gh",ف:"f",ق:"q",ك:"k",ل:"l",م:"m",ن:"n",ه:"h",و:"w",ي:"y",ى:"a",ة:"h",ﻻ:"la",ﻷ:"laa",ﻹ:"lai",ﻵ:"laa",گ:"g",چ:"ch",پ:"p",ژ:"zh",ک:"k",ی:"y","َ":"a","ً":"an","ِ":"e","ٍ":"en","ُ":"u","ٌ":"on","ْ":"","٠":"0","١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","۰":"0","۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9",က:"k",ခ:"kh",ဂ:"g",ဃ:"ga",င:"ng",စ:"s",ဆ:"sa",ဇ:"z","စျ":"za",ည:"ny",ဋ:"t",ဌ:"ta",ဍ:"d",ဎ:"da",ဏ:"na",တ:"t",ထ:"ta",ဒ:"d",ဓ:"da",န:"n",ပ:"p",ဖ:"pa",ဗ:"b",ဘ:"ba",မ:"m",ယ:"y",ရ:"ya",လ:"l",ဝ:"w",သ:"th",ဟ:"h",ဠ:"la",အ:"a","ြ":"y","ျ":"ya","ွ":"w","ြွ":"yw","ျွ":"ywa","ှ":"h",ဧ:"e","၏":"-e",ဣ:"i",ဤ:"-i",ဉ:"u",ဦ:"-u",ဩ:"aw","သြော":"aw",ဪ:"aw","၀":"0","၁":"1","၂":"2","၃":"3","၄":"4","၅":"5","၆":"6","၇":"7","၈":"8","၉":"9","္":"","့":"","း":"",č:"c",ď:"d",ě:"e",ň:"n",ř:"r",š:"s",ť:"t",ů:"u",ž:"z",Č:"C",Ď:"D",Ě:"E",Ň:"N",Ř:"R",Š:"S",Ť:"T",Ů:"U",Ž:"Z",ހ:"h",ށ:"sh",ނ:"n",ރ:"r",ބ:"b",ޅ:"lh",ކ:"k",އ:"a",ވ:"v",މ:"m",ފ:"f",ދ:"dh",ތ:"th",ލ:"l",ގ:"g",ޏ:"gn",ސ:"s",ޑ:"d",ޒ:"z",ޓ:"t",ޔ:"y",ޕ:"p",ޖ:"j",ޗ:"ch",ޘ:"tt",ޙ:"hh",ޚ:"kh",ޛ:"th",ޜ:"z",ޝ:"sh",ޞ:"s",ޟ:"d",ޠ:"t",ޡ:"z",ޢ:"a",ޣ:"gh",ޤ:"q",ޥ:"w","ަ":"a","ާ":"aa","ި":"i","ީ":"ee","ު":"u","ޫ":"oo","ެ":"e","ޭ":"ey","ޮ":"o","ޯ":"oa","ް":"",ა:"a",ბ:"b",გ:"g",დ:"d",ე:"e",ვ:"v",ზ:"z",თ:"t",ი:"i",კ:"k",ლ:"l",მ:"m",ნ:"n",ო:"o",პ:"p",ჟ:"zh",რ:"r",ს:"s",ტ:"t",უ:"u",ფ:"p",ქ:"k",ღ:"gh",ყ:"q",შ:"sh",ჩ:"ch",ც:"ts",ძ:"dz",წ:"ts",ჭ:"ch",ხ:"kh",ჯ:"j",ჰ:"h",α:"a",β:"v",γ:"g",δ:"d",ε:"e",ζ:"z",η:"i",θ:"th",ι:"i",κ:"k",λ:"l",μ:"m",ν:"n",ξ:"ks",ο:"o",π:"p",ρ:"r",σ:"s",τ:"t",υ:"y",φ:"f",χ:"x",ψ:"ps",ω:"o",ά:"a",έ:"e",ί:"i",ό:"o",ύ:"y",ή:"i",ώ:"o",ς:"s",ϊ:"i",ΰ:"y",ϋ:"y",ΐ:"i",Α:"A",Β:"B",Γ:"G",Δ:"D",Ε:"E",Ζ:"Z",Η:"I",Θ:"TH",Ι:"I",Κ:"K",Λ:"L",Μ:"M",Ν:"N",Ξ:"KS",Ο:"O",Π:"P",Ρ:"R",Σ:"S",Τ:"T",Υ:"Y",Φ:"F",Χ:"X",Ψ:"PS",Ω:"O",Ά:"A",Έ:"E",Ί:"I",Ό:"O",Ύ:"Y",Ή:"I",Ώ:"O",Ϊ:"I",Ϋ:"Y",ā:"a",ē:"e",ģ:"g",ī:"i",ķ:"k",ļ:"l",ņ:"n",ū:"u",Ā:"A",Ē:"E",Ģ:"G",Ī:"I",Ķ:"k",Ļ:"L",Ņ:"N",Ū:"U",Ќ:"Kj",ќ:"kj",Љ:"Lj",љ:"lj",Њ:"Nj",њ:"nj",Тс:"Ts",тс:"ts",ą:"a",ć:"c",ę:"e",ł:"l",ń:"n",ś:"s",ź:"z",ż:"z",Ą:"A",Ć:"C",Ę:"E",Ł:"L",Ń:"N",Ś:"S",Ź:"Z",Ż:"Z",Є:"Ye",І:"I",Ї:"Yi",Ґ:"G",є:"ye",і:"i",ї:"yi",ґ:"g",ă:"a",Ă:"A",ș:"s",Ș:"S",ț:"t",Ț:"T",ţ:"t",Ţ:"T",а:"a",б:"b",в:"v",г:"g",д:"d",е:"e",ё:"yo",ж:"zh",з:"z",и:"i",й:"i",к:"k",л:"l",м:"m",н:"n",о:"o",п:"p",р:"r",с:"s",т:"t",у:"u",ф:"f",х:"kh",ц:"c",ч:"ch",ш:"sh",щ:"sh",ъ:"",ы:"y",ь:"",э:"e",ю:"yu",я:"ya",А:"A",Б:"B",В:"V",Г:"G",Д:"D",Е:"E",Ё:"Yo",Ж:"Zh",З:"Z",И:"I",Й:"I",К:"K",Л:"L",М:"M",Н:"N",О:"O",П:"P",Р:"R",С:"S",Т:"T",У:"U",Ф:"F",Х:"Kh",Ц:"C",Ч:"Ch",Ш:"Sh",Щ:"Sh",Ъ:"",Ы:"Y",Ь:"",Э:"E",Ю:"Yu",Я:"Ya",ђ:"dj",ј:"j",ћ:"c",џ:"dz",Ђ:"Dj",Ј:"j",Ћ:"C",Џ:"Dz",ľ:"l",ĺ:"l",ŕ:"r",Ľ:"L",Ĺ:"L",Ŕ:"R",ş:"s",Ş:"S",ı:"i",İ:"I",ğ:"g",Ğ:"G",ả:"a",Ả:"A",ẳ:"a",Ẳ:"A",ẩ:"a",Ẩ:"A",đ:"d",Đ:"D",ẹ:"e",Ẹ:"E",ẽ:"e",Ẽ:"E",ẻ:"e",Ẻ:"E",ế:"e",Ế:"E",ề:"e",Ề:"E",ệ:"e",Ệ:"E",ễ:"e",Ễ:"E",ể:"e",Ể:"E",ỏ:"o",ọ:"o",Ọ:"o",ố:"o",Ố:"O",ồ:"o",Ồ:"O",ổ:"o",Ổ:"O",ộ:"o",Ộ:"O",ỗ:"o",Ỗ:"O",ơ:"o",Ơ:"O",ớ:"o",Ớ:"O",ờ:"o",Ờ:"O",ợ:"o",Ợ:"O",ỡ:"o",Ỡ:"O",Ở:"o",ở:"o",ị:"i",Ị:"I",ĩ:"i",Ĩ:"I",ỉ:"i",Ỉ:"i",ủ:"u",Ủ:"U",ụ:"u",Ụ:"U",ũ:"u",Ũ:"U",ư:"u",Ư:"U",ứ:"u",Ứ:"U",ừ:"u",Ừ:"U",ự:"u",Ự:"U",ữ:"u",Ữ:"U",ử:"u",Ử:"ư",ỷ:"y",Ỷ:"y",ỳ:"y",Ỳ:"Y",ỵ:"y",Ỵ:"Y",ỹ:"y",Ỹ:"Y",ạ:"a",Ạ:"A",ấ:"a",Ấ:"A",ầ:"a",Ầ:"A",ậ:"a",Ậ:"A",ẫ:"a",Ẫ:"A",ắ:"a",Ắ:"A",ằ:"a",Ằ:"A",ặ:"a",Ặ:"A",ẵ:"a",Ẵ:"A","⓪":"0","①":"1","②":"2","③":"3","④":"4","⑤":"5","⑥":"6","⑦":"7","⑧":"8","⑨":"9","⑩":"10","⑪":"11","⑫":"12","⑬":"13","⑭":"14","⑮":"15","⑯":"16","⑰":"17","⑱":"18","⑲":"18","⑳":"18","⓵":"1","⓶":"2","⓷":"3","⓸":"4","⓹":"5","⓺":"6","⓻":"7","⓼":"8","⓽":"9","⓾":"10","⓿":"0","⓫":"11","⓬":"12","⓭":"13","⓮":"14","⓯":"15","⓰":"16","⓱":"17","⓲":"18","⓳":"19","⓴":"20","Ⓐ":"A","Ⓑ":"B","Ⓒ":"C","Ⓓ":"D","Ⓔ":"E","Ⓕ":"F","Ⓖ":"G","Ⓗ":"H","Ⓘ":"I","Ⓙ":"J","Ⓚ":"K","Ⓛ":"L","Ⓜ":"M","Ⓝ":"N","Ⓞ":"O","Ⓟ":"P","Ⓠ":"Q","Ⓡ":"R","Ⓢ":"S","Ⓣ":"T","Ⓤ":"U","Ⓥ":"V","Ⓦ":"W","Ⓧ":"X","Ⓨ":"Y","Ⓩ":"Z","ⓐ":"a","ⓑ":"b","ⓒ":"c","ⓓ":"d","ⓔ":"e","ⓕ":"f","ⓖ":"g","ⓗ":"h","ⓘ":"i","ⓙ":"j","ⓚ":"k","ⓛ":"l","ⓜ":"m","ⓝ":"n","ⓞ":"o","ⓟ":"p","ⓠ":"q","ⓡ":"r","ⓢ":"s","ⓣ":"t","ⓤ":"u","ⓦ":"v","ⓥ":"w","ⓧ":"x","ⓨ":"y","ⓩ":"z","“":'"',"”":'"',"‘":"'","’":"'","∂":"d",ƒ:"f","™":"(TM)","©":"(C)",œ:"oe",Œ:"OE","®":"(R)","†":"+","℠":"(SM)","…":"...","˚":"o",º:"o",ª:"a","•":"*","၊":",","။":".",$:"USD","€":"EUR","₢":"BRN","₣":"FRF","£":"GBP","₤":"ITL","₦":"NGN","₧":"ESP","₩":"KRW","₪":"ILS","₫":"VND","₭":"LAK","₮":"MNT","₯":"GRD","₱":"ARS","₲":"PYG","₳":"ARA","₴":"UAH","₵":"GHS","¢":"cent","¥":"CNY",元:"CNY",円:"YEN","﷼":"IRR","₠":"EWE","฿":"THB","₨":"INR","₹":"INR","₰":"PF","₺":"TRY","؋":"AFN","₼":"AZN",лв:"BGN","៛":"KHR","₡":"CRC","₸":"KZT",ден:"MKD",zł:"PLN","₽":"RUB","₾":"GEL"},r=["်","ް"],i={"ာ":"a","ါ":"a","ေ":"e","ဲ":"e","ိ":"i","ီ":"i","ို":"o","ု":"u","ူ":"u","ေါင်":"aung","ော":"aw","ော်":"aw","ေါ":"aw","ေါ်":"aw","်":"်","က်":"et","ိုက်":"aik","ောက်":"auk","င်":"in","ိုင်":"aing","ောင်":"aung","စ်":"it","ည်":"i","တ်":"at","ိတ်":"eik","ုတ်":"ok","ွတ်":"ut","ေတ်":"it","ဒ်":"d","ိုဒ်":"ok","ုဒ်":"ait","န်":"an","ာန်":"an","ိန်":"ein","ုန်":"on","ွန်":"un","ပ်":"at","ိပ်":"eik","ုပ်":"ok","ွပ်":"ut","န်ုပ်":"nub","မ်":"an","ိမ်":"ein","ုမ်":"on","ွမ်":"un","ယ်":"e","ိုလ်":"ol","ဉ်":"in","ံ":"an","ိံ":"ein","ုံ":"on","ައް":"ah","ަށް":"ah"},a={en:{},az:{ç:"c",ə:"e",ğ:"g",ı:"i",ö:"o",ş:"s",ü:"u",Ç:"C",Ə:"E",Ğ:"G",İ:"I",Ö:"O",Ş:"S",Ü:"U"},cs:{č:"c",ď:"d",ě:"e",ň:"n",ř:"r",š:"s",ť:"t",ů:"u",ž:"z",Č:"C",Ď:"D",Ě:"E",Ň:"N",Ř:"R",Š:"S",Ť:"T",Ů:"U",Ž:"Z"},fi:{ä:"a",Ä:"A",ö:"o",Ö:"O"},hu:{ä:"a",Ä:"A",ö:"o",Ö:"O",ü:"u",Ü:"U",ű:"u",Ű:"U"},lt:{ą:"a",č:"c",ę:"e",ė:"e",į:"i",š:"s",ų:"u",ū:"u",ž:"z",Ą:"A",Č:"C",Ę:"E",Ė:"E",Į:"I",Š:"S",Ų:"U",Ū:"U"},lv:{ā:"a",č:"c",ē:"e",ģ:"g",ī:"i",ķ:"k",ļ:"l",ņ:"n",š:"s",ū:"u",ž:"z",Ā:"A",Č:"C",Ē:"E",Ģ:"G",Ī:"i",Ķ:"k",Ļ:"L",Ņ:"N",Š:"S",Ū:"u",Ž:"Z"},pl:{ą:"a",ć:"c",ę:"e",ł:"l",ń:"n",ó:"o",ś:"s",ź:"z",ż:"z",Ą:"A",Ć:"C",Ę:"e",Ł:"L",Ń:"N",Ó:"O",Ś:"S",Ź:"Z",Ż:"Z"},sv:{ä:"a",Ä:"A",ö:"o",Ö:"O"},sk:{ä:"a",Ä:"A"},sr:{љ:"lj",њ:"nj",Љ:"Lj",Њ:"Nj",đ:"dj",Đ:"Dj"},tr:{Ü:"U",Ö:"O",ü:"u",ö:"o"}},o={ar:{"∆":"delta","∞":"la-nihaya","♥":"hob","&":"wa","|":"aw","<":"aqal-men",">":"akbar-men","∑":"majmou","¤":"omla"},az:{},ca:{"∆":"delta","∞":"infinit","♥":"amor","&":"i","|":"o","<":"menys que",">":"mes que","∑":"suma dels","¤":"moneda"},cs:{"∆":"delta","∞":"nekonecno","♥":"laska","&":"a","|":"nebo","<":"mensi nez",">":"vetsi nez","∑":"soucet","¤":"mena"},de:{"∆":"delta","∞":"unendlich","♥":"Liebe","&":"und","|":"oder","<":"kleiner als",">":"groesser als","∑":"Summe von","¤":"Waehrung"},dv:{"∆":"delta","∞":"kolunulaa","♥":"loabi","&":"aai","|":"noonee","<":"ah vure kuda",">":"ah vure bodu","∑":"jumula","¤":"faisaa"},en:{"∆":"delta","∞":"infinity","♥":"love","&":"and","|":"or","<":"less than",">":"greater than","∑":"sum","¤":"currency"},es:{"∆":"delta","∞":"infinito","♥":"amor","&":"y","|":"u","<":"menos que",">":"mas que","∑":"suma de los","¤":"moneda"},fa:{"∆":"delta","∞":"bi-nahayat","♥":"eshgh","&":"va","|":"ya","<":"kamtar-az",">":"bishtar-az","∑":"majmooe","¤":"vahed"},fi:{"∆":"delta","∞":"aarettomyys","♥":"rakkaus","&":"ja","|":"tai","<":"pienempi kuin",">":"suurempi kuin","∑":"summa","¤":"valuutta"},fr:{"∆":"delta","∞":"infiniment","♥":"Amour","&":"et","|":"ou","<":"moins que",">":"superieure a","∑":"somme des","¤":"monnaie"},ge:{"∆":"delta","∞":"usasruloba","♥":"siqvaruli","&":"da","|":"an","<":"naklebi",">":"meti","∑":"jami","¤":"valuta"},gr:{},hu:{"∆":"delta","∞":"vegtelen","♥":"szerelem","&":"es","|":"vagy","<":"kisebb mint",">":"nagyobb mint","∑":"szumma","¤":"penznem"},it:{"∆":"delta","∞":"infinito","♥":"amore","&":"e","|":"o","<":"minore di",">":"maggiore di","∑":"somma","¤":"moneta"},lt:{"∆":"delta","∞":"begalybe","♥":"meile","&":"ir","|":"ar","<":"maziau nei",">":"daugiau nei","∑":"suma","¤":"valiuta"},lv:{"∆":"delta","∞":"bezgaliba","♥":"milestiba","&":"un","|":"vai","<":"mazak neka",">":"lielaks neka","∑":"summa","¤":"valuta"},my:{"∆":"kwahkhyaet","∞":"asaonasme","♥":"akhyait","&":"nhin","|":"tho","<":"ngethaw",">":"kyithaw","∑":"paungld","¤":"ngwekye"},mk:{},nl:{"∆":"delta","∞":"oneindig","♥":"liefde","&":"en","|":"of","<":"kleiner dan",">":"groter dan","∑":"som","¤":"valuta"},pl:{"∆":"delta","∞":"nieskonczonosc","♥":"milosc","&":"i","|":"lub","<":"mniejsze niz",">":"wieksze niz","∑":"suma","¤":"waluta"},pt:{"∆":"delta","∞":"infinito","♥":"amor","&":"e","|":"ou","<":"menor que",">":"maior que","∑":"soma","¤":"moeda"},ro:{"∆":"delta","∞":"infinit","♥":"dragoste","&":"si","|":"sau","<":"mai mic ca",">":"mai mare ca","∑":"suma","¤":"valuta"},ru:{"∆":"delta","∞":"beskonechno","♥":"lubov","&":"i","|":"ili","<":"menshe",">":"bolshe","∑":"summa","¤":"valjuta"},sk:{"∆":"delta","∞":"nekonecno","♥":"laska","&":"a","|":"alebo","<":"menej ako",">":"viac ako","∑":"sucet","¤":"mena"},sr:{},tr:{"∆":"delta","∞":"sonsuzluk","♥":"ask","&":"ve","|":"veya","<":"kucuktur",">":"buyuktur","∑":"toplam","¤":"para birimi"},uk:{"∆":"delta","∞":"bezkinechnist","♥":"lubov","&":"i","|":"abo","<":"menshe",">":"bilshe","∑":"suma","¤":"valjuta"},vn:{"∆":"delta","∞":"vo cuc","♥":"yeu","&":"va","|":"hoac","<":"nho hon",">":"lon hon","∑":"tong","¤":"tien te"}},c=[";","?",":","@","&","=","+","$",",","/"].join(""),u=[";","?",":","@","&","=","+","$",","].join(""),d=[".","!","~","*","'","(",")"].join(""),f=function(y,_){var A="-",m="",w="",F=!0,V={},R,Z,M,T,$,O,X,se,he,K,N,J,ae,Ge,Fe="";if(typeof y!="string")return"";if(typeof _=="string"&&(A=_),X=o.en,se=a.en,typeof _=="object"){R=_.maintainCase||!1,V=_.custom&&typeof _.custom=="object"?_.custom:V,M=+_.truncate>1&&_.truncate||!1,T=_.uric||!1,$=_.uricNoSlash||!1,O=_.mark||!1,F=!(_.symbols===!1||_.lang===!1),A=_.separator||A,T&&(Fe+=c),$&&(Fe+=u),O&&(Fe+=d),X=_.lang&&o[_.lang]&&F?o[_.lang]:F?o.en:{},se=_.lang&&a[_.lang]?a[_.lang]:_.lang===!1||_.lang===!0?{}:a.en,_.titleCase&&typeof _.titleCase.length=="number"&&Array.prototype.toString.call(_.titleCase)?(_.titleCase.forEach(function(ge){V[ge+""]=ge+""}),Z=!0):Z=!!_.titleCase,_.custom&&typeof _.custom.length=="number"&&Array.prototype.toString.call(_.custom)&&_.custom.forEach(function(ge){V[ge+""]=ge+""}),Object.keys(V).forEach(function(ge){var Ne;ge.length>1?Ne=new RegExp("\\b"+p(ge)+"\\b","gi"):Ne=new RegExp(p(ge),"gi"),y=y.replace(Ne,V[ge])});for(N in V)Fe+=N}for(Fe+=A,Fe=p(Fe),y=y.replace(/(^\s+|\s+$)/g,""),ae=!1,Ge=!1,K=0,J=y.length;K=0?(w+=N,N=""):Ge===!0?(N=i[w]+l[N],w=""):N=ae&&l[N].match(/[A-Za-z0-9]/)?" "+l[N]:l[N],ae=!1,Ge=!1):N in i?(w+=N,N="",K===J-1&&(N=i[w]),Ge=!0):X[N]&&!(T&&c.indexOf(N)!==-1)&&!($&&u.indexOf(N)!==-1)?(N=ae||m.substr(-1).match(/[A-Za-z0-9]/)?A+X[N]:X[N],N+=y[K+1]!==void 0&&y[K+1].match(/[A-Za-z0-9]/)?A:"",ae=!0):(Ge===!0?(N=i[w]+N,w="",Ge=!1):ae&&(/[A-Za-z0-9]/.test(N)||m.substr(-1).match(/A-Za-z0-9]/))&&(N=" "+N),ae=!1),m+=N.replace(new RegExp("[^\\w\\s"+Fe+"_-]","g"),A);return Z&&(m=m.replace(/(\w)(\S*)/g,function(ge,Ne,gt){var rt=Ne.toUpperCase()+(gt!==null?gt:"");return Object.keys(V).indexOf(rt.toLowerCase())<0?rt:rt.toLowerCase()})),m=m.replace(/\s+/g,A).replace(new RegExp("\\"+A+"+","g"),A).replace(new RegExp("(^\\"+A+"+|\\"+A+"+$)","g"),""),M&&m.length>M&&(he=m.charAt(M)===A,m=m.slice(0,M),he||(m=m.slice(0,m.lastIndexOf(A)))),!R&&!Z&&(m=m.toLowerCase()),m},h=function(y){return function(A){return f(A,y)}},p=function(y){return y.replace(/[-\\^$*+?.()|[\]{}\/]/g,"\\$&")},g=function(v,y){for(var _ in y)if(y[_]===v)return!0};if(typeof t<"u"&&t.exports)t.exports=f,t.exports.createSlug=h;else if(typeof define<"u"&&define.amd)define([],function(){return f});else try{if(n.getSlug||n.createSlug)throw"speakingurl: globals exists /(getSlug|createSlug)/";n.getSlug=f,n.createSlug=h}catch{}}(e)}}),cg=lf({"../../node_modules/.pnpm/speakingurl@14.0.1/node_modules/speakingurl/index.js"(e,t){L(),t.exports=sg()}});L();L();L();L();L();L();L();L();function ug(e){var t;const n=e.name||e._componentTag||e.__VUE_DEVTOOLS_COMPONENT_GUSSED_NAME__||e.__name;return n==="index"&&((t=e.__file)!=null&&t.endsWith("index.vue"))?"":n}function dg(e){const t=e.__file;if(t)return Km(qm(t,".vue"))}function Gs(e,t){return e.type.__VUE_DEVTOOLS_COMPONENT_GUSSED_NAME__=t,t}function li(e){if(e.__VUE_DEVTOOLS_NEXT_APP_RECORD__)return e.__VUE_DEVTOOLS_NEXT_APP_RECORD__;if(e.root)return e.appContext.app.__VUE_DEVTOOLS_NEXT_APP_RECORD__}async function fg(e){const{app:t,uid:n,instance:l}=e;try{if(l.__VUE_DEVTOOLS_NEXT_UID__)return l.__VUE_DEVTOOLS_NEXT_UID__;const r=await li(t);if(!r)return null;const i=r.rootInstance===l;return`${r.id}:${i?"root":n}`}catch{}}function rf(e){var t,n;const l=(t=e.subTree)==null?void 0:t.type,r=li(e);return r?((n=r==null?void 0:r.types)==null?void 0:n.Fragment)===l:!1}function ri(e){var t,n,l;const r=ug((e==null?void 0:e.type)||{});if(r)return r;if((e==null?void 0:e.root)===e)return"Root";for(const a in(n=(t=e.parent)==null?void 0:t.type)==null?void 0:n.components)if(e.parent.type.components[a]===(e==null?void 0:e.type))return Gs(e,a);for(const a in(l=e.appContext)==null?void 0:l.components)if(e.appContext.components[a]===(e==null?void 0:e.type))return Gs(e,a);const i=dg((e==null?void 0:e.type)||{});return i||"Anonymous Component"}function aa(e,t){return t=t||`${e.id}:root`,e.instanceMap.get(t)||e.instanceMap.get(":root")}function hg(){const e={top:0,bottom:0,left:0,right:0,get width(){return e.right-e.left},get height(){return e.bottom-e.top}};return e}var Br;function pg(e){return Br||(Br=document.createRange()),Br.selectNode(e),Br.getBoundingClientRect()}function vg(e){const t=hg();if(!e.children)return t;for(let n=0,l=e.children.length;ne.bottom)&&(e.bottom=t.bottom),(!e.left||t.lefte.right)&&(e.right=t.right),e}var Ks={top:0,left:0,right:0,bottom:0,width:0,height:0};function Dn(e){const t=e.subTree.el;return typeof window>"u"?Ks:rf(e)?vg(e.subTree):(t==null?void 0:t.nodeType)===1?t==null?void 0:t.getBoundingClientRect():e.subTree.component?Dn(e.subTree.component):Ks}L();function ao(e){return rf(e)?gg(e.subTree):e.subTree?[e.subTree.el]:[]}function gg(e){if(!e.children)return[];const t=[];return e.children.forEach(n=>{n.component?t.push(...ao(n.component)):n!=null&&n.el&&t.push(n.el)}),t}var af="__vue-devtools-component-inspector__",of="__vue-devtools-component-inspector__card__",sf="__vue-devtools-component-inspector__name__",cf="__vue-devtools-component-inspector__indicator__",uf={display:"block",zIndex:2147483640,position:"fixed",backgroundColor:"#42b88325",border:"1px solid #42b88350",borderRadius:"5px",transition:"all 0.1s ease-in",pointerEvents:"none"},Eg={fontFamily:"Arial, Helvetica, sans-serif",padding:"5px 8px",borderRadius:"4px",textAlign:"left",position:"absolute",left:0,color:"#e9e9e9",fontSize:"14px",fontWeight:600,lineHeight:"24px",backgroundColor:"#42b883",boxShadow:"0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1)"},_g={display:"inline-block",fontWeight:400,fontStyle:"normal",fontSize:"12px",opacity:.7};function dl(){return document.getElementById(af)}function bg(){return document.getElementById(of)}function yg(){return document.getElementById(cf)}function Ag(){return document.getElementById(sf)}function oo(e){return{left:`${Math.round(e.left*100)/100}px`,top:`${Math.round(e.top*100)/100}px`,width:`${Math.round(e.width*100)/100}px`,height:`${Math.round(e.height*100)/100}px`}}function so(e){var t;const n=document.createElement("div");n.id=(t=e.elementId)!=null?t:af,Object.assign(n.style,{...uf,...oo(e.bounds),...e.style});const l=document.createElement("span");l.id=of,Object.assign(l.style,{...Eg,top:e.bounds.top<35?0:"-35px"});const r=document.createElement("span");r.id=sf,r.innerHTML=`<${e.name}> `;const i=document.createElement("i");return i.id=cf,i.innerHTML=`${Math.round(e.bounds.width*100)/100} x ${Math.round(e.bounds.height*100)/100}`,Object.assign(i.style,_g),l.appendChild(r),l.appendChild(i),n.appendChild(l),document.body.appendChild(n),n}function co(e){const t=dl(),n=bg(),l=Ag(),r=yg();t&&(Object.assign(t.style,{...uf,...oo(e.bounds)}),Object.assign(n.style,{top:e.bounds.top<35?0:"-35px"}),l.innerHTML=`<${e.name}> `,r.innerHTML=`${Math.round(e.bounds.width*100)/100} x ${Math.round(e.bounds.height*100)/100}`)}function kg(e){const t=Dn(e);if(!t.width&&!t.height)return;const n=ri(e);dl()?co({bounds:t,name:n}):so({bounds:t,name:n})}function df(){const e=dl();e&&(e.style.display="none")}var oa=null;function sa(e){const t=e.target;if(t){const n=t.__vueParentComponent;if(n&&(oa=n,n.vnode.el)){const r=Dn(n),i=ri(n);dl()?co({bounds:r,name:i}):so({bounds:r,name:i})}}}function wg(e,t){var n;if(e.preventDefault(),e.stopPropagation(),oa){const l=(n=Ze.value)==null?void 0:n.app;fg({app:l,uid:l.uid,instance:oa}).then(r=>{t(r)})}}var zr=null;function Bg(){df(),window.removeEventListener("mouseover",sa),window.removeEventListener("click",zr,!0),zr=null}function Cg(){return window.addEventListener("mouseover",sa),new Promise(e=>{function t(n){n.preventDefault(),n.stopPropagation(),wg(n,l=>{window.removeEventListener("click",t,!0),zr=null,window.removeEventListener("mouseover",sa);const r=dl();r&&(r.style.display="none"),e(JSON.stringify({id:l}))})}zr=t,window.addEventListener("click",t,!0)})}function xg(e){const t=aa(Ze.value,e.id);if(t){const[n]=ao(t);if(typeof n.scrollIntoView=="function")n.scrollIntoView({behavior:"smooth"});else{const l=Dn(t),r=document.createElement("div"),i={...oo(l),position:"absolute"};Object.assign(r.style,i),document.body.appendChild(r),r.scrollIntoView({behavior:"smooth"}),setTimeout(()=>{document.body.removeChild(r)},2e3)}setTimeout(()=>{const l=Dn(t);if(l.width||l.height){const r=ri(t),i=dl();i?co({...e,name:r,bounds:l}):so({...e,name:r,bounds:l}),setTimeout(()=>{i&&(i.style.display="none")},1500)}},1200)}}L();var qs,Ws;(Ws=(qs=Y).__VUE_DEVTOOLS_COMPONENT_INSPECTOR_ENABLED__)!=null||(qs.__VUE_DEVTOOLS_COMPONENT_INSPECTOR_ENABLED__=!0);function Sg(e){let t=0;const n=setInterval(()=>{Y.__VUE_INSPECTOR__&&(clearInterval(n),t+=30,e()),t>=5e3&&clearInterval(n)},30)}function Tg(){const e=Y.__VUE_INSPECTOR__,t=e.openInEditor;e.openInEditor=async(...n)=>{e.disable(),t(...n)}}function Lg(){return new Promise(e=>{function t(){Tg(),e(Y.__VUE_INSPECTOR__)}Y.__VUE_INSPECTOR__?t():Sg(()=>{t()})})}L();L();function Og(e){return!!(e&&e.__v_isReadonly)}function ff(e){return Og(e)?ff(e.__v_raw):!!(e&&e.__v_isReactive)}function Fi(e){return!!(e&&e.__v_isRef===!0)}function bl(e){const t=e&&e.__v_raw;return t?bl(t):e}var Dg=class{constructor(){this.refEditor=new Pg}set(e,t,n,l){const r=Array.isArray(t)?t:t.split(".");for(;r.length>1;){const o=r.shift();e instanceof Map&&(e=e.get(o)),e instanceof Set?e=Array.from(e.values())[o]:e=e[o],this.refEditor.isRef(e)&&(e=this.refEditor.get(e))}const i=r[0],a=this.refEditor.get(e)[i];l?l(e,i,n):this.refEditor.isRef(a)?this.refEditor.set(a,n):e[i]=n}get(e,t){const n=Array.isArray(t)?t:t.split(".");for(let l=0;l"u")return!1;const l=Array.isArray(t)?t.slice():t.split("."),r=n?2:1;for(;e&&l.length>r;){const i=l.shift();e=e[i],this.refEditor.isRef(e)&&(e=this.refEditor.get(e))}return e!=null&&Object.prototype.hasOwnProperty.call(e,l[0])}createDefaultSetCallback(e){return(t,n,l)=>{if((e.remove||e.newKey)&&(Array.isArray(t)?t.splice(n,1):bl(t)instanceof Map?t.delete(n):bl(t)instanceof Set?t.delete(Array.from(t.values())[n]):Reflect.deleteProperty(t,n)),!e.remove){const r=t[e.newKey||n];this.refEditor.isRef(r)?this.refEditor.set(r,l):bl(t)instanceof Map?t.set(e.newKey||n,l):bl(t)instanceof Set?t.add(l):t[e.newKey||n]=l}}}},Pg=class{set(e,t){if(Fi(e))e.value=t;else{if(e instanceof Set&&Array.isArray(t)){e.clear(),t.forEach(r=>e.add(r));return}const n=Object.keys(t);if(e instanceof Map){const r=new Set(e.keys());n.forEach(i=>{e.set(i,Reflect.get(t,i)),r.delete(i)}),r.forEach(i=>e.delete(i));return}const l=new Set(Object.keys(e));n.forEach(r=>{Reflect.set(e,r,Reflect.get(t,r)),l.delete(r)}),l.forEach(r=>Reflect.deleteProperty(e,r))}}get(e){return Fi(e)?e.value:e}isRef(e){return Fi(e)||ff(e)}};L();L();L();var Ig="__VUE_DEVTOOLS_KIT_TIMELINE_LAYERS_STATE__";function Fg(){if(!Xd||typeof localStorage>"u"||localStorage===null)return{recordingState:!1,mouseEventEnabled:!1,keyboardEventEnabled:!1,componentEventEnabled:!1,performanceEventEnabled:!1,selected:""};const e=localStorage.getItem(Ig);return e?JSON.parse(e):{recordingState:!1,mouseEventEnabled:!1,keyboardEventEnabled:!1,componentEventEnabled:!1,performanceEventEnabled:!1,selected:""}}L();L();L();var Js,Ys;(Ys=(Js=Y).__VUE_DEVTOOLS_KIT_TIMELINE_LAYERS)!=null||(Js.__VUE_DEVTOOLS_KIT_TIMELINE_LAYERS=[]);var Rg=new Proxy(Y.__VUE_DEVTOOLS_KIT_TIMELINE_LAYERS,{get(e,t,n){return Reflect.get(e,t,n)}});function Mg(e,t){je.timelineLayersState[t.id]=!1,Rg.push({...e,descriptorId:t.id,appRecord:li(t.app)})}var Zs,Qs;(Qs=(Zs=Y).__VUE_DEVTOOLS_KIT_INSPECTOR__)!=null||(Zs.__VUE_DEVTOOLS_KIT_INSPECTOR__=[]);var uo=new Proxy(Y.__VUE_DEVTOOLS_KIT_INSPECTOR__,{get(e,t,n){return Reflect.get(e,t,n)}}),hf=rl(()=>{fl.hooks.callHook("sendInspectorToClient",pf())});function Vg(e,t){var n,l;uo.push({options:e,descriptor:t,treeFilterPlaceholder:(n=e.treeFilterPlaceholder)!=null?n:"Search tree...",stateFilterPlaceholder:(l=e.stateFilterPlaceholder)!=null?l:"Search state...",treeFilter:"",selectedNodeId:"",appRecord:li(t.app)}),hf()}function pf(){return uo.filter(e=>e.descriptor.app===Ze.value.app).filter(e=>e.descriptor.id!=="components").map(e=>{var t;const n=e.descriptor,l=e.options;return{id:l.id,label:l.label,logo:n.logo,icon:`custom-ic-baseline-${(t=l==null?void 0:l.icon)==null?void 0:t.replace(/_/g,"-")}`,packageName:n.packageName,homepage:n.homepage,pluginId:n.id}})}function Tr(e,t){return uo.find(n=>n.options.id===e&&(t?n.descriptor.app===t:!0))}function Ng(){const e=tf();e.hook("addInspector",({inspector:l,plugin:r})=>{Vg(l,r.descriptor)});const t=rl(async({inspectorId:l,plugin:r})=>{var i;if(!l||!((i=r==null?void 0:r.descriptor)!=null&&i.app)||je.highPerfModeEnabled)return;const a=Tr(l,r.descriptor.app),o={app:r.descriptor.app,inspectorId:l,filter:(a==null?void 0:a.treeFilter)||"",rootNodes:[]};await new Promise(c=>{e.callHookWith(async u=>{await Promise.all(u.map(d=>d(o))),c()},"getInspectorTree")}),e.callHookWith(async c=>{await Promise.all(c.map(u=>u({inspectorId:l,rootNodes:o.rootNodes})))},"sendInspectorTreeToClient")},120);e.hook("sendInspectorTree",t);const n=rl(async({inspectorId:l,plugin:r})=>{var i;if(!l||!((i=r==null?void 0:r.descriptor)!=null&&i.app)||je.highPerfModeEnabled)return;const a=Tr(l,r.descriptor.app),o={app:r.descriptor.app,inspectorId:l,nodeId:(a==null?void 0:a.selectedNodeId)||"",state:null},c={currentTab:`custom-inspector:${l}`};o.nodeId&&await new Promise(u=>{e.callHookWith(async d=>{await Promise.all(d.map(f=>f(o,c))),u()},"getInspectorState")}),e.callHookWith(async u=>{await Promise.all(u.map(d=>d({inspectorId:l,nodeId:o.nodeId,state:o.state})))},"sendInspectorStateToClient")},120);return e.hook("sendInspectorState",n),e.hook("customInspectorSelectNode",({inspectorId:l,nodeId:r,plugin:i})=>{const a=Tr(l,i.descriptor.app);a&&(a.selectedNodeId=r)}),e.hook("timelineLayerAdded",({options:l,plugin:r})=>{Mg(l,r.descriptor)}),e.hook("timelineEventAdded",({options:l,plugin:r})=>{var i;const a=["performance","component-event","keyboard","mouse"];je.highPerfModeEnabled||!((i=je.timelineLayersState)!=null&&i[r.descriptor.id])&&!a.includes(l.layerId)||e.callHookWith(async o=>{await Promise.all(o.map(c=>c(l)))},"sendTimelineEventToClient")}),e.hook("getComponentInstances",async({app:l})=>{const r=l.__VUE_DEVTOOLS_NEXT_APP_RECORD__;if(!r)return null;const i=r.id.toString();return[...r.instanceMap].filter(([o])=>o.split(":")[0]===i).map(([,o])=>o)}),e.hook("getComponentBounds",async({instance:l})=>Dn(l)),e.hook("getComponentName",({instance:l})=>ri(l)),e.hook("componentHighlight",({uid:l})=>{const r=Ze.value.instanceMap.get(l);r&&kg(r)}),e.hook("componentUnhighlight",()=>{df()}),e}var Xs,ec;(ec=(Xs=Y).__VUE_DEVTOOLS_KIT_APP_RECORDS__)!=null||(Xs.__VUE_DEVTOOLS_KIT_APP_RECORDS__=[]);var tc,nc;(nc=(tc=Y).__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD__)!=null||(tc.__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD__={});var lc,rc;(rc=(lc=Y).__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD_ID__)!=null||(lc.__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD_ID__="");var ic,ac;(ac=(ic=Y).__VUE_DEVTOOLS_KIT_CUSTOM_TABS__)!=null||(ic.__VUE_DEVTOOLS_KIT_CUSTOM_TABS__=[]);var oc,sc;(sc=(oc=Y).__VUE_DEVTOOLS_KIT_CUSTOM_COMMANDS__)!=null||(oc.__VUE_DEVTOOLS_KIT_CUSTOM_COMMANDS__=[]);var Cn="__VUE_DEVTOOLS_KIT_GLOBAL_STATE__";function jg(){return{connected:!1,clientConnected:!1,vitePluginDetected:!0,appRecords:[],activeAppRecordId:"",tabs:[],commands:[],highPerfModeEnabled:!0,devtoolsClientDetected:{},perfUniqueGroupId:0,timelineLayersState:Fg()}}var cc,uc;(uc=(cc=Y)[Cn])!=null||(cc[Cn]=jg());var Hg=rl(e=>{fl.hooks.callHook("devtoolsStateUpdated",{state:e})});rl((e,t)=>{fl.hooks.callHook("devtoolsConnectedUpdated",{state:e,oldState:t})});var ii=new Proxy(Y.__VUE_DEVTOOLS_KIT_APP_RECORDS__,{get(e,t,n){return t==="value"?Y.__VUE_DEVTOOLS_KIT_APP_RECORDS__:Y.__VUE_DEVTOOLS_KIT_APP_RECORDS__[t]}}),Ze=new Proxy(Y.__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD__,{get(e,t,n){return t==="value"?Y.__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD__:t==="id"?Y.__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD_ID__:Y.__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD__[t]}});function vf(){Hg({...Y[Cn],appRecords:ii.value,activeAppRecordId:Ze.id,tabs:Y.__VUE_DEVTOOLS_KIT_CUSTOM_TABS__,commands:Y.__VUE_DEVTOOLS_KIT_CUSTOM_COMMANDS__})}function zg(e){Y.__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD__=e,vf()}function $g(e){Y.__VUE_DEVTOOLS_KIT_ACTIVE_APP_RECORD_ID__=e,vf()}var je=new Proxy(Y[Cn],{get(e,t){return t==="appRecords"?ii:t==="activeAppRecordId"?Ze.id:t==="tabs"?Y.__VUE_DEVTOOLS_KIT_CUSTOM_TABS__:t==="commands"?Y.__VUE_DEVTOOLS_KIT_CUSTOM_COMMANDS__:Y[Cn][t]},deleteProperty(e,t){return delete e[t],!0},set(e,t,n){return{...Y[Cn]},e[t]=n,Y[Cn][t]=n,!0}});function Ug(e={}){var t,n,l;const{file:r,host:i,baseUrl:a=window.location.origin,line:o=0,column:c=0}=e;if(r){if(i==="chrome-extension"){const u=r.replace(/\\/g,"\\\\"),d=(n=(t=window.VUE_DEVTOOLS_CONFIG)==null?void 0:t.openInEditorHost)!=null?n:"/";fetch(`${d}__open-in-editor?file=${encodeURI(r)}`).then(f=>{if(!f.ok){const h=`Opening component ${u} failed`;console.log(`%c${h}`,"color:red")}})}else if(je.vitePluginDetected){const u=(l=Y.__VUE_DEVTOOLS_OPEN_IN_EDITOR_BASE_URL__)!=null?l:a;Y.__VUE_INSPECTOR__.openInEditor(u,r,o,c)}}}L();L();L();L();L();var dc,fc;(fc=(dc=Y).__VUE_DEVTOOLS_KIT_PLUGIN_BUFFER__)!=null||(dc.__VUE_DEVTOOLS_KIT_PLUGIN_BUFFER__=[]);var fo=new Proxy(Y.__VUE_DEVTOOLS_KIT_PLUGIN_BUFFER__,{get(e,t,n){return Reflect.get(e,t,n)}});function ca(e){const t={};return Object.keys(e).forEach(n=>{t[n]=e[n].defaultValue}),t}function ho(e){return`__VUE_DEVTOOLS_NEXT_PLUGIN_SETTINGS__${e}__`}function Gg(e){var t,n,l;const r=(n=(t=fo.find(i=>{var a;return i[0].id===e&&!!((a=i[0])!=null&&a.settings)}))==null?void 0:t[0])!=null?n:null;return(l=r==null?void 0:r.settings)!=null?l:null}function mf(e,t){var n,l,r;const i=ho(e);if(i){const a=localStorage.getItem(i);if(a)return JSON.parse(a)}if(e){const a=(l=(n=fo.find(o=>o[0].id===e))==null?void 0:n[0])!=null?l:null;return ca((r=a==null?void 0:a.settings)!=null?r:{})}return ca(t)}function Kg(e,t){const n=ho(e);localStorage.getItem(n)||localStorage.setItem(n,JSON.stringify(ca(t)))}function qg(e,t,n){const l=ho(e),r=localStorage.getItem(l),i=JSON.parse(r||"{}"),a={...i,[t]:n};localStorage.setItem(l,JSON.stringify(a)),fl.hooks.callHookWith(o=>{o.forEach(c=>c({pluginId:e,key:t,oldValue:i[t],newValue:n,settings:a}))},"setPluginSettings")}L();L();L();L();L();L();L();L();L();L();L();var hc,pc,ft=(pc=(hc=Y).__VUE_DEVTOOLS_HOOK)!=null?pc:hc.__VUE_DEVTOOLS_HOOK=tf(),Wg={vueAppInit(e){ft.hook("app:init",e)},vueAppUnmount(e){ft.hook("app:unmount",e)},vueAppConnected(e){ft.hook("app:connected",e)},componentAdded(e){return ft.hook("component:added",e)},componentEmit(e){return ft.hook("component:emit",e)},componentUpdated(e){return ft.hook("component:updated",e)},componentRemoved(e){return ft.hook("component:removed",e)},setupDevtoolsPlugin(e){ft.hook("devtools-plugin:setup",e)},perfStart(e){return ft.hook("perf:start",e)},perfEnd(e){return ft.hook("perf:end",e)}},Jg={on:Wg,setupDevToolsPlugin(e,t){return ft.callHook("devtools-plugin:setup",e,t)}},Yg=class{constructor({plugin:e,ctx:t}){this.hooks=t.hooks,this.plugin=e}get on(){return{visitComponentTree:e=>{this.hooks.hook("visitComponentTree",e)},inspectComponent:e=>{this.hooks.hook("inspectComponent",e)},editComponentState:e=>{this.hooks.hook("editComponentState",e)},getInspectorTree:e=>{this.hooks.hook("getInspectorTree",e)},getInspectorState:e=>{this.hooks.hook("getInspectorState",e)},editInspectorState:e=>{this.hooks.hook("editInspectorState",e)},inspectTimelineEvent:e=>{this.hooks.hook("inspectTimelineEvent",e)},timelineCleared:e=>{this.hooks.hook("timelineCleared",e)},setPluginSettings:e=>{this.hooks.hook("setPluginSettings",e)}}}notifyComponentUpdate(e){var t;if(je.highPerfModeEnabled)return;const n=pf().find(l=>l.packageName===this.plugin.descriptor.packageName);if(n!=null&&n.id){if(e){const l=[e.appContext.app,e.uid,(t=e.parent)==null?void 0:t.uid,e];ft.callHook("component:updated",...l)}else ft.callHook("component:updated");this.hooks.callHook("sendInspectorState",{inspectorId:n.id,plugin:this.plugin})}}addInspector(e){this.hooks.callHook("addInspector",{inspector:e,plugin:this.plugin}),this.plugin.descriptor.settings&&Kg(e.id,this.plugin.descriptor.settings)}sendInspectorTree(e){je.highPerfModeEnabled||this.hooks.callHook("sendInspectorTree",{inspectorId:e,plugin:this.plugin})}sendInspectorState(e){je.highPerfModeEnabled||this.hooks.callHook("sendInspectorState",{inspectorId:e,plugin:this.plugin})}selectInspectorNode(e,t){this.hooks.callHook("customInspectorSelectNode",{inspectorId:e,nodeId:t,plugin:this.plugin})}visitComponentTree(e){return this.hooks.callHook("visitComponentTree",e)}now(){return je.highPerfModeEnabled?0:Date.now()}addTimelineLayer(e){this.hooks.callHook("timelineLayerAdded",{options:e,plugin:this.plugin})}addTimelineEvent(e){je.highPerfModeEnabled||this.hooks.callHook("timelineEventAdded",{options:e,plugin:this.plugin})}getSettings(e){return mf(e??this.plugin.descriptor.id,this.plugin.descriptor.settings)}getComponentInstances(e){return this.hooks.callHook("getComponentInstances",{app:e})}getComponentBounds(e){return this.hooks.callHook("getComponentBounds",{instance:e})}getComponentName(e){return this.hooks.callHook("getComponentName",{instance:e})}highlightElement(e){const t=e.__VUE_DEVTOOLS_NEXT_UID__;return this.hooks.callHook("componentHighlight",{uid:t})}unhighlightElement(){return this.hooks.callHook("componentUnhighlight")}},Zg=Yg;L();L();L();L();var Qg="__vue_devtool_undefined__",Xg="__vue_devtool_infinity__",e4="__vue_devtool_negative_infinity__",t4="__vue_devtool_nan__";L();L();var n4={[Qg]:"undefined",[t4]:"NaN",[Xg]:"Infinity",[e4]:"-Infinity"};Object.entries(n4).reduce((e,[t,n])=>(e[n]=t,e),{});L();L();L();L();L();var vc,mc;(mc=(vc=Y).__VUE_DEVTOOLS_KIT__REGISTERED_PLUGIN_APPS__)!=null||(vc.__VUE_DEVTOOLS_KIT__REGISTERED_PLUGIN_APPS__=new Set);function l4(e,t){const[n,l]=e;if(n.app!==t)return;const r=new Zg({plugin:{setupFn:l,descriptor:n},ctx:fl});n.packageName==="vuex"&&r.on.editInspectorState(i=>{r.sendInspectorState(i.inspectorId)}),l(r)}function gf(e){Y.__VUE_DEVTOOLS_KIT__REGISTERED_PLUGIN_APPS__.has(e)||je.highPerfModeEnabled||(Y.__VUE_DEVTOOLS_KIT__REGISTERED_PLUGIN_APPS__.add(e),fo.forEach(t=>{l4(t,e)}))}L();L();var Hl="__VUE_DEVTOOLS_ROUTER__",il="__VUE_DEVTOOLS_ROUTER_INFO__",gc,Ec;(Ec=(gc=Y)[il])!=null||(gc[il]={currentRoute:null,routes:[]});var _c,bc;(bc=(_c=Y)[Hl])!=null||(_c[Hl]={});new Proxy(Y[il],{get(e,t){return Y[il][t]}});new Proxy(Y[Hl],{get(e,t){if(t==="value")return Y[Hl]}});function r4(e){const t=new Map;return((e==null?void 0:e.getRoutes())||[]).filter(n=>!t.has(n.path)&&t.set(n.path,1))}function po(e){return e.map(t=>{let{path:n,name:l,children:r,meta:i}=t;return r!=null&&r.length&&(r=po(r)),{path:n,name:l,children:r,meta:i}})}function i4(e){if(e){const{fullPath:t,hash:n,href:l,path:r,name:i,matched:a,params:o,query:c}=e;return{fullPath:t,hash:n,href:l,path:r,name:i,params:o,query:c,matched:po(a)}}return e}function a4(e,t){function n(){var l;const r=(l=e.app)==null?void 0:l.config.globalProperties.$router,i=i4(r==null?void 0:r.currentRoute.value),a=po(r4(r)),o=console.warn;console.warn=()=>{},Y[il]={currentRoute:i?Us(i):{},routes:Us(a)},Y[Hl]=r,console.warn=o}n(),Jg.on.componentUpdated(rl(()=>{var l;((l=t.value)==null?void 0:l.app)===e.app&&(n(),!je.highPerfModeEnabled&&fl.hooks.callHook("routerInfoUpdated",{state:Y[il]}))},200))}function o4(e){return{async getInspectorTree(t){const n={...t,app:Ze.value.app,rootNodes:[]};return await new Promise(l=>{e.callHookWith(async r=>{await Promise.all(r.map(i=>i(n))),l()},"getInspectorTree")}),n.rootNodes},async getInspectorState(t){const n={...t,app:Ze.value.app,state:null},l={currentTab:`custom-inspector:${t.inspectorId}`};return await new Promise(r=>{e.callHookWith(async i=>{await Promise.all(i.map(a=>a(n,l))),r()},"getInspectorState")}),n.state},editInspectorState(t){const n=new Dg,l={...t,app:Ze.value.app,set:(r,i=t.path,a=t.state.value,o)=>{n.set(r,i,a,o||n.createDefaultSetCallback(t.state))}};e.callHookWith(r=>{r.forEach(i=>i(l))},"editInspectorState")},sendInspectorState(t){const n=Tr(t);e.callHook("sendInspectorState",{inspectorId:t,plugin:{descriptor:n.descriptor,setupFn:()=>({})}})},inspectComponentInspector(){return Cg()},cancelInspectComponentInspector(){return Bg()},getComponentRenderCode(t){const n=aa(Ze.value,t);if(n)return(n==null?void 0:n.type)instanceof Function?n.type.toString():n.render.toString()},scrollToComponent(t){return xg({id:t})},openInEditor:Ug,getVueInspector:Lg,toggleApp(t){const n=ii.value.find(l=>l.id===t);n&&($g(t),zg(n),a4(n,Ze),hf(),gf(n.app))},inspectDOM(t){const n=aa(Ze.value,t);if(n){const[l]=ao(n);l&&(Y.__VUE_DEVTOOLS_INSPECT_DOM_TARGET__=l)}},updatePluginSettings(t,n,l){qg(t,n,l)},getPluginSettings(t){return{options:Gg(t),values:mf(t)}}}}L();var yc,Ac;(Ac=(yc=Y).__VUE_DEVTOOLS_ENV__)!=null||(yc.__VUE_DEVTOOLS_ENV__={vitePluginDetected:!1});var kc=Ng(),wc,Bc;(Bc=(wc=Y).__VUE_DEVTOOLS_KIT_CONTEXT__)!=null||(wc.__VUE_DEVTOOLS_KIT_CONTEXT__={hooks:kc,get state(){return{...je,activeAppRecordId:Ze.id,activeAppRecord:Ze.value,appRecords:ii.value}},api:o4(kc)});var fl=Y.__VUE_DEVTOOLS_KIT_CONTEXT__;L();og(cg());var Cc,xc;(xc=(Cc=Y).__VUE_DEVTOOLS_NEXT_APP_RECORD_INFO__)!=null||(Cc.__VUE_DEVTOOLS_NEXT_APP_RECORD_INFO__={id:0,appIds:new Set});L();function s4(e){je.highPerfModeEnabled=e??!je.highPerfModeEnabled,!e&&Ze.value&&gf(Ze.value.app)}L();L();L();function c4(e){je.devtoolsClientDetected={...je.devtoolsClientDetected,...e};const t=Object.values(je.devtoolsClientDetected).some(Boolean);s4(!t)}var Sc,Tc;(Tc=(Sc=Y).__VUE_DEVTOOLS_UPDATE_CLIENT_DETECTED__)!=null||(Sc.__VUE_DEVTOOLS_UPDATE_CLIENT_DETECTED__=c4);L();L();L();L();L();L();L();var u4=class{constructor(){this.keyToValue=new Map,this.valueToKey=new Map}set(e,t){this.keyToValue.set(e,t),this.valueToKey.set(t,e)}getByKey(e){return this.keyToValue.get(e)}getByValue(e){return this.valueToKey.get(e)}clear(){this.keyToValue.clear(),this.valueToKey.clear()}},Ef=class{constructor(e){this.generateIdentifier=e,this.kv=new u4}register(e,t){this.kv.getByValue(e)||(t||(t=this.generateIdentifier(e)),this.kv.set(t,e))}clear(){this.kv.clear()}getIdentifier(e){return this.kv.getByValue(e)}getValue(e){return this.kv.getByKey(e)}},d4=class extends Ef{constructor(){super(e=>e.name),this.classToAllowedProps=new Map}register(e,t){typeof t=="object"?(t.allowProps&&this.classToAllowedProps.set(e,t.allowProps),super.register(e,t.identifier)):super.register(e,t)}getAllowedProps(e){return this.classToAllowedProps.get(e)}};L();L();function f4(e){if("values"in Object)return Object.values(e);const t=[];for(const n in e)e.hasOwnProperty(n)&&t.push(e[n]);return t}function h4(e,t){const n=f4(e);if("find"in n)return n.find(t);const l=n;for(let r=0;rt(l,n))}function Lr(e,t){return e.indexOf(t)!==-1}function Lc(e,t){for(let n=0;nt.isApplicable(e))}findByName(e){return this.transfomers[e]}};L();L();var v4=e=>Object.prototype.toString.call(e).slice(8,-1),_f=e=>typeof e>"u",m4=e=>e===null,zl=e=>typeof e!="object"||e===null||e===Object.prototype?!1:Object.getPrototypeOf(e)===null?!0:Object.getPrototypeOf(e)===Object.prototype,ua=e=>zl(e)&&Object.keys(e).length===0,pn=e=>Array.isArray(e),g4=e=>typeof e=="string",E4=e=>typeof e=="number"&&!isNaN(e),_4=e=>typeof e=="boolean",b4=e=>e instanceof RegExp,$l=e=>e instanceof Map,Ul=e=>e instanceof Set,bf=e=>v4(e)==="Symbol",y4=e=>e instanceof Date&&!isNaN(e.valueOf()),A4=e=>e instanceof Error,Oc=e=>typeof e=="number"&&isNaN(e),k4=e=>_4(e)||m4(e)||_f(e)||E4(e)||g4(e)||bf(e),w4=e=>typeof e=="bigint",B4=e=>e===1/0||e===-1/0,C4=e=>ArrayBuffer.isView(e)&&!(e instanceof DataView),x4=e=>e instanceof URL;L();var yf=e=>e.replace(/\./g,"\\."),Ri=e=>e.map(String).map(yf).join("."),Dl=e=>{const t=[];let n="";for(let r=0;rnull,()=>{}),Nt(w4,"bigint",e=>e.toString(),e=>typeof BigInt<"u"?BigInt(e):(console.error("Please add a BigInt polyfill."),e)),Nt(y4,"Date",e=>e.toISOString(),e=>new Date(e)),Nt(A4,"Error",(e,t)=>{const n={name:e.name,message:e.message};return t.allowedErrorProps.forEach(l=>{n[l]=e[l]}),n},(e,t)=>{const n=new Error(e.message);return n.name=e.name,n.stack=e.stack,t.allowedErrorProps.forEach(l=>{n[l]=e[l]}),n}),Nt(b4,"regexp",e=>""+e,e=>{const t=e.slice(1,e.lastIndexOf("/")),n=e.slice(e.lastIndexOf("/")+1);return new RegExp(t,n)}),Nt(Ul,"set",e=>[...e.values()],e=>new Set(e)),Nt($l,"map",e=>[...e.entries()],e=>new Map(e)),Nt(e=>Oc(e)||B4(e),"number",e=>Oc(e)?"NaN":e>0?"Infinity":"-Infinity",Number),Nt(e=>e===0&&1/e===-1/0,"number",()=>"-0",Number),Nt(x4,"URL",e=>e.toString(),e=>new URL(e))];function ai(e,t,n,l){return{isApplicable:e,annotation:t,transform:n,untransform:l}}var kf=ai((e,t)=>bf(e)?!!t.symbolRegistry.getIdentifier(e):!1,(e,t)=>["symbol",t.symbolRegistry.getIdentifier(e)],e=>e.description,(e,t,n)=>{const l=n.symbolRegistry.getValue(t[1]);if(!l)throw new Error("Trying to deserialize unknown symbol");return l}),S4=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,Uint8ClampedArray].reduce((e,t)=>(e[t.name]=t,e),{}),wf=ai(C4,e=>["typed-array",e.constructor.name],e=>[...e],(e,t)=>{const n=S4[t[1]];if(!n)throw new Error("Trying to deserialize unknown typed array");return new n(e)});function Bf(e,t){return e!=null&&e.constructor?!!t.classRegistry.getIdentifier(e.constructor):!1}var Cf=ai(Bf,(e,t)=>["class",t.classRegistry.getIdentifier(e.constructor)],(e,t)=>{const n=t.classRegistry.getAllowedProps(e.constructor);if(!n)return{...e};const l={};return n.forEach(r=>{l[r]=e[r]}),l},(e,t,n)=>{const l=n.classRegistry.getValue(t[1]);if(!l)throw new Error("Trying to deserialize unknown class - check https://github.com/blitz-js/superjson/issues/116#issuecomment-773996564");return Object.assign(Object.create(l.prototype),e)}),xf=ai((e,t)=>!!t.customTransformerRegistry.findApplicable(e),(e,t)=>["custom",t.customTransformerRegistry.findApplicable(e).name],(e,t)=>t.customTransformerRegistry.findApplicable(e).serialize(e),(e,t,n)=>{const l=n.customTransformerRegistry.findByName(t[1]);if(!l)throw new Error("Trying to deserialize unknown custom value");return l.deserialize(e)}),T4=[Cf,kf,xf,wf],Dc=(e,t)=>{const n=Lc(T4,r=>r.isApplicable(e,t));if(n)return{value:n.transform(e,t),type:n.annotation(e,t)};const l=Lc(Af,r=>r.isApplicable(e,t));if(l)return{value:l.transform(e,t),type:l.annotation}},Sf={};Af.forEach(e=>{Sf[e.annotation]=e});var L4=(e,t,n)=>{if(pn(t))switch(t[0]){case"symbol":return kf.untransform(e,t,n);case"class":return Cf.untransform(e,t,n);case"custom":return xf.untransform(e,t,n);case"typed-array":return wf.untransform(e,t,n);default:throw new Error("Unknown transformation: "+t)}else{const l=Sf[t];if(!l)throw new Error("Unknown transformation: "+t);return l.untransform(e,n)}};L();var $n=(e,t)=>{const n=e.keys();for(;t>0;)n.next(),t--;return n.next().value};function Tf(e){if(Lr(e,"__proto__"))throw new Error("__proto__ is not allowed as a property");if(Lr(e,"prototype"))throw new Error("prototype is not allowed as a property");if(Lr(e,"constructor"))throw new Error("constructor is not allowed as a property")}var O4=(e,t)=>{Tf(t);for(let n=0;n{if(Tf(t),t.length===0)return n(e);let l=e;for(let i=0;ifa(i,t,[...n,...Dl(a)]));return}const[l,r]=e;r&&al(r,(i,a)=>{fa(i,t,[...n,...Dl(a)])}),t(l,n)}function D4(e,t,n){return fa(t,(l,r)=>{e=da(e,r,i=>L4(i,l,n))}),e}function P4(e,t){function n(l,r){const i=O4(e,Dl(r));l.map(Dl).forEach(a=>{e=da(e,a,()=>i)})}if(pn(t)){const[l,r]=t;l.forEach(i=>{e=da(e,Dl(i),()=>e)}),r&&al(r,n)}else al(t,n);return e}var I4=(e,t)=>zl(e)||pn(e)||$l(e)||Ul(e)||Bf(e,t);function F4(e,t,n){const l=n.get(e);l?l.push(t):n.set(e,[t])}function R4(e,t){const n={};let l;return e.forEach(r=>{if(r.length<=1)return;t||(r=r.map(o=>o.map(String)).sort((o,c)=>o.length-c.length));const[i,...a]=r;i.length===0?l=a.map(Ri):n[Ri(i)]=a.map(Ri)}),l?ua(n)?[l]:[l,n]:ua(n)?void 0:n}var Lf=(e,t,n,l,r=[],i=[],a=new Map)=>{var o;const c=k4(e);if(!c){F4(e,r,t);const g=a.get(e);if(g)return l?{transformedValue:null}:g}if(!I4(e,n)){const g=Dc(e,n),v=g?{transformedValue:g.value,annotations:[g.type]}:{transformedValue:e};return c||a.set(e,v),v}if(Lr(i,e))return{transformedValue:null};const u=Dc(e,n),d=(o=u==null?void 0:u.value)!=null?o:e,f=pn(d)?[]:{},h={};al(d,(g,v)=>{if(v==="__proto__"||v==="constructor"||v==="prototype")throw new Error(`Detected property ${v}. This is a prototype pollution risk, please remove it from your object.`);const y=Lf(g,t,n,l,[...r,v],[...i,e],a);f[v]=y.transformedValue,pn(y.annotations)?h[v]=y.annotations:zl(y.annotations)&&al(y.annotations,(_,A)=>{h[yf(v)+"."+A]=_})});const p=ua(h)?{transformedValue:f,annotations:u?[u.type]:void 0}:{transformedValue:f,annotations:u?[u.type,h]:h};return c||a.set(e,p),p};L();L();function Of(e){return Object.prototype.toString.call(e).slice(8,-1)}function Pc(e){return Of(e)==="Array"}function M4(e){if(Of(e)!=="Object")return!1;const t=Object.getPrototypeOf(e);return!!t&&t.constructor===Object&&t===Object.prototype}function V4(e,t,n,l,r){const i={}.propertyIsEnumerable.call(l,t)?"enumerable":"nonenumerable";i==="enumerable"&&(e[t]=n),r&&i==="nonenumerable"&&Object.defineProperty(e,t,{value:n,enumerable:!1,writable:!0,configurable:!0})}function ha(e,t={}){if(Pc(e))return e.map(r=>ha(r,t));if(!M4(e))return e;const n=Object.getOwnPropertyNames(e),l=Object.getOwnPropertySymbols(e);return[...n,...l].reduce((r,i)=>{if(Pc(t.props)&&!t.props.includes(i))return r;const a=e[i],o=ha(a,t);return V4(r,i,o,e,t.nonenumerable),r},{})}var Te=class{constructor({dedupe:e=!1}={}){this.classRegistry=new d4,this.symbolRegistry=new Ef(t=>{var n;return(n=t.description)!=null?n:""}),this.customTransformerRegistry=new p4,this.allowedErrorProps=[],this.dedupe=e}serialize(e){const t=new Map,n=Lf(e,t,this,this.dedupe),l={json:n.transformedValue};n.annotations&&(l.meta={...l.meta,values:n.annotations});const r=R4(t,this.dedupe);return r&&(l.meta={...l.meta,referentialEqualities:r}),l}deserialize(e){const{json:t,meta:n}=e;let l=ha(t);return n!=null&&n.values&&(l=D4(l,n.values,this)),n!=null&&n.referentialEqualities&&(l=P4(l,n.referentialEqualities)),l}stringify(e){return JSON.stringify(this.serialize(e))}parse(e){return this.deserialize(JSON.parse(e))}registerClass(e,t){this.classRegistry.register(e,t)}registerSymbol(e,t){this.symbolRegistry.register(e,t)}registerCustom(e,t){this.customTransformerRegistry.register({name:t,...e})}allowErrorProps(...e){this.allowedErrorProps.push(...e)}};Te.defaultInstance=new Te;Te.serialize=Te.defaultInstance.serialize.bind(Te.defaultInstance);Te.deserialize=Te.defaultInstance.deserialize.bind(Te.defaultInstance);Te.stringify=Te.defaultInstance.stringify.bind(Te.defaultInstance);Te.parse=Te.defaultInstance.parse.bind(Te.defaultInstance);Te.registerClass=Te.defaultInstance.registerClass.bind(Te.defaultInstance);Te.registerSymbol=Te.defaultInstance.registerSymbol.bind(Te.defaultInstance);Te.registerCustom=Te.defaultInstance.registerCustom.bind(Te.defaultInstance);Te.allowErrorProps=Te.defaultInstance.allowErrorProps.bind(Te.defaultInstance);L();L();L();L();L();L();L();L();L();L();L();L();L();L();L();L();L();L();L();L();L();L();L();var Ic,Fc;(Fc=(Ic=Y).__VUE_DEVTOOLS_KIT_MESSAGE_CHANNELS__)!=null||(Ic.__VUE_DEVTOOLS_KIT_MESSAGE_CHANNELS__=[]);var Rc,Mc;(Mc=(Rc=Y).__VUE_DEVTOOLS_KIT_RPC_CLIENT__)!=null||(Rc.__VUE_DEVTOOLS_KIT_RPC_CLIENT__=null);var Vc,Nc;(Nc=(Vc=Y).__VUE_DEVTOOLS_KIT_RPC_SERVER__)!=null||(Vc.__VUE_DEVTOOLS_KIT_RPC_SERVER__=null);var jc,Hc;(Hc=(jc=Y).__VUE_DEVTOOLS_KIT_VITE_RPC_CLIENT__)!=null||(jc.__VUE_DEVTOOLS_KIT_VITE_RPC_CLIENT__=null);var zc,$c;($c=(zc=Y).__VUE_DEVTOOLS_KIT_VITE_RPC_SERVER__)!=null||(zc.__VUE_DEVTOOLS_KIT_VITE_RPC_SERVER__=null);var Uc,Gc;(Gc=(Uc=Y).__VUE_DEVTOOLS_KIT_BROADCAST_RPC_SERVER__)!=null||(Uc.__VUE_DEVTOOLS_KIT_BROADCAST_RPC_SERVER__=null);L();L();L();L();L();L();L();const N4=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/wen-zhi-huai-83","Github":"https://github.com/Zephery","Gitee":"https://gitee.com/zephery.com.cn","BiliBili":"https://space.bilibili.com/3118581","WechatPay":"https://wenzhihuai.com/donate"}},"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":"带我回家"},"navbar":[{"text":"主页","icon":"home","link":"/"},{"text":"好玩的","icon":"interesting","link":"/interesting/"},{"text":"Java","icon":"java","link":"/java/"},{"text":"中间件","icon":"middleware","link":"/middleware/"},{"text":"数据库","icon":"database","link":"/database/"},{"text":"大数据","icon":"bigdata","link":"/bigdata/"},{"text":"Kubernetes","icon":"Kubernetes","link":"/kubernetes/"},{"text":"系统设计","icon":"system-design","link":"/system-design/"},{"text":"股票预测","icon":"stock","link":"/stock/"},{"text":"捐赠","icon":"donate","link":"/donate/"},{"text":"网站相关","icon":"about","children":[{"text":"关于作者","icon":"zuozhe","link":"/about-the-author/personal-life/wewe.md"},{"text":"友链","icon":"link","link":"/link/main.md"}]}],"sidebar":{"/":[{"text":"首页","icon":"home","collapsible":false,"children":"structure"}],"/interesting/":[{"text":"好玩的","icon":"interesting","collapsible":false,"children":"structure"}],"/java/":[{"text":"Java","icon":"java","collapsible":false,"children":"structure"}],"/database/":[{"text":"MySQL","prefix":"mysql/","icon":"mysql","collapsible":false,"children":"structure"},{"text":"Redis","prefix":"redis/","icon":"redis","collapsible":false,"children":"structure"},{"text":"Elasticsearch","prefix":"elasticsearch/","icon":"elasticsearch","collapsible":false,"children":"structure"},{"text":"MongoDB","prefix":"mongodb/","icon":"mongodb","collapsible":false,"children":"structure"}],"/link/":[{"text":"友链","icon":"link","link":"main","collapsible":false}],"/bigdata/":[{"text":"Spark","prefix":"spark/","icon":"bigdata","collapsible":false,"children":"structure"}],"/middleware/":[{"text":"Kafka","prefix":"kafka/","icon":"kafka","collapsible":false,"children":"structure"},{"text":"Zookeeper","prefix":"zookeeper/","icon":"zookeeper","collapsible":false,"children":"structure"},{"text":"Canal","prefix":"canal/","icon":"canal","collapsible":false,"children":"structure"}],"/kubernetes/":[{"text":"Kubernetes","icon":"kubernetes","collapsible":false,"children":"structure"}],"/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"}],"/stock/":[{"text":"股票预测","link":"README","icon":"README"}],"/system-design/":[{"text":"系统设计","icon":"system-design","collapsible":false,"children":"structure"}],"/donate/":[{"text":"微信支付","link":"README","icon":"README"}],"/life/":[{"text":"生活","icon":"life","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"]}}}}'),j4=ee(N4),Df=()=>j4,Pf=Symbol(""),H4=()=>{const e=Se(Pf);if(!e)throw new Error("useThemeLocaleData() is called without provider.");return e},z4=(e,t)=>{const{locales:n,...l}=e;return{...l,...n==null?void 0:n[t]}},$4=Bt({enhance({app:e}){const t=Df(),n=e._context.provides[Ja],l=k(()=>z4(t.value,n.routeLocale.value));e.provide(Pf,l),Object.defineProperties(e.config.globalProperties,{$theme:{get(){return t.value}},$themeLocale:{get(){return l.value}}})}}),U4=Object.freeze(Object.defineProperty({__proto__:null,default:$4},Symbol.toStringTag,{value:"Module"})),G4=/language-(shellscript|shell|bash|sh|zsh)/,K4=({delay:e=500,duration:t=2e3,locales:n,selector:l,showInMobile:r,ignoreSelector:i=[],transform:a})=>{const o=Qa("(max-width: 419px)"),c=k(()=>!o.value||r),u=Fn(n),d=Oe(),f=y=>{var A;if(y.hasAttribute("copy-code"))return;const _=document.createElement("button");_.type="button",_.classList.add("vp-copy-code-button"),_.setAttribute("aria-label",u.value.copy),_.setAttribute("data-copied",u.value.copied),(A=y.parentElement)==null||A.insertBefore(_,y),y.setAttribute("copy-code","")};pe(()=>[d.value.path,c.value],async()=>{document.body.classList.toggle("no-copy-code",!c.value),c.value&&(await Qt(),await no(e),document.querySelectorAll(l.join(",")).forEach(f))},{immediate:!0});const{copy:p}=Tv({legacy:!0}),g=new WeakMap,v=async(y,_,A)=>{const m=_.cloneNode(!0);i.length&&m.querySelectorAll(i.join(",")).forEach(V=>{V.remove()}),a&&a(m);let w=m.textContent||"";if(G4.test(y.className)&&(w=w.replace(/^ *(\$|>) /gm,"")),await p(w),t<=0)return;A.classList.add("copied"),clearTimeout(g.get(A));const F=setTimeout(()=>{A.classList.remove("copied"),A.blur(),g.delete(A)},t);g.set(A,F)};Ie("click",y=>{const _=y.target;if(c.value&&_.matches('div[class*="language-"] > button.vp-copy-code-button')){const A=_.parentElement,m=_.nextElementSibling;if(!A||!m)return;v(A,m,_)}})};var q4=[],W4={"/":{copy:"复制代码",copied:"已复制"}},J4=['[vp-content] div[class*="language-"] pre'];const Y4=Bt({setup:()=>{K4({selector:J4,ignoreSelector:q4,locales:W4,duration:2e3,delay:500,showInMobile:!1})}}),Z4=Object.freeze(Object.defineProperty({__proto__:null,default:Y4},Symbol.toStringTag,{value:"Module"})),Q4=(e,t)=>{const n=Fn(t),l=ve(),r=Oe(),i=k(()=>!!l.value.copy||l.value.copy!==!1&&e.global),a=k(()=>nr(l.value.copy)?l.value.copy:null),o=k(()=>{var v;return((v=a.value)==null?void 0:v.disableCopy)??e.disableCopy??!1}),c=k(()=>{var v;return i.value?((v=a.value)==null?void 0:v.disableSelection)??e.disableSelection??!1:!1}),u=k(()=>{var v;return i.value?((v=a.value)==null?void 0:v.maxLength)??e.maxLength??0:0}),d=k(()=>{var v;return((v=a.value)==null?void 0:v.triggerLength)??e.triggerLength??100}),f=v=>v?`${Zr(gn(v)?v:`https://${v}`)}${r.value.path}`:window.location.href,h=(v,y)=>{const{author:_,license:A,link:m}=n.value;return[v?_.replace(":author",v):"",y?A.replace(":license",y):"",m.replace(":link",f(e.canonical))].filter(w=>w).join(`
+`)},p=()=>{if(ke(r.value.copyright))return r.value.copyright.replace(":link",f());const{author:v,license:y}=r.value.copyright??{};return h(v??e.author,y??e.license)},g=v=>{const y=getSelection();if(y){const _=y.getRangeAt(0);if(i.value){const A=_.toString().length;if(o.value||u.value&&A>u.value){v.preventDefault();return}if(A>=d.value){v.preventDefault();const m=p(),w=document.createElement("div");w.appendChild(y.getRangeAt(0).cloneContents()),v.clipboardData&&(v.clipboardData.setData("text/html",`${w.innerHTML}${m.replace(/\\n/g," ")}
`),v.clipboardData.setData("text/plain",`${y.getRangeAt(0).cloneContents().textContent||""}
+------
+${m}`))}}}};we(()=>{const v=document.querySelector("#app");Ie(v,"copy",g),za(()=>{v.style.userSelect=c.value?"none":"auto"})})};var X4={"/":{author:"著作权归:author所有",license:"基于:license协议",link:"原文链接::link"}},e3={canonical:"https://wenzhihuai.com/",author:"wenzhihuai.com",license:"MIT",global:!0,disableCopy:!1,disableSelection:!1,triggerLength:100,maxLength:700},t3=Bt({setup:()=>{Q4(e3,X4)}});const n3=Object.freeze(Object.defineProperty({__proto__:null,default:t3},Symbol.toStringTag,{value:"Module"})),l3=Bt({setup(){Ie("beforeprint",()=>{document.querySelectorAll("details").forEach(e=>{e.open=!0})})}}),r3=Object.freeze(Object.defineProperty({__proto__:null,default:l3},Symbol.toStringTag,{value:"Module"})),i3=Object.freeze(Object.defineProperty({__proto__:null},Symbol.toStringTag,{value:"Module"}));let a3={};const If=Symbol(""),o3=()=>Se(If),s3=e=>{e.provide(If,a3)},c3=(async()=>{}).constructor,u3=(e,t,n)=>t==="js"?c3("myChart",`let width,height,option,__echarts_config__;
+{
+${e}
+__echarts_config__={width,height,option};
+}
+return __echarts_config__;
+`)(n):Promise.resolve({option:JSON.parse(e)});var d3=H({name:"ECharts",props:{config:{type:String,required:!0},id:{type:String,required:!0},title:{type:String,default:""},type:{type:String,default:"json"}},setup(e){const t=o3(),n=ee(!0),l=$e();let r;return Ie("resize",Nd(()=>r==null?void 0:r.resize(),100)),we(()=>{Promise.all([C(()=>import("./index-AN989yVn.js"),[]),no(800)]).then(async([i])=>{var c;await((c=t.setup)==null?void 0:c.call(t)),r=i.init(l.value);const{option:a,...o}=await u3(pm(e.config),e.type,r);r.resize(o),r.setOption({...t.option,...a}),n.value=!1})}),cl(()=>{r==null||r.dispose()}),()=>[e.title?s("div",{class:"echarts-title"},decodeURIComponent(e.title)):null,s("div",{class:"echarts-wrapper"},[s("div",{ref:l,class:"echarts-container",id:e.id}),n.value?s(to,{class:"echarts-loading",height:360}):null])]}});const f3={enhance:({app:e})=>{e.component("ECharts",d3),s3(e)}},h3=Object.freeze(Object.defineProperty({__proto__:null,default:f3},Symbol.toStringTag,{value:"Module"})),p3=ee({}),Ff=Symbol(""),v3=()=>Se(Ff),m3=e=>{e.provide(Ff,p3)},g3='',E3=e=>ke(e)?Array.from(document.querySelectorAll(e)):e.map(t=>Array.from(document.querySelectorAll(t))).flat(),Rf=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(Rf(e))},e.onerror=()=>{n()})}),_3=(e,{download:t=!0,fullscreen:n=!0}={})=>{e.on("uiRegister",()=>{if(e.ui.registerElement({name:"bulletsIndicator",className:"photo-swipe-bullets-indicator",appendTo:"wrapper",onInit:l=>{const r=[];let i=-1;for(let a=0;a{e.goTo(r.indexOf(c.target))},r.push(o),l.appendChild(o)}e.on("change",()=>{i>=0&&r[i].classList.remove("active"),r[e.currIndex].classList.add("active"),i=e.currIndex})}}),n){const{isSupported:l,toggle:r}=ti();l.value&&e.ui.registerElement({name:"fullscreen",order:7,isButton:!0,html:' ',onClick:()=>{r()}})}t&&e.ui.registerElement({name:"download",order:8,isButton:!0,tagName:"a",html:{isCustomSVG:!0,inner:' ',outlineID:"pswp__icn-download"},onInit:l=>{l.setAttribute("download",""),l.setAttribute("target","_blank"),l.setAttribute("rel","noopener"),e.on("change",()=>{l.setAttribute("href",e.currSlide.data.src)})}})})},b3=(e,{scrollToClose:t=!0,download:n=!0,fullscreen:l=!0,...r})=>C(async()=>{const{default:i}=await import("./photoswipe.esm-GXRgw7eJ.js");return{default:i}},[]).then(({default:i})=>{let a=null;const o=e.map(c=>({html:g3,element:c,msrc:c.src}));return e.forEach((c,u)=>{const d=()=>{a==null||a.destroy(),a=new i({preloaderDelay:0,showHideAnimationType:"zoom",...r,dataSource:o,index:u,...t?{closeOnVerticalDrag:!0,wheelToZoom:!1}:{}}),_3(a,{download:n,fullscreen:l}),a.addFilter("thumbEl",()=>c),a.addFilter("placeholderSrc",()=>c.src),a.init()};c.getAttribute("photo-swipe")||(c.style.cursor="zoom-in",c.addEventListener("click",()=>{d()}),c.addEventListener("keypress",({key:f})=>{f==="Enter"&&d()}),c.setAttribute("photo-swipe","")),Rf(c).then(f=>{o.splice(u,1,f),a==null||a.refreshSlideContent(u)})}),t?Ie("wheel",()=>{a==null||a.close()}):()=>{}}),y3=({selector:e,locales:t,delay:n=500,download:l=!0,fullscreen:r=!0,scrollToClose:i=!0})=>{const a=v3(),o=Fn(t),c=Oe(),u=ve();let d=null;const f=()=>{const{photoSwipe:h}=u.value;h!==!1&&Qt().then(()=>no(n)).then(async()=>{const p=ke(h)?h:e;d=await b3(E3(p),{...a.value,...o.value,download:l,fullscreen:r,scrollToClose:i})})};we(()=>{f(),pe(()=>[c.value.path,a.value],()=>{d==null||d(),f()})}),cl(()=>{d==null||d()})};var A3={"/":{closeTitle:"关闭",downloadTitle:"下载图片",fullscreenTitle:"切换全屏",zoomTitle:"缩放",arrowPrevTitle:"上一个 (左箭头)",arrowNextTitle:"下一个 (右箭头)"}};const k3="[vp-content] :not(a) > img:not([no-view])",w3=A3,B3=800,C3=!0,x3=!0,S3=!0;var T3=Bt({enhance:({app:e})=>{m3(e)},setup:()=>{y3({selector:k3,delay:B3,locales:w3,download:C3,fullscreen:x3,scrollToClose:S3})}});const L3=Object.freeze(Object.defineProperty({__proto__:null,default:T3},Symbol.toStringTag,{value:"Module"})),O3=e=>e instanceof Element?document.activeElement===e&&(["TEXTAREA","SELECT","INPUT"].includes(e.tagName)||e.hasAttribute("contenteditable")):!1,D3=(e,t)=>t.some(n=>{if(ke(n))return n===e.key;const{key:l,ctrl:r=!1,shift:i=!1,alt:a=!1}=n;return l===e.key&&r===e.ctrlKey&&i===e.shiftKey&&a===e.altKey}),P3=/[^\x00-\x7F]/,I3=e=>e.split(/\s+/g).map(t=>t.trim()).filter(t=>!!t),Kc=e=>e.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),qc=(e,t)=>{const n=t.join(" "),l=I3(e);if(P3.test(e))return l.some(a=>n.toLowerCase().indexOf(a)>-1);const r=e.endsWith(" ");return new RegExp(l.map((a,o)=>l.length===o+1&&!r?`(?=.*\\b${Kc(a)})`:`(?=.*\\b${Kc(a)}\\b)`).join("")+".+","gi").test(n)},F3=({input:e,hotKeys:t})=>{if(t.value.length===0)return;const n=l=>{e.value&&D3(l,t.value)&&!O3(l.target)&&(l.preventDefault(),e.value.focus())};we(()=>{document.addEventListener("keydown",n)}),Jr(()=>{document.removeEventListener("keydown",n)})},R3=[{title:"关于我",headers:[],path:"/about-the-author/",pathLocale:"/",extraFields:[]},{title:"Spark",headers:[],path:"/bigdata/",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/cloudnative/",pathLocale:"/",extraFields:[]},{title:"Database",headers:[],path:"/database/",pathLocale:"/",extraFields:[]},{title:"微信支付",headers:[],path:"/donate/",pathLocale:"/",extraFields:[]},{title:"好玩的",headers:[],path:"/interesting/",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:"/interesting/chatgpt.html",pathLocale:"/",extraFields:[]},{title:"Jetbrains Idea设置",headers:[{level:2,title:"一、类注释",slug:"一、类注释",link:"#一、类注释",children:[]},{level:2,title:"二、方法注释",slug:"二、方法注释",link:"#二、方法注释",children:[]},{level:2,title:"三、关闭Annotate With Git Blame",slug:"三、关闭annotate-with-git-blame",link:"#三、关闭annotate-with-git-blame",children:[]}],path:"/interesting/idea%E8%AE%BE%E7%BD%AE.html",pathLocale:"/",extraFields:[]},{title:"StarCraft Ⅱ 人工智能教程",headers:[],path:"/interesting/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:"/interesting/tesla.html",pathLocale:"/",extraFields:[]},{title:"一些不常用但很实用的命令",headers:[],path:"/interesting/%E4%B8%80%E4%BA%9B%E4%B8%8D%E5%B8%B8%E7%94%A8%E4%BD%86%E5%BE%88%E5%AE%9E%E7%94%A8%E7%9A%84%E5%91%BD%E4%BB%A4.html",pathLocale:"/",extraFields:[]},{title:"基于OLAP做业务监控",headers:[{level:2,title:"一、两者的比较",slug:"一、两者的比较",link:"#一、两者的比较",children:[]},{level:2,title:"二、为什么要用OLAP数据库来做监控",slug:"二、为什么要用olap数据库来做监控",link:"#二、为什么要用olap数据库来做监控",children:[]}],path:"/interesting/%E5%9F%BA%E4%BA%8EOLAP%E5%81%9A%E4%B8%9A%E5%8A%A1%E7%9B%91%E6%8E%A7.html",pathLocale:"/",extraFields:[]},{title:"小程序反编译",headers:[{level:3,title:"第一步:电脑端提取",slug:"第一步-电脑端提取",link:"#第一步-电脑端提取",children:[]},{level:3,title:"第二步:解密wxapkg包",slug:"第二步-解密wxapkg包",link:"#第二步-解密wxapkg包",children:[]},{level:3,title:"第三步:解包",slug:"第三步-解包",link:"#第三步-解包",children:[]}],path:"/interesting/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%8F%8D%E7%BC%96%E8%AF%91.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:"/interesting/%E5%B9%BF%E5%B7%9E%E5%9B%BE%E4%B9%A6%E9%A6%86%E5%80%9F%E9%98%85%E6%8A%93%E5%8F%96.html",pathLocale:"/",extraFields:[]},{title:"开发工具整理",headers:[{level:2,title:"ShadowsocksX",slug:"shadowsocksx",link:"#shadowsocksx",children:[]},{level:2,title:"IDEA激活",slug:"idea激活",link:"#idea激活",children:[]},{level:2,title:"",slug:"",link:"#",children:[]}],path:"/interesting/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E6%95%B4%E7%90%86.html",pathLocale:"/",extraFields:[]},{title:"程序员副业探索之电商",headers:[{level:2,title:"一、小程序化妆品",slug:"一、小程序化妆品",link:"#一、小程序化妆品",children:[{level:3,title:"1.1 小程序准备(营业执照&微信支付&小程序appId)",slug:"_1-1-小程序准备-营业执照-微信支付-小程序appid",link:"#_1-1-小程序准备-营业执照-微信支付-小程序appid",children:[]},{level:3,title:"1.2 小程序开发",slug:"_1-2-小程序开发",link:"#_1-2-小程序开发",children:[]}]},{level:2,title:"二、拼多多电商",slug:"二、拼多多电商",link:"#二、拼多多电商",children:[]},{level:2,title:"三、跨境电商",slug:"三、跨境电商",link:"#三、跨境电商",children:[]},{level:2,title:"四、总结",slug:"四、总结",link:"#四、总结",children:[]}],path:"/interesting/%E7%A8%8B%E5%BA%8F%E5%91%98%E5%89%AF%E4%B8%9A%E6%8E%A2%E7%B4%A2%E4%B9%8B%E7%94%B5%E5%95%86.html",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/interview/tiktok2023.html",pathLocale:"/",extraFields:[]},{title:"Java",headers:[],path:"/java/",pathLocale:"/",extraFields:[]},{title:"被挖矿攻击",headers:[],path:"/java/serverlog.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:"流程编排LiteFlow",headers:[{level:2,title:"背景",slug:"背景",link:"#背景",children:[]},{level:2,title:"一、为什么需要流程编排",slug:"一、为什么需要流程编排",link:"#一、为什么需要流程编排",children:[]},{level:2,title:"二、它可以解决什么问题",slug:"二、它可以解决什么问题",link:"#二、它可以解决什么问题",children:[]},{level:2,title:"三、LiteFlow改造之后",slug:"三、liteflow改造之后",link:"#三、liteflow改造之后",children:[]},{level:2,title:"总结",slug:"总结",link:"#总结",children:[]},{level:2,title:"文档&参考",slug:"文档-参考",link:"#文档-参考",children:[]}],path:"/java/%E6%B5%81%E7%A8%8B%E7%BC%96%E6%8E%92LiteFlow.html",pathLocale:"/",extraFields:[]},{title:"高可用",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:[]}],path:"/java/%E9%AB%98%E5%8F%AF%E7%94%A8.html",pathLocale:"/",extraFields:[]},{title:"高并发",headers:[{level:2,title:"负载均衡",slug:"负载均衡",link:"#负载均衡",children:[]},{level:2,title:"池化技术",slug:"池化技术",link:"#池化技术",children:[]},{level:2,title:"流量漏斗",slug:"流量漏斗",link:"#流量漏斗",children:[]}],path:"/java/%E9%AB%98%E5%B9%B6%E5%8F%91.html",pathLocale:"/",extraFields:[]},{title:"高性能",headers:[{level:2,title:"缓存",slug:"缓存",link:"#缓存",children:[]},{level:2,title:"异步",slug:"异步",link:"#异步",children:[]},{level:2,title:"I/O(网络、数据、文件)",slug:"i-o-网络、数据、文件",link:"#i-o-网络、数据、文件",children:[]},{level:2,title:"分库分表",slug:"分库分表",link:"#分库分表",children:[]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/java/%E9%AB%98%E6%80%A7%E8%83%BD.html",pathLocale:"/",extraFields:[]},{title:"高性能高并发高可用的一些思考",headers:[{level:2,title:"异步",slug:"异步",link:"#异步",children:[]},{level:2,title:"Jmeter",slug:"jmeter",link:"#jmeter",children:[]},{level:2,title:"JProfiler",slug:"jprofiler",link:"#jprofiler",children:[]},{level:2,title:"火焰图",slug:"火焰图",link:"#火焰图",children:[]},{level:2,title:"缓存",slug:"缓存",link:"#缓存",children:[]},{level:2,title:"限流熔断",slug:"限流熔断",link:"#限流熔断",children:[]},{level:2,title:"Kafka",slug:"kafka",link:"#kafka",children:[]},{level:2,title:"序列化",slug:"序列化",link:"#序列化",children:[]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/java/%E9%AB%98%E6%80%A7%E8%83%BD%E9%AB%98%E5%B9%B6%E5%8F%91%E9%AB%98%E5%8F%AF%E7%94%A8%E7%9A%84%E4%B8%80%E4%BA%9B%E6%80%9D%E8%80%83.html",pathLocale:"/",extraFields:[]},{title:"Jenkins的一些笔记",headers:[{level:2,title:"一、在全局安全配置中",slug:"一、在全局安全配置中",link:"#一、在全局安全配置中",children:[]},{level:2,title:"二、获取TOKEN",slug:"二、获取token",link:"#二、获取token",children:[]},{level:2,title:"三、获取Jenkins-Crumb",slug:"三、获取jenkins-crumb",link:"#三、获取jenkins-crumb",children:[]},{level:2,title:"四、值得注意的事",slug:"四、值得注意的事",link:"#四、值得注意的事",children:[]}],path:"/kubernetes/Jenkins%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AC%94%E8%AE%B0.html",pathLocale:"/",extraFields:[]},{title:"Kubernetes容器日志收集",headers:[{level:2,title:"日志采集方式",slug:"日志采集方式",link:"#日志采集方式",children:[]},{level:2,title:"一、原生方式",slug:"一、原生方式",link:"#一、原生方式",children:[{level:3,title:"1.1 控制台stdout方式",slug:"_1-1-控制台stdout方式",link:"#_1-1-控制台stdout方式",children:[]},{level:3,title:"1.2 新版本的subPathExpr",slug:"_1-2-新版本的subpathexpr",link:"#_1-2-新版本的subpathexpr",children:[]}]},{level:2,title:"二、Daemonset方式",slug:"二、daemonset方式",link:"#二、daemonset方式",children:[]},{level:2,title:"三、Sidecar模式",slug:"三、sidecar模式",link:"#三、sidecar模式",children:[]},{level:2,title:"四、总结",slug:"四、总结",link:"#四、总结",children:[]}],path:"/kubernetes/Kubernetes%E5%AE%B9%E5%99%A8%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86.html",pathLocale:"/",extraFields:[]},{title:"目录",headers:[],path:"/kubernetes/",pathLocale:"/",extraFields:[]},{title:"Kubernetes之request 和 limit详解",headers:[],path:"/kubernetes/request_limit.html",pathLocale:"/",extraFields:[]},{title:"spark on k8s operator",headers:[],path:"/kubernetes/spark%20on%20k8s%20operator.html",pathLocale:"/",extraFields:[]},{title:"2017",headers:[],path:"/life/2017.html",pathLocale:"/",extraFields:[]},{title:"2018",headers:[{level:2,title:"心惊胆战的裸辞经历",slug:"心惊胆战的裸辞经历",link:"#心惊胆战的裸辞经历",children:[]},{level:2,title:"工作工作",slug:"工作工作",link:"#工作工作",children:[]},{level:2,title:"跑步跑步",slug:"跑步跑步",link:"#跑步跑步",children:[]},{level:2,title:"Others",slug:"others",link:"#others",children:[]},{level:2,title:"2019",slug:"_2019",link:"#_2019",children:[]}],path:"/life/2018.html",pathLocale:"/",extraFields:[]},{title:"2019",headers:[{level:2,title:"工作",slug:"工作",link:"#工作",children:[]},{level:2,title:"学习",slug:"学习",link:"#学习",children:[]},{level:2,title:"感情",slug:"感情",link:"#感情",children:[]},{level:2,title:"运动",slug:"运动",link:"#运动",children:[]},{level:2,title:"其他",slug:"其他",link:"#其他",children:[]},{level:2,title:"2020展望",slug:"_2020展望",link:"#_2020展望",children:[]}],path:"/life/2019.html",pathLocale:"/",extraFields:[]},{title:"友链地址",headers:[],path:"/link/main.html",pathLocale:"/",extraFields:[]},{title:"中间件",headers:[],path:"/middleware/",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/open-source-project/",pathLocale:"/",extraFields:[]},{title:"股票预测",headers:[],path:"/stock/",pathLocale:"/",extraFields:[]},{title:"赛力斯",headers:[],path:"/stock/%E8%B5%9B%E5%8A%9B%E6%96%AF.html",pathLocale:"/",extraFields:[]},{title:"Feed系统设计",headers:[],path:"/system-design/feed.html",pathLocale:"/",extraFields:[]},{title:"2024-07-24",headers:[],path:"/about-the-author/personal-life/2024-07-24.html",pathLocale:"/",extraFields:[]},{title:"2024-11-09上海迪斯尼",headers:[],path:"/about-the-author/personal-life/2024-11-09%E4%B8%8A%E6%B5%B7%E8%BF%AA%E6%96%AF%E5%B0%BC.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:"一、es的分布式搜索过程",slug:"一、es的分布式搜索过程",link:"#一、es的分布式搜索过程",children:[{level:3,title:"1.1 搜索入口",slug:"_1-1-搜索入口",link:"#_1-1-搜索入口",children:[]}]},{level:2,title:"二、初步调用流程",slug:"二、初步调用流程",link:"#二、初步调用流程",children:[]},{level:2,title:"三、协调节点",slug:"三、协调节点",link:"#三、协调节点",children:[{level:3,title:"3.1 query阶段",slug:"_3-1-query阶段",link:"#_3-1-query阶段",children:[]},{level:3,title:"3.2 Fetch阶段",slug:"_3-2-fetch阶段",link:"#_3-2-fetch阶段",children:[]}]},{level:2,title:"四、数据节点",slug:"四、数据节点",link:"#四、数据节点",children:[{level:3,title:"4.1 执行query、fetch流程",slug:"_4-1-执行query、fetch流程",link:"#_4-1-执行query、fetch流程",children:[]}]},{level:2,title:"五、数据返回",slug:"五、数据返回",link:"#五、数据返回",children:[]},{level:2,title:"六、总结",slug:"六、总结",link:"#六、总结",children:[]},{level:2,title:"本文参考",slug:"本文参考",link:"#本文参考",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:"基础",headers:[{level:2,title:"一、ElasticSearch基础",slug:"一、elasticsearch基础",link:"#一、elasticsearch基础",children:[]},{level:2,title:"二、ES的写入流程",slug:"二、es的写入流程",link:"#二、es的写入流程",children:[]},{level:2,title:"三、ES的更新和删除流程",slug:"三、es的更新和删除流程",link:"#三、es的更新和删除流程",children:[]},{level:2,title:"四、ES的搜索流程",slug:"四、es的搜索流程",link:"#四、es的搜索流程",children:[]},{level:2,title:"五、ES在高并发下如何保证读写一致性?",slug:"五、es在高并发下如何保证读写一致性",link:"#五、es在高并发下如何保证读写一致性",children:[]},{level:2,title:"六、ES集群如何选举Master节点",slug:"六、es集群如何选举master节点",link:"#六、es集群如何选举master节点",children:[]},{level:2,title:"七、建立索引阶段性能提升方法",slug:"七、建立索引阶段性能提升方法",link:"#七、建立索引阶段性能提升方法",children:[]},{level:2,title:"八、ES的深度分页与滚动搜索scroll",slug:"八、es的深度分页与滚动搜索scroll",link:"#八、es的深度分页与滚动搜索scroll",children:[]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/database/elasticsearch/%E5%9F%BA%E7%A1%80.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:"行锁,表锁,意向锁",headers:[],path:"/database/mysql/%E8%A1%8C%E9%94%81%EF%BC%8C%E8%A1%A8%E9%94%81%EF%BC%8C%E6%84%8F%E5%90%91%E9%94%81.html",pathLocale:"/",extraFields:[]},{title:"RedissonLock分布式锁源码分析",headers:[{level:2,title:"一、实现分布式锁的要求",slug:"一、实现分布式锁的要求",link:"#一、实现分布式锁的要求",children:[]},{level:2,title:"二、Redis实现分布式锁的常用命令",slug:"二、redis实现分布式锁的常用命令",link:"#二、redis实现分布式锁的常用命令",children:[]},{level:2,title:"三、常见写法",slug:"三、常见写法",link:"#三、常见写法",children:[]},{level:2,title:"四、Redisson",slug:"四、redisson",link:"#四、redisson",children:[{level:3,title:"4.1 测试例子",slug:"_4-1-测试例子",link:"#_4-1-测试例子",children:[]}]},{level:2,title:"五、RedissonLock源码分析",slug:"五、redissonlock源码分析",link:"#五、redissonlock源码分析",children:[{level:3,title:"5.1 使用到的全局变量",slug:"_5-1-使用到的全局变量",link:"#_5-1-使用到的全局变量",children:[]},{level:3,title:"5.2 加锁",slug:"_5-2-加锁",link:"#_5-2-加锁",children:[]},{level:3,title:"5.3 解锁",slug:"_5-3-解锁",link:"#_5-3-解锁",children:[]}]},{level:2,title:"总结",slug:"总结",link:"#总结",children:[]}],path:"/database/redis/RedissonLock%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.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:"一致性hash算法和哈希槽",headers:[],path:"/database/redis/%E4%B8%80%E8%87%B4%E6%80%A7hash%E7%AE%97%E6%B3%95%E5%92%8C%E5%93%88%E5%B8%8C%E6%A7%BD.html",pathLocale:"/",extraFields:[]},{title:"mini主机",headers:[],path:"/interesting/mini%E4%B8%BB%E6%9C%BA/",pathLocale:"/",extraFields:[]},{title:"mac通过网线连接主机(fnOS)",headers:[{level:2,title:"一、mac端",slug:"一、mac端",link:"#一、mac端",children:[]},{level:2,title:"二、主机端",slug:"二、主机端",link:"#二、主机端",children:[]},{level:2,title:"三、最后",slug:"三、最后",link:"#三、最后",children:[]}],path:"/interesting/mini%E4%B8%BB%E6%9C%BA/mac%E8%BF%9E%E6%8E%A5%E4%B8%BB%E6%9C%BA.html",pathLocale:"/",extraFields:[]},{title:"买了个mini主机",headers:[{level:2,title:"一、系统的安装",slug:"一、系统的安装",link:"#一、系统的安装",children:[]},{level:2,title:"二、连接wifi",slug:"二、连接wifi",link:"#二、连接wifi",children:[{level:3,title:"步骤 1: 检查网络接口",slug:"步骤-1-检查网络接口",link:"#步骤-1-检查网络接口",children:[]},{level:3,title:"步骤 2: 启用 Wi-Fi 网卡",slug:"步骤-2-启用-wi-fi-网卡",link:"#步骤-2-启用-wi-fi-网卡",children:[]},{level:3,title:"步骤 3: 扫描可用的 Wi-Fi 网络",slug:"步骤-3-扫描可用的-wi-fi-网络",link:"#步骤-3-扫描可用的-wi-fi-网络",children:[]},{level:3,title:"步骤 4: 连接到 Wi-Fi 网络",slug:"步骤-4-连接到-wi-fi-网络",link:"#步骤-4-连接到-wi-fi-网络",children:[]},{level:3,title:"步骤 5: 验证连接状态",slug:"步骤-5-验证连接状态",link:"#步骤-5-验证连接状态",children:[]}]},{level:2,title:"三、VNC远程连接",slug:"三、vnc远程连接",link:"#三、vnc远程连接",children:[]},{level:2,title:"四、docker 配置",slug:"四、docker-配置",link:"#四、docker-配置",children:[]},{level:2,title:"五、文件共享",slug:"五、文件共享",link:"#五、文件共享",children:[]}],path:"/interesting/mini%E4%B8%BB%E6%9C%BA/%E4%B9%B0%E4%BA%86%E4%B8%AAmini%E4%B8%BB%E6%9C%BA.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:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html",pathLocale:"/",extraFields:[]},{title:"10.历时8年最终改版",headers:[{level:2,title:"一、博客的安装",slug:"一、博客的安装",link:"#一、博客的安装",children:[]},{level:2,title:"二、配置",slug:"二、配置",link:"#二、配置",children:[]},{level:2,title:"三、为文章增加评论",slug:"三、为文章增加评论",link:"#三、为文章增加评论",children:[]},{level:2,title:"四、博客的部署",slug:"四、博客的部署",link:"#四、博客的部署",children:[]},{level:2,title:"五、Github pages自定义域名",slug:"五、github-pages自定义域名",link:"#五、github-pages自定义域名",children:[]},{level:2,title:"六、Typora图床",slug:"六、typora图床",link:"#六、typora图床",children:[]},{level:2,title:"七、为自己的内容增加收入",slug:"七、为自己的内容增加收入",link:"#七、为自己的内容增加收入",children:[]},{level:2,title:"常见问题",slug:"常见问题",link:"#常见问题",children:[]}],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/10.%E5%8E%86%E6%97%B68%E5%B9%B4%E6%9C%80%E7%BB%88%E6%94%B9%E7%89%88.html",pathLocale:"/",extraFields:[]},{title:"2.Lucene的使用",headers:[{level:3,title:"Lucene的整体架构",slug:"lucene的整体架构",link:"#lucene的整体架构",children:[]},{level:3,title:"搜索引擎的几个重要概念:",slug:"搜索引擎的几个重要概念",link:"#搜索引擎的几个重要概念",children:[]},{level:3,title:"Lucene中的几个概念",slug:"lucene中的几个概念",link:"#lucene中的几个概念",children:[]},{level:3,title:"lucene在本网站的使用:",slug:"lucene在本网站的使用",link:"#lucene在本网站的使用",children:[]},{level:2,title:"一、搜索",slug:"一、搜索",link:"#一、搜索",children:[]},{level:2,title:"二、lucene自动补全",slug:"二、lucene自动补全",link:"#二、lucene自动补全",children:[]}],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html",pathLocale:"/",extraFields:[]},{title:"3.定时任务",headers:[{level:3,title:"一.特点:",slug:"一-特点",link:"#一-特点",children:[]},{level:3,title:"二.主要组成部分",slug:"二-主要组成部分",link:"#二-主要组成部分",children:[]},{level:3,title:"三、Quartz设计",slug:"三、quartz设计",link:"#三、quartz设计",children:[]},{level:3,title:"四、使用",slug:"四、使用",link:"#四、使用",children:[]},{level:2,title:"Spring的高级特性之定时任务",slug:"spring的高级特性之定时任务",link:"#spring的高级特性之定时任务",children:[]}],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html",pathLocale:"/",extraFields:[]},{title:"4.日志系统.md",headers:[{level:2,title:"1.网站代码安装",slug:"_1-网站代码安装",link:"#_1-网站代码安装",children:[]},{level:2,title:"2.根据API获取数据",slug:"_2-根据api获取数据",link:"#_2-根据api获取数据",children:[]},{level:2,title:"3.构建请求",slug:"_3-构建请求",link:"#_3-构建请求",children:[]},{level:2,title:"4.实际运用",slug:"_4-实际运用",link:"#_4-实际运用",children:[]},{level:2,title:"5.基本代码",slug:"_5-基本代码",link:"#_5-基本代码",children:[]},{level:2,title:"6.展示数据",slug:"_6-展示数据",link:"#_6-展示数据",children:[]}],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html",pathLocale:"/",extraFields:[]},{title:"5.小集群部署.md",headers:[{level:2,title:"1.1 Nginx的安装",slug:"_1-1-nginx的安装",link:"#_1-1-nginx的安装",children:[]},{level:2,title:"1.2 Nginx的配置",slug:"_1-2-nginx的配置",link:"#_1-2-nginx的配置",children:[]},{level:2,title:"测试:",slug:"测试",link:"#测试",children:[]}],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html",pathLocale:"/",extraFields:[]},{title:"6.数据库备份",headers:[{level:3,title:"2.1 创建所用的复制账号",slug:"_2-1-创建所用的复制账号",link:"#_2-1-创建所用的复制账号",children:[]},{level:3,title:"2.2 配置master",slug:"_2-2-配置master",link:"#_2-2-配置master",children:[]},{level:3,title:"2.3 配置slave",slug:"_2-3-配置slave",link:"#_2-3-配置slave",children:[]}],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html",pathLocale:"/",extraFields:[]},{title:"7.那些牛逼的插件",headers:[{level:2,title:"wowslider",slug:"wowslider",link:"#wowslider",children:[]},{level:2,title:"畅言",slug:"畅言",link:"#畅言",children:[]},{level:2,title:"Editor.md",slug:"editor-md",link:"#editor-md",children:[]},{level:2,title:"图表",slug:"图表",link:"#图表",children:[]},{level:2,title:"百度分享",slug:"百度分享",link:"#百度分享",children:[]},{level:2,title:"瀑布流",slug:"瀑布流",link:"#瀑布流",children:[]},{level:2,title:"天气插件",slug:"天气插件",link:"#天气插件",children:[]},{level:2,title:"标签云",slug:"标签云",link:"#标签云",children:[]}],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html",pathLocale:"/",extraFields:[]},{title:"8.基于贝叶斯的情感分析",headers:[],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/8.%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%9A%84%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90.html",pathLocale:"/",extraFields:[]},{title:"9.网站性能优化",headers:[],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html",pathLocale:"/",extraFields:[]},{title:"个人网站",headers:[],path:"/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/",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/JVM%E8%B0%83%E4%BC%98%E5%8F%82%E6%95%B0.html",pathLocale:"/",extraFields:[]},{title:"Java内存模型(JMM)",headers:[{level:2,title:"1 CPU和内存的交互",slug:"_1-cpu和内存的交互",link:"#_1-cpu和内存的交互",children:[{level:3,title:"1.1.1 内存屏障(Memory Barrier)",slug:"_1-1-1-内存屏障-memory-barrier",link:"#_1-1-1-内存屏障-memory-barrier",children:[]}]},{level:2,title:"2. Java内存区域",slug:"_2-java内存区域",link:"#_2-java内存区域",children:[{level:3,title:"2.1 五大内存区域",slug:"_2-1-五大内存区域",link:"#_2-1-五大内存区域",children:[]}]},{level:2,title:"3.内存溢出",slug:"_3-内存溢出",link:"#_3-内存溢出",children:[]},{level:2,title:"4.GC简介",slug:"_4-gc简介",link:"#_4-gc简介",children:[]},{level:2,title:"4.1.为什么需要学习GC",slug:"_4-1-为什么需要学习gc",link:"#_4-1-为什么需要学习gc",children:[]},{level:2,title:"4.2 堆的回收区域",slug:"_4-2-堆的回收区域",link:"#_4-2-堆的回收区域",children:[]},{level:2,title:"5 判断对象是否存活算法",slug:"_5-判断对象是否存活算法",link:"#_5-判断对象是否存活算法",children:[]},{level:2,title:"5 垃圾收集算法",slug:"_5-垃圾收集算法",link:"#_5-垃圾收集算法",children:[{level:3,title:"5.1 三大垃圾收集算法",slug:"_5-1-三大垃圾收集算法",link:"#_5-1-三大垃圾收集算法",children:[]},{level:3,title:"5.2 枚举根节点算法",slug:"_5-2-枚举根节点算法",link:"#_5-2-枚举根节点算法",children:[]}]},{level:2,title:"6.垃圾收集器",slug:"_6-垃圾收集器",link:"#_6-垃圾收集器",children:[{level:3,title:"新生代收集器",slug:"新生代收集器",link:"#新生代收集器",children:[]},{level:3,title:"6.1 Serial",slug:"_6-1-serial",link:"#_6-1-serial",children:[]},{level:3,title:"6.2 ParNew收集器",slug:"_6-2-parnew收集器",link:"#_6-2-parnew收集器",children:[]},{level:3,title:"6.3 Parallel Scavenge",slug:"_6-3-parallel-scavenge",link:"#_6-3-parallel-scavenge",children:[]},{level:3,title:"老年代收集器",slug:"老年代收集器",link:"#老年代收集器",children:[]}]},{level:2,title:"6.4 Serial Old",slug:"_6-4-serial-old",link:"#_6-4-serial-old",children:[]},{level:2,title:"6.5 Parallel Old",slug:"_6-5-parallel-old",link:"#_6-5-parallel-old",children:[{level:3,title:"6.6 CMS",slug:"_6-6-cms",link:"#_6-6-cms",children:[]},{level:3,title:"6.7 G1收集器",slug:"_6-7-g1收集器",link:"#_6-7-g1收集器",children:[]}]},{level:2,title:"7 Minor GC、Major GC、FULL GC、mixed gc",slug:"_7-minor-gc、major-gc、full-gc、mixed-gc",link:"#_7-minor-gc、major-gc、full-gc、mixed-gc",children:[{level:3,title:"7.1 Minor GC",slug:"_7-1-minor-gc",link:"#_7-1-minor-gc",children:[]},{level:3,title:"7.2 Major GC",slug:"_7-2-major-gc",link:"#_7-2-major-gc",children:[]},{level:3,title:"7.3 Full GC",slug:"_7-3-full-gc",link:"#_7-3-full-gc",children:[]},{level:3,title:"7.4 mixed GC【g1特有】",slug:"_7-4-mixed-gc【g1特有】",link:"#_7-4-mixed-gc【g1特有】",children:[]}]},{level:2,title:"8 查看GC日志",slug:"_8-查看gc日志",link:"#_8-查看gc日志",children:[{level:3,title:"8.3 自带的jconsole工具、jstat命令",slug:"_8-3-自带的jconsole工具、jstat命令",link:"#_8-3-自带的jconsole工具、jstat命令",children:[]}]},{level:2,title:"几个疑问",slug:"几个疑问",link:"#几个疑问",children:[{level:3,title:"1.GC是怎么判断对象是被标记的",slug:"_1-gc是怎么判断对象是被标记的",link:"#_1-gc是怎么判断对象是被标记的",children:[]},{level:3,title:"2.什么时候触发GC",slug:"_2-什么时候触发gc",link:"#_2-什么时候触发gc",children:[]},{level:3,title:"3.cms收集器是否会扫描年轻代",slug:"_3-cms收集器是否会扫描年轻代",link:"#_3-cms收集器是否会扫描年轻代",children:[]},{level:3,title:"4.什么是空间分配担保",slug:"_4-什么是空间分配担保",link:"#_4-什么是空间分配担保",children:[]},{level:3,title:"5.为什么复制算法要分两个Survivor,而不直接移到老年代",slug:"_5-为什么复制算法要分两个survivor-而不直接移到老年代",link:"#_5-为什么复制算法要分两个survivor-而不直接移到老年代",children:[]},{level:3,title:"6.各个版本的JVM使用的垃圾收集器是怎么样的",slug:"_6-各个版本的jvm使用的垃圾收集器是怎么样的",link:"#_6-各个版本的jvm使用的垃圾收集器是怎么样的",children:[]},{level:3,title:"7 stop the world具体是什么,有没有办法避免",slug:"_7-stop-the-world具体是什么-有没有办法避免",link:"#_7-stop-the-world具体是什么-有没有办法避免",children:[]},{level:3,title:"8 新生代什么样的情况会晋升为老年代",slug:"_8-新生代什么样的情况会晋升为老年代",link:"#_8-新生代什么样的情况会晋升为老年代",children:[]},{level:3,title:"8.怎么理解g1,适用于什么场景",slug:"_8-怎么理解g1-适用于什么场景",link:"#_8-怎么理解g1-适用于什么场景",children:[]}]},{level:2,title:"总结",slug:"总结",link:"#总结",children:[]}],path:"/java/JVM/Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B.html",pathLocale:"/",extraFields:[]},{title:"JVM",headers:[],path:"/java/JVM/",pathLocale:"/",extraFields:[]},{title:"CMS",headers:[],path:"/java/JVM/cms.html",pathLocale:"/",extraFields:[]},{title:"G1",headers:[{level:2,title:"G1的内存模型和分代策略",slug:"g1的内存模型和分代策略",link:"#g1的内存模型和分代策略",children:[{level:3,title:"G1收集器相关参数",slug:"g1收集器相关参数",link:"#g1收集器相关参数",children:[]},{level:3,title:"G1分区(Region)机制和分代策略",slug:"g1分区-region-机制和分代策略",link:"#g1分区-region-机制和分代策略",children:[]},{level:3,title:"G1 卡片(Card)标记机制",slug:"g1-卡片-card-标记机制",link:"#g1-卡片-card-标记机制",children:[]},{level:3,title:"G1 堆(Heap)空间调整机制",slug:"g1-堆-heap-空间调整机制",link:"#g1-堆-heap-空间调整机制",children:[]},{level:3,title:"本地分配缓冲 Local allocation buffer (Lab)",slug:"本地分配缓冲-local-allocation-buffer-lab",link:"#本地分配缓冲-local-allocation-buffer-lab",children:[]}]},{level:2,title:"Remember Set(RSet)和Collection Set(CSet)",slug:"remember-set-rset-和collection-set-cset",link:"#remember-set-rset-和collection-set-cset",children:[{level:3,title:"为什么需要RSet?",slug:"为什么需要rset",link:"#为什么需要rset",children:[]},{level:3,title:"RSet的实现机制",slug:"rset的实现机制",link:"#rset的实现机制",children:[]},{level:3,title:"Per Region Table(PRT)机制",slug:"per-region-table-prt-机制",link:"#per-region-table-prt-机制",children:[]},{level:3,title:"RSet记录的引用类型",slug:"rset记录的引用类型",link:"#rset记录的引用类型",children:[]},{level:3,title:"CSet(收集集合,Collection Set)",slug:"cset-收集集合-collection-set",link:"#cset-收集集合-collection-set",children:[]},{level:3,title:"RSet的维护",slug:"rset的维护",link:"#rset的维护",children:[]},{level:3,title:"屏障(Barrier)",slug:"屏障-barrier",link:"#屏障-barrier",children:[]},{level:3,title:"始快照算法(Snapshot at the Beginning,SATB)",slug:"始快照算法-snapshot-at-the-beginning-satb",link:"#始快照算法-snapshot-at-the-beginning-satb",children:[]},{level:3,title:"并发优化线程 (Concurrence Refinement Threads)",slug:"并发优化线程-concurrence-refinement-threads",link:"#并发优化线程-concurrence-refinement-threads",children:[]}]},{level:2,title:"G1的垃圾回收流程",slug:"g1的垃圾回收流程",link:"#g1的垃圾回收流程",children:[{level:3,title:"G1的GC模式",slug:"g1的gc模式",link:"#g1的gc模式",children:[]},{level:3,title:"GC 工作线程数(-XX:ParallelGCThreads)",slug:"gc-工作线程数-xx-parallelgcthreads",link:"#gc-工作线程数-xx-parallelgcthreads",children:[]},{level:3,title:"Young GC核心流程",slug:"young-gc核心流程",link:"#young-gc核心流程",children:[]},{level:3,title:"Mixed GC核心流程——混合收集周期(Mixed GC Cycle)",slug:"mixed-gc核心流程——混合收集周期-mixed-gc-cycle",link:"#mixed-gc核心流程——混合收集周期-mixed-gc-cycle",children:[]},{level:3,title:"并发标记周期 (Concurrent Marking Cycle)",slug:"并发标记周期-concurrent-marking-cycle",link:"#并发标记周期-concurrent-marking-cycle",children:[]},{level:3,title:"初始标记(Initial Mark,STW)",slug:"初始标记-initial-mark-stw",link:"#初始标记-initial-mark-stw",children:[]},{level:3,title:"并发标记(Concurrent Mark)",slug:"并发标记-concurrent-mark",link:"#并发标记-concurrent-mark",children:[]},{level:3,title:"最终标记(Final Mark)",slug:"最终标记-final-mark",link:"#最终标记-final-mark",children:[]},{level:3,title:"筛选回收(Clean Up)",slug:"筛选回收-clean-up",link:"#筛选回收-clean-up",children:[]},{level:3,title:"混合回收周期(Mixed GC Cycle)",slug:"混合回收周期-mixed-gc-cycle",link:"#混合回收周期-mixed-gc-cycle",children:[]},{level:3,title:"Young GC、Mixed GC 和 Full GC的触发时机",slug:"young-gc、mixed-gc-和-full-gc的触发时机",link:"#young-gc、mixed-gc-和-full-gc的触发时机",children:[]}]},{level:2,title:"JDK的G1垃圾回收器和CMS有什么区别",slug:"jdk的g1垃圾回收器和cms有什么区别",link:"#jdk的g1垃圾回收器和cms有什么区别",children:[]},{level:2,title:"总结",slug:"总结",link:"#总结",children:[]}],path:"/java/JVM/g1.html",pathLocale:"/",extraFields:[]},{title:"JVM(java虚拟机)",headers:[{level:2,title:"一、了解JVM",slug:"一、了解jvm",link:"#一、了解jvm",children:[]},{level:2,title:"二、运行时数据区",slug:"二、运行时数据区",link:"#二、运行时数据区",children:[]},{level:2,title:"三、类加载机制",slug:"三、类加载机制",link:"#三、类加载机制",children:[{level:3,title:"1、类的生命周期(7个)",slug:"_1、类的生命周期-7个",link:"#_1、类的生命周期-7个",children:[]},{level:3,title:"2、类加载的五个过程",slug:"_2、类加载的五个过程",link:"#_2、类加载的五个过程",children:[]},{level:3,title:"3、类加载器",slug:"_3、类加载器",link:"#_3、类加载器",children:[]},{level:3,title:"4、类加载机制(双亲委派)",slug:"_4、类加载机制-双亲委派",link:"#_4、类加载机制-双亲委派",children:[]}]},{level:2,title:"四、垃圾回收",slug:"四、垃圾回收",link:"#四、垃圾回收",children:[{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:3,title:"4、JVM内存分代机制",slug:"_4、jvm内存分代机制",link:"#_4、jvm内存分代机制",children:[]},{level:3,title:"5、Minor GC、Major GC、Full GC之间的区别",slug:"_5、minor-gc、major-gc、full-gc之间的区别",link:"#_5、minor-gc、major-gc、full-gc之间的区别",children:[]},{level:3,title:"6、Minor GC、Major GC、Full GC触发条件",slug:"_6、minor-gc、major-gc、full-gc触发条件",link:"#_6、minor-gc、major-gc、full-gc触发条件",children:[]}]}],path:"/java/JVM/jvm(java%E8%99%9A%E6%8B%9F%E6%9C%BA).html",pathLocale:"/",extraFields:[]},{title:"ZGC",headers:[{level:2,title:"1 内存多重映射",slug:"_1-内存多重映射",link:"#_1-内存多重映射",children:[]},{level:2,title:"2 染色指针",slug:"_2-染色指针",link:"#_2-染色指针",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:"3 内存布局",slug:"_3-内存布局",link:"#_3-内存布局",children:[]},{level:2,title:"4 读屏障",slug:"_4-读屏障",link:"#_4-读屏障",children:[]},{level:2,title:"5 GC 过程",slug:"_5-gc-过程",link:"#_5-gc-过程",children:[{level:3,title:"5.1 初始标记",slug:"_5-1-初始标记",link:"#_5-1-初始标记",children:[]},{level:3,title:"5.2 并发标记",slug:"_5-2-并发标记",link:"#_5-2-并发标记",children:[]},{level:3,title:"5.3 再标记",slug:"_5-3-再标记",link:"#_5-3-再标记",children:[]},{level:3,title:"5.4 初始转移",slug:"_5-4-初始转移",link:"#_5-4-初始转移",children:[]},{level:3,title:"5.5 并发转移",slug:"_5-5-并发转移",link:"#_5-5-并发转移",children:[]},{level:3,title:"5.6 重定位",slug:"_5-6-重定位",link:"#_5-6-重定位",children:[]}]},{level:2,title:"6 垃圾收集算法",slug:"_6-垃圾收集算法",link:"#_6-垃圾收集算法",children:[{level:3,title:"6.1 JDK 16 之前",slug:"_6-1-jdk-16-之前",link:"#_6-1-jdk-16-之前",children:[]},{level:3,title:"6.2 JDK 16 改进",slug:"_6-2-jdk-16-改进",link:"#_6-2-jdk-16-改进",children:[]}]},{level:2,title:"7 总结",slug:"_7-总结",link:"#_7-总结",children:[]}],path:"/java/JVM/zgc.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/JVM/%E4%B8%80%E6%AC%A1jvm%E8%B0%83%E4%BC%98%E8%BF%87%E7%A8%8B.html",pathLocale:"/",extraFields:[]},{title:"主流GC收集器采用的算法",headers:[{level:2,title:"是否可以使用两种或多种垃圾回收器",slug:"是否可以使用两种或多种垃圾回收器",link:"#是否可以使用两种或多种垃圾回收器",children:[]},{level:2,title:"查看java进程用的是哪种垃圾回收器",slug:"查看java进程用的是哪种垃圾回收器",link:"#查看java进程用的是哪种垃圾回收器",children:[]},{level:2,title:"怎么查看java进程eden、survivor等各个区的内存占用",slug:"怎么查看java进程eden、survivor等各个区的内存占用",link:"#怎么查看java进程eden、survivor等各个区的内存占用",children:[]},{level:2,title:"参考:",slug:"参考",link:"#参考",children:[]}],path:"/java/JVM/%E5%B8%B8%E7%94%A8GC%E5%9B%9E%E6%94%B6%E5%99%A8.html",pathLocale:"/",extraFields:[]},{title:"引用计数和根可达算法",headers:[{level:3,title:"硬件角度来看什么叫做垃圾?",slug:"硬件角度来看什么叫做垃圾",link:"#硬件角度来看什么叫做垃圾",children:[]},{level:3,title:"Java中的垃圾",slug:"java中的垃圾",link:"#java中的垃圾",children:[]},{level:2,title:"如何寻找垃圾?",slug:"如何寻找垃圾",link:"#如何寻找垃圾",children:[{level:3,title:"引用计数(Reference Count)",slug:"引用计数-reference-count",link:"#引用计数-reference-count",children:[]},{level:3,title:"根可达算法(Root Search)",slug:"根可达算法-root-search",link:"#根可达算法-root-search",children:[]},{level:3,title:"哪些是GC Root?",slug:"哪些是gc-root",link:"#哪些是gc-root",children:[]},{level:3,title:"线程栈 (Thread Stacks)",slug:"线程栈-thread-stacks",link:"#线程栈-thread-stacks",children:[]},{level:3,title:"静态变量 (Static Variables)",slug:"静态变量-static-variables",link:"#静态变量-static-variables",children:[]},{level:3,title:"常量池 (Constant Pool)",slug:"常量池-constant-pool",link:"#常量池-constant-pool",children:[]},{level:3,title:"JNI 引用 (JNI References)",slug:"jni-引用-jni-references",link:"#jni-引用-jni-references",children:[]},{level:3,title:"根可达算法原理",slug:"根可达算法原理",link:"#根可达算法原理",children:[]}]},{level:2,title:"总结",slug:"总结",link:"#总结",children:[]}],path:"/java/JVM/%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0%E5%92%8C%E6%A0%B9%E5%8F%AF%E8%BE%BE%E7%AE%97%E6%B3%95.html",pathLocale:"/",extraFields:[]},{title:"JVM调优思路",headers:[{level:2,title:"一、监控发现问题",slug:"一、监控发现问题",link:"#一、监控发现问题",children:[]},{level:2,title:"二、工具分析问题",slug:"二、工具分析问题",link:"#二、工具分析问题",children:[]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/java/JVM/%E8%B0%83%E4%BC%98%E6%80%9D%E8%B7%AF.html",pathLocale:"/",extraFields:[]},{title:"SpringBoot",headers:[],path:"/java/SpringBoot/",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:"I/O",headers:[],path:"/java/io/",pathLocale:"/",extraFields:[]},{title:"JAVA NIO",headers:[{level:2,title:"一、简介",slug:"一、简介",link:"#一、简介",children:[{level:3,title:"1.1典型的多路复用IO实现",slug:"_1-1典型的多路复用io实现",link:"#_1-1典型的多路复用io实现",children:[]}]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/java/io/nio.html",pathLocale:"/",extraFields:[]},{title:"线程",headers:[],path:"/java/%E7%BA%BF%E7%A8%8B/",pathLocale:"/",extraFields:[]},{title:"synchronized",headers:[{level:2,title:"一、什么是synchronized",slug:"一、什么是synchronized",link:"#一、什么是synchronized",children:[]},{level:2,title:"二、Synchronized 原理",slug:"二、synchronized-原理",link:"#二、synchronized-原理",children:[]},{level:2,title:"三、Synchronized 优化",slug:"三、synchronized-优化",link:"#三、synchronized-优化",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:2,title:"四、扩展",slug:"四、扩展",link:"#四、扩展",children:[{level:3,title:"4.1 Synchronized 和 ReenTrantLock 的对比",slug:"_4-1-synchronized-和-reentrantlock-的对比",link:"#_4-1-synchronized-和-reentrantlock-的对比",children:[]},{level:3,title:"4.2 Synchronized 与 ThreadLocal 的对比",slug:"_4-2-synchronized-与-threadlocal-的对比",link:"#_4-2-synchronized-与-threadlocal-的对比",children:[]},{level:3,title:"4.3 synchronized与volatile区别",slug:"_4-3-synchronized与volatile区别",link:"#_4-3-synchronized与volatile区别",children:[]}]},{level:2,title:"五、各种锁",slug:"五、各种锁",link:"#五、各种锁",children:[]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/java/%E7%BA%BF%E7%A8%8B/synchronized.html",pathLocale:"/",extraFields:[]},{title:"volatile",headers:[{level:2,title:"可见性",slug:"可见性",link:"#可见性",children:[]},{level:2,title:"有序性",slug:"有序性",link:"#有序性",children:[]}],path:"/java/%E7%BA%BF%E7%A8%8B/volatile.html",pathLocale:"/",extraFields:[]},{title:"TCP/IP、HTTP、HTTPS、HTTP2.0",headers:[{level:2,title:"一、TCP/IP",slug:"一、tcp-ip",link:"#一、tcp-ip",children:[]},{level:2,title:"二、HTTP",slug:"二、http",link:"#二、http",children:[{level:3,title:"2.1 HTTP报文分析",slug:"_2-1-http报文分析",link:"#_2-1-http报文分析",children:[]},{level:3,title:"2.2 HTTP特性",slug:"_2-2-http特性",link:"#_2-2-http特性",children:[]},{level:3,title:"2.3 影响HTTP的因素",slug:"_2-3-影响http的因素",link:"#_2-3-影响http的因素",children:[]}]},{level:2,title:"三、HTTPS",slug:"三、https",link:"#三、https",children:[{level:3,title:"3.1 SSL/TLS",slug:"_3-1-ssl-tls",link:"#_3-1-ssl-tls",children:[]},{level:3,title:"3.2 SPDY",slug:"_3-2-spdy",link:"#_3-2-spdy",children:[]},{level:3,title:"3.3 HTTPS报文分析",slug:"_3-3-https报文分析",link:"#_3-3-https报文分析",children:[]},{level:3,title:"3.4 HTTPS全站化",slug:"_3-4-https全站化",link:"#_3-4-https全站化",children:[]}]},{level:2,title:"四、HTTP2.0",slug:"四、http2-0",link:"#四、http2-0",children:[{level:3,title:"4.1 历史",slug:"_4-1-历史",link:"#_4-1-历史",children:[]},{level:3,title:"4.2 HTTP2.0新特性",slug:"_4-2-http2-0新特性",link:"#_4-2-http2-0新特性",children:[]},{level:3,title:"4.3 HTTP1.1与HTTP2.0的对比",slug:"_4-3-http1-1与http2-0的对比",link:"#_4-3-http1-1与http2-0的对比",children:[]},{level:3,title:"4.4 报文",slug:"_4-4-报文",link:"#_4-4-报文",children:[]}]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/java/%E7%BD%91%E7%BB%9C/IP%E3%80%81HTTP%E3%80%81HTTPS%E3%80%81HTTP2.0.html",pathLocale:"/",extraFields:[]},{title:"网络",headers:[],path:"/java/%E7%BD%91%E7%BB%9C/",pathLocale:"/",extraFields:[]},{title:"DevOps",headers:[],path:"/kubernetes/devops/",pathLocale:"/",extraFields:[]},{title:"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:"/kubernetes/devops/devops-ping-tai.html",pathLocale:"/",extraFields:[]},{title:"canal小记",headers:[{level:2,title:"问题一:测试环境一切正常,但是正式环境中,这几个字段全为0,不知道为什么",slug:"问题一-测试环境一切正常-但是正式环境中-这几个字段全为0-不知道为什么",link:"#问题一-测试环境一切正常-但是正式环境中-这几个字段全为0-不知道为什么",children:[]},{level:2,title:"问题二:canal.properties中四种模式的差别",slug:"问题二-canal-properties中四种模式的差别",link:"#问题二-canal-properties中四种模式的差别",children:[]},{level:2,title:"问题三:如果要订阅的是mysql的从库改怎么做?",slug:"问题三-如果要订阅的是mysql的从库改怎么做",link:"#问题三-如果要订阅的是mysql的从库改怎么做",children:[]},{level:2,title:"问题四:部分字段没有更新",slug:"问题四-部分字段没有更新",link:"#问题四-部分字段没有更新",children:[]}],path:"/middleware/canal/%E4%B8%AD%E9%97%B4%E4%BB%B6%E2%80%94%E2%80%94canal%E5%B0%8F%E8%AE%B0.html",pathLocale:"/",extraFields:[]},{title:"kafka面试题",headers:[],path:"/middleware/kafka/kafka.html",pathLocale:"/",extraFields:[]},{title:"Spring Cloud Sentinel",headers:[{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/middleware/sentinel/springcloud_sentinel.html",pathLocale:"/",extraFields:[]},{title:"入门使用",headers:[{level:2,title:"参考",slug:"参考",link:"#参考",children:[]}],path:"/middleware/sentinel/%E5%85%A5%E9%97%A8%E4%BD%BF%E7%94%A8.html",pathLocale:"/",extraFields:[]},{title:"Zookeeper",headers:[],path:"/middleware/zookeeper/zookeeper.html",pathLocale:"/",extraFields:[]},{title:"基于ZooKeeper的队列爬虫",headers:[{level:2,title:"一、整体架构",slug:"一、整体架构",link:"#一、整体架构",children:[]},{level:2,title:"二、ZooKeeper队列原理",slug:"二、zookeeper队列原理",link:"#二、zookeeper队列原理",children:[{level:3,title:"2.1 介绍",slug:"_2-1-介绍",link:"#_2-1-介绍",children:[]},{level:3,title:"2.2 Watcher介绍",slug:"_2-2-watcher介绍",link:"#_2-2-watcher介绍",children:[]},{level:3,title:"2.3 源码",slug:"_2-3-源码",link:"#_2-3-源码",children:[]}]},{level:2,title:"三、多线程并发",slug:"三、多线程并发",link:"#三、多线程并发",children:[]},{level:2,title:"四、使用",slug:"四、使用",link:"#四、使用",children:[{level:3,title:"实验结果",slug:"实验结果",link:"#实验结果",children:[]},{level:3,title:"实验二",slug:"实验二",link:"#实验二",children:[]}]},{level:2,title:"总结",slug:"总结",link:"#总结",children:[]}],path:"/middleware/zookeeper/%E5%9F%BA%E4%BA%8EZooKeeper%E7%9A%84%E9%98%9F%E5%88%97%E7%88%AC%E8%99%AB.html",pathLocale:"/",extraFields:[]},{title:"推荐工程-概述",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:[]}],path:"/system-design/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/%E6%8E%A8%E8%8D%90%E5%B7%A5%E7%A8%8B-%E6%A6%82%E8%BF%B0.html",pathLocale:"/",extraFields:[]},{title:"推荐系统入门",headers:[{level:2,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:3,title:"2.3、推荐系统应用场景",slug:"_2-3、推荐系统应用场景",link:"#_2-3、推荐系统应用场景",children:[]},{level:3,title:"2.4、搜索、推荐、广告三者的异同",slug:"_2-4、搜索、推荐、广告三者的异同",link:"#_2-4、搜索、推荐、广告三者的异同",children:[]}]},{level:2,title:"三、推荐系统通用框架",slug:"三、推荐系统通用框架",link:"#三、推荐系统通用框架",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、Item-CF 的算法流程",slug:"_4-3、item-cf-的算法流程",link:"#_4-3、item-cf-的算法流程",children:[]}]},{level:2,title:"五、如何实现推荐系统",slug:"五、如何实现推荐系统",link:"#五、如何实现推荐系统",children:[{level:3,title:"5.1、选择数据集",slug:"_5-1、选择数据集",link:"#_5-1、选择数据集",children:[]},{level:3,title:"5.2、读取原始数据",slug:"_5-2、读取原始数据",link:"#_5-2、读取原始数据",children:[]},{level:3,title:"5.3、构造物品的相似度矩阵",slug:"_5-3、构造物品的相似度矩阵",link:"#_5-3、构造物品的相似度矩阵",children:[]},{level:3,title:"5.4、基于相似度矩阵推荐物品",slug:"_5-4、基于相似度矩阵推荐物品",link:"#_5-4、基于相似度矩阵推荐物品",children:[]},{level:3,title:"5.5、调用推荐系统",slug:"_5-5、调用推荐系统",link:"#_5-5、调用推荐系统",children:[]}]},{level:2,title:"六、问题与展望",slug:"六、问题与展望",link:"#六、问题与展望",children:[]}],path:"/system-design/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F%E5%85%A5%E9%97%A8.html",pathLocale:"/",extraFields:[]},{title:"计算广告基本概念入门总结",headers:[],path:"/system-design/%E8%AE%A1%E7%AE%97%E5%B9%BF%E5%91%8A/%E8%AE%A1%E7%AE%97%E5%B9%BF%E5%91%8A%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%E5%85%A5%E9%97%A8%E6%80%BB%E7%BB%93.html",pathLocale:"/",extraFields:[]},{title:"",headers:[],path:"/404.html",pathLocale:"/",extraFields:[]},{title:"Interview",headers:[],path:"/interview/",pathLocale:"/",extraFields:[]},{title:"Life",headers:[],path:"/life/",pathLocale:"/",extraFields:[]},{title:"Link",headers:[],path:"/link/",pathLocale:"/",extraFields:[]},{title:"System Design",headers:[],path:"/system-design/",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:"Elasticsearch",headers:[],path:"/database/elasticsearch/",pathLocale:"/",extraFields:[]},{title:"Mysql",headers:[],path:"/database/mysql/",pathLocale:"/",extraFields:[]},{title:"Redis",headers:[],path:"/database/redis/",pathLocale:"/",extraFields:[]},{title:"Canal",headers:[],path:"/middleware/canal/",pathLocale:"/",extraFields:[]},{title:"Kafka",headers:[],path:"/middleware/kafka/",pathLocale:"/",extraFields:[]},{title:"Sentinel",headers:[],path:"/middleware/sentinel/",pathLocale:"/",extraFields:[]},{title:"Zookeeper",headers:[],path:"/middleware/zookeeper/",pathLocale:"/",extraFields:[]},{title:"推荐系统",headers:[],path:"/system-design/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/",pathLocale:"/",extraFields:[]},{title:"计算广告",headers:[],path:"/system-design/%E8%AE%A1%E7%AE%97%E5%B9%BF%E5%91%8A/",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:[]},{title:"",headers:[],path:"/slide/",pathLocale:"/",extraFields:[]}],M3=ee(R3),V3=()=>M3,N3=({searchIndex:e,routeLocale:t,query:n,maxSuggestions:l})=>{const r=k(()=>e.value.filter(i=>i.pathLocale===t.value));return k(()=>{const i=n.value.trim().toLowerCase();if(!i)return[];const a=[],o=(c,u)=>{qc(i,[u.title])&&a.push({link:`${c.path}#${u.slug}`,title:c.title,header:u.title});for(const d of u.children){if(a.length>=l.value)return;o(c,d)}};for(const c of r.value){if(a.length>=l.value)break;if(qc(i,[c.title,...c.extraFields])){a.push({link:c.path,title:c.title});continue}for(const u of c.headers){if(a.length>=l.value)break;o(c,u)}}return a})},j3=e=>{const t=ee(0);return{focusIndex:t,focusNext:()=>{t.value{t.value>0?t.value-=1:t.value=e.value.length-1}}},H3=H({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:l}=zp(e),r=en(),i=Mt(),a=V3(),o=ee(null),c=ee(!1),u=ee(""),d=k(()=>t.value[i.value]??{}),f=N3({searchIndex:a,routeLocale:i,query:u,maxSuggestions:l}),{focusIndex:h,focusNext:p,focusPrev:g}=j3(f);F3({input:o,hotKeys:n});const v=k(()=>c.value&&!!f.value.length),y=()=>{v.value&&g()},_=()=>{v.value&&p()},A=m=>{if(!v.value)return;const w=f.value[m];w&&r.push(w.link).then(()=>{u.value="",h.value=0})};return()=>s("form",{class:"search-box",role:"search"},[s("input",{ref:o,type:"search",placeholder:d.value.placeholder,autocomplete:"off",spellcheck:!1,value:u.value,onFocus:()=>c.value=!0,onBlur:()=>c.value=!1,onInput:m=>u.value=m.target.value,onKeydown:m=>{switch(m.key){case"ArrowUp":{y();break}case"ArrowDown":{_();break}case"Enter":{m.preventDefault(),A(h.value);break}}}}),v.value&&s("ul",{class:"suggestions",onMouseleave:()=>h.value=-1},f.value.map(({link:m,title:w,header:F},V)=>s("li",{class:["suggestion",{focus:h.value===V}],onMouseenter:()=>h.value=V,onMousedown:()=>A(V)},s("a",{href:m,onClick:R=>R.preventDefault()},[s("span",{class:"page-title"},w),F&&s("span",{class:"page-header"},`> ${F}`)]))))])}});var z3=["s","/"],$3={"/":{placeholder:"搜索"}};const U3=$3,G3=z3,K3=10,q3=Bt({enhance({app:e}){e.component("SearchBox",t=>s(H3,{locales:U3,hotKeys:G3,maxSuggestions:K3,...t}))}}),W3=Object.freeze(Object.defineProperty({__proto__:null,default:q3},Symbol.toStringTag,{value:"Module"})),Mf="VUEPRESS_REDIRECT_STATUS",Wc=Vv(Mf,{}),Jc=Hv(Mf,{}),J3=e=>{const t=Nv(),n=Mt(),l=En(e.config);return k(()=>{if(l.some(([r])=>n.value===r)){for(const r of t.value)for(const[i,a]of l)if(a.includes(r))return i===n.value?null:{lang:r,localePath:i}}return null})};var Y3=H({name:"RedirectModal",props:{config:{type:Object,required:!0},locales:{type:Object,required:!0}},setup(e){const t=en(),n=Pd(),l=Mt(),r=J3(e.config),i=ee(),a=eo(i),o=ee(!1),c=k(()=>{if(!r.value)return null;const{lang:d,localePath:f}=r.value,h=[e.locales[f],e.locales[l.value]];return{hint:h.map(({hint:p})=>p.replace("$1",d)),switch:h.map(({switch:p})=>p.replace("$1",d)).join(" / "),cancel:h.map(({cancel:p})=>p).join(" / "),remember:h.map(({remember:p})=>p).join(" / ")}}),u=()=>{Jc.value[l.value]=!0,o.value&&(Wc.value[l.value]=!0),a.value=!1};return pe(n,()=>{a.value=!1}),we(async()=>{i.value=document.body,await Qt(),r.value&&!Jc.value[l.value]&&!Wc.value[l.value]&&(a.value=!0)}),Jr(()=>{a.value=!1}),()=>s(gd,{name:"redirect-modal-fade"},()=>{var d,f,h,p;return a.value?s("div",{key:"mask",class:"redirect-modal-mask"},s("div",{key:"popup",class:"redirect-modal-wrapper"},[s("div",{class:"redirect-modal-content"},(d=c.value)==null?void 0:d.hint.map(g=>s("p",g))),s("div",{class:"redirect-modal-hint"},[s("input",{id:"remember-redirect",type:"checkbox",value:o.value,onChange:()=>{o.value=!o.value}}),s("label",{for:"remember-redirect"},(f=c.value)==null?void 0:f.remember)]),s("button",{type:"button",class:"redirect-modal-action primary",onClick:()=>{u(),t.replace(n.value.replace(l.value,r.value.localePath))}},(h=c.value)==null?void 0:h.switch),s("button",{type:"button",class:"redirect-modal-action",onClick:()=>{u()}},(p=c.value)==null?void 0:p.cancel)])):null})}}),Z3={config:{},autoLocale:!1,localeFallback:!0,defaultBehavior:"defaultLocale"},Q3={"/":{name:"简体中文",hint:"您的首选语言是 $1,是否切换到该语言?",switch:"切换到 $1",cancel:"取消",remember:"记住我的选择"}};const Vf=Z3;var X3=Bt({setup(){},rootComponents:[()=>s(Y3,{config:Vf,locales:Q3})]});const e8=Object.freeze(Object.defineProperty({__proto__:null,config:Vf,default:X3},Symbol.toStringTag,{value:"Module"})),qe=e=>{const{icon:t="",color:n,size:l}=e,r=n||l?{}:null;return n&&(r.color=n),l&&(r.height=Number.isNaN(Number(l))?l:`${l}px`),gn(t)?s("img",{class:"icon",src:t,alt:"","no-view":"",style:r}):ni(t)?s("img",{class:"icon",src:Ae(t),alt:"","aria-hidden":"","no-view":"",style:r}):s(kt("FontIcon"),e)};qe.displayName="HopeIcon";const Nf=()=>{const e=ce();return k(()=>e.value.author)},t8="http://.",Rn=()=>{const e=en(),t=Ut();return n=>{if(n)if(ni(n))t.path!==n&&e.push(n);else if(tr(n))window&&window.open(n);else{const l=t.path.slice(0,t.path.lastIndexOf("/"));e.push(new URL(`${l}/${encodeURI(n)}`,t8).pathname)}}};var Yc={"/":{word:"约 $word 字",less1Minute:"小于 1 分钟",time:"大约 $time 分钟"}};const jf=()=>{const e=Oe();return k(()=>e.value.readingTime??null)},Hf=(e,t)=>{const{minutes:n,words:l}=e,{less1Minute:r,word:i,time:a}=t;return{time:n<1?r:a.replace("$time",Math.round(n).toString()),words:i.replace("$word",l.toString())}},Zc={words:"",time:""},pa=typeof Yc>"u"?null:Yc,zf=()=>pa?Fn(pa):k(()=>null),n8=()=>{if(typeof pa>"u")return k(()=>Zc);const e=jf(),t=zf();return k(()=>e.value&&t.value?Hf(e.value,t.value):Zc)},me=({name:e="",color:t="currentColor",ariaLabel:n},{attrs:l,slots:r})=>{var i;return s("svg",{xmlns:"http://www.w3.org/2000/svg",class:["icon",`${e}-icon`],viewBox:"0 0 1024 1024",fill:t,"aria-label":n??`${e} icon`,...l},(i=r.default)==null?void 0:i.call(r))};me.displayName="IconBase";const vo=(e,{slots:t})=>{var n;return(n=t.default)==null?void 0:n.call(t)},l8=e=>gn(e)?e:`https://github.com/${e}`,mo=(e="")=>!gn(e)||e.includes("github.com")?"GitHub":e.includes("bitbucket.org")?"Bitbucket":e.includes("gitlab.com")?"GitLab":e.includes("gitee.com")?"Gitee":null,$f=()=>s(me,{name:"github"},()=>s("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"}));$f.displayName="GitHubIcon";const Uf=()=>s(me,{name:"gitee"},()=>s("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"}));Uf.displayName="GiteeIcon";const Gf=()=>s(me,{name:"bitbucket"},()=>s("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"}));Gf.displayName="BitbucketIcon";const Kf=()=>s(me,{name:"source"},()=>s("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"}));Kf.displayName="SourceIcon";const qf=({link:e,type:t=mo(e??"")})=>{if(!t)return null;const n=t.toLowerCase();return s(n==="bitbucket"?Gf:n==="github"?$f:n==="gitlab"?"GitLab":n==="gitee"?Uf:Kf)},r8=(e,t=0)=>{let n=3735928559^t,l=1103547991^t;for(let r=0,i;r>>16,2246822507),n^=Math.imul(l^l>>>13,3266489909),l=Math.imul(l^l>>>16,2246822507),l^=Math.imul(n^n>>>13,3266489909),4294967296*(2097151&l)+(n>>>0)},sr=(e,t)=>r8(e)%t;class i8{constructor(){ui(this,"containerElement");ui(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 l=document.createElement("div"),r=Date.now();return l.className="message move-in",l.innerHTML=t,this.containerElement.appendChild(l),this.messageElements[r]=l,n>0&&setTimeout(()=>{this.close(r)},n),r}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 hn(this.messageElements).forEach(n=>this.close(Number(n)))}destroy(){document.body.removeChild(this.containerElement)}}const Wf=/#.*$/u,a8=e=>{const t=Wf.exec(e);return t?t[0]:""},Qc=e=>decodeURI(e).replace(Wf,"").replace(/\/index\.html$/iu,"/").replace(/\/(README|index)\.md$/iu,"/").replace(/\.(?:html|md)$/iu,""),Jf=(e,t)=>{if(!Jd(t))return!1;const n=Qc(e.path),l=Qc(t),r=a8(t);return r?r===e.hash&&(!l||n===l):n===l};var o8=e=>Object.prototype.toString.call(e)==="[object Object]",Gl=e=>typeof e=="string";const{isArray:Yf}=Array,Xc=e=>o8(e)&&Gl(e.name),Kl=(e,t=!1)=>e?Yf(e)?e.map(n=>Gl(n)?{name:n}:Xc(n)?n:null).filter(n=>n!==null):Gl(e)?[{name:e}]:Xc(e)?[e]:(console.error(`Expect "author" to be \`AuthorInfo[] | AuthorInfo | string[] | string ${t?"":"| false"} | undefined\`, but got`,e),[]):[],Zf=(e,t)=>{if(e){if(Yf(e)&&e.every(Gl))return e;if(Gl(e))return[e];console.error(`Expect ${t} to be \`string[] | string | undefined\`, but got`,e)}return[]},Qf=e=>Zf(e,"category"),Xf=e=>Zf(e,"tag"),tn=()=>Df(),ce=()=>H4(),eh=()=>{const e=ve(),t=Nf();return k(()=>{const{author:n}=e.value;return n?Kl(n):n===!1?[]:Kl(t.value,!1)})},s8=()=>{const e=ve(),t=Se(Symbol.for("categoryMap"));return k(()=>Qf(e.value.category??e.value.categories).map(n=>{var l;return{name:n,path:((l=t==null?void 0:t.value.map[n])==null?void 0:l.path)??""}}))},c8=()=>{const e=ve(),t=Se(Symbol.for("tagMap"));return k(()=>Xf(e.value.tag??e.value.tags).map(n=>{var l;return{name:n,path:((l=t==null?void 0:t.value.map[n])==null?void 0:l.path)??""}}))},u8=()=>{const e=ve(),t=Oe();return k(()=>{const n=lo(e.value.date);if(n)return n;const{createdTime:l}=t.value.git??{};return l?new Date(l):null})},d8=()=>{const e=ce(),t=Oe(),n=ve(),l=eh(),r=s8(),i=c8(),a=u8(),o=jf(),c=n8(),u=k(()=>({author:l.value,category:r.value,date:a.value,localizedDate:t.value.localizedDate,tag:i.value,isOriginal:n.value.isOriginal??!1,readingTime:o.value,readingTimeLocale:c.value,pageview:n.value.pageview??!0})),d=k(()=>n.value.pageInfo??e.value.pageInfo??null);return{info:u,items:d}},ot=()=>{const e=tn();return k(()=>!!e.value.pure)},go=(e,t)=>"activeMatch"in t?new RegExp(t.activeMatch,"u").test(e.path):Jf(e,t.link),Eo=(e,t)=>"children"in t?!!t.prefix&&Jf(e,t.prefix)||t.children.some(n=>Eo(e,n)):go(e,t),_o={"/":["",{text:"",prefix:"cloudnative/",collapsible:!0,children:[""]},{text:"",prefix:"open-source-project/",collapsible:!0,children:[""]},{text:"Database",prefix:"database/",collapsible:!0,children:["",{text:"Elasticsearch",prefix:"elasticsearch/",collapsible:!0,children:["基础","【elasticsearch】搜索过程详解","elasticsearch源码debug"]},{text:"Mysql",prefix:"mysql/",collapsible:!0,children:["1mysql","数据库缓存"]},{text:"Redis",prefix:"redis/",collapsible:!0,children:["RedissonLock分布式锁源码分析","redis缓存"]}]},{text:"Interview",prefix:"interview/",collapsible:!0,children:["tiktok2023"]},{text:"Java",prefix:"java/",collapsible:!0,children:[{text:"I/O",prefix:"io/",collapsible:!0,icon:"pen",children:["nio"]},{text:"JVM",prefix:"JVM/",collapsible:!0,icon:"pen",children:["cms","g1","Java内存模型","JVM调优参数","zgc","一次jvm调优过程","常用GC回收器","引用计数和根可达算法"]},{text:"SpringBoot",prefix:"SpringBoot/",collapsible:!0,icon:"pen",children:["aop","Spring Boot Prometheus使用","webflux"]},{text:"线程",prefix:"线程/",collapsible:!0,icon:"pen",children:["synchronized","volatile"]},{text:"网络",prefix:"网络/",collapsible:!0,icon:"pen",children:["IP、HTTP、HTTPS、HTTP2.0"]},"在 Spring 6 中使用虚拟线程","基于kubernetes的分布式限流","流程编排LiteFlow","serverlog","高可用","高并发","高性能","高性能高并发高可用的一些思考"]},{text:"Life",prefix:"life/",collapsible:!0,children:["2017","2018","2019"]},{text:"Link",prefix:"link/",collapsible:!0,children:["main"]},{text:"Spark",prefix:"bigdata/",collapsible:!0,children:["",{text:"Spark",prefix:"spark/",collapsible:!0,children:["elastic-spark"]}]},{text:"System Design",prefix:"system-design/",collapsible:!0,children:["feed",{text:"推荐系统",prefix:"推荐系统/",collapsible:!0,children:["推荐工程-概述","推荐系统入门"]},{text:"计算广告",prefix:"计算广告/",collapsible:!0,children:["计算广告基本概念入门总结"]}]},{text:"中间件",prefix:"middleware/",collapsible:!0,children:["",{text:"Canal",prefix:"canal/",collapsible:!0,children:["中间件——canal小记"]},{text:"Kafka",prefix:"kafka/",collapsible:!0,children:["kafka"]},{text:"Sentinel",prefix:"sentinel/",collapsible:!0,children:[]},{text:"Zookeeper",prefix:"zookeeper/",collapsible:!0,children:["zookeeper","基于ZooKeeper的队列爬虫"]}]},{text:"关于我",prefix:"about-the-author/",collapsible:!0,children:["",{text:"Personal Life",prefix:"personal-life/",collapsible:!0,children:["2024-07-24","2024-11-09上海迪斯尼","wewe"]},{text:"Works",prefix:"works/",collapsible:!0,children:["个人作品"]}]},{text:"好玩的",prefix:"interesting/",collapsible:!0,children:[{text:"个人网站",prefix:"个人网站/",collapsible:!0,icon:"pen",children:["1.历史与架构","2.Lucene的使用","3.定时任务","4.日志系统","5.小集群部署","6.数据库备份","7.那些牛逼的插件","8.基于贝叶斯的情感分析","9.网站性能优化","10.历时8年最终改版"]},{text:"mini主机",prefix:"mini主机/",collapsible:!0,icon:"pen",children:["mac连接主机","买了个mini主机"]},"idea设置","starcraft-ai","tesla","一些不常用但很实用的命令","基于OLAP做业务监控","小程序反编译","广州图书馆借阅抓取","开发工具整理","chatgpt","程序员副业探索之电商"]},{text:"微信支付",prefix:"donate/",collapsible:!0,children:[""]},{text:"目录",prefix:"kubernetes/",collapsible:!0,children:[{text:"DevOps",prefix:"devops/",collapsible:!0,icon:"pen",children:["devops-ping-tai"]},"Jenkins的一些笔记","request_limit","Kubernetes容器日志收集","spark on k8s operator"]},{text:"股票预测",prefix:"stock/",collapsible:!0,children:["","赛力斯"]}],"/interesting/":[{text:"个人网站",prefix:"个人网站/",collapsible:!0,icon:"pen",children:["1.历史与架构","2.Lucene的使用","3.定时任务","4.日志系统","5.小集群部署","6.数据库备份","7.那些牛逼的插件","8.基于贝叶斯的情感分析","9.网站性能优化","10.历时8年最终改版"]},{text:"mini主机",prefix:"mini主机/",collapsible:!0,icon:"pen",children:["mac连接主机","买了个mini主机"]},"idea设置","starcraft-ai","tesla","一些不常用但很实用的命令","基于OLAP做业务监控","小程序反编译","广州图书馆借阅抓取","开发工具整理","chatgpt","程序员副业探索之电商"],"/java/":[{text:"I/O",prefix:"io/",collapsible:!0,icon:"pen",children:["nio"]},{text:"JVM",prefix:"JVM/",collapsible:!0,icon:"pen",children:["cms","g1","Java内存模型","JVM调优参数","zgc","一次jvm调优过程","常用GC回收器","引用计数和根可达算法"]},{text:"SpringBoot",prefix:"SpringBoot/",collapsible:!0,icon:"pen",children:["aop","Spring Boot Prometheus使用","webflux"]},{text:"线程",prefix:"线程/",collapsible:!0,icon:"pen",children:["synchronized","volatile"]},{text:"网络",prefix:"网络/",collapsible:!0,icon:"pen",children:["IP、HTTP、HTTPS、HTTP2.0"]},"在 Spring 6 中使用虚拟线程","基于kubernetes的分布式限流","流程编排LiteFlow","serverlog","高可用","高并发","高性能","高性能高并发高可用的一些思考"],"/database/mysql/":["1mysql","数据库缓存"],"/database/redis/":["RedissonLock分布式锁源码分析","redis缓存"],"/database/elasticsearch/":["基础","【elasticsearch】搜索过程详解","elasticsearch源码debug"],"/database/mongodb/":[],"/bigdata/spark/":["elastic-spark"],"/middleware/kafka/":["kafka"],"/middleware/zookeeper/":["zookeeper","基于ZooKeeper的队列爬虫"],"/middleware/canal/":["中间件——canal小记"],"/kubernetes/":[{text:"DevOps",prefix:"devops/",collapsible:!0,icon:"pen",children:["devops-ping-tai"]},"Jenkins的一些笔记","request_limit","Kubernetes容器日志收集","spark on k8s operator"],"/system-design/":["feed",{text:"推荐系统",prefix:"推荐系统/",collapsible:!0,children:["推荐工程-概述","推荐系统入门"]},{text:"计算广告",prefix:"计算广告/",collapsible:!0,children:["计算广告基本概念入门总结"]}],"/life/":["2017","2018","2019"],"/about-the-author/personal-life/":["2024-07-24","2024-11-09上海迪斯尼","wewe"],"/about-the-author/works/":["个人作品"],"/about-the-author/talking/":[]},f8=(e,t)=>{const n=e.replace(t,"/").split("/"),l=[];let r=Zr(t);return n.forEach((i,a)=>{a!==n.length-1?(r+=`${i}/`,l.push({link:r,name:i||"Home"})):i!==""&&(r+=i,l.push({link:r,name:i}))}),l},va=e=>!Ka(e)&&!tr(e);let Mi=null,El=null;const ma={wait:()=>Mi,pending:()=>{Mi=new Promise(e=>{El=e})},resolve:()=>{El==null||El(),Mi=null,El=null}};var Qe;(function(e){e.title="t",e.shortTitle="s",e.icon="i",e.index="I",e.order="O",e.breadcrumbExclude="b"})(Qe||(Qe={}));var Ke;(function(e){e.type="y",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"})(Ke||(Ke={}));var ga;(function(e){e.article="a",e.home="h",e.slide="s",e.page="p"})(ga||(ga={}));const $r=(e,t=!1,n)=>{const{meta:l,path:r,notFound:i}=wt(e,n);return i?{text:r,link:r}:{text:!t&&l[Qe.shortTitle]?l[Qe.shortTitle]:l[Qe.title]||r,link:r,...l[Qe.icon]?{icon:l[Qe.icon]}:{}}},xn=(e="",t="")=>ni(t)||tr(t)?t:`${_d(e)}${t}`,th=(e,t)=>{const n=ke(e)?$r(xn(t,e)):e.link?{...e,link:va(e.link)?wt(xn(t,e.link)).path:e.link}:e;if("children"in n){const l=xn(t,n.prefix),r=n.children==="structure"?_o[l]:n.children;return{...n,prefix:l,children:r.map(i=>th(i,l))}}return{...n}},Ea=({config:e,prefix:t=""})=>e.map(n=>th(n,t)),h8=({config:e,routePath:t,headerDepth:n})=>{const l=hn(e).sort((r,i)=>i.length-r.length);for(const r of l)if(Hr(decodeURI(t),r)){const i=e[r];return Ea({config:i==="structure"?_o[r]:i||[],headerDepth:n,prefix:r})}return console.warn(`${decodeURI(t)} is missing sidebar config.`),[]},p8=({config:e,headerDepth:t,routeLocale:n,routePath:l})=>e==="structure"?Ea({config:_o[n],headerDepth:t,prefix:n}):ra(e)?Ea({config:e,headerDepth:t}):nr(e)?h8({config:e,routePath:l,headerDepth:t}):[],nh=Symbol(""),v8=()=>{const e=ve(),t=ce(),n=Mt(),l=Pd(),r=k(()=>e.value.home?!1:e.value.sidebar??t.value.sidebar??"structure"),i=k(()=>e.value.headerDepth??t.value.headerDepth??2),a=k(()=>p8({config:r.value,headerDepth:i.value,routeLocale:n.value,routePath:l.value}));Ot(nh,a)},bo=()=>{const e=Se(nh);if(!e)throw new Error("useSidebarItems() is called without provider.");return e},eu=(e,t)=>e===!1?e:nr(e)?{...e,link:$r(e.link,!0,t).link}:ke(e)?$r(e,!0,t):null,_a=(e,t,n)=>{const l=e.findIndex(i=>i.link===t);if(l!==-1){const i=e[l+n];return i?i.link?i:"prefix"in i&&!wt(i.prefix).notFound?{...i,link:i.prefix}:null:null}for(const i of e)if("children"in i){const a=_a(i.children,t,n);if(a)return a}const r=e.findIndex(i=>"prefix"in i&&i.prefix===t);if(r!==-1){const i=e[r+n];return i?i.link?i:"prefix"in i&&!wt(i.prefix).notFound?{...i,link:i.prefix}:null:null}return null},m8=()=>{const e=ve(),t=ce(),n=bo(),l=Ut(),r=k(()=>{const a=eu(e.value.prev,l.path);return a===!1?null:a??(t.value.prevLink===!1?null:_a(n.value,l.path,-1))}),i=k(()=>{const a=eu(e.value.next,l.path);return a===!1?null:a??(t.value.nextLink===!1?null:_a(n.value,l.path,1))});return{prevLink:r,nextLink:i}},g8="719px",E8="1440px",_8="true",b8="9",_n={mobileBreakPoint:g8,pcBreakPoint:E8,enableThemeColor:_8,"theme-1":"#2196f3","theme-2":"#f26d6d","theme-3":"#3eaf7c","theme-4":"#fb9b5f",colorNumber:b8},{mobileBreakPoint:y8,pcBreakPoint:A8}=_n,tu=e=>e.endsWith("px")?Number(e.slice(0,-2)):null,cr=()=>{const e=ee(!1),t=ee(!1),n=()=>{e.value=window.innerWidth<=(tu(y8)??719),t.value=window.innerWidth>=(tu(A8)??1440)};return Ie("resize",n,!1),Ie("orientationchange",n,!1),we(()=>{n()}),{isMobile:e,isPC:t}},lh=Symbol(""),ur=()=>{const e=Se(lh);if(!e)throw new Error("useDarkmode() is called without provider.");return e},k8=e=>{const t=tn(),n=Pv(),l=k(()=>t.value.darkmode??"switch"),r=Xa("vuepress-theme-hope-scheme","auto"),i=k(()=>{const o=l.value;return o==="disable"?!1:o==="enable"?!0:o==="auto"?n.value:o==="toggle"?r.value==="dark":r.value==="dark"||r.value==="auto"&&n.value}),a=k(()=>{const o=l.value;return o==="switch"||o==="toggle"});e.provide(lh,{canToggle:a,config:l,isDarkmode:i,status:r}),Object.defineProperties(e.config.globalProperties,{$isDarkmode:{get:()=>i.value}})},w8=()=>{const{config:e,isDarkmode:t,status:n}=ur();za(()=>{e.value==="disable"?n.value="light":e.value==="enable"?n.value="dark":e.value==="toggle"&&n.value==="auto"&&(n.value="light")}),we(()=>{pe(t,l=>document.documentElement.setAttribute("data-theme",l?"dark":"light"),{immediate:!0})})},B8=H({name:"PageFooter",setup(){const e=tn(),t=ce(),n=ve(),l=eh(),r=k(()=>{const{copyright:u,footer:d}=n.value;return d!==!1&&!!(u||d||t.value.displayFooter)}),i=k(()=>{const{footer:u}=n.value;return u===!1?!1:ke(u)?u:t.value.footer??""}),a=k(()=>l.value.map(({name:u})=>u).join(", ")),o=u=>`Copyright © ${new Date().getFullYear()} ${a.value} ${u?`${u} Licensed`:""}`,c=k(()=>{const{copyright:u,license:d=""}=n.value,{license:f}=e.value,{copyright:h}=t.value;return u??(d?o(d):h??(a.value||f?o(f):!1))});return()=>r.value?s("footer",{class:"vp-footer-wrapper","vp-footer":""},[i.value?s("div",{class:"vp-footer",innerHTML:i.value}):null,c.value?s("div",{class:"vp-copyright",innerHTML:c.value}):null]):null}}),Or=()=>null,it=H({name:"AutoLink",props:{config:{type:Object,required:!0}},emits:["focusout"],slots:Object,setup(e,{emit:t,slots:n}){return()=>{const{icon:l}=e.config;return s(cv,{...e,onFocusout:()=>t("focusout")},{default:n.default?()=>n.default():null,before:n.before?()=>n.before():l?()=>s(qe,{icon:l}):null,after:n.after?()=>n.after():null})}}}),C8=H({name:"NavbarDropdown",props:{config:{type:Object,required:!0}},slots:Object,setup(e,{slots:t}){const n=Oe(),l=sl(e,"config"),r=k(()=>l.value.ariaLabel??l.value.text),i=ee(!1);pe(()=>n.value.path,()=>{i.value=!1});const a=o=>{o.detail===0&&(i.value=!i.value)};return()=>{var o;return s("div",{class:["vp-dropdown-wrapper",{open:i.value}]},[s("button",{type:"button",class:"vp-dropdown-title","aria-label":r.value,onClick:a},[((o=t.title)==null?void 0:o.call(t))||[s(qe,{icon:l.value.icon}),e.config.text],s("span",{class:"arrow"}),s("ul",{class:"vp-dropdown"},l.value.children.map((c,u)=>{const d=u===l.value.children.length-1;return s("li",{class:"vp-dropdown-item"},"children"in c?[s("h4",{class:"vp-dropdown-subtitle"},c.link?s(it,{config:c,onFocusout:()=>{c.children.length===0&&d&&(i.value=!1)}}):c.text),s("ul",{class:"vp-dropdown-subitems"},c.children.map((f,h)=>s("li",{class:"vp-dropdown-subitem"},s(it,{config:f,onFocusout:()=>{h===c.children.length-1&&d&&(i.value=!1)}}))))]:s(it,{config:c,onFocusout:()=>{d&&(i.value=!1)}}))}))])])}}}),rh=(e,t="")=>ke(e)?$r(xn(t,e)):"children"in e?{...e,...e.link&&va(e.link)?{link:wt(xn(t,e.link)).path}:{},children:e.children.map(n=>rh(n,xn(t,e.prefix)))}:{...e,link:va(e.link)?wt(xn(t,e.link)).path:e.link},ih=()=>{const e=ce();return k(()=>(e.value.navbar||[]).map(t=>rh(t)))},x8=()=>{const e=ce(),t=k(()=>e.value.repo),n=k(()=>t.value?l8(t.value):null),l=k(()=>t.value?mo(t.value):null),r=k(()=>n.value?e.value.repoLabel??l.value??"Source":null);return k(()=>!n.value||!r.value||e.value.repoDisplay===!1?null:{type:l.value??"Source",label:r.value,link:n.value})},S8=H({name:"NavScreenMenu",props:{config:{type:Object,required:!0}},setup(e){const t=Oe(),n=sl(e,"config"),l=k(()=>n.value.ariaLabel??n.value.text),r=ee(!1);pe(()=>t.value.path,()=>{r.value=!1});const i=(a,o)=>o[o.length-1]===a;return()=>[s("button",{type:"button",class:["vp-nav-screen-menu-title",{active:r.value}],"aria-label":l.value,onClick:()=>{r.value=!r.value}},[s("span",{class:"text"},[s(qe,{icon:n.value.icon}),e.config.text]),s("span",{class:["arrow",r.value?"down":"end"]})]),s("ul",{class:["vp-nav-screen-menu",{hide:!r.value}]},n.value.children.map(a=>s("li",{class:"vp-nav-screen-menu-item"},"children"in a?[s("h4",{class:"vp-nav-screen-menu-subtitle"},a.link?s(it,{config:a,onFocusout:()=>{i(a,n.value.children)&&a.children.length===0&&(r.value=!1)}}):a.text),s("ul",{class:"vp-nav-screen-menu-subitems"},a.children.map(o=>s("li",{class:"vp-nav-screen-menu-subitem"},s(it,{config:o,onFocusout:()=>{i(o,a.children)&&i(a,n.value.children)&&(r.value=!1)}}))))]:s(it,{config:a,onFocusout:()=>{i(a,n.value.children)&&(r.value=!1)}}))))]}}),T8=H({name:"NavScreenLinks",setup(){const e=ih();return()=>e.value.length?s("nav",{class:"nav-screen-links"},e.value.map(t=>s("div",{class:"navbar-links-item"},"children"in t?s(S8,{config:t}):s(it,{config:t})))):null}}),ah=()=>s(me,{name:"dark"},()=>s("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"}));ah.displayName="DarkIcon";const oh=()=>s(me,{name:"light"},()=>s("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"}));oh.displayName="LightIcon";const sh=()=>s(me,{name:"auto"},()=>s("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"}));sh.displayName="AutoIcon";const ch=()=>s(me,{name:"enter-fullscreen"},()=>s("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"}));ch.displayName="EnterFullScreenIcon";const uh=()=>s(me,{name:"cancel-fullscreen"},()=>s("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"}));uh.displayName="CancelFullScreenIcon";const dh=()=>s(me,{name:"outlook"},()=>[s("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"})]);dh.displayName="OutlookIcon";const fh=H({name:"ColorModeSwitch",setup(){const{config:e,isDarkmode:t,status:n}=ur(),l=ot(),r=()=>{e.value==="switch"?n.value={light:"dark",dark:"auto",auto:"light"}[n.value]:n.value=n.value==="light"?"dark":"light"},i=async a=>{if(!(document.startViewTransition&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches&&!l.value)||!a){r();return}const c=a.clientX,u=a.clientY,d=Math.hypot(Math.max(c,innerWidth-c),Math.max(u,innerHeight-u)),f=t.value;await document.startViewTransition(async()=>{r(),await Qt()}).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()=>s("button",{type:"button",class:"vp-color-mode-switch",id:"color-mode-switch",onClick:i},[s(sh,{style:{display:n.value==="auto"?"block":"none"}}),s(ah,{style:{display:n.value==="dark"?"block":"none"}}),s(oh,{style:{display:n.value==="light"?"block":"none"}})])}}),L8=H({name:"ColorMode",setup(){const e=ce(),{canToggle:t}=ur(),n=k(()=>e.value.outlookLocales.darkmode);return()=>t.value?s("div",{class:"vp-color-mode"},[s("label",{class:"vp-color-mode-title",for:"color-mode-switch"},n.value),s(fh)]):null}}),Vi="VUEPRESS_THEME_COLOR",O8=H({name:"ThemeColorPicker",props:{themeColor:{type:Object,required:!0}},setup(e){const t=(n="")=>{const l=document.documentElement.classList,r=hn(e.themeColor);if(!n){localStorage.removeItem(Vi),l.remove(...r);return}l.remove(...r.filter(i=>i!==n)),l.add(n),localStorage.setItem(Vi,n)};return we(()=>{const n=localStorage.getItem(Vi);n&&t(n)}),()=>s("ul",{class:"vp-theme-color-picker",id:"theme-color-picker"},[s("li",s("span",{class:"theme-color",onClick:()=>t()})),En(e.themeColor).map(([n,l])=>s("li",s("span",{style:{background:l},onClick:()=>t(n)})))])}}),Zn=_n.enableThemeColor==="true",D8=Zn?mm(En(_n).filter(([e])=>e.startsWith("theme-"))):{},P8=H({name:"ThemeColor",setup(){const e=ce(),t=k(()=>e.value.outlookLocales.themeColor);return()=>Zn?s("div",{class:"vp-theme-color"},[s("label",{class:"vp-theme-color-title",for:"theme-color-picker"},t.value),s(O8,{themeColor:D8})]):null}}),I8=H({name:"ToggleFullScreenButton",setup(){const{isSupported:e,isFullscreen:t,toggle:n}=ti();return()=>e?s("button",{type:"button",id:"full-screen-switch",class:"full-screen",ariaPressed:t.value,onClick:()=>n()},t.value?s(uh):s(ch)):null}}),hh=H({name:"ToggleFullScreenButton",setup(){const e=ce(),{isSupported:t}=ti(),n=k(()=>e.value.outlookLocales.fullscreen);return()=>t?s("div",{class:"full-screen-wrapper"},[s("label",{class:"full-screen-title",for:"full-screen-switch"},n.value),s(I8)]):null}}),ph=H({name:"OutlookSettings",setup(){const e=tn(),t=ot(),n=k(()=>!t.value&&e.value.fullscreen);return()=>s(Rd,()=>[Zn?s(P8):null,s(L8),n.value?s(hh):null])}}),F8=H({name:"NavScreen",props:{show:Boolean},emits:["close"],slots:Object,setup(e,{emit:t,slots:n}){const l=Oe(),{isMobile:r}=cr(),i=$e(),a=eo(i);return we(()=>{i.value=document.body,pe(r,o=>{!o&&e.show&&(a.value=!1,t("close"))}),pe(()=>l.value.path,()=>{a.value=!1,t("close")})}),cl(()=>{a.value=!1}),()=>s(el,{name:"fade",onEnter:()=>{a.value=!0},onAfterLeave:()=>{a.value=!1}},()=>{var o,c;return e.show?s("div",{id:"nav-screen",class:"vp-nav-screen"},s("div",{class:"vp-nav-screen-container"},[(o=n.before)==null?void 0:o.call(n),s(T8),s("div",{class:"vp-outlook-wrapper"},s(ph)),(c=n.after)==null?void 0:c.call(n)])):null})}}),R8=H({name:"NavbarBrand",setup(){const e=Mt(),t=lr(),n=ce(),l=k(()=>n.value.home??e.value),r=k(()=>t.value.title),i=k(()=>n.value.navbarTitle??r.value),a=k(()=>n.value.logo?Ae(n.value.logo):null),o=k(()=>n.value.logoDark?Ae(n.value.logoDark):null);return()=>s(He,{to:l.value,class:"vp-brand","aria-label":n.value.routeLocales.home},()=>[a.value?s("img",{class:["vp-nav-logo",{light:!!o.value}],src:a.value,alt:""}):null,o.value?s("img",{class:["vp-nav-logo dark"],src:o.value,alt:""}):null,i.value?s("span",{class:["vp-site-name",{"hide-in-pad":a.value&&(n.value.hideSiteNameOnMobile??!0)}]},i.value):null])}}),M8=H({name:"NavbarLinks",setup(){const e=ih();return()=>e.value.length?s("nav",{class:"vp-nav-links"},e.value.map(t=>s("div",{class:"vp-nav-item hide-in-mobile"},"children"in t?s(C8,{config:t}):s(it,{config:t})))):null}}),V8=H({name:"RepoLink",setup(){const e=x8();return()=>e.value?s("div",{class:"vp-nav-item vp-action"},s("a",{class:"vp-action-link",href:e.value.link,target:"_blank",rel:"noopener noreferrer","aria-label":e.value.label},s(qf,{type:e.value.type,style:{width:"1.25rem",height:"1.25rem",verticalAlign:"middle"}}))):null}}),vh=({active:e=!1},{emit:t})=>s("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")},s("span",[s("span",{class:"vp-top"}),s("span",{class:"vp-middle"}),s("span",{class:"vp-bottom"})]));vh.displayName="ToggleNavbarButton";const yo=(e,{emit:t})=>s("button",{type:"button",class:"vp-toggle-sidebar-button",title:"Toggle Sidebar",onClick:()=>t("toggle")},s("span",{class:"icon"}));yo.displayName="ToggleSidebarButton";yo.emits=["toggle"];const N8=H({name:"OutlookButton",setup(){const e=tn(),t=Oe(),{canToggle:n}=ur(),{isSupported:l}=ti(),r=ot(),i=ee(!1),a=k(()=>!r.value&&e.value.fullscreen&&l),o=k(()=>Zn||n.value||a.value);return pe(()=>t.value.path,()=>{i.value=!1}),()=>o.value?s("div",{class:"vp-nav-item hide-in-mobile"},n.value&&!a.value&&!Zn?s(fh):a.value&&!n.value&&!Zn?s(hh):s("button",{type:"button",class:["vp-outlook-button",{open:i.value}],tabindex:"-1","aria-hidden":!0},[s(dh),s("div",{class:"vp-outlook-dropdown"},s(ph))])):null}}),j8=H({name:"NavBar",emits:["toggleSidebar"],slots:Object,setup(e,{emit:t,slots:n}){const l=ce(),{isMobile:r}=cr(),i=ee(!1),a=k(()=>{const{navbarAutoHide:d="mobile"}=l.value;return d!=="none"&&(d==="always"||r.value)}),o=k(()=>l.value.navbarLayout??{start:["Brand"],center:["Links"],end:["Language","Repo","Outlook","Search"]}),c={Brand:R8,Language:Or,Links:M8,Repo:V8,Outlook:N8,Search:Ft("SearchBox")?kt("SearchBox"):Or},u=d=>c[d]??(Ft(d)?kt(d):Or);return()=>{var d,f,h,p,g,v,y,_,A;return[s("header",{key:"navbar",id:"navbar",class:["vp-navbar",{"auto-hide":a.value}],"vp-navbar":""},[s("div",{class:"vp-navbar-start"},[s(yo,{onToggle:()=>{i.value&&(i.value=!1),t("toggleSidebar")}}),(d=n.startBefore)==null?void 0:d.call(n),(f=o.value.start)==null?void 0:f.map(m=>s(u(m))),(h=n.startAfter)==null?void 0:h.call(n)]),s("div",{class:"vp-navbar-center"},[(p=n.centerBefore)==null?void 0:p.call(n),(g=o.value.center)==null?void 0:g.map(m=>s(u(m))),(v=n.centerAfter)==null?void 0:v.call(n)]),s("div",{class:"vp-navbar-end"},[(y=n.endBefore)==null?void 0:y.call(n),(_=o.value.end)==null?void 0:_.map(m=>s(u(m))),(A=n.endAfter)==null?void 0:A.call(n),s(vh,{active:i.value,onToggle:()=>{i.value=!i.value}})])]),s(F8,{show:i.value,onClose:()=>{i.value=!1}},{before:n.screenTop?()=>n.screenTop():null,after:n.screenBottom?()=>n.screenBottom():null})]}}}),H8=H({name:"SidebarChild",props:{config:{type:Object,required:!0}},setup(e){const t=Ut();return()=>ke(e.config.link)?s(it,{class:["vp-sidebar-link",{active:go(t,e.config)}],config:{...e.config,exact:!0}}):s("p",e,[s(qe,{icon:e.config.icon}),e.config.text])}}),z8=H({name:"SidebarGroup",props:{config:{type:Object,required:!0},open:{type:Boolean,required:!0}},emits:["toggle"],setup(e,{emit:t}){const n=Ut(),l=ee(!1),r=k(()=>Eo(n,e.config)),i=k(()=>go(n,e.config)),a=k(()=>e.open||e.config.expanded&&!l.value);return()=>{const{collapsible:o,children:c=[],icon:u,prefix:d,link:f,text:h}=e.config;return s("section",{class:"vp-sidebar-group"},[s(o?"button":"p",{class:["vp-sidebar-header",{clickable:o||f,exact:i.value,active:r.value}],...o?{type:"button",onClick:()=>{l.value=!0,t("toggle")}}:{}},[s(qe,{icon:u}),f?s(it,{class:"vp-sidebar-title no-external-link-icon",config:{text:h,link:f}}):s("span",{class:"vp-sidebar-title"},h),o?s("span",{class:["vp-arrow",a.value?"down":"end"]}):null]),a.value||!o?s(mh,{key:d,config:c}):null])}}}),mh=H({name:"SidebarLinks",props:{config:{type:Array,required:!0}},setup(e){const t=Ut(),n=ee(-1),l=r=>{n.value=r===n.value?-1:r};return pe(()=>t.path,()=>{const r=e.config.findIndex(i=>Eo(t,i));n.value=r},{immediate:!0,flush:"post"}),()=>s("ul",{class:"vp-sidebar-links"},e.config.map((r,i)=>s("li","children"in r?s(z8,{config:r,open:i===n.value,onToggle:()=>l(i)}):s(H8,{config:r}))))}}),$8=H({name:"SideBar",slots:Object,setup(e,{slots:t}){const n=Ut(),l=bo(),r=$e();return we(()=>{pe(()=>n.hash,i=>{const a=document.querySelector(`.vp-sidebar a.vp-sidebar-link[href="${n.path}${i}"]`);if(!a)return;const{top:o,height:c}=r.value.getBoundingClientRect(),{top:u,height:d}=a.getBoundingClientRect();uo+c&&a.scrollIntoView(!1)},{immediate:!0})}),()=>{var i,a,o;return s("aside",{ref:r,key:"sidebar",id:"sidebar",class:"vp-sidebar","vp-sidebar":""},[(i=t.top)==null?void 0:i.call(t),((a=t.default)==null?void 0:a.call(t))??s(mh,{config:l.value}),(o=t.bottom)==null?void 0:o.call(t)])}}}),Ao=H({name:"CommonWrapper",props:{containerClass:{type:String,default:""},noNavbar:Boolean,noSidebar:Boolean,noToc:Boolean},slots:Object,setup(e,{slots:t}){const n=en(),l=ve(),r=tn(),i=ce(),{isMobile:a,isPC:o}=cr(),c=ot(),[u,d]=ta(!1),[f,h]=ta(!1),p=bo(),g=ee(!1),v=k(()=>e.noNavbar||l.value.navbar===!1||i.value.navbar===!1?!1:!!(i.value.logo??i.value.repo??i.value.navbar)),y=k(()=>e.noSidebar?!1:l.value.sidebar!==!1&&p.value.length!==0&&!l.value.home),_=k(()=>l.value.externalLinkIcon??r.value.externalLinkIcon??!0),A=k(()=>!e.noToc&&!l.value.home&&(l.value.toc??i.value.toc??!0)),m={x:0,y:0},w=R=>{m.x=R.changedTouches[0].clientX,m.y=R.changedTouches[0].clientY},F=R=>{const Z=R.changedTouches[0].clientX-m.x,M=R.changedTouches[0].clientY-m.y;Math.abs(Z)>Math.abs(M)*1.5&&Math.abs(Z)>40&&(Z>0&&m.x<=80?d(!0):d(!1))};let V=0;return Ie("scroll",kv(()=>{const R=window.scrollY;R<=58||R{R||d(!1)}),we(()=>{const R=eo(document.body);pe(u,M=>{R.value=M});const Z=n.afterEach(()=>{d(!1)});cl(()=>{R.value=!1,Z()})}),()=>s(Ft("GlobalEncrypt")?kt("GlobalEncrypt"):vo,()=>s("div",{class:["theme-container",{"hide-navbar":g.value,"no-navbar":!v.value,"sidebar-collapsed":!a.value&&!o.value&&f.value,"sidebar-open":a.value&&u.value,"no-sidebar":!y.value&&!t.sidebar&&!t.sidebarTop&&!t.sidebarBottom,"external-link-icon":_.value,pure:c.value,"has-toc":A.value},e.containerClass,l.value.containerClass??""],"vp-container":"",onTouchStart:w,onTouchEnd:F},[v.value?s(j8,{onToggleSidebar:()=>d()},{startBefore:t.navbarStartBefore?()=>t.navbarStartBefore():null,startAfter:t.navbarStartAfter?()=>t.navbarStartAfter():null,centerBefore:t.navbarCenterBefore?()=>t.navbarCenterBefore():null,centerAfter:t.navbarCenterAfter?()=>t.navbarCenterAfter():null,endBefore:t.navbarEndBefore?()=>t.navbarEndBefore():null,endAfter:t.navbarEndAfter?()=>t.navbarEndAfter():null,screenTop:t.navScreenTop?()=>t.navScreenTop():null,screenBottom:t.navScreenBottom?()=>t.navScreenBottom():null}):null,s(el,{name:"fade"},()=>u.value?s("div",{class:"vp-sidebar-mask",onClick:()=>d(!1)}):null),s(el,{name:"fade"},()=>a.value?null:s("div",{class:"toggle-sidebar-wrapper",onClick:()=>h()},s("span",{class:["arrow",f.value?"end":"start"]}))),s($8,{},{default:t.sidebar?()=>t.sidebar():null,top:t.sidebarTop?()=>t.sidebarTop():null,bottom:t.sidebarBottom?()=>t.sidebarBottom():null}),t.default(),s(B8)]))}}),ba=(e,{slots:t})=>{var f,h;const{bgImage:n,bgImageDark:l,bgImageStyle:r,color:i,description:a,image:o,imageDark:c,header:u,features:d=[]}=e;return s("div",{class:"vp-feature-wrapper"},[n?s("div",{class:["vp-feature-bg",{light:l}],style:[{"background-image":`url(${n})`},r]}):null,l?s("div",{class:"vp-feature-bg dark",style:[{"background-image":`url(${l})`},r]}):null,s("div",{class:"vp-feature",style:i?{color:i}:{}},[((f=t.image)==null?void 0:f.call(t,e))??[o?s("img",{class:["vp-feature-image",{light:c}],src:Ae(o),alt:""}):null,c?s("img",{class:"vp-feature-image dark",src:Ae(c),alt:""}):null],((h=t.info)==null?void 0:h.call(t,e))??[u?s("h2",{class:"vp-feature-header"},u):null,a?s("p",{class:"vp-feature-description",innerHTML:a}):null],d.length?s("div",{class:"vp-features"},d.map(({icon:p,title:g,details:v,link:y})=>{const _=[s("h3",{class:"vp-feature-title"},[s(qe,{icon:p}),s("span",{innerHTML:g})]),s("p",{class:"vp-feature-details",innerHTML:v})];return y?Ka(y)?s("a",{class:"vp-feature-item link",href:y,"aria-label":g,target:"_blank"},_):s(He,{class:"vp-feature-item link",to:y,"aria-label":g},()=>_):s("div",{class:"vp-feature-item"},_)})):null])])};ba.displayName="FeaturePanel";const oe=H({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=r=>{r.style.transition=`transform ${e.duration}s ease-in-out ${e.delay}s, opacity ${e.duration}s ease-in-out ${e.delay}s`,r.style.transform="translateY(-20px)",r.style.opacity="0"},l=r=>{r.style.transform="translateY(0)",r.style.opacity="1"};return()=>{const r={name:"drop",appear:e.appear,onAppear:n,onAfterAppear:l,onEnter:n,onAfterEnter:l,onBeforeLeave:n},i=()=>t.default();return e.type==="group"?s(gd,r,i):s(el,r,i)}}}),gh=(e,{slots:t})=>s(el,{name:"fade-slide-y",mode:"out-in",onBeforeEnter:ma.resolve,onBeforeLeave:ma.pending},()=>t.default());gh.displayName="FadeSlideY";const U8=H({name:"HeroInfo",slots:Object,setup(e,{slots:t}){const n=ve(),l=lr(),r=k(()=>n.value.heroFullScreen??!1),i=k(()=>{const{heroText:u,tagline:d}=n.value;return{text:u??l.value.title??"Hello",tagline:d??l.value.description??"",isFullScreen:r.value}}),a=k(()=>{const{heroText:u,heroImage:d,heroImageDark:f,heroAlt:h,heroImageStyle:p}=n.value;return{image:d?Ae(d):null,imageDark:f?Ae(f):null,imageStyle:p,alt:h??u??"",isFullScreen:r.value}}),o=k(()=>{const{bgImage:u,bgImageDark:d,bgImageStyle:f}=n.value;return{image:ke(u)?Ae(u):null,imageDark:ke(d)?Ae(d):null,bgStyle:f,isFullScreen:r.value}}),c=k(()=>n.value.actions??[]);return()=>{var u,d,f;return s("header",{class:["vp-hero-info-wrapper",{fullscreen:r.value}]},[((u=t.bg)==null?void 0:u.call(t,o.value))??[o.value.image?s("div",{class:["vp-hero-mask",{light:o.value.imageDark}],style:[{"background-image":`url(${o.value.image})`},o.value.bgStyle]}):null,o.value.imageDark?s("div",{class:"vp-hero-mask dark",style:[{"background-image":`url(${o.value.imageDark})`},o.value.bgStyle]}):null],s("div",{class:"vp-hero-info"},[((d=t.logo)==null?void 0:d.call(t,a.value))??s(oe,{appear:!0,type:"group"},()=>{const{image:h,imageDark:p,imageStyle:g,alt:v}=a.value;return[h?s("img",{key:"light",class:["vp-hero-image",{light:p}],style:g,src:h,alt:v}):null,p?s("img",{key:"dark",class:"vp-hero-image dark",style:g,src:p,alt:v}):null]}),((f=t.info)==null?void 0:f.call(t,i.value))??s("div",{class:"vp-hero-infos"},[i.value.text?s(oe,{appear:!0,delay:.04},()=>s("h1",{id:"main-title",class:"vp-hero-title"},i.value.text)):null,i.value.tagline?s(oe,{appear:!0,delay:.08},()=>s("p",{id:"main-description",innerHTML:i.value.tagline})):null,c.value.length?s(oe,{appear:!0,delay:.12},()=>s("p",{class:"vp-hero-actions"},c.value.map(h=>s(it,{class:["vp-hero-action",h.type??"default","no-external-link-icon"],config:h},h.icon?{before:()=>s(qe,{icon:h.icon})}:{})))):null])])])}}}),Eh=(e,{slots:t})=>{var h,p,g;const{bgImage:n,bgImageDark:l,bgImageStyle:r,color:i,description:a,image:o,imageDark:c,header:u,highlights:d=[],type:f="un-order"}=e;return s("div",{class:"vp-highlight-wrapper",style:i?{color:i}:{}},[n?s("div",{class:["vp-highlight-bg",{light:l}],style:[{"background-image":`url(${n})`},r]}):null,l?s("div",{class:"vp-highlight-bg dark",style:[{"background-image":`url(${l})`},r]}):null,s("div",{class:"vp-highlight"},[((h=t.image)==null?void 0:h.call(t,e))??[o?s("img",{class:["vp-highlight-image",{light:c}],src:Ae(o),alt:""}):null,c?s("img",{class:"vp-highlight-image dark",src:Ae(c),alt:""}):null],((p=t.info)==null?void 0:p.call(t,e))??[s("div",{class:"vp-highlight-info-wrapper"},s("div",{class:"vp-highlight-info"},[u?s("h2",{class:"vp-highlight-header",innerHTML:u}):null,a?s("p",{class:"vp-highlight-description",innerHTML:a}):null,((g=t.highlights)==null?void 0:g.call(t,d))??s(f==="order"?"ol":f==="no-order"?"dl":"ul",{class:"vp-highlights"},d.map(({icon:v,title:y,details:_,link:A})=>{const m=[s(f==="no-order"?"dt":"h3",{class:"vp-highlight-title"},[v?s(qe,{class:"vp-highlight-icon",icon:v}):null,s("span",{innerHTML:y})]),_?s(f==="no-order"?"dd":"p",{class:"vp-highlight-details",innerHTML:_}):null];return s(f==="no-order"?"div":"li",{class:["vp-highlight-item-wrapper",{link:A}]},A?Ka(A)?s("a",{class:"vp-highlight-item link",href:A,"aria-label":y,target:"_blank"},m):s(He,{class:"vp-highlight-item link",to:A,"aria-label":y},()=>m):s("div",{class:"vp-highlight-item"},m))}))]))]])])};Eh.displayName="HighlightPanel";const hl=({custom:e})=>s(Md,{class:["theme-hope-content",{custom:e}],"vp-content":""});hl.displayName="MarkdownContent";hl.props={custom:Boolean};const G8=H({name:"HomePage",slots:Object,setup(e,{slots:t}){const n=ve(),l=k(()=>{const{features:i}=n.value;return ra(i)?i:null}),r=k(()=>{const{highlights:i}=n.value;return ra(i)?i:null});return()=>{var i,a,o,c;return s("main",{id:"main-content",class:"vp-page vp-project-home","aria-labelledby":n.value.heroText===null?"":"main-title"},[(i=t.top)==null?void 0:i.call(t),s(U8),((a=r.value)==null?void 0:a.map(u=>"features"in u?s(ba,u):s(Eh,u)))??(l.value?s(oe,{appear:!0,delay:.24},()=>s(ba,{features:l.value})):null),(o=t.center)==null?void 0:o.call(t),s(oe,{appear:!0,delay:.32},()=>s(hl)),(c=t.bottom)==null?void 0:c.call(t)])}}}),K8=H({name:"BreadCrumb",setup(){const e=Oe(),t=Mt(),n=ve(),l=ce(),r=$e([]),i=k(()=>(n.value.breadcrumb??l.value.breadcrumb??!0)&&r.value.length>1),a=k(()=>n.value.breadcrumbIcon??l.value.breadcrumbIcon??!0),o=()=>{const c=f8(e.value.path,t.value).map(({link:u,name:d})=>{const{path:f,meta:h,notFound:p}=wt(u);return p||h[Qe.breadcrumbExclude]?null:{title:h[Qe.shortTitle]||h[Qe.title]||d,icon:h[Qe.icon],path:f}}).filter(u=>u!==null);c.length>1&&(r.value=c)};return we(()=>{pe(()=>e.value.path,o,{immediate:!0})}),()=>s("nav",{class:["vp-breadcrumb",{disable:!i.value}]},i.value?s("ol",{vocab:"https://schema.org/",typeof:"BreadcrumbList"},r.value.map((c,u)=>s("li",{class:{"is-active":r.value.length-1===u},property:"itemListElement",typeof:"ListItem"},[s(He,{to:c.path,property:"item",typeof:"WebPage"},()=>[a.value?s(qe,{icon:c.icon}):null,s("span",{property:"name"},c.title||"Unknown")]),s("meta",{property:"position",content:u+1})]))):[])}}),q8=H({name:"PageNav",setup(){const e=ce(),t=Rn(),{prevLink:n,nextLink:l}=m8();return Ie("keydown",r=>{r.altKey&&(r.key==="ArrowRight"?l.value&&(t(l.value.link),r.preventDefault()):r.key==="ArrowLeft"&&n.value&&(t(n.value.link),r.preventDefault()))}),()=>n.value||l.value?s("nav",{class:"vp-page-nav"},[n.value?s(it,{class:"prev",config:n.value},()=>{var r,i;return[s("div",{class:"hint"},[s("span",{class:"arrow start"}),e.value.metaLocales.prev]),s("div",{class:"link"},[s(qe,{icon:(r=n.value)==null?void 0:r.icon}),(i=n.value)==null?void 0:i.text])]}):null,l.value?s(it,{class:"next",config:l.value},()=>{var r,i;return[s("div",{class:"hint"},[e.value.metaLocales.next,s("span",{class:"arrow end"})]),s("div",{class:"link"},[(r=l.value)==null?void 0:r.text,s(qe,{icon:(i=l.value)==null?void 0:i.icon})])]}):null]):null}}),_h=()=>s(me,{name:"author"},()=>s("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"}));_h.displayName="AuthorIcon";const bh=()=>s(me,{name:"calendar"},()=>s("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"}));bh.displayName="CalendarIcon";const yh=()=>s(me,{name:"category"},()=>s("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"}));yh.displayName="CategoryIcon";const Ah=()=>s(me,{name:"print"},()=>s("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"}));Ah.displayName="PrintIcon";const kh=()=>s(me,{name:"tag"},()=>s("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"}));kh.displayName="TagIcon";const wh=()=>s(me,{name:"timer"},()=>s("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"}));wh.displayName="TimerIcon";const Bh=()=>s(me,{name:"word"},()=>[s("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"}),s("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"})]);Bh.displayName="WordIcon";const W8=()=>{const e=ce(),t=Oe(),n=ve();return k(()=>{var r;return n.value.contributors??e.value.contributors??!0?((r=t.value.git)==null?void 0:r.contributors)??null:null})},J8={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"},Y8=({docsRepo:e,docsBranch:t,docsDir:n,filePathRelative:l,editLinkPattern:r})=>{if(!l)return null;const i=mo(e);let a;return r?a=r:i!==null&&(a=J8[i]),a?a.replace(/:repo/u,gn(e)?e:`https://github.com/${e}`).replace(/:branch/u,t).replace(/:path/u,bd(`${Zr(n)}/${l}`)):null},Z8=()=>{const e=ce(),t=Oe(),n=ve();return k(()=>{const{repo:l,docsRepo:r=l,docsBranch:i="main",docsDir:a="",editLink:o,editLinkPattern:c=""}=e.value;if(!(n.value.editLink??o??!0)||!r)return null;const d=Y8({docsRepo:r,docsBranch:i,docsDir:a,editLinkPattern:c,filePathRelative:t.value.filePathRelative});return d?{text:e.value.metaLocales.editLink,link:d}:null})},bn=()=>{const e=ce();return k(()=>e.value.metaLocales)},Q8=()=>{const e=lr(),t=ce(),n=Oe(),l=ve();return k(()=>{var a,o;return!(l.value.lastUpdated??t.value.lastUpdated??!0)||!((a=n.value.git)!=null&&a.updatedTime)?null:new Date((o=n.value.git)==null?void 0:o.updatedTime).toLocaleString(e.value.lang)})},X8=H({name:"AuthorInfo",inheritAttrs:!1,props:{author:{type:Array,required:!0}},setup(e){const t=bn(),n=ot();return()=>e.author.length?s("span",{class:"page-author-info","aria-label":`${t.value.author}${n.value?"":"🖊"}`,...n.value?{}:{"data-balloon-pos":"up"}},[s(_h),s("span",e.author.map(l=>l.url?s("a",{class:"page-author-item",href:l.url,target:"_blank",rel:"noopener noreferrer"},l.name):s("span",{class:"page-author-item"},l.name))),s("span",{property:"author",content:e.author.map(l=>l.name).join(", ")})]):null}}),e6=H({name:"CategoryInfo",inheritAttrs:!1,props:{category:{type:Array,required:!0}},setup(e){const t=bn(),n=Rn(),l=ot();return()=>e.category.length?s("span",{class:"page-category-info","aria-label":`${t.value.category}${l.value?"":"🌈"}`,...l.value?{}:{"data-balloon-pos":"up"}},[s(yh),e.category.map(({name:r,path:i})=>s("span",{class:["page-category-item",{[`color${sr(r,Number(_n.colorNumber))}`]:!l.value,clickable:i}],role:i?"navigation":"",onClick:()=>{i&&n(i)}},r)),s("meta",{property:"articleSection",content:e.category.map(({name:r})=>r).join(",")})]):null}}),t6=H({name:"DateInfo",inheritAttrs:!1,props:{date:{type:Object,default:null},localizedDate:{type:String,default:""}},setup(e){const t=ei(),n=bn(),l=ot();return()=>e.date?s("span",{class:"page-date-info","aria-label":`${n.value.date}${l.value?"":"📅"}`,...l.value?{}:{"data-balloon-pos":"up"}},[s(bh),s("span",{"data-allow-mismatch":"text"},e.localizedDate||e.date.toLocaleDateString(t.value)),s("meta",{property:"datePublished",content:e.date.toISOString()||""})]):null}}),n6=H({name:"OriginalInfo",inheritAttrs:!1,props:{isOriginal:Boolean},setup(e){const t=bn();return()=>e.isOriginal?s("span",{class:"page-original-info"},t.value.origin):null}}),l6=H({name:"ReadingTimeInfo",inheritAttrs:!1,props:{readingTime:{type:Object,default:()=>null},readingTimeLocale:{type:Object,default:()=>null}},setup(e){const t=bn(),n=ot(),l=k(()=>{if(!e.readingTime)return null;const{minutes:r}=e.readingTime;return r<1?"PT1M":`PT${Math.round(r)}M`});return()=>{var r,i;return(r=e.readingTimeLocale)!=null&&r.time?s("span",{class:"page-reading-time-info","aria-label":`${t.value.readingTime}${n.value?"":"⌛"}`,...n.value?{}:{"data-balloon-pos":"up"}},[s(wh),s("span",(i=e.readingTimeLocale)==null?void 0:i.time),s("meta",{property:"timeRequired",content:l.value})]):null}}}),r6=H({name:"TagInfo",inheritAttrs:!1,props:{tag:{type:Array,default:()=>[]}},setup(e){const t=bn(),n=Rn(),l=ot();return()=>e.tag.length?s("span",{class:"page-tag-info","aria-label":`${t.value.tag}${l.value?"":"🏷"}`,...l.value?{}:{"data-balloon-pos":"up"}},[s(kh),e.tag.map(({name:r,path:i})=>s("span",{class:["page-tag-item",{[`color${sr(r,Number(_n.colorNumber))}`]:!l.value,clickable:i}],role:i?"navigation":"",onClick:()=>{i&&n(i)}},r)),s("meta",{property:"keywords",content:e.tag.map(({name:r})=>r).join(",")})]):null}}),i6=H({name:"ReadTimeInfo",inheritAttrs:!1,props:{readingTime:{type:Object,default:()=>null},readingTimeLocale:{type:Object,default:()=>null}},setup(e){const t=bn(),n=ot();return()=>{var l,r,i;return(l=e.readingTimeLocale)!=null&&l.words?s("span",{class:"page-word-info","aria-label":`${t.value.words}${n.value?"":"🔠"}`,...n.value?{}:{"data-balloon-pos":"up"}},[s(Bh),s("span",(r=e.readingTimeLocale)==null?void 0:r.words),s("meta",{property:"wordCount",content:(i=e.readingTime)==null?void 0:i.words})]):null}}}),Ch=H({name:"PageInfo",components:{AuthorInfo:X8,CategoryInfo:e6,DateInfo:t6,OriginalInfo:n6,PageViewInfo:Or,ReadingTimeInfo:l6,TagInfo:r6,WordInfo:i6},props:{items:{type:[Array,Boolean],default:()=>["Author","Original","Date","PageView","ReadingTime","Category","Tag"]},info:{type:Object,required:!0}},setup(e){const t=ot();return()=>e.items?s("div",{class:"page-info"},e.items.map(n=>s(kt(`${n}Info`),{...e.info,isPure:t.value}))):null}}),a6=H({name:"PageTitle",setup(){const e=Oe(),t=ve(),n=ce(),{info:l,items:r}=d8();return()=>s("div",{class:"vp-page-title"},[s("h1",[n.value.titleIcon===!1?null:s(qe,{icon:t.value.icon}),e.value.title]),s(Ch,{info:l.value,...r.value===null?{}:{items:r.value}}),s("hr")])}}),xh=()=>s(me,{name:"edit"},()=>[s("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"}),s("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"})]);xh.displayName="EditIcon";const o6=H({name:"PageMeta",setup(){const e=ce(),t=Z8(),n=Q8(),l=W8();return()=>{var i;const{metaLocales:r}=e.value;return s("footer",{class:"vp-page-meta"},[t.value?s("div",{class:"vp-meta-item edit-link"},s(it,{class:"vp-meta-label",config:t.value},{before:()=>s(xh)})):null,s("div",{class:"vp-meta-item git-info"},[n.value?s("div",{class:"update-time"},[s("span",{class:"vp-meta-label"},`${r.lastUpdated}: `),s("span",{class:"vp-meta-info","data-allow-mismatch":"text"},n.value)]):null,(i=l.value)!=null&&i.length?s("div",{class:"contributors"},[s("span",{class:"vp-meta-label"},`${r.contributors}: `),l.value.map(({email:a,name:o},c)=>[s("span",{class:"vp-meta-info",title:`email: ${a}`},o),c!==l.value.length-1?",":""])]):null])])}}}),s6=H({name:"PrintButton",setup(){const e=tn(),t=ce();return()=>e.value.print===!1?null:s("button",{type:"button",class:"print-button",title:t.value.metaLocales.print,onClick:()=>{window.print()}},s(Ah))}}),Sh=H({name:"TOC",props:{items:{type:Array,default:()=>[]},headerDepth:{type:Number,default:2}},slots:Object,setup(e,{slots:t}){const n=Ut(),l=Oe(),r=bn(),[i,a]=ta(),o=$e(),c=ee("-1.7rem"),u=f=>{var h;(h=o.value)==null||h.scrollTo({top:f,behavior:"smooth"})},d=()=>{if(o.value){const f=document.querySelector(".vp-toc-item.active");f?c.value=`${f.getBoundingClientRect().top-o.value.getBoundingClientRect().top+o.value.scrollTop}px`:c.value="-1.7rem"}else c.value="-1.7rem"};return we(()=>{pe(()=>n.hash,f=>{if(o.value){const h=document.querySelector(`#toc a.vp-toc-link[href$="${f}"]`);if(!h)return;const{top:p,height:g}=o.value.getBoundingClientRect(),{top:v,height:y}=h.getBoundingClientRect();vp+g&&u(o.value.scrollTop+v+y-p-g)}}),pe(()=>n.fullPath,d,{flush:"post",immediate:!0})}),()=>{var g,v;const f=({title:y,level:_,slug:A})=>s(He,{to:`#${A}`,class:["vp-toc-link",`level${_}`],onClick:()=>{a()}},()=>y),h=(y,_)=>y.length&&_>0?s("ul",{class:"vp-toc-list"},y.map(A=>{const m=h(A.children,_-1);return[s("li",{class:["vp-toc-item",{active:n.hash===`#${A.slug}`}]},f(A)),m?s("li",m):null]})):null,p=e.items.length?h(e.items,e.headerDepth):l.value.headers?h(l.value.headers,e.headerDepth):null;return p?s("div",{class:"vp-toc-placeholder"},[s("aside",{id:"toc","vp-toc":""},[(g=t.before)==null?void 0:g.call(t),s("div",{class:"vp-toc-header",onClick:()=>{a()}},[r.value.toc,s(s6),s("div",{class:["arrow",i.value?"down":"end"]})]),s("div",{class:["vp-toc-wrapper",i.value?"open":""],ref:o},[p,s("div",{class:"vp-toc-marker",style:{top:c.value}})]),(v=t.after)==null?void 0:v.call(t)])]):null}}}),c6=H({name:"NormalPage",slots:Object,setup(e,{slots:t}){const n=ve(),{isDarkmode:l}=ur(),r=ce(),i=k(()=>n.value.toc??r.value.toc??!0),a=k(()=>n.value.headerDepth??r.value.headerDepth??2);return()=>s("main",{id:"main-content",class:"vp-page"},s(Ft("LocalEncrypt")?kt("LocalEncrypt"):vo,()=>{var o,c,u,d;return[(o=t.top)==null?void 0:o.call(t),n.value.cover?s("div",{class:"page-cover"},s("img",{src:Ae(n.value.cover),alt:"","no-view":""})):null,s(K8),s(a6),i.value?s(Sh,{headerDepth:a.value},{before:t.tocBefore?()=>t.tocBefore():null,after:t.tocAfter?()=>t.tocAfter():null}):null,(c=t.contentBefore)==null?void 0:c.call(t),s(hl),(u=t.contentAfter)==null?void 0:u.call(t),s(o6),s(q8),Ft("CommentService")?s(kt("CommentService"),{darkmode:l.value}):null,(d=t.bottom)==null?void 0:d.call(t)]}))}}),u6=(e,t)=>{const n=e.__vccOpts||e;for(const[l,r]of t)n[l]=r;return n},d6={name:"adsense-inline",components:{"normal-page":c6},mounted(){this.adsenseAddLoad()},methods:{adsenseAddLoad(){let e=document.createElement("script");e.type="text/javascript",e.text="(adsbygoogle = window.adsbygoogle || []).push({});",document.getElementsByTagName("body")[0].appendChild(e)},loadBaiduAdAsync(){(window.slotbydup=window.slotbydup||[]).push({id:"u6953633",container:"_vyps37o7ou",async:!0})}}};function f6(e,t,n,l,r,i){const a=kt("normal-page",!0);return U1(),K1(a,null,{contentBefore:$i(()=>t[0]||(t[0]=[Sl("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)])),tocAfter:$i(()=>t[1]||(t[1]=[Sl("div",{class:"slot-demo-block"},"小站收益甚微,请帮忙点击下文章上面的广告(需关闭广告屏蔽插件)也可微信支付打赏鼓励作者 ",-1),Sl("img",{class:"slot-img",src:"https://github-images.wenzhihuai.com/test/image-20240901210440204.png",alt:""},null,-1)])),_:1})}const h6=u6(d6,[["render",f6],["__scopeId","data-v-826d2cba"],["__file","NormalPage.vue"]]),p6=H({name:"PortfolioHero",slots:Object,setup(e,{slots:t}){const n=Nf(),l=ve(),r=ee(0),i=k(()=>{var h;return((h=l.value.titles)==null?void 0:h[r.value])??""}),a=ee(""),o=k(()=>{const{name:h,avatar:p,avatarDark:g,avatarAlt:v,avatarStyle:y}=l.value;return{name:h??n.value.name,avatar:p?Ae(p):null,avatarDark:g?Ae(g):null,avatarStyle:y,alt:(v||h)??""}}),c=k(()=>{const{bgImage:h,bgImageDark:p,bgImageStyle:g}=l.value;return{image:ke(h)?Ae(h):null,imageDark:ke(p)?Ae(p):null,bgStyle:g}}),u=k(()=>{const{welcome:h,name:p,titles:g,medias:v}=l.value;return{name:p??n.value.name,welcome:h??"👋 Hi There, I'm",title:a.value,titles:g??[],medias:v??[]}}),d=()=>{a.value="";let h=0,p=!1;const g=async()=>{if(!p)if(a.value+=i.value[h],h+=1,await Qt(),h{g()},150);else{const v=u.value.titles.length;setTimeout(()=>{r.value=v<=1||r.value===u.value.titles.length-1?0:r.value+1},1e3)}};return g(),()=>{p=!0}};let f;return we(()=>{pe(i,()=>{f==null||f(),f=d()},{immediate:!0})}),()=>{var h,p,g;return s("section",{id:"portfolio",class:["vp-portfolio",{bg:c.value.image}]},[((h=t.bg)==null?void 0:h.call(t,c.value))??[c.value.image?s("div",{class:["vp-portfolio-mask",{light:c.value.imageDark}],style:[{background:`url(${c.value.image}) center/cover no-repeat`},c.value.bgStyle]}):null,c.value.imageDark?s("div",{class:"vp-portfolio-mask dark",style:[{background:`url(${c.value.imageDark}) center/cover no-repeat`},c.value.bgStyle]}):null],((p=t.avatar)==null?void 0:p.call(t,o.value))??s("div",{class:"vp-portfolio-avatar"},[s(oe,{delay:.04},()=>{const{avatarDark:v,name:y,alt:_,avatarStyle:A}=o.value;return[s("img",{key:"light",class:{light:v},src:o.value.avatar,title:y,alt:_,style:A}),v?s("img",{key:"dark",class:"dark",src:v,title:y,alt:_,style:A}):null]})]),s("div",{class:"vp-portfolio-container"},((g=t.info)==null?void 0:g.call(t,u.value))??s("div",{class:"vp-portfolio-info"},[s(oe,{appear:!0,delay:.08},()=>s("h6",{class:"vp-portfolio-welcome"},u.value.welcome)),s(oe,{appear:!0,delay:.12},()=>s("h1",{class:"vp-portfolio-name",id:"main-title"},u.value.name)),s(oe,{appear:!0,delay:.16},()=>s("h2",{class:"vp-portfolio-title"},a.value)),s(oe,{appear:!0,delay:.2},()=>u.value.medias.length?s("div",{class:"vp-portfolio-medias"},u.value.medias.map(({name:v,url:y,icon:_})=>s("a",{class:"vp-portfolio-media",href:y,rel:"noopener noreferrer",target:"_blank",title:v},s(qe,{icon:_})))):Ft("SocialMedias")?s(kt("SocialMedias")):null)]))])}}}),v6=H({name:"PortfolioHome",setup(){const e=ve(),t=k(()=>e.value.content??"portfolio");return()=>s("main",{id:"main-content",class:"vp-page vp-portfolio-home","aria-labelledby":"main-title"},[s(p6),t.value==="none"?null:s("div",{},s(oe,{appear:!0,delay:.24},()=>s(hl,{class:{"vp-portfolio-content":t.value==="portfolio"}})))])}}),ko=H({name:"SkipLink",props:{content:{type:String,default:"main-content"}},setup(e){const t=Oe(),n=ce(),l=$e(),r=({target:i})=>{const a=document.querySelector(i.hash);if(a){const o=()=>{a.removeAttribute("tabindex"),a.removeEventListener("blur",o)};a.setAttribute("tabindex","-1"),a.addEventListener("blur",o),a.focus(),window.scrollTo(0,0)}};return we(()=>{pe(()=>t.value.path,()=>l.value.focus())}),()=>[s("span",{ref:l,tabindex:"-1"}),s("a",{href:`#${e.content}`,class:"vp-skip-link sr-only",onClick:r},n.value.routeLocales.skipToContent)]}}),m6=H({name:"Layout",slots:Object,setup(e,{slots:t}){const n=tn(),l=ce(),r=Oe(),i=ve(),a=ot(),{isMobile:o}=cr(),c=k(()=>{var u,d;return((u=l.value.blog)==null?void 0:u.sidebarDisplay)??((d=n.value.blog)==null?void 0:d.sidebarDisplay)??"mobile"});return()=>[s(ko),s(Ao,{},{default:()=>{var u;return((u=t.default)==null?void 0:u.call(t))??(i.value.portfolio?s(v6):i.value.home?s(G8):s(a.value?vo:gh,()=>s(h6,{key:r.value.path},{top:t.top?()=>t.top():null,bottom:t.bottom?()=>t.bottom():null,contentBefore:t.contentBefore?()=>t.contentBefore():null,contentAfter:t.contentAfter?()=>t.contentAfter():null,tocBefore:t.tocBefore?()=>t.tocBefore():null,tocAfter:t.tocAfter?()=>t.tocAfter():null})))},navScreenBottom:c.value==="none"&&Ft("BloggerInfo")?()=>s(kt("BloggerInfo")):null,sidebar:!o.value&&c.value==="always"&&Ft("BloggerInfo")?()=>s(kt("BloggerInfo")):null})]}}),g6=H({name:"NotFoundHint",setup(){const e=ce(),t=()=>{const n=e.value.routeLocales.notFoundMsg;return n[Math.floor(Math.random()*n.length)]};return()=>s("div",{class:"not-found-hint"},[s("p",{class:"error-code"},"404"),s("h1",{class:"error-title"},e.value.routeLocales.notFoundTitle),s("p",{class:"error-hint"},t())])}}),E6=H({name:"NotFound",slots:Object,setup(e,{slots:t}){const n=en(),l=Mt(),r=ce();return()=>[s(ko),s(Ao,{noSidebar:!0},()=>{var i;return s("main",{id:"main-content",class:"vp-page not-found"},((i=t.default)==null?void 0:i.call(t))??[s(g6),s("div",{class:"actions"},[s("button",{type:"button",class:"action-button",onClick:()=>{window.history.go(-1)}},r.value.routeLocales.back),s("button",{type:"button",class:"action-button",onClick:()=>{n.push(r.value.home??l.value)}},r.value.routeLocales.home)])])})]}}),_6={Zhihu:' ',Github:' ',Gitee:' ',BiliBili:' ',WechatPay:' '},b6={category:{"/":{path:"/category/",map:{}}},tag:{"/":{path:"/tag/",map:{}}}},Th=["/interesting/mini%E4%B8%BB%E6%9C%BA/mac%E8%BF%9E%E6%8E%A5%E4%B8%BB%E6%9C%BA.html","/system-design/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/%E6%8E%A8%E8%8D%90%E5%B7%A5%E7%A8%8B-%E6%A6%82%E8%BF%B0.html","/about-the-author/personal-life/2024-11-09%E4%B8%8A%E6%B5%B7%E8%BF%AA%E6%96%AF%E5%B0%BC.html","/interesting/mini%E4%B8%BB%E6%9C%BA/%E4%B9%B0%E4%BA%86%E4%B8%AAmini%E4%B8%BB%E6%9C%BA.html","/java/%E6%B5%81%E7%A8%8B%E7%BC%96%E6%8E%92LiteFlow.html","/system-design/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F%E5%85%A5%E9%97%A8.html","/system-design/%E8%AE%A1%E7%AE%97%E5%B9%BF%E5%91%8A/%E8%AE%A1%E7%AE%97%E5%B9%BF%E5%91%8A%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%E5%85%A5%E9%97%A8%E6%80%BB%E7%BB%93.html","/interesting/%E7%A8%8B%E5%BA%8F%E5%91%98%E5%89%AF%E4%B8%9A%E6%8E%A2%E7%B4%A2%E4%B9%8B%E7%94%B5%E5%95%86.html","/about-the-author/personal-life/2024-07-24.html","/stock/","/stock/%E8%B5%9B%E5%8A%9B%E6%96%AF.html","/interesting/","/interesting/%E5%9F%BA%E4%BA%8EOLAP%E5%81%9A%E4%B8%9A%E5%8A%A1%E7%9B%91%E6%8E%A7.html","/interesting/idea%E8%AE%BE%E7%BD%AE.html","/interesting/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%8F%8D%E7%BC%96%E8%AF%91.html","/interesting/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E6%95%B4%E7%90%86.html","/java/%E9%AB%98%E5%8F%AF%E7%94%A8.html","/java/%E9%AB%98%E5%B9%B6%E5%8F%91.html","/java/%E9%AB%98%E6%80%A7%E8%83%BD.html","/system-design/feed.html","/database/mysql/%E8%A1%8C%E9%94%81%EF%BC%8C%E8%A1%A8%E9%94%81%EF%BC%8C%E6%84%8F%E5%90%91%E9%94%81.html","/database/redis/%E4%B8%80%E8%87%B4%E6%80%A7hash%E7%AE%97%E6%B3%95%E5%92%8C%E5%93%88%E5%B8%8C%E6%A7%BD.html","/java/JVM/jvm(java%E8%99%9A%E6%8B%9F%E6%9C%BA).html","/java/io/nio.html","/middleware/sentinel/springcloud_sentinel.html","/middleware/sentinel/%E5%85%A5%E9%97%A8%E4%BD%BF%E7%94%A8.html","/database/elasticsearch/%E5%9F%BA%E7%A1%80.html","/interesting/%E4%B8%80%E4%BA%9B%E4%B8%8D%E5%B8%B8%E7%94%A8%E4%BD%86%E5%BE%88%E5%AE%9E%E7%94%A8%E7%9A%84%E5%91%BD%E4%BB%A4.html","/kubernetes/Jenkins%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AC%94%E8%AE%B0.html","/kubernetes/Kubernetes%E5%AE%B9%E5%99%A8%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86.html","/kubernetes/request_limit.html","/java/JVM/%E8%B0%83%E4%BC%98%E6%80%9D%E8%B7%AF.html","/java/JVM/%E5%B8%B8%E7%94%A8GC%E5%9B%9E%E6%94%B6%E5%99%A8.html","/java/JVM/Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B.html","/java/JVM/%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0%E5%92%8C%E6%A0%B9%E5%8F%AF%E8%BE%BE%E7%AE%97%E6%B3%95.html","/java/%E7%BA%BF%E7%A8%8B/synchronized.html","/interesting/mini%E4%B8%BB%E6%9C%BA/","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/","/java/JVM/","/java/JVM/cms.html","/java/JVM/g1.html","/java/JVM/zgc.html","/java/SpringBoot/","/java/io/","/java/%E7%BA%BF%E7%A8%8B/","/java/%E7%BA%BF%E7%A8%8B/volatile.html","/java/%E7%BD%91%E7%BB%9C/","/kubernetes/devops/","/database/redis/RedissonLock%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.html","/middleware/canal/%E4%B8%AD%E9%97%B4%E4%BB%B6%E2%80%94%E2%80%94canal%E5%B0%8F%E8%AE%B0.html","/middleware/zookeeper/%E5%9F%BA%E4%BA%8EZooKeeper%E7%9A%84%E9%98%9F%E5%88%97%E7%88%AC%E8%99%AB.html","/java/%E7%BD%91%E7%BB%9C/IP%E3%80%81HTTP%E3%80%81HTTPS%E3%80%81HTTP2.0.html","/java/%E9%AB%98%E6%80%A7%E8%83%BD%E9%AB%98%E5%B9%B6%E5%8F%91%E9%AB%98%E5%8F%AF%E7%94%A8%E7%9A%84%E4%B8%80%E4%BA%9B%E6%80%9D%E8%80%83.html","/link/main.html","/interesting/%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","/java/SpringBoot/aop.html","/java/SpringBoot/Spring%20Boot%20Prometheus%E4%BD%BF%E7%94%A8.html","/about-the-author/works/%E4%B8%AA%E4%BA%BA%E4%BD%9C%E5%93%81.html","/java/SpringBoot/webflux.html","/interesting/starcraft-ai.html","/about-the-author/personal-life/wewe.html","/about-the-author/","/middleware/zookeeper/zookeeper.html","/interesting/chatgpt.html","/interesting/tesla.html","/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","/database/elasticsearch/elasticsearch%E6%BA%90%E7%A0%81debug.html","/database/","/donate/","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/10.%E5%8E%86%E6%97%B68%E5%B9%B4%E6%9C%80%E7%BB%88%E6%94%B9%E7%89%88.html","/open-source-project/","/middleware/","/interview/tiktok2023.html","/database/mysql/1mysql.html","/database/mysql/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%BC%93%E5%AD%98.html","/kubernetes/spark%20on%20k8s%20operator.html","/bigdata/spark/elastic-spark.html","/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","/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","/middleware/kafka/kafka.html","/life/2017.html","/life/2019.html","/java/serverlog.html","/life/2018.html","/database/redis/redis%E7%BC%93%E5%AD%98.html","/java/JVM/JVM%E8%B0%83%E4%BC%98%E5%8F%82%E6%95%B0.html","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/1.%E5%8E%86%E5%8F%B2%E4%B8%8E%E6%9E%B6%E6%9E%84.html","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/2.Lucene%E7%9A%84%E4%BD%BF%E7%94%A8.html","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/3.%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/4.%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F.html","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/5.%E5%B0%8F%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2.html","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/6.%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD.html","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/7.%E9%82%A3%E4%BA%9B%E7%89%9B%E9%80%BC%E7%9A%84%E6%8F%92%E4%BB%B6.html","/java/JVM/%E4%B8%80%E6%AC%A1jvm%E8%B0%83%E4%BC%98%E8%BF%87%E7%A8%8B.html","/bigdata/","/cloudnative/","/java/","/kubernetes/","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/8.%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%9A%84%E6%83%85%E6%84%9F%E5%88%86%E6%9E%90.html","/interesting/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/9.%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96.html","/kubernetes/devops/devops-ping-tai.html"],y6={article:{"/":{path:"/article/",indexes:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]}},star:{"/":{path:"/star/",indexes:[]}},timeline:{"/":{path:"/timeline/",indexes:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]}},slide:{"/":{path:"/slide/",indexes:[]}}},ya=$e(b6);In(ya);const Lh=e=>{const t=Oe(),n=ve(),l=Mt();return k(()=>{var o;const r=e??((o=n.value.blog)==null?void 0:o.key)??"";if(!r)return console.warn("useBlogCategory: key not found"),{path:"/",map:{}};if(!(r in ya.value))throw new Error(`useBlogCategory: key ${r} is invalid`);const i=ya.value[r][l.value],a={path:i.path,map:{}};for(const c in i.map){const u=i.map[c];a.map[c]={path:u.path,items:[]};for(const d of u.indexes){const{path:f,meta:h}=wt(Th[d]);a.map[c].items.push({path:f,info:h})}t.value.path===u.path&&(a.currentItems=a.map[c].items)}return a})},Aa=$e(y6);In(Aa);const oi=e=>{const t=ve(),n=Mt();return k(()=>{var a;const l=e??((a=t.value.blog)==null?void 0:a.key)??"";if(!l)return console.warn("useBlogType: key not found"),{path:"/",items:[]};if(!(l in Aa.value))throw new Error(`useBlogType: key ${e} is invalid`);const r=Aa.value[l][n.value],i={path:r.path,items:[]};for(const o of r.indexes){const{path:c,meta:u}=wt(Th[o]);i.items.push({path:c,info:u})}return i})},Oh=Symbol(""),wo=()=>{const e=Se(Oh);if(!e)throw new Error("useTimeline() is called without provider.");return e},A6=()=>{const e=oi("timeline"),t=ei(),n=k(()=>{const l=[];return e.value.items.forEach(({info:r,path:i})=>{const a=lo(r[Ke.date]);if(a){const o=a.getFullYear();(!l[0]||l[0].year!==o)&&l.unshift({year:o,items:[]}),l[0].items.push({date:a.toLocaleDateString(t.value,{month:"numeric",day:"numeric"}),info:r,path:i})}}),{...e.value,config:l.reverse()}});Ot(Oh,n)},Dh=Symbol(""),dr=()=>{const e=Se(Dh);if(!e)throw new Error("useArticles() is called without provider.");return e},k6=()=>{const e=oi("article");Ot(Dh,e)},Ph=Symbol.for("categoryMap"),fr=()=>{const e=Se(Ph);if(!e)throw new Error("useCategoryMap() is called without provider.");return e},w6=()=>{const e=Lh("category");Ot(Ph,e)},Ih=Symbol(""),Bo=()=>{const e=Se(Ih);if(!e)throw new Error("useStars() is called without provider.");return e},B6=()=>{const e=oi("star");Ot(Ih,e)},Fh=Symbol.for("tagMap"),hr=()=>{const e=Se(Fh);if(!e)throw new Error("useTagMap() is called without provider.");return e},C6=()=>{const e=Lh("tag");Ot(Fh,e)},x6=()=>{k6(),w6(),B6(),C6(),A6()},pr=()=>{const e=tn(),t=ce();return k(()=>({...e.value.blog,...t.value.blog}))},S6=e=>{const t=ce();return k(()=>{const{[Ke.author]:n}=e.value;return n?Kl(n):n===!1?[]:Kl(t.value.author,!1)})},T6=e=>{const t=fr();return k(()=>Qf(e.value[Ke.category]).map(n=>({name:n,path:t.value.map[n].path})))},L6=e=>{const t=hr();return k(()=>Xf(e.value[Ke.tag]).map(n=>({name:n,path:t.value.map[n].path})))},O6=e=>k(()=>{const{[Ke.date]:t}=e.value;return lo(t)}),D6=e=>{const t=sl(e,"info"),n=pr(),l=S6(t),r=T6(t),i=L6(t),a=O6(t),o=zf(),c=k(()=>({author:l.value,category:r.value,date:a.value,localizedDate:t.value[Ke.localizedDate]??"",tag:i.value,isOriginal:t.value[Ke.isOriginal]??!1,readingTime:t.value[Ke.readingTime]??null,readingTimeLocale:t.value[Ke.readingTime]&&o.value?Hf(t.value[Ke.readingTime],o.value):null,pageview:e.path})),u=k(()=>n.value.articleInfo);return{info:c,items:u}},Rh=H({name:"SocialMedias",setup(){const e=pr(),t=ot(),n=k(()=>En(e.value.medias??{}).map(([l,r])=>typeof r=="string"?{name:l,icon:_6[l],link:r}:{name:l,...r}));return()=>n.value.length?s("div",{class:"vp-social-medias"},n.value.map(({name:l,icon:r,link:i})=>s("a",{class:"vp-social-media",href:i,rel:"noopener noreferrer",target:"_blank","aria-label":l||"",...t.value?{}:{"data-balloon-pos":"up"},innerHTML:gn(r)?` `:r}))):null}}),Co=H({name:"BloggerInfo",setup(){const e=pr(),t=lr(),n=ce(),l=dr(),r=fr(),i=hr(),a=wo(),o=Rn(),c=k(()=>{var h;return e.value.name??((h=Kl(n.value.author)[0])==null?void 0:h.name)??t.value.title}),u=k(()=>e.value.avatar??n.value.logo),d=k(()=>n.value.blogLocales),f=k(()=>e.value.intro);return()=>{const{article:h,category:p,tag:g,timeline:v}=d.value,y=[[l.value.path,l.value.items.length,h],[r.value.path,hn(r.value.map).length,p],[i.value.path,hn(i.value.map).length,g],[a.value.path,a.value.items.length,v]];return s("div",{class:"vp-blogger-info",vocab:"https://schema.org/",typeof:"Person"},[s("div",{class:"vp-blogger",...f.value?{"aria-label":d.value.intro,"data-balloon-pos":"down",role:"link",onClick:()=>o(f.value)}:{}},[u.value?s("img",{class:"vp-blogger-avatar",src:Ae(u.value),property:"image",alt:"Blogger Avatar",loading:"lazy"}):null,c.value?s("div",{class:"vp-blogger-name",property:"name"},c.value):null,e.value.description?s("div",{class:"vp-blogger-description",innerHTML:e.value.description}):null,f.value?s("meta",{property:"url",content:Ae(f.value)}):null]),s("div",{class:"vp-blog-counts"},y.map(([_,A,m])=>s(He,{class:"vp-blog-count",to:_},()=>[s("div",{class:"count"},A),s("div",m)]))),s(Rh)])}}}),xo=()=>s(me,{name:"category"},()=>s("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"}));xo.displayName="CategoryIcon";const So=()=>s(me,{name:"tag"},()=>s("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"}));So.displayName="TagIcon";const To=()=>s(me,{name:"timeline"},()=>s("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"}));To.displayName="TimelineIcon";const Mh=()=>s(me,{name:"slides"},()=>s("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"}));Mh.displayName="SlideIcon";const Vh=()=>s(me,{name:"sticky"},()=>[s("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"})]);Vh.displayName="StickyIcon";const si=()=>s(me,{name:"article"},()=>s("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"}));si.displayName="ArticleIcon";const Nh=()=>s(me,{name:"book"},()=>s("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"}));Nh.displayName="BookIcon";const jh=()=>s(me,{name:"link"},()=>s("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"}));jh.displayName="LinkIcon";const Hh=()=>s(me,{name:"project"},()=>s("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"}));Hh.displayName="ProjectIcon";const zh=()=>s(me,{name:"friend"},()=>s("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"}));zh.displayName="FriendIcon";const ka=()=>s(me,{name:"slide-down"},()=>s("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"}));ka.displayName="SlideDownIcon";const $h=()=>s("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:' '});$h.displayName="EmptyIcon";const Uh=()=>s(me,{name:"lock"},()=>s("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"}));Uh.displayName="LockIcon";const P6=H({name:"ArticleItem",props:{info:{type:Object,required:!0},path:{type:String,required:!0}},slots:Object,setup(e,{slots:t}){const n=sl(e,"info"),{info:l,items:r}=D6(e);return()=>{var h,p,g;const{[Qe.title]:i,[Ke.type]:a,[Ke.isEncrypted]:o=!1,[Ke.cover]:c,[Ke.excerpt]:u,[Ke.sticky]:d}=n.value,f=l.value;return s("div",{class:"vp-article-wrapper"},s("article",{class:"vp-article-item",vocab:"https://schema.org/",typeof:"Article"},[((h=t.cover)==null?void 0:h.call(t,{cover:c}))??(c?[s("img",{class:"vp-article-cover",src:Ae(c),alt:"",loading:"lazy"}),s("meta",{property:"image",content:Ae(c)})]:[]),d?s(Vh):null,s(He,{to:e.path},()=>{var v;return((v=t.title)==null?void 0:v.call(t,{title:i,isEncrypted:o,type:a}))??s("header",{class:"vp-article-title"},[o?s(Uh):null,a===ga.slide?s(Mh):null,s("span",{property:"headline"},i)])}),((p=t.excerpt)==null?void 0:p.call(t,{excerpt:u}))??(u?s("div",{class:"vp-article-excerpt",innerHTML:u}):null),s("hr",{class:"vp-article-hr"}),((g=t.info)==null?void 0:g.call(t,{info:f}))??s(Ch,{info:f,...r.value?{items:r.value}:{}})]))}}}),I6=H({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 l=ce(),r=ee(""),i=k(()=>l.value.paginationLocales),a=k(()=>Math.ceil(e.total/e.perPage)),o=k(()=>!!a.value&&a.value!==1),c=k(()=>a.value<7?!1:e.current>4),u=k(()=>a.value<7?!1:e.current{const{current:p}=e;let g=1,v=a.value;const y=[];a.value>=7&&(p<=4&&p4&&p>=a.value-3?(v=a.value,g=a.value-4):a.value>7&&(g=p-2,v=p+2));for(let _=g;_<=v;_++)y.push(_);return y}),f=p=>t("updateCurrentPage",p),h=p=>{const g=parseInt(p,10);g<=a.value&&g>0?f(g):n.pop(` ${i.value.errorText.replace(/\$page/gu,a.value.toString())}`)};return we(()=>{n=new i8}),()=>s("div",{class:"vp-pagination"},o.value?s("nav",{class:"vp-pagination-list"},[s("div",{class:"vp-pagination-number "},[e.current>1?s("div",{class:"prev",role:"navigation",unselectable:"on",onClick:()=>f(e.current-1)},i.value.prev):null,c.value?[s("div",{role:"navigation",onClick:()=>f(1)},1),s("div",{class:"ellipsis"},"...")]:null,d.value.map(p=>s("div",{key:p,class:{active:e.current===p},role:"navigation",onClick:()=>f(p)},p)),u.value?[s("div",{class:"ellipsis"},"..."),s("div",{role:"navigation",onClick:()=>f(a.value)},a.value)]:null,e.currentf(e.current+1)},i.value.next):null]),s("div",{class:"vp-pagination-nav"},[s("label",{for:"navigation-text"},`${i.value.navigate}: `),s("input",{id:"navigation-text",value:r.value,onInput:({target:p})=>{r.value=p.value},onKeydown:p=>{p.key==="Enter"&&(p.preventDefault(),h(r.value))}}),s("button",{class:"vp-pagination-button",type:"button",role:"navigation",title:i.value.action,onClick:()=>h(r.value)},i.value.action)])]):[])}}),Lo=H({name:"ArticleList",props:{items:{type:Array,default:()=>[]}},setup(e){const t=Ut(),n=en(),l=pr(),r=ee(1),i=k(()=>l.value.articlePerPage??10),a=k(()=>e.items.slice((r.value-1)*i.value,r.value*i.value)),o=async c=>{r.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 we(()=>{const{page:c}=t.query;o(c?Number(c):1),pe(r,()=>{const u=document.querySelector("#article-list").getBoundingClientRect().top+window.scrollY;setTimeout(()=>{window.scrollTo(0,u)},100)})}),()=>s("div",{id:"article-list",class:"vp-article-list",role:"feed"},a.value.length?[...a.value.map(({info:c,path:u},d)=>s(oe,{appear:!0,delay:d*.04},()=>s(P6,{key:u,info:c,path:u}))),s(I6,{current:r.value,perPage:i.value,total:e.items.length,onUpdateCurrentPage:o})]:s($h))}}),Gh=H({name:"CategoryList",setup(){const e=Oe(),t=fr();return()=>s("ul",{class:"vp-category-list"},En(t.value.map).sort(([,n],[,l])=>l.items.length-n.items.length).map(([n,{path:l,items:r}])=>s("li",{class:["vp-category",`color${sr(n,Number(_n.colorNumber))}`,{active:l===e.value.path}]},s(He,{to:l},()=>[n,s("span",{class:"vp-category-count"},r.length)]))))}}),Kh=H({name:"TagList",setup(){const e=ve(),t=hr(),n=l=>{var r;return l===((r=e.value.blog)==null?void 0:r.name)};return()=>s("ul",{class:"vp-tag-list"},En(t.value.map).sort(([,l],[,r])=>r.items.length-l.items.length).map(([l,{path:r,items:i}])=>s("li",{class:["vp-tag",`color${sr(l,Number(_n.colorNumber))}`,{active:n(l)}]},s(He,{to:r},()=>[l,s("span",{class:"vp-tag-count"},i.length)]))))}}),F6=H({name:"TimelineList",setup(){const e=ce(),t=wo(),n=Rn(),l=k(()=>e.value.blogLocales.timeline);return()=>s("div",{class:"timeline-list-wrapper"},[s("div",{class:"timeline-list-title",onClick:()=>n(t.value.path)},[s(To),s("span",{class:"num"},t.value.items.length),l.value]),s("hr"),s("div",{class:"timeline-content"},s("ul",{class:"timeline-list"},t.value.config.map(({year:r,items:i},a)=>s(oe,{appear:!0,delay:.08*(a+1)},()=>s("li",[s("h3",{class:"timeline-year"},r),s("ul",{class:"timeline-year-wrapper"},i.map(({date:o,info:c,path:u})=>s("li",{class:"timeline-item"},[s("span",{class:"timeline-date"},o),s(He,{class:"timeline-title",to:u},()=>c[Qe.title])])))])))))])}}),R6={article:si,category:xo,tag:So,timeline:To},qh=H({name:"InfoList",setup(){const e=ce(),t=dr(),n=fr(),l=k(()=>hn(n.value.map).length),r=Bo(),i=hr(),a=k(()=>hn(i.value.map).length),o=Rn(),c=ee("article"),u=k(()=>e.value.blogLocales);return()=>s("div",{class:"vp-blog-infos"},[s("div",{class:"vp-blog-type-switcher"},En(R6).map(([d,f])=>s("button",{type:"button",class:"vp-blog-type-button",onClick:()=>{c.value=d}},s("div",{class:["vp-blog-type-icon-wrapper",{active:c.value===d}],"aria-label":u.value[d],"data-balloon-pos":"up"},s(f))))),s(oe,()=>c.value==="article"?s("div",{class:"vp-star-article-wrapper"},[s("div",{class:"title",onClick:()=>o(t.value.path)},[s(si),s("span",{class:"num"},t.value.items.length),u.value.article]),s("hr"),r.value.items.length?s("ul",{class:"vp-star-articles"},r.value.items.map(({info:d,path:f},h)=>s(oe,{appear:!0,delay:.08*(h+1)},()=>s("li",{class:"vp-star-article"},s(He,{to:f},()=>d[Qe.title]))))):s("div",{class:"vp-star-article-empty"},u.value.empty.replace("$text",u.value.star))]):c.value==="category"?s("div",{class:"vp-category-wrapper"},[l.value?[s("div",{class:"title",onClick:()=>o(n.value.path)},[s(xo),s("span",{class:"num"},l.value),u.value.category]),s("hr"),s(oe,{delay:.04},()=>s(Gh))]:s("div",{class:"vp-category-empty"},u.value.empty.replace("$text",u.value.category))]):c.value==="tag"?s("div",{class:"vp-tag-wrapper"},[a.value?[s("div",{class:"title",onClick:()=>o(i.value.path)},[s(So),s("span",{class:"num"},a.value),u.value.tag]),s("hr"),s(oe,{delay:.04},()=>s(Kh))]:s("div",{class:"vp-tag-empty"},u.value.empty.replace("$text",u.value.tag))]):s(oe,()=>s(F6)))])}}),ci=H({name:"BlogWrapper",slots:Object,setup(e,{slots:t}){const{isMobile:n}=cr();return()=>[s(ko),s(Ao,{noSidebar:!0,noToc:!0},{default:()=>t.default(),navScreenBottom:()=>s(Co),sidebar:n.value?()=>s(qh):null})]}}),vr=()=>s("aside",{class:"vp-blog-info-wrapper"},[s(oe,()=>s(Co)),s(oe,{delay:.04},()=>s(qh))]);vr.displayName="InfoPanel";const M6=H({name:"BlogPage",setup(){const e=Oe(),t=ve(),n=fr(),l=hr();return()=>{const{key:r="",name:i=""}=t.value.blog||{},a=i?r==="category"?n.value.map[i].items:r==="tag"?l.value.map[i].items:[]:[];return s(ci,()=>s("div",{class:"vp-page vp-blog"},s("div",{class:"blog-page-wrapper"},[s("main",{id:"main-content",class:"vp-blog-main"},[s(oe,()=>r==="category"?s(Gh):r==="tag"?s(Kh):null),i?s(oe,{appear:!0,delay:.24},()=>s(Lo,{key:e.value.path,items:a})):null]),s(oe,{delay:.16},()=>s(vr,{key:"blog"}))])))}}}),V6="//theme-hope-assets.vuejs.press/hero/default.jpg",N6=H({name:"BlogHero",slots:Object,setup(e,{slots:t}){const n=ve(),l=lr(),r=$e(),i=k(()=>n.value.heroFullScreen??!1),a=k(()=>{const{heroText:c,heroImage:u,heroImageDark:d,heroAlt:f,heroImageStyle:h,tagline:p}=n.value;return{text:c??l.value.title??"Hello",tagline:p??"",image:u?Ae(u):null,imageDark:d?Ae(d):null,alt:f??c??"",imageStyle:h,isFullScreen:i.value}}),o=k(()=>{const{bgImage:c,bgImageDark:u,bgImageStyle:d}=n.value;return{image:ke(c)?Ae(c):c===!1?null:V6,imageDark:ke(u)?Ae(u):null,bgStyle:d,isFullScreen:i.value}});return()=>{var c,u;return n.value.hero===!1?null:s("div",{ref:r,class:["vp-blog-hero",{fullscreen:i.value,"no-bg":!o.value.image}]},[((c=t.bg)==null?void 0:c.call(t,o.value))??[o.value.image?s("div",{class:["vp-blog-mask",{light:o.value.imageDark}],style:[{background:`url(${o.value.image}) center/cover no-repeat`},o.value.bgStyle]}):null,o.value.imageDark?s("div",{class:"vp-blog-mask dark",style:[{background:`url(${o.value.imageDark}) center/cover no-repeat`},o.value.bgStyle]}):null],((u=t.info)==null?void 0:u.call(t,a.value))??[s(oe,{appear:!0,type:"group",delay:.04},()=>{const{image:d,imageDark:f,imageStyle:h,alt:p}=a.value;return[d?s("img",{key:"light",class:["vp-blog-hero-image",{light:f}],style:h,src:d,alt:p}):null,f?s("img",{key:"dark",class:"vp-blog-hero-image dark",style:h,src:f,alt:p}):null]}),s(oe,{appear:!0,delay:.08},()=>a.value.text?s("h1",{class:"vp-blog-hero-title"},a.value.text):null),s(oe,{appear:!0,delay:.12},()=>a.value.tagline?s("p",{class:"vp-blog-hero-description",innerHTML:a.value.tagline}):null)],a.value.isFullScreen?s("button",{type:"button",class:"slide-down-button",onClick:()=>{window.scrollTo({top:r.value.clientHeight,behavior:"smooth"})}},[s(ka),s(ka)]):null])}}}),j6=["link","article","book","project","friend"],H6=H({name:"ProjectPanel",components:{ArticleIcon:si,BookIcon:Nh,FriendIcon:zh,LinkIcon:jh,ProjectIcon:Hh},props:{items:{type:Array,required:!0}},setup(e){const t=ot(),n=Rn(),l=(r="",i="icon")=>j6.includes(r)?s(kt(`${r}-icon`)):gn(r)?s("img",{class:"vp-project-image",src:r,alt:i}):ni(r)?s("img",{class:"vp-project-image",src:Ae(r),alt:i}):s(qe,{icon:r});return()=>s("div",{class:"vp-project-panel"},e.items.map(({icon:r,link:i,name:a,desc:o,background:c})=>s("div",{class:["vp-project-card",{[`color${sr(a,Number(_n.colorNumber))}`]:!t.value&&!c}],...c?{style:c}:{},onClick:()=>n(i)},[l(r,a),s("div",{class:"vp-project-name"},a),s("div",{class:"vp-project-desc"},o)])))}}),z6=H({name:"BlogHomePage",setup(){const e=dr(),t=ve(),n=k(()=>t.value.projects??[]);return()=>s("div",{class:"vp-page vp-blog-home"},[s(N6),s("div",{class:"blog-page-wrapper"},[s("main",{id:"main-content",class:"vp-blog-main"},[n.value.length?s(oe,{appear:!0,delay:.16},()=>s(H6,{items:n.value})):null,s(oe,{appear:!0,delay:.24},()=>s(Lo,{items:e.value.items}))]),s(oe,{appear:!0,delay:.16},()=>s(vr,{key:"blog"}))]),s(oe,{appear:!0,delay:.28},()=>s(hl))])}}),Wh=()=>s(ci,()=>s(z6));Wh.displayName="BlogHome";var $6=[{key:"slide",path:"/slide/"}];const U6=H({name:"ArticleType",setup(){const e=Oe(),t=Mt(),n=ce(),l=dr(),r=Bo(),i=k(()=>{const a=n.value.blogLocales;return[{text:a.all,path:l.value.path},{text:a.star,path:r.value.path},...$6.map(({key:o,path:c})=>{const u=c.replace(/^\//,t.value);return{text:a[o]??wt(u).meta[Qe.title]??o,path:u}})]});return()=>s("ul",{class:"vp-article-type-wrapper"},i.value.map(a=>s("li",{class:["vp-article-type",{active:a.path===e.value.path}]},s(He,{to:a.path},()=>a.text))))}}),G6=H({name:"BlogPage",setup(){const e=oi(),t=ve(),n=Oe(),l=dr(),r=Bo(),i=k(()=>{const{key:a="",type:o}=t.value.blog||{};return a==="star"?r.value.items:o==="type"&&a?e.value.items:l.value.items});return()=>s(ci,()=>s("div",{class:"vp-page vp-blog"},s("div",{class:"blog-page-wrapper"},[s("main",{id:"main-content",class:"vp-blog-main"},[s(oe,()=>s(U6)),s(oe,{appear:!0,delay:.24},()=>s(Lo,{key:n.value.path,items:i.value}))]),s(oe,{delay:.16},()=>s(vr,{key:"blog"}))])))}}),K6=H({name:"TimelineItems",setup(){const e=pr(),t=ce(),n=wo(),l=k(()=>e.value.timeline??t.value.blogLocales.timelineTitle),r=k(()=>n.value.config.map(({year:i})=>({title:i.toString(),level:2,slug:i.toString(),children:[]})));return()=>s("div",{class:"timeline-wrapper"},s("ul",{class:"timeline-content"},[s(oe,()=>s("li",{class:"motto"},l.value)),s(Sh,{items:r.value}),n.value.config.map(({year:i,items:a},o)=>s(oe,{appear:!0,delay:.08*(o+1),type:"group"},()=>[s("h3",{key:"title",id:i,class:"timeline-year-title"},s("span",i)),s("li",{key:"content",class:"timeline-year-list"},[s("ul",{class:"timeline-year-wrapper"},a.map(({date:c,info:u,path:d})=>s("li",{class:"timeline-item"},[s("span",{class:"timeline-date"},c),s(He,{class:"timeline-title",to:d},()=>u[Qe.title])])))])]))]))}}),Jh=()=>s(ci,()=>s("div",{class:"vp-page vp-blog"},s("div",{class:"blog-page-wrapper"},[s("main",{id:"main-content",class:"vp-blog-main"},[s(oe,{appear:!0,delay:.24},()=>s(K6))]),s(oe,{delay:.16},()=>s(vr,{key:"blog"}))])));Jh.displayName="Timeline";gm(e=>{const t=e.t,n=e.I!==!1,l=e.i;return n?{title:t,content:l?()=>[s(qe,{icon:l}),t]:null,order:e.O,index:e.I}:null});const q6={enhance:({app:e,router:t})=>{const{scrollBehavior:n}=t.options;t.options.scrollBehavior=async(...l)=>(await ma.wait(),n(...l)),k8(e),e.component("HopeIcon",qe),e.component("BloggerInfo",Co),e.component("SocialMedias",Rh)},setup:()=>{w8(),v8(),x6()},layouts:{Layout:m6,NotFound:E6,BlogCategory:M6,BlogHome:Wh,BlogType:G6,Timeline:Jh}},W6=Object.freeze(Object.defineProperty({__proto__:null,default:q6},Symbol.toStringTag,{value:"Module"}));var J6={provider:"Giscus",comment:!0,repo:"Zephery/MyWebsite",repoId:"MDEwOlJlcG9zaXRvcnkyMDM2MDIyMDQ=",category:"General",categoryId:"DIC_kwDODCK5HM4Ccp32"};const Y6=J6,Z6=ee(Y6),Yh=Symbol(""),Zh=()=>Se(Yh),Q6=Zh,X6=e=>{e.provide(Yh,Z6)},Qh=()=>s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"32",height:"32",preserveAspectRatio:"xMidYMid",viewBox:"0 0 100 100"},[s("circle",{cx:"28",cy:"75",r:"11",fill:"currentColor"},s("animate",{attributeName:"fill-opacity",begin:"0s",dur:"1s",keyTimes:"0;0.2;1",repeatCount:"indefinite",values:"0;1;1"})),s("path",{fill:"none",stroke:"#88baf0","stroke-width":"10",d:"M28 47a28 28 0 0 1 28 28"},s("animate",{attributeName:"stroke-opacity",begin:"0.1s",dur:"1s",keyTimes:"0;0.2;1",repeatCount:"indefinite",values:"0;1;1"})),s("path",{fill:"none",stroke:"#88baf0","stroke-width":"10",d:"M28 25a50 50 0 0 1 50 50"},s("animate",{attributeName:"stroke-opacity",begin:"0.2s",dur:"1s",keyTimes:"0;0.2;1",repeatCount:"indefinite",values:"0;1;1"}))]);Qh.displayName="LoadingIcon";const nu=["ar","ca","da","de","en","eo","es","fa","fr","he","id","it","ja","ko","nl","pl","pt","ro","ru","th","tr","uk","uz","vi","zh-CN","zh-TW"],eE=H({name:"GiscusComment",props:{identifier:{type:String,required:!0},darkmode:Boolean},setup(e){const t=Q6(),n=ei(),l=k(()=>!!(t.value.repo&&t.value.repoId&&t.value.category&&t.value.categoryId)),r=ee(!1),i=k(()=>{if(nu.includes(n.value))return n.value;const o=n.value.split("-")[0];return nu.includes(o)?o:"en"}),a=k(()=>({repo:t.value.repo,repoId:t.value.repoId,category:t.value.category,categoryId:t.value.categoryId,lang:i.value,theme:e.darkmode?t.value.darkTheme||"dark":t.value.lightTheme||"light",mapping:t.value.mapping||"pathname",term:e.identifier,inputPosition:t.value.inputPosition||"top",reactionsEnabled:t.value.reactionsEnabled===!1?"0":"1",strict:t.value.strict===!1?"0":"1",loading:t.value.lazyLoading===!1?"eager":"lazy",emitMetadata:"0"}));return we(async()=>{await C(()=>import("./giscus-BZxmVUME.js"),[]),r.value=!0}),()=>l.value?s("div",{id:"comment",class:["giscus-wrapper",{"input-top":t.value.inputPosition!=="bottom"}]},r.value?s("giscus-widget",a.value):s(Qh)):null}}),tE=H({name:"CommentService",props:{darkmode:Boolean},setup(e){const t=Zh(),n=Oe(),l=ve(),r=k(()=>l.value.comment??t.value.comment!==!1);return()=>s(eE,{class:"vp-comment","vp-comment":"",identifier:l.value.commentID??n.value.path,darkmode:e.darkmode,style:{display:r.value?"block":"none"}})}}),nE=Bt({enhance:({app:e})=>{X6(e),e.component("CommentService",tE)}}),lE=Object.freeze(Object.defineProperty({__proto__:null,default:nE},Symbol.toStringTag,{value:"Module"}));var rE={"/":{source:"源代码"}},iE=H({name:"SiteInfo",props:{name:{type:String,required:!0},desc:{type:String,default:""},logo:{type:String,default:""},url:{type:String,required:!0},preview:{type:String,required:!0},repo:{type:String,default:""}},setup(e){const t=Fn(rE);return()=>s("div",{class:"vp-site-info","data-name":e.name},[s("a",{class:["vp-site-info-navigator","no-external-link-icon"],title:e.name,href:e.url,target:"_blank"}),s("div",{class:"vp-site-info-preview",style:{background:`url(${Ae(e.preview)}) center/cover no-repeat`}}),s("div",{class:"vp-site-info-detail"},[e.logo?s("img",{class:"vp-site-info-logo",src:e.logo,alt:"",loading:"lazy","no-view":""}):null,s("div",{class:"vp-site-info-name"},e.name),s("div",{class:"vp-site-info-desc"},e.desc)]),e.repo?s("div",{class:"vp-site-info-source-wrapper"},s("a",{class:"vp-site-info-source",href:e.repo,"aria-label":t.value.source,"data-balloon-pos":"left",title:t.value.source,target:"_blank"},s(qf,{link:e.repo}))):null])}});const aE="accelerometer; autoplay; clipboard-write; encrypted-media; fullscreen; gyroscope; picture-in-picture",lu=e=>ke(e)?e:`${e}px`,oE=(e,t=0)=>{const n=$e(),l=k(()=>lu(St(e.width)??"100%")),r=ee("auto"),i=c=>{if(ke(c)){const[u,d]=c.split(":"),f=Number(u)/Number(d);if(!Number.isNaN(f))return f}return typeof c=="number"?c:16/9},a=c=>{const u=St(e.height),d=i(St(e.ratio));return u?lu(u):`${Number(c)/d+St(t)}px`},o=()=>{n.value&&(r.value=a(n.value.clientWidth))};return we(()=>{o(),Re(t)&&pe(t,o),Ie("orientationchange",o),Ie("resize",o)}),{el:n,width:l,height:r,resize:o}},ru="https://player.bilibili.com/player.html";var sE=H({name:"BiliBili",props:{bvid:{type:String,default:""},aid:{type:String,default:""},cid:{type:String,default:""},title:{type:String,default:"A BiliBili video"},page:{type:[String,Number],default:1},width:{type:[String,Number],default:"100%"},height:{type:[String,Number],default:void 0},ratio:{type:[String,Number],default:16/9},time:{type:[String,Number],default:0},autoplay:Boolean},setup(e){const{el:t,width:n,height:l,resize:r}=oE(e),i=ee(!1),a=k(()=>{const{aid:o,bvid:c,cid:u,autoplay:d,time:f,page:h}=e;return o&&u?`${ru}?aid=${o}&cid=${u}&t=${f}&autoplay=${d?1:0}&p=${h}`:c?`${ru}?bvid=${c}&t=${f}&autoplay=${d?1:0}`:null});return()=>a.value?[s("div",{class:"bilibili-desc"},s("a",{class:"sr-only",href:a.value},e.title)),s("iframe",{ref:t,src:a.value,title:e.title,class:"bilibili-iframe",allow:aE,style:{width:n.value,height:i.value?l.value:0},onLoad:()=>{i.value=!0,r()}}),i.value?null:s(to)]:[]}});const cE={enhance:({app:e})=>{Ft("SiteInfo")||e.component("SiteInfo",iE),Ft("BiliBili")||e.component("BiliBili",sE)},setup:()=>{},rootComponents:[]},uE=Object.freeze(Object.defineProperty({__proto__:null,default:cE},Symbol.toStringTag,{value:"Module"})),Cr=[fv,hv,Yv,km,xm,Pm,U4,Z4,n3,r3,i3,h3,L3,W3,e8,W6,lE,uE].map(e=>e.default).filter(Boolean),dE=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":"alternate","type":"application/atom+xml","href":"http://www.wenzhihuai.com/atom.xml","title":"个人博客 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"http://www.wenzhihuai.com/feed.json","title":"个人博客 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"http://www.wenzhihuai.com/rss.xml","title":"个人博客 RSS Feed"}],["link",{"rel":"icon","href":"/favicon.ico"}]],"locales":{}}');var yl=$e(dE),fE=T2,hE=()=>{const e=ev({history:fE(Zr("/")),routes:[{name:"vuepress-route",path:"/:catchAll(.*)",components:{}}],scrollBehavior:(t,n,l)=>l||(t.hash?{el:t.hash}:{top:0})});return e.beforeResolve(async(t,n)=>{if(t.path!==n.path||n===Wt){const l=wt(t.fullPath);if(l.path!==t.fullPath)return l.path;const r=await l.loader();t.meta={...l.meta,_pageChunk:r}}else t.path===n.path&&(t.meta=n.meta)}),e},pE=e=>{e.component("ClientOnly",Rd),e.component("Content",Md),e.component("RouteLink",He)},vE=(e,t,n)=>{const l=k(()=>t.currentRoute.value.path),r=Cu((y,_)=>({get(){return y(),t.currentRoute.value.meta._pageChunk},set(A){t.currentRoute.value.meta._pageChunk=A,_()}})),i=k(()=>kn.resolveLayouts(n)),a=k(()=>kn.resolveRouteLocale(yl.value.locales,l.value)),o=k(()=>kn.resolveSiteLocaleData(yl.value,a.value)),c=k(()=>r.value.comp),u=k(()=>r.value.data),d=k(()=>u.value.frontmatter),f=k(()=>kn.resolvePageHeadTitle(u.value,o.value)),h=k(()=>kn.resolvePageHead(f.value,d.value,o.value)),p=k(()=>kn.resolvePageLang(u.value,o.value)),g=k(()=>kn.resolvePageLayout(u.value,i.value)),v={layouts:i,pageData:u,pageComponent:c,pageFrontmatter:d,pageHead:h,pageHeadTitle:f,pageLang:p,pageLayout:g,redirects:ea,routeLocale:a,routePath:l,routes:Yn,siteData:yl,siteLocaleData:o};return e.provide(Ja,v),Object.defineProperties(e.config.globalProperties,{$frontmatter:{get:()=>d.value},$head:{get:()=>h.value},$headTitle:{get:()=>f.value},$lang:{get:()=>p.value},$page:{get:()=>u.value},$routeLocale:{get:()=>a.value},$site:{get:()=>yl.value},$siteLocale:{get:()=>o.value},$withBase:{get:()=>Ae}}),v},mE=()=>{const e=lv(),t=ei();let n=[];const l=()=>{e.value.forEach(a=>{const o=gE(a);o&&n.push(o)})},r=()=>{const a=[];return e.value.forEach(o=>{const c=EE(o);c&&a.push(c)}),a},i=()=>{document.documentElement.lang=t.value;const a=r();n.forEach((o,c)=>{const u=a.findIndex(d=>o.isEqualNode(d));u===-1?(o.remove(),delete n[c]):a.splice(u,1)}),a.forEach(o=>document.head.appendChild(o)),n=[...n.filter(o=>!!o),...a]};Ot(av,i),we(()=>{l(),pe(e,i,{immediate:!1})})},gE=([e,t,n=""])=>{const l=Object.entries(t).map(([o,c])=>ke(c)?`[${o}=${JSON.stringify(c)}]`:c===!0?`[${o}]`:"").join(""),r=`head > ${e}${l}`;return Array.from(document.querySelectorAll(r)).find(o=>o.innerText===n)||null},EE=([e,t,n])=>{if(!ke(e))return null;const l=document.createElement(e);return nr(t)&&Object.entries(t).forEach(([r,i])=>{ke(i)?l.setAttribute(r,i):i===!0&&l.setAttribute(r,"")}),ke(n)&&l.appendChild(document.createTextNode(n)),l},_E=R0,bE=async()=>{var n;const e=_E({name:"Vuepress",setup(){var i;mE();for(const a of Cr)(i=a.setup)==null||i.call(a);const l=Cr.flatMap(({rootComponents:a=[]})=>a.map(o=>s(o))),r=rv();return()=>[s(r.value),l]}}),t=hE();pE(e),vE(e,t,Cr);for(const l of Cr)await((n=l.enhance)==null?void 0:n.call(l,{app:e,router:t,siteData:yl}));return e.use(t),{app:e,router:t}};bE().then(({app:e,router:t})=>{t.isReady().then(()=>{e.mount("#app")})});export{u6 as _,Sl as a,Ve as b,AE as c,bE as createVueApp,kE as d,U1 as o,kt as r};
diff --git a/assets/chatgpt.html-BgeRWiYw.js b/assets/chatgpt.html-BgeRWiYw.js
new file mode 100644
index 00000000..14ee856a
--- /dev/null
+++ b/assets/chatgpt.html-BgeRWiYw.js
@@ -0,0 +1,101 @@
+import{_ as i,c as a,d as n,o as e}from"./app-ftEjETWs.js";const h={};function l(t,s){return e(),a("div",null,s[0]||(s[0]=[n(`想体验的可以去微信上搜索【旅行的树】公众号。
openai提供服务的区域,美国最好,这个解决办法是搞个翻墙,或者买一台美国的服务器更好。
国外邮箱,hotmail或者google最好,qq邮箱可能会对这些平台进行邮件过滤。
国外手机号,没有的话也可以去https://sms-activate.org ,费用大概需要1美元,这个网站记得也用国外邮箱注册,需要先充值,使用支付宝支付。
之后再搜索框填openai进行下单购买即可。
openai在国内不提供服务的,而且也通过ip识别是不是在国内,解决办法用vpn也行,或者,自己去买一台国外的服务器也行。我这里使用的是腾讯云轻量服务器,最低配置54元/月,选择windows的主要原因毕竟需要注册openai,需要看页面,同时也可以搭建nginx,当然,用ubuntu如果能自己搞界面也行。
购买完之后,就可以直接打开openai的官网了,然后去https://platform.openai.com/signup官网里注册,注册过程具体就不讲了,讲下核心问题——短信验证码
然后回sms查看验证码。
注册成功之后就可以在chatgpt里聊天啦,能够识别各种语言,发起多轮会话的时候,可能回出现访问超过限制什么的。
通过chatgpt聊天不是我们最终想要的,我们需要的是在微信公众号也提供智能客服的聊天回复,所以我们需要在通过openai的api来进行调用。
跟页面一样,OpenAI的调用也是不能再国内访问的,这里,我们使用同一台服务器来搭建nginx,还是保留使用windows吧,主要还是得注意下面这段话,如果API key被泄露了,OpenAI可能会自动重新更新你的API key,这个规则似乎是API key如果被多个ip使用,就会触发这个规则,调试阶段还是尽量使用windows的服务器吧,万一被更新了,还能去页面上重新找到。
Do not share your API key with interesting, 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个月,继续薅羊毛,当然,如果自己开发能力足够,也可以自己从0开始开发。
提供了各种语言的模版,方便快速开发,OpenAI官方提供的sdk是node和python,这里我们选择express(node)。
微信官方的源码在这,https://github.com/WeixinCloud/wxcloudrun-express,我们直接fork一份自己来开发。
一个简单的消息回复功能(无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,服务会自动从环境变量里取。
提交代码只github或者gitee都可以,值得注意的是,OpenAI判断key泄露的规则,不知道是不是判断调用的ip地址不一样,还是github的提交记录里含有这块,有点玄学,同样的key本地调用一次,然后在云托管也调用的话,OpenAI就很容易把key给重新更新。
部署完之后,云托管也提供了云端调试功能,相当于在服务里发送了http请求。这一步很重要,如果没有调用成功,则无法进行云托管消息推送。
这里填上你自己的url,我们这里配置的是/meesage/simple,如果没有成功,需要进行下面步骤进行排查:
(1)服务有没有正常启动,看日志
(2)端口有没有设置错误,这个很多次没有注意到
保存成功之后,就可以在微信公众号里测试了。
体验还可以
很多OpenAI的回答都要几十秒,有的甚至更久,比如对chatgpt问“写一篇1000字关于深圳的文章”,就需要几十秒,而微信的主动回复接口,是需要我们3s内返回给用户。
订阅号的消息推送分几种:
被动消息回复 :指用户给公众号发一条消息,系统接收到后,可以回复一条消息。主动回复/客服消息 :可以脱离被动消息的5秒超时权限,在48小时内可以主动回复。但需要公众号完成微信认证。根据微信官方文档,没有认证的公众号是没有调用主动回复接口权限的,https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Explanation_of_interface_privileges.html
对于有微信认证的订阅号或者服务号,可以调用微信官方的/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 ' );
+}
之后就可以实现会话之间的保存通信了。
chatgpt毕竟也是新上线的,火热是肯定的,聊天窗口只能开几个,api调用的话,也是有限频的,但是规则具体没有找到,只是在调用次数过多的时候会报429的错误,出现之后就需要等待一个小时左右。
对于这个的解决办法只能是多开几个账号,一旦429就只能换个账号重试了。
没有找到详细的规则,凭个人经验的话,可能github提交的代码会被扫描,可能ip调用的来源不一样,最好还是开发一个秘钥,生产一个秘钥吧。
我们这里用的模型算法是text-davinci-003,具体可以参考:https://platform.openai.com/docs/models/overview,也算是一个比较老的样本了吧
从官方文档来看,官方服务版的 ChatGPT 的模型并非基础版的text-davinci-003
,而是经过了「微调:fine-tunes」。文档地址在这:platform.openai.com/docs/guides…
有时候消息没有回复,真的不是我们的问题,chatgpt毕竟太火了,官网的这个能力都经常挂掉,也可以订阅官网修复的通知,一旦修复则会发邮件告知你。
参考:https://juejin.cn/post/7200769439335546935
记得去微信关注【旅行的树】公众号体验 代码地址:https://github.com/Zephery/wechat-gpt
`,90)]))}const k=i(h,[["render",l],["__file","chatgpt.html.vue"]]),r=JSON.parse('{"path":"/interesting/chatgpt.html","title":"微信公众号-chatgpt智能客服搭建","lang":"zh-CN","frontmatter":{"description":"微信公众号-chatgpt智能客服搭建 想体验的可以去微信上搜索【旅行的树】公众号。 一、ChatGPT注册 1.1 短信手机号申请 openai提供服务的区域,美国最好,这个解决办法是搞个翻墙,或者买一台美国的服务器更好。 国外邮箱,hotmail或者google最好,qq邮箱可能会对这些平台进行邮件过滤。 国外手机号,没有的话也可以去https:/...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/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:/..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-11T18:24:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-11T18:24:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"微信公众号-chatgpt智能客服搭建\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-05-11T18:24:35.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":1715451875000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":9.96,"words":2987},"filePathRelative":"interesting/chatgpt.md","localizedDate":"2024年1月25日","excerpt":"\\n想体验的可以去微信上搜索【旅行的树】公众号。
\\n一、ChatGPT注册 ","autoDesc":true}');export{k as comp,r as data};
diff --git a/assets/cms.html-Dfw5I__q.js b/assets/cms.html-Dfw5I__q.js
new file mode 100644
index 00000000..cf7da1d9
--- /dev/null
+++ b/assets/cms.html-Dfw5I__q.js
@@ -0,0 +1 @@
+import{_ as e,c as o,d as a,o as n}from"./app-ftEjETWs.js";const r={};function p(c,t){return n(),o("div",null,t[0]||(t[0]=[a('JDK14已经将CMS回收器完全移除,这里只需要记住它的缺点即可。
CPU资源消耗 :CMS垃圾回收器在运行过程中会与应用线程并发执行,这可能会导致较高的CPU资源消耗。
内存碎片问题 :CMS垃圾回收器在进行垃圾回收时,不会对对象进行压缩和整理,这可能会导致内存碎片问题。当内存碎片过多时,可能会导致无法找到足够大的连续内存空间来分配大对象,从而提前触发Full GC。
预测性差 :CMS垃圾回收器的暂停时间和CPU资源消耗都很难预测,这可能会对系统的性能造成影响。
维护复杂 :CMS垃圾回收器的代码相对复杂,需要更多的维护工作。
',6)]))}const s=e(r,[["render",p],["__file","cms.html.vue"]]),m=JSON.parse('{"path":"/java/JVM/cms.html","title":"CMS","lang":"zh-CN","frontmatter":{"description":"CMS JDK14已经将CMS回收器完全移除,这里只需要记住它的缺点即可。 CPU资源消耗:CMS垃圾回收器在运行过程中会与应用线程并发执行,这可能会导致较高的CPU资源消耗。 内存碎片问题:CMS垃圾回收器在进行垃圾回收时,不会对对象进行压缩和整理,这可能会导致内存碎片问题。当内存碎片过多时,可能会导致无法找到足够大的连续内存空间来分配大对象,从而提...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/JVM/cms.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"CMS"}],["meta",{"property":"og:description","content":"CMS JDK14已经将CMS回收器完全移除,这里只需要记住它的缺点即可。 CPU资源消耗:CMS垃圾回收器在运行过程中会与应用线程并发执行,这可能会导致较高的CPU资源消耗。 内存碎片问题:CMS垃圾回收器在进行垃圾回收时,不会对对象进行压缩和整理,这可能会导致内存碎片问题。当内存碎片过多时,可能会导致无法找到足够大的连续内存空间来分配大对象,从而提..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-16T09:22:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-16T09:22:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"CMS\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-16T09:22:35.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1708056026000,"updatedTime":1708075355000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":0.73,"words":218},"filePathRelative":"java/JVM/cms.md","localizedDate":"2024年2月16日","excerpt":"\\nJDK14已经将CMS回收器完全移除,这里只需要记住它的缺点即可。
\\nCPU资源消耗 :CMS垃圾回收器在运行过程中会与应用线程并发执行,这可能会导致较高的CPU资源消耗。
","autoDesc":true}');export{s as comp,m as data};
diff --git a/assets/devops-ping-tai.html-CjTXGrBr.js b/assets/devops-ping-tai.html-CjTXGrBr.js
new file mode 100644
index 00000000..62407a11
--- /dev/null
+++ b/assets/devops-ping-tai.html-CjTXGrBr.js
@@ -0,0 +1,237 @@
+import{_ as n,c as a,d as e,o as i}from"./app-ftEjETWs.js";const l={};function p(t,s){return i(),a("div",null,s[0]||(s[0]=[e(`DevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
公司技术部目前几百人左右吧,但是整个技术栈还是比较落后的,尤其是DevOps、容器这一块,需要将全线打通,当时进来也主要是负责DevOps这一块的工作,应该说也是没怎么做好,其中也走了不少弯路,下面主要是自己踩过的坑吧。
主要还是基于jenkins里面构建一个自由风格的软件项目,当时参考的是阿里的codepipeline,就是对jenkins封装一层,包括创建job、立即构建、获取构建进度等都进行封装,并将需要的东西进行存库,没有想到码代码的时候,一堆的坑,比如: 1.连续点击立即构建,jenkins是不按顺序返回的,(分布式锁解决) 2.跨域调用,csrf,这个还好,不过容易把jenkins搞的无法登录(注意配置,具体可以点击这里 ) 3.创建job的时候只支持xml格式,还要转换一下,超级坑(xstream强行转换) 4.docker构建的时候,需要挂载宿主机的docker(想过用远程的,但效率不高) 5.数据库与jenkins的job一致性问题,任务创建失败,批量删除太慢(目前没想好怎么解决) 6.由于使用了数据库,需要检测job是否构建完成,为了自定义参数,我们自写了个通知插件,将构建状态返回到kafka,然后管理平台在进行消息处理。
完成了以上的东西,不过由于太过于简单,导致只能进行单条线的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>
上面的过程也仍然没有没住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方案。
分布式构建jenkins x 首先要解决的是多个构建同时运行的问题,很久之前就调研过jenkins x,它必须要使用在kubernetes上,由于当时官方文档不全,而且我们的DevOps项目处于初始期,所有没有使用。jenkins的master slave结构就不多说了。jenkins x应该说是个全家桶,包含了helm仓库、nexus仓库、docker registry等,代码是jenkins-x-image 。
serverless jenkins 好像跟谷歌的tekton相关,用了下,没调通,只能用于GitHub。感觉还不如直接使用tekton。
阿里云云效 提供了图形化配置DevOps流程,支持定时触发,可惜没有跟gitlab触发结合,如果需要个公司级的DevOps,需要将公司的jira、gitlab、jenkins等集合起来,但是图形化jenkins pipeline是个特别好的参考方向,可以结合阿里云云效来做一个自己的DevOps产品。
微软Pipeline 微软也是提供了DevOps解决方案的,也是提供了yaml格式的写法,即:在右边填写完之后会转化成yaml。如果想把DevOps打造成一款产品,这样的设计显然不是最好的。
谷歌tekton kubernetes的官方cicd,目前已用于kubernetes的release发版过程,目前也仅仅是与GitHub相结合,gitlab无法使用,全过程可使用yaml文件来创建,跑起来就是类似kubernetes的job一样,用完即销毁,可惜目前比较新,依旧处于alpha版本,无法用于生产。有兴趣可以参考下:Knative 初体验:CICD 极速入门
在调研DockOne以及各个产商的DevOps产品时,发现,真的只有阿里云的云效才是真正比较完美的DevOps产品,用户不需要知道pipeline的语法,也不需要掌握kubernetes的相关知识,甚至不用写yaml文件,对于开发、测试来说简直就是神一样的存在了。云效对小公司(创业公司)免费,但是有一定的量之后,就要开始收费了。在调研了一番云效的东西之后,发现云效也是基于jenkins x改造的,不过阿里毕竟人多,虽然能约莫看出是pipeline的语法,但是阿里彻底改造成了能够使用yaml来与后台交互。 下面是以阿里云的云效界面以及配合jenkins的pipeline语法来讲解:
PMD是一款可拓展的静态代码分析器它不仅可以对代码分析器,它不仅可以对代码风格进行检查,还可以检查设计、多线程、性能等方面的问题。阿里云的是简单的集成了一下而已,对于我们来说,底层使用了sonar来接入,所有的代码扫描结果都接入了sonar。
stage('Clone') {
+ steps{
+ git branch: 'master', credentialsId: 'xxxx', url: "xxx"
+ }
+}
+stage('check') {
+ steps{
+ container('maven') {
+ echo "mvn pmd:pmd"
+ }
+ }
+}
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"
+ }
+ }
+}
镜像的构建比较想使用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}"
+ }
+ }
+}
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}"
+}
代码扫描,单元测试,构建镜像三个并行运行,等三个完成之后,在进行部署
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中查看:
jenkins blue ocean步骤日志:
云效中的日志:
triggers {
+ cron('H H * * *') //每天
+ }
pipeline中除了有对于时间的trigger,还支持了gitlab的触发,需要各种配置,不过如果真的对于gitlab的cicd有要求,直接使用gitlab-ci会更好,我们同时也对gitlab进行了runner的配置来支持gitlab的cicd。gitlab的cicd也提供了构建完后即销毁的过程。
功能最强大的过程莫过于自己使用pipeline脚本实现,选取最适合自己的,但是对于一个公司来说,如果要求业务方来掌握这些,特别是IT流动性大的时候,既需要重新培训,同个问题又会被问多遍,所以,只能将DevOps实现成一个图形化的东西,方便,简单,相对来说功能还算强大。
DevOps最难的可能都不是以上这些,关键是让用户接受,容器云最初推行时,公司原本传统的很多发版方式都需要进行改变,有些业务方不愿意改,或者有些代码把持久化的东西存到了代码中而不是分布式存储里,甚至有些用户方都不愿意维护老代码,看都不想看然后想上容器,一个公司在做技术架构的时候,过于混乱到最后填坑要么需要耗费太多精力甚至大换血。
最后,DevOps是云原生的必经之路!!!
文章同步: 博客园:https://www.cnblogs.com/w1570631036/p/11524673.html 个人网站:http://www.wenzhihuai.com/getblogdetail.html?blogid=663 gitbook:https://gitbook.wenzhihuai.com/devops/devops-ping-tai
`,61)]))}const c=n(l,[["render",p],["__file","devops-ping-tai.html.vue"]]),r=JSON.parse('{"path":"/kubernetes/devops/devops-ping-tai.html","title":"DevOps平台.md","lang":"zh-CN","frontmatter":{"description":"DevOps平台.md DevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。 公司技术部目前几百人左右吧...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/kubernetes/devops/devops-ping-tai.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"DevOps平台.md"}],["meta",{"property":"og:description","content":"DevOps平台.md DevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。 公司技术部目前几百人左右吧..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/201908111044201770944400.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-06T07:53:39.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-06T07:53:39.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"DevOps平台.md\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/201908111044201770944400.png\\",\\"https://github-images.wenzhihuai.com/images/201908170612301464716259.png\\",\\"https://github-images.wenzhihuai.com/images/201908100346011648784131.png\\",\\"https://github-images.wenzhihuai.com/images/201908100429061448084424.png\\",\\"https://github-images.wenzhihuai.com/images/20190915082632234251996.png\\",\\"https://github-images.wenzhihuai.com/images/201908100428501805517052.png\\",\\"https://github-images.wenzhihuai.com/images/20190810043129475121819.png\\",\\"https://github-images.wenzhihuai.com/images/201908100431461365428934.png\\",\\"https://github-images.wenzhihuai.com/images/2019081004491578636427.png\\",\\"https://github-images.wenzhihuai.com/images/201908100524291184838290.png\\"],\\"dateModified\\":\\"2024-02-06T07:53:39.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":1566437746000,"updatedTime":1707206019000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":11.96,"words":3589},"filePathRelative":"kubernetes/devops/devops-ping-tai.md","localizedDate":"2019年8月22日","excerpt":"\\nDevOps定义(来自维基百科): DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
","autoDesc":true}');export{c as comp,r as data};
diff --git a/assets/elastic-spark.html-Cz2jVT52.js b/assets/elastic-spark.html-Cz2jVT52.js
new file mode 100644
index 00000000..ff777585
--- /dev/null
+++ b/assets/elastic-spark.html-Cz2jVT52.js
@@ -0,0 +1,27 @@
+import{_ as i,c as a,d as n,o as t}from"./app-ftEjETWs.js";const e={};function h(l,s){return t(),a("div",null,s[0]||(s[0]=[n(`Hadoop允许Elasticsearch在Spark中以两种方式使用:通过自2.1以来的原生RDD支持,或者通过自2.0以来的Map/Reduce桥接器。从5.0版本开始,elasticsearch-hadoop就支持Spark 2.0。目前spark支持的数据源有: (1)文件系统:LocalFS、HDFS、Hive、text、parquet、orc、json、csv (2)数据RDBMS:mysql、oracle、mssql (3)NOSQL数据库:HBase、ES、Redis (4)消息对象:Redis
elasticsearch相对hdfs来说,容易搭建、并且有可视化kibana支持,非常方便spark的初学入门,本文主要讲解用elasticsearch-spark的入门。
Spark - Apache Spark 相关库引入:
< dependency >
+ < groupId >org.elasticsearch</ groupId >
+ < artifactId >elasticsearch-spark-30_2.13</ artifactId >
+ < version >8.1.3</ version >
+ </ dependency >
SparkConf配置,更多详细的请点击这里 或者源码ConfigurationOptions 。
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 ;
+}
这里用的是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语句。
支持序列化对象、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的实时处理,es5.0的时候开始支持,目前
1.Apache Spark support
2.elasticsearch-hadoop
3.使用SparkSQL操作Elasticsearch - Spark入门教程
`,27)]))}const p=i(e,[["render",h],["__file","elastic-spark.html.vue"]]),r=JSON.parse('{"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、t...","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、t..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://databricks.com/wp-content/uploads/2019/02/largest-open-source-apache-spark.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-25T11:42:16.000Z"}],["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\\":[\\"https://databricks.com/wp-content/uploads/2019/02/largest-open-source-apache-spark.png\\"],\\"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":1651578150000,"updatedTime":1706182936000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":1.71,"words":514},"filePathRelative":"bigdata/spark/elastic-spark.md","localizedDate":"2022年5月3日","excerpt":"\\nHadoop允许Elasticsearch在Spark中以两种方式使用:通过自2.1以来的原生RDD支持,或者通过自2.0以来的Map/Reduce桥接器。从5.0版本开始,elasticsearch-hadoop就支持Spark 2.0。目前spark支持的数据源有: \\n(1)文件系统:LocalFS、HDFS、Hive、text、parquet、orc、json、csv \\n(2)数据RDBMS:mysql、oracle、mssql \\n(3)NOSQL数据库:HBase、ES、Redis \\n(4)消息对象:Redis
","autoDesc":true}');export{p as comp,r as data};
diff --git "a/assets/elasticsearch\346\272\220\347\240\201debug.html-Bo6HcrbI.js" "b/assets/elasticsearch\346\272\220\347\240\201debug.html-Bo6HcrbI.js"
new file mode 100644
index 00000000..901d4b75
--- /dev/null
+++ "b/assets/elasticsearch\346\272\220\347\240\201debug.html-Bo6HcrbI.js"
@@ -0,0 +1 @@
+import{_ as a,c as t,d as i,o as s}from"./app-ftEjETWs.js";const r={};function c(h,e){return s(),t("div",null,e[0]||(e[0]=[i('直接用idea下载代码https://github.com/elastic/elasticsearch.git
切换到特定版本的分支:比如7.17,之后idea会自己加上Run/Debug Elasitcsearch的,配置可以不用改,默认就好
为了方便, 在 gradle/run.gradle 中关闭 Auth 认证:
setting 'xpack.security.enabled', 'false'
或者使用其中的用户名密码:
user username: 'elastic-admin', password: 'elastic-password', role: 'superuser'
先启动上面的 remote debug, 然后用 gradlew 启动项目:
./gradlew :run --debug-jvm 打开浏览器http://localhost:9200即可看到es相关信息了
',12)]))}const g=a(r,[["render",c],["__file","elasticsearch源码debug.html.vue"]]),p=JSON.parse('{"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 image 切换到特定版本的分支:比如7.17,之后idea会自己加上Run/Debug Elasitcsearch的,配置可以不用改,默认就好 image 二、修改设置(可选) ...","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 image 切换到特定版本的分支:比如7.17,之后idea会自己加上Run/Debug Elasitcsearch的,配置可以不用改,默认就好 image 二、修改设置(可选) ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/755525-20220124160719006-851383635.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-26T03:58:56.000Z"}],["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\\":[\\"https://github-images.wenzhihuai.com/images/755525-20220124160719006-851383635.png\\",\\"https://github-images.wenzhihuai.com/images/755525-20220124160709513-361605195.png\\",\\"https://github-images.wenzhihuai.com/images/755525-20220124160657219-1269826381.png\\"],\\"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一、下载源代码 \\n直接用idea下载代码https://github.com/elastic/elasticsearch.git \\n
","autoDesc":true}');export{g as comp,p as data};
diff --git a/assets/feed.html-BcapapFL.js b/assets/feed.html-BcapapFL.js
new file mode 100644
index 00000000..c91498bd
--- /dev/null
+++ b/assets/feed.html-BcapapFL.js
@@ -0,0 +1 @@
+import{_ as n,c as a,a as e,o as r}from"./app-ftEjETWs.js";const i={};function o(s,t){return r(),a("div",null,t[0]||(t[0]=[e("h1",{id:"feed系统设计",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#feed系统设计"},[e("span",null,"Feed系统设计")])],-1),e("p",null,[e("a",{href:"https://blog.csdn.net/weixin_45583158/article/details/128195940",target:"_blank",rel:"noopener noreferrer"},"https://blog.csdn.net/weixin_45583158/article/details/128195940")],-1)]))}const l=n(i,[["render",o],["__file","feed.html.vue"]]),c=JSON.parse('{"path":"/system-design/feed.html","title":"Feed系统设计","lang":"zh-CN","frontmatter":{"description":"Feed系统设计 https://blog.csdn.net/weixin_45583158/article/details/128195940","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/system-design/feed.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"Feed系统设计"}],["meta",{"property":"og:description","content":"Feed系统设计 https://blog.csdn.net/weixin_45583158/article/details/128195940"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-10T14:39:30.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-10T14:39:30.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Feed系统设计\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-10T14:39:30.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[],"git":{"createdTime":1710081570000,"updatedTime":1710081570000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":1}]},"readingTime":{"minutes":0.02,"words":7},"filePathRelative":"system-design/feed.md","localizedDate":"2024年3月10日","excerpt":"\\nhttps://blog.csdn.net/weixin_45583158/article/details/128195940
","autoDesc":true}');export{l as comp,c as data};
diff --git a/assets/g1.html-CcgAHdWl.js b/assets/g1.html-CcgAHdWl.js
new file mode 100644
index 00000000..d64cb372
--- /dev/null
+++ b/assets/g1.html-CcgAHdWl.js
@@ -0,0 +1 @@
+import{_ as t,c as i,d as a,o as n}from"./app-ftEjETWs.js";const r={};function l(o,e){return n(),i("div",null,e[0]||(e[0]=[a('本文转载自增量式垃圾回收器——带你深入理解G1垃圾回收器
G1垃圾回收器是在Java 7之后引入的一种垃圾回收器。它被设计为一种分代、增量、并行和并发的标记-复制垃圾回收器,旨在适应不断扩大的内存和增加的处理器数量,以显著降低垃圾回收造成的暂停时间,同时保持良好的吞吐量,主要有以下特点:
并行与并发: G1回收器在垃圾回收的不同阶段使用了并行和并发的方式,充分利用多核处理器的优势,提高了垃圾回收的效率。分代回收: G1垃圾回收器依旧采用分代回收的思想,但是和CMS等分代回收算法不同,G1不是将整个堆内存划分为年轻代、老年代和元空间。而是将堆内存划分为一个个固定大小的region,每个region可以属于年轻代或老年代。垃圾回收的基本单位是region,而不是整个堆,这使得垃圾回收更加灵活。增量回收: G1采用增量回收的方式,将整个垃圾回收过程分解为多个阶段进行,这样更有利于分散垃圾回收的压力,减小每次暂停的时间,提高系统的响应性。Compacting回收: 与CMS回收器不同,G1是一种compacting回收器,其回收的内存空间是连续的。这样就可以避免CMS收集器由于不连续内存空间造成的所需堆空间更大和浮动垃圾的问题。连续空间意味着G1垃圾回收器可以不必采用空闲链表的内存分配方式,而可以直接采用bump-the-pointer的方式;软实时: G1回收器具有软实时(soft real-time)的特性,用户可以指定垃圾回收时间的限时。虽然G1会努力在限定时间内完成垃圾回收,但并不保证每次都能在时限内完成。通过设定合理的目标,可以使大部分垃圾回收时间都在规定的时限内完成。G1垃圾回收器以其创新性的设计和优越的性能特点,逐渐成为Java应用程序中首选的垃圾回收器之一。通过分代、增量、并行、并发等多种技术手段的结合,G1回收器在处理大内存和多核处理器的环境下表现出色,为Java应用程序提供了更好的性能和响应能力。
参数 默认值 描述 -XX:G1NewSizePercent 整堆的5% 年轻代的初始空间百分比。 -XX:G1MaxNewSizePercent 60% 年轻代的最大空间百分比 -XX:MaxGCPauseMillis 200ms 指定的最大垃圾收集暂停时间 -XX:NewRatio - 与-Xmn一同设置,年轻代和老年代的比例 -Xmn - 设置年轻代的固定大小 -XX:G1HeapRegionSize 1MB~32MB 分区大小,每个分区是G1的基本单位 -XX:GCTimeRatio 9 GC与应用程序的耗时比例 -XX:G1MaxNewSizePercent 99 GC与应用程序的耗时比例,CMS默认为99,G1默认为9
img 如上面的图所示,G1垃圾回收器采用了内存分区(Region)思路,将整个堆空间分成若干个大小相等的内存区域,这些内存区域的大小一般大小在1MB~32MB之间,可以通过设置启动参数 -XX:G1HeapRegionSize=n
来指定分区的大小。
每次垃圾回收的时候,G1会逐段地回收这些内存区域,而且不要求对象的存储在物理上是连续的,只要在逻辑上是连续的即可。这样的好处在于,分代垃圾收集将关注点聚焦在最近分配的对象上,无需全堆扫描,从而避免了对长生命周期对象的频繁拷贝。并且年轻代和老年代的垃圾回收过程相互独立,有助于降低系统整体的响应时间。
虽然G1内存分区不要求内存分配是非连续的,但它依然逻辑上将内存划分为年轻代和老年代。然而,和CMS等分代的垃圾回收器不同,G1垃圾回收器不是将一大块连续的内存区域划分成年轻代和老年代,而是将每一个分区(Region)划分成Eden区、Survivor区、Huge区和Old区等。
并且和CMS等分代垃圾回收器不同的是,对于G1收集器来说,当现有年轻代分区被占满时,JVM会为年轻代动态分配新的空闲分区。
年轻代的整体内存大小会在初始空间(通过参数-XX:G1NewSizePercent
设置,默认整堆的5%)和最大空间(通过参数-XX:G1MaxNewSizePercent
设置,默认60%)之间动态变化。这个动态变化的过程由目标暂停时间(通过参数-XX:MaxGCPauseMillis
设置,默认200ms)、需要扩缩容的大小以及分区的已记忆集合(RSet)共同决定。总结下上面说的,G1垃圾回收器的分区和分代机制主要有下面3个特点:
分区(Region)大小可调: G1垃圾回收器可以设置分区(Region)大小范围为1MB~32MB,且必须是2的幂,默认情况下,整个堆被划分为2048个分区,但可以根据应用程序的需求进行调整。逻辑连续性: G1垃圾回收器并不强制要求对象在物理上的存储是连续的,而是以逻辑上的连续性为目标,这样一来可以更灵活的分配内存,使对象的存储不受物理位置的限制。动态分代: 每个分区并不固定地为某个代服务,分区(Region)可以被划分成Eden区、Survivor区、Huge区和Old区等。并且可以按需在年轻代和老年代之间切换,G1可以根据实际情况调整内存分区的使用。G1垃圾回收器通过引入分区设计和分代策略,以逻辑上的连续性为基础,克服了传统垃圾回收器对物理连续性的依赖。这种设计使得对象的存储更加灵活,同时允许动态调整分区的使用,为应对不同应用场景提供了更好的适应性。
img 如上图所示,在G1垃圾回收器中,每个分区内部进一步被划分为若干大小为512 Byte的卡片(Card)。这些卡片用于标识堆内存的最小可用粒度。所有分区的卡片记录在全局卡片表中(Global Card Table),而分配的对象将占用物理上连续的若干个卡片,总结起来主要有以下几点:
卡片(Card): G1将每个分区(Region)进一步划分为大小为512 Byte的卡片,这是最小的标记单位,对象的分配和回收都以卡片为基本单位进行,这个卡片的大小是可以进行设置和调整的。全局卡表(Global Card Table ): 所有分区的卡片状态会被记录在全局卡片表中,这个表维护了对每个卡片的引用状态,用于在垃圾回收过程中准确地追踪对象引用关系。对象分配物理连续性: 分配的对象会占用物理上连续的若干个卡片,这种设计有助于提高内存的利用率,并简化对内存的管理。引用查找: 对分区(Region)内对象引用的查找通过记录卡片(Card)的方式实现,G1维护了一个叫做RSet(Remembered Set)的数据结构,用于记录在分区内对象的引用关系。回收处理: 每次对内存的回收都涉及对指定分区的卡片进行处理。通过检查RSet中的信息,G1能够确定哪些对象是不再被引用的,从而进行相应的回收操作。G1垃圾回收器利用卡片标记机制,将堆内存划分为最小的可标记单位,实现了对对象引用关系的准确追踪。这种分区和卡片的设计有助于提高垃圾回收的效率,同时为更精细的内存管理提供了基础。
G1垃圾回收器提供了一套灵活的堆空间调整机制,通过自动调整堆空间大小来适应不同的应用场景,可以指定堆空间的大小,也可以设置堆空间的比例来调整GC的频率。
指定堆空间大小: 通过标准的JVM参数 -Xms
(初始堆大小)和 -Xmx
(最大堆大小)可以手动指定堆空间的大小。自动调整: G1在发生年轻代收集或混合收集时,会根据GC与应用的耗费时间比进行自动调整堆空间大小。这个比例由目标参数 -XX:GCTimeRatio
决定,默认值为9。G1根据应用和GC的相对耗时,动态调整堆空间,以减少GC的频率和相应的时间开销。GC频率控制: 如果GC频率过高,G1可以通过增加堆的尺寸来减少GC的频率,从而降低GC占用的时间。这是通过自动调整堆空间大小实现的。空间不足处理: 当发生对象空间分配或转移失败时,G1会首先尝试增加堆空间。如果扩容成功,问题得以解决;如果扩容失败,G1会触发一次担保的Full GC,Full GC后,G1重新计算堆尺寸,调整堆空间大小。通过这套机制,G1垃圾回收器在运行时可以动态适应不同的工作负载,提高垃圾回收的效率,同时降低GC对应用程序的影响。
img 在JVM中一个对象被创建之后,JVM首先要做的事就是给这个对象分配一块儿内存空间。但是,执行这个内存分配工作
的也是一个线程,那么只要涉及到多线程就可能会出现线程安全问题,于是就有了LAB(本地分配缓冲)的概念。
LAB(本地分配缓冲,Local allocation buffer )的意思是每个线程都有自己独立的一个分区(Region)来进行内存分配,这样线程之前的内存互不打扰,就保障了线程的安全。
结合G1垃圾回收器来说,由于采用了分区(Region)的思想,所以每个线程都可以“认领”某个分区用于线程本地的内存分配,而无需顾忌内存空间是否连续。每个应用线程和GC线程都会独立的使用某个分区,从而减少同步所耗费的时间,提升GC效率,这个分区被称为”本地分配缓冲区“(Lab),除了Lab之外还有TLAB、PLAB和GCLAB等概念,如下:
TLAB(Threads Local Allocation Buffer,线程本地分配缓冲区): 每一个应用线程(App thread)都可以独占一个本地缓冲区(即Region)来创建对象,TLAB通常属于 Eden 空间,因为大部分对象会首先在 Eden 区被分配(大型对象除外)。*GCLab(***GC Local Allocation Buffer,GC 本地缓冲区): 每个GC线程在进行垃圾收集时,同样可以独占一个本地缓冲区(GCLAB,即Region)用于转移对象,在每次回收过程中,对象会被复制到 Survivor 空间或老年代空间。 *PLAB(***Promotion Local allocation buffer,晋升本地缓冲区): 对于从 Eden 或 Survivor 空间晋升到 Survivor 或老年代空间的对象,即Old对象,同样有GC线程独占的本地缓冲区进行操作,该部分称为晋升本地缓冲区(PLAB)。 这种分区和本地缓冲区的设计使得每个线程有了自己独立的Region,有助于提高并发性和减少同步开销,从而提升垃圾收集的效率。
前面说过,对于G1收集器而言内存区域会被划分成Eden Region、Survivor Region、Old Region和Humongous Region等不同分代的区域,而这些区域内部又会按照512 Bytes的大小为一个Card,进一步被划成为多个Card。
G1收集器在分配对象的时候,是按照完整Card的来进行分配的,也就是说一个对象可以占用1个、2个甚至多个cards,即使这些Cards没有被完全占满,也会分配整数个Cards给这个对象使用。那么这样一来,当G1垃圾回收器需要回收某一个对象的时候就只需要回收对象对应的Cards就可以了,这样既高效也不会影响到其它对象的正常使用。
img G1回收器在对某个Region进行垃圾回收的时候,首先会使用的**“根可达算法” 和“ 三色标记 **”算法从GC Roots开始进行垃圾标记。在垃圾标记的过程中,由于晋升等原因,某些Region当中对象可能会被移动到其它Region,但是G1收集器中对对象的引用是到Region中的Cards级别的。
在G1 垃圾收集器中的对象是可以晋升的,和其它垃圾收集器类似当年轻代的对象存活超过一定时间之后,就可以从年轻代晋升为老年代。如上图所示,假设GC Roots分别引用了Eden Region 中的A对象和Survivor Region中的B对象,而在GC过程中这两个对象由于晋升等原因被移动到了Old Region。而此时,对象A和B依旧还是引用了处于Eden和Survivor中的C、D对象,这也就发生了跨区域(Region)的引用。
除了上面所说的从老年代到新生代的引用之外,根据G1的设计思路,还存在以下几种引用情况:
分区内部有引用关系 新生代分区到新生代分区之间有引用关系 新生代分区到老生代分区之间有引用关系 老生代分区到新生代分区之间有引用关系 老生代分区到老生代分区之间有引用关系 另外,G1垃圾回收器也是分代垃圾回收器,也存在着新生代垃圾回收 (Young GC,回收Eden区、Survivor区)、混合回收 (Mixed GC,Eden区、Survivor 区、Old 区)和Full GC (Eden区、Survivor区、Old区、Huge区,Meta Space等)。
那么,假设Young GC发生的时候,就按照上图的例子,如果我们发现处于Eden区或者Survivor区的对象被Old区或者其它区域的对象所引用,这种时候如何才能将当前区域的对象成功标记为存活对象呢?
最简单的办法当然是整体扫描所有区域来得到其它区域对当前区域的引用,那就相当于每次Young GC都要进行一次Full GC才能找到所有引用关系,保证不发生漏标。但是,这种方法无异于高射炮打蚊子,得不偿失,会导致G1垃圾回收器效率极低。
所以,如果对于当前Region中的某个对象,我们知道它被什么对象所引用,或者换句话说有一个当前对象的**反向指针。这样以来,**我们就能够更快速的判断当前区域中的对象是否被GC Root所引用,是否应该被标记成存活对象。此时我们的主角就呼之欲出了——RSet。
RSet作为用于记录引用关系的数据结构,在有效地追踪这些引用。通过精确地维护RSet,G1能够更有效地执行垃圾回收,从而最大程度地减少对可用空间的影响。这种详细的引用关系分析有助于优化垃圾回收算法,提高Java应用程序的性能和资源利用率。
img 由于G1垃圾回收器的回收粒度是按照区域(Region进行的),为了记录Region之间对象引用关系,当Region初始化的时候,JVM会拿出这个Region的一部分区域用来初始化一个RSet(Remembered Set,已记忆集合),这个集合的作用是记录和跟踪其它Region指向该Region中对象的Card的引用。在进行垃圾标记的时候,除了从GC Roots开始遍历,还会从RSet开始遍历,确保该区域中所有存活的对象都会被标记到。
RSet是一种典型的空间换时间的策略,对于Old->Young、Old-Old的跨代对象引用,只需要扫描RSet即可。RSet中记录了其它Region钟对象引用本Region中的对象,属于Point-Into(谁引用了我),而Card Table则属于Point-Out(我引用了谁)。但是,由于RSet是属于每一个Region的,如果单个Region中被引用的对象过多,对内存的开销就会太大,因此引入了我们接着需要介绍的节省RSet空间的机制——PRT机制。
**RSet内部采用Per Region Table(PRT)**来记录分区的引用情况。由于RSet的记录会占用分区的空间,当一个分区变得非常“热门”时,RSet占用的空间会增加,从而降低了分区的可用空间。为了应对这个问题,G1采用了改变RSet密度的策略,即在PRT中使用三种不同的模式来记录引用:
RSet储存状态 描述 实现方式描述 稀疏模式(Sparse) 对于不那么热门的Region,直接记录引用对象的Card的索引,可以直接通过RSet找到对应对象,空间耗费最大,效率最高。 通过哈希表方式实现。数组的Key是当前Region的地址,而值是Card地址数组。 细粒度模式(Fine-grained) 记录引用对象的Region索引,可以通过RSet找到对应的Region. 通过Region地址链表实现,维护当前Region中所有Card的BitMap集合。当Card被引用时,对应的Bit被设置为1。同时,维护一个对应Region的索引数量,用于跟踪引用情况。 粗粒度模式(Coarse-grained) 只记录引用情况,每个分区对应一个比特位,只记录了引用的存在与否,需要通过整堆扫描才能找出所有引用,因此扫描速度是最慢的。 通过BitMap来表示所有Region。如果有其他Region对当前Region有指针引用,就设置其对应的Bit为1,否则标记为0。
这种灵活的模式选择允许G1根据分区的特性和使用情况动态调整RSet的记录密度,以平衡空间占用和引用追踪的性能。这种策略的实施有助于在分区受欢迎的情况下最大限度地减少对可用空间的影响。
同时,由于G1垃圾回收器在YGC的时候会对所有的Eden区和Survivor区域都进行扫描和回收,因此,从年轻代到年轻代的引用是无需记录的。更多的引用关系如下:
引用关系 是否记录在RSet中 说明 分区内部有引用关系 不记录 回收是针对一个分区进行的,回收时会遍历整个分区,无需记录分区内部引用关系。 新生代分区->新生代分区 不记录 G1回收器在Young GC的时候会全量处理所有新生代分区,无需额外记录这一引用关系。 新生代分区->老生代分区 不记录 YGC针对的是新生代分区,混合GC使用新生代分区作为根,FGC处理所有分区,无需额外记录这一引用关系。 老生代分区->新生代分区 记录 YGC时有两种根,一是栈空间/全局空间变量的引用,另一是老生代分区到新生代分区的引用,需要记录。 老生代分区->老生代分区 记录 在混合GC时可能只有部分分区被回收,必须记录引用关系以快速找到活跃对象。
如上表所示,由于G1回收器不同类型的GC所处理的区域不同,并不是所有其它区域对本区域的引用关系都需要被记录的,简单来说只有“老年代分区到新生代分区”的引用、“老年代分区到老年代”分区的引用需要被RSet记录下来。
img G1收集器中的CSet(收集集合,Collection Set)是一组被选中进行垃圾回收的Region的集合。G1收集器是以Region为单位的,并且分为YGC和Mixed GC,这两种GC方式都是需要STW的,但是G1收集器的一个优势就是它是增量式的垃圾回收器,可以根据设置的回收停顿时间来动态调整每次的回收量。CSet就可以很好的支持增量回收的特性,其中存储的就每次YGC或者Mixed GC时需要回收清理的所有Region。当回收的时,CSet中的所有Region都将被释放,区域存活的对象将被移动到分配的空闲分区(Free Region)中。
由于G1收集器分为Young GC和Mixed GC两种模式,因此存在着两种不同的CSet分别在这两种模式下使用:
Young GC中的CSet: 在Young GC中,CSet包含所有Young区域,即Eden和Survivor分区。当Eden区域满时,触发Young GC,CSet中的对象将被移动或复制到Survivor分区或老年代。这个过程确保Young GC时只处理一小部分内存,减小了每次垃圾回收的暂停时间。**Mixed GC中的CSet:**在Mixed GC中,CSet包括一部分老年代区域,这些区域被选中进行部分垃圾回收。与Young GC不同,Mixed GC关注的是整个堆的内存回收,而不仅仅是年轻代的部分。G1在Mixed GC过程中会优先选择收益高的老年代区域,以提高垃圾回收的效率。 通过使用CSet,G1收集器可以更灵活地控制垃圾回收的范围,同时通过优先处理收益高的区域,提高了内存回收的效率。这种策略使得G1可以在更可控的停顿时间内实现高效的垃圾回收。
由于不能整堆扫描,又需要计算分区确切的活跃度,因此,G1需要一个增量式的完全标记并发算法,通过维护RSet,得到准确的分区引用信息。在G1中,RSet的维护主要来源两个方面:写栅栏(Write Barrier)和并发优化线程(Concurrence Refinement Threads)
img 屏障(Barrier)是指在原生代码片段中,当某些语句被执行时,屏障代码也会被执行。而G1主要在赋值语句中,使用写前屏障(Pre-Write Barrier)和写后屏障(Post-Write Barrier),如下:
写前屏障 (Pre-Write Barrier):即将执行一段赋值语句时,等式左侧对象将修改引用到另一个对象。那么等式左侧对象原先引用的对象所在分区将因此丧失一个引用。此时,JVM需要在赋值语句生效之前,记录丧失引用的对象。JVM并不会立即维护RSet,而是通过批量处理,在将来RSet更新(见SATB)。 写后屏障 (Post-Write Barrier):当执行一段赋值语句后,等式右侧对象获取了左侧对象的引用。那么等式右侧对象所在分区的RSet也应该得到更新。同样为了降低开销,写后屏障发生后,RSet也不会立即更新,同样只是记录此次更新日志,在将来批量处理(见Concurrence Refinement Threads)。 事实上,写屏障的指令序列开销非常昂贵,应用吞吐量也会根据屏障复杂度而降低。
SATB是由Taiichi Tuasa 提出的增量式完全并发标记算法,主要应用于标记-清除垃圾收集器的并发标记阶段。SATB 针对 G1 的分区块堆结构设计,同时解决了 CMS(Concurrent Mark-Sweep)的一个主要问题,即重新标记暂停时间长导致的潜在风险。
SATB 的核心思想是创建一个对象图,类似于堆的逻辑快照,以确保在并发标记阶段能够鉴别出所有的垃圾对象。当赋值语句发生时,应用会改变其对象图,因此 JVM 需要记录被覆盖的对象。为此,写前屏障会在引用变更前,将值记录在 SATB 日志或缓冲区中。每个线程都有一个独占的 SATB 缓冲区,初始时有 256 条记录空间。当空间用尽时,线程会分配新的 SATB 缓冲区继续使用,而旧的缓冲区则加入全局列表。
在并发标记阶段,标记线程会定期检查和处理全局缓冲区列表的记录。然后,根据标记位图分片的标记位,扫描引用字段来更新 RSet(Remembered Set)。这个过程也被称为并发标记/SATB写前屏障。
G1 中使用基于 Urs Holzle 的快速写屏障,将屏障开销缩减到 2 个额外的指令。屏障将会更新一个 card table type 的结构来跟踪代间引用。当赋值语句发生后,写后屏障会先通过 G1 的过滤技术判断是否是跨分区的引用更新,并将跨分区更新对象的卡片加入缓冲区序列,即更新日志缓冲区或脏卡片队列。与 SATB 类似,一旦日志缓冲区用尽,则分配一个新的日志缓冲区,并将原来的缓冲区加入全局列表中。
并发优化线程 (Concurrence Refinement Threads) 专注于扫描日志缓冲区记录的卡片,以维护更新 RSet。可以通过设置参数 -XX:G1ConcRefinementThreads
来控制并发优化线程的最大数量,默认等于 -XX:ParallelGCThreads
。
并发优化线程一直保持活跃,一旦发现全局列表中有记录存在,就开始并发处理。如果记录增长迅速或者处理不及时,G1 会使用分层的方式调度,以使更多的线程处理全局列表。如果并发优化线程无法跟上缓冲区数量,Mutator 线程 (Java 应用线程) 可能会挂起应用并被加入来协助处理,直到全部处理完成。因此,需要尽量避免出现这种情况。
G1提供了两种GC模式,分别是Young GC(即YGC)和Mixed GC,它们都是完全停顿(”Stop The World“)的垃圾回收方式,需要暂停用户线程。而Full GC实际上是采用了Serial Old的GC方式,不是G1提供的GC模式,如下:
Young GC(年轻代GC) :选择所有年轻代中的Region进行回收,通过控制年轻代的Region数量,即年轻代内存大小,来控制Young GC的时间开销。Mixed GC(混合GC) :同样选择所有年轻代中的Region,加上根据全局并发标记(global concurrent marking)统计的若干老年代Region进行回收。在用户指定的开销目标范围内,尽可能选择收益高的老年代Region。**Full GC:**Mixed GC并非完全回收堆内存的Full GC,它只回收部分老年代的Region。如果Mixed GC无法跟上程序分配内存的速度,导致老年代填满无法继续进行Mixed GC,系统会使用Serial Old GC(Full GC)来收集整个GC heap。 以上3种GC模式中,Young GC和Mixed GC,是G1回收空间的主要活动。当应用运行开始时,堆内存可用空间还比较大,只会在年轻代满时,触发Young GC进行垃圾回收;随着老年代内存增长,当到达IHOP阈值-XX:InitiatingHeapOccupancyPercent
(老年代占整堆比,默认45%)时,G1就会根据一定的条件(参考后面内容)来触发Mixed GC和Full GC。
JVM可以通过参数-XX:ParallelGCThreads来指定GC工作的线程数量。该参数的默认值并非固定,而是根据当前的CPU资源进行计算。如果用户没有指定,并且CPU核数小于等于8,则默认与CPU核数相等;如果CPU核数大于8,则JVM会经过计算得到一个小于CPU核数的线程数。用户也可以手动指定线程数,例如与CPU核数相等。
Young GC的核心流程就是采用STW的方式对所有的Young Region进行回收,将需要晋升的对象复制到老年代,这个过程不仅需要遍历GC Roots 还需要对CSet进行扫描。
当应用程序刚开始运行的时候,堆内的可用空间较多,当Young Region满的时候,就会触发Young GC。这个过程中,G1收集器会将所有的Young Region,即Eden区,放到CSet当中。Eden分区中存活的对象将被复制到Survivor分区。原有的Survivor分区中存活的对象将根据存活次数(年龄)的任期阈值分别晋升到PLAB(Parallel Live Allocation Buffer)、新的Survivor区,或Old区,原有的Eden分区将被整体回收。
具体来说,当JVM无法将新对象分配到Eden区域时,会触发Young GC,也称为"evacuation pause",这是一个用户线程完全暂停的过程,虽然其中部分步骤是并行执行的,但整个过程会导致STW,如下:
**1. 选择收集集合(Choose CSet):**G1会在遵循用户设置的GC暂停时间上限的基础上,选择一个最大Eden区域数,将这个数量的所有Eden区域作为收集集合。 **2. 根处理(Root Scanning):**从GC Roots开始遍历,查找从roots引用直达到CSet的对象(存活对象),并将它们移动到Survivor区域。同时将存活对象引用的对象加入标记栈(Mark Stack),这一阶段确保CSet中存活的对象被正确复制。 **3.RSet扫描(Scan RS):**在RSet扫描之前会先更新RSet(Update RS),因为RSet是先写日志,再通过一个Refine线程进行处理日志来维护RSet数据的。这里的更新RSet就是为了保证RSet日志被处理完成,RSet数据完整才可以进行扫描。然后,遍历RSet,将可直达到CSet的对象(存活对象)移动到Survivor区,同时将存活对象引用的对象加入标记栈。 **4. 移动(Evacuation/Object Copy):**遍历标记栈,将栈内的所有对象(存活对象)复制到Survivor区域。这一步是整个"evacuation pause"的核心,确保所有需要移动的对象都被正确复制。这个过程的目标是将年轻代的存活对象转移到Survivor区域,并确保相关引用关系得以更新。整个"evacuation pause"是一个短暂的停顿,但会保证内存中的对象关系得以正确维护。 **5. 收尾步骤:**年龄超过晋升阈值的对象会直接移动到老年代区域。执行一些收尾工作,如Redirty(与并发标记配合使用)、Clear CT(清理Card Table)、Free CSet(清理回收集合)等,这些操作通常耗时很短。 Young GC还负责维护对象的年龄(存活次数),辅助判断老化(tenuring)对象晋升的时候是到Survivor分区还是到老年代分区。Young GC会将晋升对象尺寸总和、对象年龄信息维护到年龄表中,再根据年龄表、Survivor尺寸、Survivor填充容量-XX:TargetSurvivorRatio(默认50%)、最大任期阈值-XX:MaxTenuringThreshold(默认15),计算出一个恰当的任期阈值,凡是超过任期阈值的对象都会被晋升到老年代。
Young GC和Mixed GC是G1回收内存的主要活动。当应用程序启动时,堆内存可用空间相对较大,此时只有在年轻代填满时才会触发Young GC。随着应用程序的运行,老年代内存逐渐增长。当老年代占整个堆的比例达到初始化堆占用百分比阈值(InitiatingHeapOccupancyPercent,默认为45%)时,G1开始准备进行老年代的收集。
但是G1收集器不会直接进行Mixed GC的收集阶段,而是先通过“并发标记周期”(Concurrent Marking Cycle)来标记出高收益的老年代分区,确定下次Mixed GC的CSet(Choose CSet),之后再执行混合收集周期(Mixed GC Cycle)。
img 当不断的Young GC达到IHOP阈值-XX:InitiatingHeapOccupancyPercent
(老年代占整堆比,默认45%)时,就会触发并发标记周期,它的执行过程类似于CMS(Concurrent Mark-Sweep),执行过程包括以下四个步骤:
初始标记(Initial Mark,STW) :和CMS一样,这个阶段是需要STW的,只标记从GC Root开始直接可达的对象。并发标记(Concurrent Marking) :并行标记线程与应用程序线程一起执行,标记整个heap中的对象,并收集各个Region的存活对象信息。最终标记(Remark,STW) :标记在并发标记阶段发生变化的对象,准备进行回收,这个阶段主要是重新标记在并发标记阶段产生的新垃圾,需要STW。 另外,由于G1采用的**三色标记算法 ,在并发标记阶段可能会出现 “多标”和“漏标” 的情况。相对来说“多标”是可以容忍的,只需要等到下次GC的时候进行处理即可;但是“漏标”会导致正常使用的对象被释放,因此是不能容忍的。在CMS中会采用 “写屏障 + 原始快照” ** 的方法来处理漏标问题,而这个方法需要将发生变化的对象进行重新标记。筛选回收(Cleanup) :筛选回收环节会对Old Region的回收价值和成本进行排序,根据用户指定的停顿时间等来确定回收性价比最高的Region。这个阶段和CMS不同,是需要STW的。初始标记(Initial Mark)的任务是标记所有直接可达的根对象,如原生栈对象、全局对象和JNI对象。由于根是对象图的起点,这个阶段需要暂停Mutator线程(Java应用线程),即需要一个STW的时间段。
实际上,当达到IHOP阈值时,G1并不会立即启动并发标记周期,而是等待下一次年轻代收集。这时,它利用年轻代收集的STW时间段来完成初始标记,这种方式称为借道(Piggybacking)。在初始标记暂停期间,分区的NTAMS都被设置到分区顶部Top。初始标记是并发执行的,直到所有分区都得到处理。
初始标记暂停结束后,年轻代收集已完成对象复制到Survivor的工作,应用线程开始活跃。为了保证标记算法的正确性,所有新复制到Survivor分区的对象都需要进行扫描并标记为根。这个过程被称为根分区扫描(Root Region Scanning),同时扫描的Survivor分区也被称为根分区(Root Region)。
根分区扫描必须在下一次年轻代垃圾收集启动之前完成,因为在并发标记的过程中可能会被若干次年轻代垃圾收集打断。这确保了每次GC都有准确的存活对象集合。
在并发标记阶段,并发标记线程与应用线程并发执行,并发标记阶段通过参数-XX:ConcGCThreads(默认为GC线程数的1/4,即-XX:ParallelGCThreads/4)控制启动数量。
每个线程负责扫描一个分区,从而标记出存活对象图。在这个过程中,处理Previous/Next标记位图,扫描标记对象的引用字段。并发标记线程定期检查和处理STAB全局缓冲区列表的记录,更新对象引用信息。若开启参数-XX:+ClassUnloadingWithConcurrentMark,当一个类如果在Final Mark阶段不可达,将直接卸载。
标记任务必须在堆满之前完成扫描,否则会触发担保机制,经历一次长时间的串行Full GC。
存活数据计算(Live Data Accounting)是标记操作的附加产物,一旦对象被标记,将计算其字节数并记录到分区空间。只有NTAMS以下的对象会被标记和计算,标记周期结束时,Next位图将被清空,为下次标记周期做准备。
重新标记(Remark)是标记阶段的最后一步。在这个阶段,G1需要进行一次短时间的停顿,来处理剩余的SATB(并发标记产生的存活对象记录)日志缓冲区和所有的更新。
其目标是找出所有未被访问的存活对象,并安全地完成存活数据计算。这个阶段也是并行执行的,可以通过参数-XX:ParallelGCThread来设置在GC暂停时可用的并行GC线程数。
与此同时,引用处理也是重新标记阶段的一部分,对于所有强引用、软引用、弱引用、虚引用以及最终引用的对象,都会在引用处理中产生一些额外的开销。
筛选回收的阶段,同样是一个STW(Stop-The-World)的过程,并且是并发执行的,主要会进行以下主要操作:
RSet梳理: 启发式算法会根据活跃度和RSet尺寸对分区进行不同等级的定义。同时,RSet的梳理也有助于发现无用的引用。可以通过参数-XX:+PrintAdaptiveSizePolicy来开启打印启发式算法决策的详细信息。整理堆分区: 为Mixed GC Cycle识别回收效益高(基于释放空间和暂停目标)的Old Region集合。识别所有空闲分区: 即发现无存活对象的分区,这些分区在筛选回收阶段可以直接回收,无需等待下次Mixed GC Cycle。筛选回收阶段结束之后,就可能会启动Mixed GC Cycle,Mixed GC Cycle会根据该过程中整理出的回收效益高的分区来决定是否要将这些Region加入CSet并进行回收。
当G1发起并发标记周期之后,并不会马上开始Mixed GC Cycle,G1会先等待下一次Young GC,然后在该收集阶段中,确定下次混合收集的CSet(Choose CSet),之后才会决定是否开启混合回收周期。
单次的Mixed GC与Young GC在操作上别无二致,可以参考前面的Young GC的流程。但是Mixed GC为了减小垃圾回收的停顿时间,Old Region可能无法在一次Mixed GC中被完全处理。
因此,G1会启动连续多次的Mixed GC,这一系列的Mixed GC被称为混合收集周期(Mixed Collection Cycle)。在Mixed GC Cycle中,G1会进行一系列的计算和决策,来确定单次收集的分区数量以及是否结束Mixed GC:
计算每次加入到CSet中的分区数量; 确定混合收集进行的次数; 在上一次Young GC以及接下来的Mixed GC中,确定下一次加入CSet的分区(Choose CSet)的Region; 确定是否结束Mixed GC Cycle,以及是否启动Full GC; 这些计算和决策是为了优化整个混合收集周期,使得在每次垃圾回收中都能有效地处理老年代的分区,同时控制停顿时间,以提高应用程序的响应性。
Young GC触发时机: Young GC的触发时机是当年轻代空间逐渐填满,无法再Eden区域分配新的对象时。*Mixed GC***触发时机: Mixed GC的触发取决于一些参数的设定,这些参数包括: 参数 含义 G1HeapWastePercent 在全局并发标记结束后,系统检查Old Regions中即将被回收的垃圾百分比,只有达到此参数设定的百分比时,下次才会触发Mixed GC G1MixedGCLiveThresholdPercent Old Region中存活对象的占比,只有在此参数设定的阈值以下,Region才会被选入CSet(Collection Set,回收集) G1MixedGCCountTarget 一次全局并发标记后,最多执行Mixed GC的次数 G1OldCSetRegionThresholdPercent 一次Mixed GC中可选入CSet的最多老年代Region数量的百分比
*Full GC***触发时机: 在G1垃圾收集器中,当堆空间无法分配新的分区时,即无法满足对象的分配需求时,G1会启动担保机制,执行一次完全暂停(STW)的、Serial Old单线程的Full GC。Full GC的过程涉及整个堆的标记、清理和压缩,最终留下只包含存活对象的堆。Full GC发生时,G1会在日志中记录 "to-space-exhausted" 和 "Evacuation Failure",以下是触发Full GC的一些场景,: 从Young Region拷贝存活对象时 :当G1尝试将Young Region的存活对象拷贝到其他分区时,如果找不到可用的Free Region,就会触发Full GC。从Old Region转移存活对象时 :在尝试将Old Region的存活对象转移到其他分区时,如果找不到可用的Free Region,同样会触发Full GC。分配巨型对象时 :当G1需要为巨型对象分配内存空间时,如果在Old Region找不到足够的连续分区,就会触发Full GC。 这些情况下,Full GC是G1的一种应对措施,但由于Full GC的代价昂贵,会导致暂停时间较长,因此应该尽量避免触发Full GC。
1.内存划分:CMS垃圾回收器将Java堆划分为年轻代和老年代,而G1垃圾回收器则将Java堆划分为多个大小相等的区域(region),每个区域都可能是Eden区、Survivor区或Old区。
2.并发阶段:CMS垃圾回收器在标记和清除阶段都有并发的操作,而G1垃圾回收器只在标记阶段有并发的操作。
3.内存碎片处理:CMS垃圾回收器在进行垃圾回收时,不会对对象进行压缩和整理,这可能会导致内存碎片问题。而G1垃圾回收器在垃圾回收过程中可以对对象进行压缩和整理,从而减少内存碎片。
4.可预测性:G1垃圾回收器引入了暂停时间目标(Pause Time Goal),可以让用户指定期望的垃圾回收暂停时间,从而提供更好的可预测性。
5.垃圾回收策略:CMS垃圾回收器主要关注的是降低老年代的垃圾回收暂停时间,而G1垃圾回收器则试图在整个Java堆上都实现低暂停时间。
G1是一款卓越的垃圾收集器,适用于大型堆内存应用,并简化了性能调优的工作。通过主要参数设置初始堆、最大堆以及最大允许的GC暂停目标,可以获得良好的性能。尽管G1对内存空间的浪费较高,但通过"首先收集尽可能多的垃圾"的设计原则,能够及时发现过期对象,保持内存占用在合理水平。
G1的垃圾收集过程包括初始标记、并发标记、重新标记、清除、转移回收等步骤,同时以一个串行收集器做担保机制。然而,与其他垃圾收集器的过程描述不同,G1的设计原则是"Garbage First",不等待内存耗尽开始垃圾收集,而是在内部采用启发式算法,在老年代找出高收集收益的分区进行收集。
G1还能根据用户设置的暂停时间目标自动调整年轻代和总堆大小,使得暂停目标越短,年轻代空间越小、总空间越大。采用内存分区的思路,G1将内存划分为相等大小的内存分区,在回收时以分区为单位进行操作,将存活的对象复制到另一个空闲分区中。由于操作单位相等,G1天然是一种压缩方案(局部压缩)。
尽管G1是分代收集器,但内存分区不存在物理上的年轻代与老年代的区别,也无需独立的survivor(to space)堆。G1只有逻辑上的分代概念,每个分区都可能在不同代之间前后切换。
G1的收集过程是STW的,但年轻代和老年代的收集界限比较模糊,采用了混合(mixed)收集的方式。每次收集既可能只收集年轻代分区(年轻代收集),也可能在收集年轻代的同时,包含部分老年代分区(混合收集)。这种方式即使在堆内存很大时,也可以限制收集范围,从而降低停顿。
',142)]))}const d=t(r,[["render",l],["__file","g1.html.vue"]]),s=JSON.parse('{"path":"/java/JVM/g1.html","title":"G1","lang":"zh-CN","frontmatter":{"description":"G1 本文转载自增量式垃圾回收器——带你深入理解G1垃圾回收器 G1垃圾回收器是在Java 7之后引入的一种垃圾回收器。它被设计为一种分代、增量、并行和并发的标记-复制垃圾回收器,旨在适应不断扩大的内存和增加的处理器数量,以显著降低垃圾回收造成的暂停时间,同时保持良好的吞吐量,主要有以下特点: 并行与并发: G1回收器在垃圾回收的不同阶段使用了并行和并...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/java/JVM/g1.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"G1"}],["meta",{"property":"og:description","content":"G1 本文转载自增量式垃圾回收器——带你深入理解G1垃圾回收器 G1垃圾回收器是在Java 7之后引入的一种垃圾回收器。它被设计为一种分代、增量、并行和并发的标记-复制垃圾回收器,旨在适应不断扩大的内存和增加的处理器数量,以显著降低垃圾回收造成的暂停时间,同时保持良好的吞吐量,主要有以下特点: 并行与并发: G1回收器在垃圾回收的不同阶段使用了并行和并..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/v2-ddd707766e13fb354940a1a2e8ab5055_1440w.webp"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-16T09:55:09.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-16T09:55:09.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"G1\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/v2-ddd707766e13fb354940a1a2e8ab5055_1440w.webp\\",\\"https://github-images.wenzhihuai.com/images/v2-e2aee61fa6f90ea5ee2471f9b260617e_1440w.webp\\",\\"https://github-images.wenzhihuai.com/images/v2-73c5aa7da8361788952fbecac20caad2_1440w.webp\\",\\"https://github-images.wenzhihuai.com/images/v2-27e44887ebaf83e0951f452714b8b311_1440w.webp\\",\\"https://github-images.wenzhihuai.com/images/v2-819a31c0caf633685200ef331d027b70_1440w.webp\\",\\"https://github-images.wenzhihuai.com/images/v2-37b4072e5746748e329d07c8f00b5f5b_1440w.webp\\",\\"https://github-images.wenzhihuai.com/images/v2-557807dd7a05a5bb13b0fdb0d5a16b1d_1440w.webp\\",\\"https://github-images.wenzhihuai.com/images/v2-1351bbae5aad68fcd85ebb0c1d2bc9ac_1440w.webp\\"],\\"dateModified\\":\\"2024-02-16T09:55:09.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"Zephery\\",\\"url\\":\\"https://wenzhihuai.com/article/\\"}]}"]]},"headers":[{"level":2,"title":"G1的内存模型和分代策略","slug":"g1的内存模型和分代策略","link":"#g1的内存模型和分代策略","children":[{"level":3,"title":"G1收集器相关参数","slug":"g1收集器相关参数","link":"#g1收集器相关参数","children":[]},{"level":3,"title":"G1分区(Region)机制和分代策略","slug":"g1分区-region-机制和分代策略","link":"#g1分区-region-机制和分代策略","children":[]},{"level":3,"title":"G1 卡片(Card)标记机制","slug":"g1-卡片-card-标记机制","link":"#g1-卡片-card-标记机制","children":[]},{"level":3,"title":"G1 堆(Heap)空间调整机制","slug":"g1-堆-heap-空间调整机制","link":"#g1-堆-heap-空间调整机制","children":[]},{"level":3,"title":"本地分配缓冲 Local allocation buffer (Lab)","slug":"本地分配缓冲-local-allocation-buffer-lab","link":"#本地分配缓冲-local-allocation-buffer-lab","children":[]}]},{"level":2,"title":"Remember Set(RSet)和Collection Set(CSet)","slug":"remember-set-rset-和collection-set-cset","link":"#remember-set-rset-和collection-set-cset","children":[{"level":3,"title":"为什么需要RSet?","slug":"为什么需要rset","link":"#为什么需要rset","children":[]},{"level":3,"title":"RSet的实现机制","slug":"rset的实现机制","link":"#rset的实现机制","children":[]},{"level":3,"title":"Per Region Table(PRT)机制","slug":"per-region-table-prt-机制","link":"#per-region-table-prt-机制","children":[]},{"level":3,"title":"RSet记录的引用类型","slug":"rset记录的引用类型","link":"#rset记录的引用类型","children":[]},{"level":3,"title":"CSet(收集集合,Collection Set)","slug":"cset-收集集合-collection-set","link":"#cset-收集集合-collection-set","children":[]},{"level":3,"title":"RSet的维护","slug":"rset的维护","link":"#rset的维护","children":[]},{"level":3,"title":"屏障(Barrier)","slug":"屏障-barrier","link":"#屏障-barrier","children":[]},{"level":3,"title":"始快照算法(Snapshot at the Beginning,SATB)","slug":"始快照算法-snapshot-at-the-beginning-satb","link":"#始快照算法-snapshot-at-the-beginning-satb","children":[]},{"level":3,"title":"并发优化线程 (Concurrence Refinement Threads)","slug":"并发优化线程-concurrence-refinement-threads","link":"#并发优化线程-concurrence-refinement-threads","children":[]}]},{"level":2,"title":"G1的垃圾回收流程","slug":"g1的垃圾回收流程","link":"#g1的垃圾回收流程","children":[{"level":3,"title":"G1的GC模式","slug":"g1的gc模式","link":"#g1的gc模式","children":[]},{"level":3,"title":"GC 工作线程数(-XX:ParallelGCThreads)","slug":"gc-工作线程数-xx-parallelgcthreads","link":"#gc-工作线程数-xx-parallelgcthreads","children":[]},{"level":3,"title":"Young GC核心流程","slug":"young-gc核心流程","link":"#young-gc核心流程","children":[]},{"level":3,"title":"Mixed GC核心流程——混合收集周期(Mixed GC Cycle)","slug":"mixed-gc核心流程——混合收集周期-mixed-gc-cycle","link":"#mixed-gc核心流程——混合收集周期-mixed-gc-cycle","children":[]},{"level":3,"title":"并发标记周期 (Concurrent Marking Cycle)","slug":"并发标记周期-concurrent-marking-cycle","link":"#并发标记周期-concurrent-marking-cycle","children":[]},{"level":3,"title":"初始标记(Initial Mark,STW)","slug":"初始标记-initial-mark-stw","link":"#初始标记-initial-mark-stw","children":[]},{"level":3,"title":"并发标记(Concurrent Mark)","slug":"并发标记-concurrent-mark","link":"#并发标记-concurrent-mark","children":[]},{"level":3,"title":"最终标记(Final Mark)","slug":"最终标记-final-mark","link":"#最终标记-final-mark","children":[]},{"level":3,"title":"筛选回收(Clean Up)","slug":"筛选回收-clean-up","link":"#筛选回收-clean-up","children":[]},{"level":3,"title":"混合回收周期(Mixed GC Cycle)","slug":"混合回收周期-mixed-gc-cycle","link":"#混合回收周期-mixed-gc-cycle","children":[]},{"level":3,"title":"Young GC、Mixed GC 和 Full GC的触发时机","slug":"young-gc、mixed-gc-和-full-gc的触发时机","link":"#young-gc、mixed-gc-和-full-gc的触发时机","children":[]}]},{"level":2,"title":"JDK的G1垃圾回收器和CMS有什么区别","slug":"jdk的g1垃圾回收器和cms有什么区别","link":"#jdk的g1垃圾回收器和cms有什么区别","children":[]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1708056026000,"updatedTime":1708077309000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":39.5,"words":11851},"filePathRelative":"java/JVM/g1.md","localizedDate":"2024年2月16日","excerpt":"\\n本文转载自增量式垃圾回收器——带你深入理解G1垃圾回收器
","autoDesc":true}');export{d as comp,s as data};
diff --git a/assets/giscus-BZxmVUME.js b/assets/giscus-BZxmVUME.js
new file mode 100644
index 00000000..9d2a50ab
--- /dev/null
+++ b/assets/giscus-BZxmVUME.js
@@ -0,0 +1,66 @@
+/**
+ * @license
+ * Copyright 2019 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const H=globalThis,V=H.ShadowRoot&&(H.ShadyCSS===void 0||H.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,q=Symbol(),J=new WeakMap;let ht=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==q)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(V&&t===void 0){const s=e!==void 0&&e.length===1;s&&(t=J.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),s&&J.set(e,t))}return t}toString(){return this.cssText}};const ut=i=>new ht(typeof i=="string"?i:i+"",void 0,q),$t=(i,...t)=>{const e=i.length===1?i[0]:t.reduce((s,r,o)=>s+(n=>{if(n._$cssResult$===!0)return n.cssText;if(typeof n=="number")return n;throw Error("Value passed to 'css' function must be a 'css' function result: "+n+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(r)+i[o+1],i[0]);return new ht(e,i,q)},_t=(i,t)=>{if(V)i.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const e of t){const s=document.createElement("style"),r=H.litNonce;r!==void 0&&s.setAttribute("nonce",r),s.textContent=e.cssText,i.appendChild(s)}},Z=V?i=>i:i=>i instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return ut(e)})(i):i;/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const{is:gt,defineProperty:ft,getOwnPropertyDescriptor:mt,getOwnPropertyNames:At,getOwnPropertySymbols:yt,getPrototypeOf:St}=Object,A=globalThis,Q=A.trustedTypes,vt=Q?Q.emptyScript:"",Y=A.reactiveElementPolyfillSupport,U=(i,t)=>i,L={toAttribute(i,t){switch(t){case Boolean:i=i?vt:null;break;case Object:case Array:i=i==null?i:JSON.stringify(i)}return i},fromAttribute(i,t){let e=i;switch(t){case Boolean:e=i!==null;break;case Number:e=i===null?null:Number(i);break;case Object:case Array:try{e=JSON.parse(i)}catch{e=null}}return e}},K=(i,t)=>!gt(i,t),X={attribute:!0,type:String,converter:L,reflect:!1,hasChanged:K};Symbol.metadata??(Symbol.metadata=Symbol("metadata")),A.litPropertyMetadata??(A.litPropertyMetadata=new WeakMap);class E extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??(this.l=[])).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=X){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)??X}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(Z(r))}else t!==void 0&&e.push(Z(t));return e}static _$Eu(t,e){const s=e.attribute;return s===!1?void 0:typeof s=="string"?s:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){var t;this._$ES=new Promise(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),(t=this.constructor.l)==null||t.forEach(e=>e(this))}addController(t){var e;(this._$EO??(this._$EO=new Set)).add(t),this.renderRoot!==void 0&&this.isConnected&&((e=t.hostConnected)==null||e.call(t))}removeController(t){var e;(e=this._$EO)==null||e.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const s of e.keys())this.hasOwnProperty(s)&&(t.set(s,this[s]),delete this[s]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return _t(t,this.constructor.elementStyles),t}connectedCallback(){var t;this.renderRoot??(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),(t=this._$EO)==null||t.forEach(e=>{var s;return(s=e.hostConnected)==null?void 0:s.call(e)})}enableUpdating(t){}disconnectedCallback(){var t;(t=this._$EO)==null||t.forEach(e=>{var s;return(s=e.hostDisconnected)==null?void 0:s.call(e)})}attributeChangedCallback(t,e,s){this._$AK(t,s)}_$EC(t,e){var o;const s=this.constructor.elementProperties.get(t),r=this.constructor._$Eu(t,s);if(r!==void 0&&s.reflect===!0){const n=(((o=s.converter)==null?void 0:o.toAttribute)!==void 0?s.converter:L).toAttribute(e,s.type);this._$Em=t,n==null?this.removeAttribute(r):this.setAttribute(r,n),this._$Em=null}}_$AK(t,e){var o;const s=this.constructor,r=s._$Eh.get(t);if(r!==void 0&&this._$Em!==r){const n=s.getPropertyOptions(r),a=typeof n.converter=="function"?{fromAttribute:n.converter}:((o=n.converter)==null?void 0:o.fromAttribute)!==void 0?n.converter:L;this._$Em=r,this[r]=a.fromAttribute(e,n.type),this._$Em=null}}requestUpdate(t,e,s){if(t!==void 0){if(s??(s=this.constructor.getPropertyOptions(t)),!(s.hasChanged??K)(this[t],e))return;this.P(t,e,s)}this.isUpdatePending===!1&&(this._$ES=this._$ET())}P(t,e,s){this._$AL.has(t)||this._$AL.set(t,e),s.reflect===!0&&this._$Em!==t&&(this._$Ej??(this._$Ej=new Set)).add(t)}async _$ET(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var s;if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??(this.renderRoot=this.createRenderRoot()),this._$Ep){for(const[o,n]of this._$Ep)this[o]=n;this._$Ep=void 0}const r=this.constructor.elementProperties;if(r.size>0)for(const[o,n]of r)n.wrapped!==!0||this._$AL.has(o)||this[o]===void 0||this.P(o,this[o],n)}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),(s=this._$EO)==null||s.forEach(r=>{var o;return(o=r.hostUpdate)==null?void 0:o.call(r)}),this.update(e)):this._$EU()}catch(r){throw t=!1,this._$EU(),r}t&&this._$AE(e)}willUpdate(t){}_$AE(t){var e;(e=this._$EO)==null||e.forEach(s=>{var r;return(r=s.hostUpdated)==null?void 0:r.call(s)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EU(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Ej&&(this._$Ej=this._$Ej.forEach(e=>this._$EC(e,this[e]))),this._$EU()}updated(t){}firstUpdated(t){}}E.elementStyles=[],E.shadowRootOptions={mode:"open"},E[U("elementProperties")]=new Map,E[U("finalized")]=new Map,Y==null||Y({ReactiveElement:E}),(A.reactiveElementVersions??(A.reactiveElementVersions=[])).push("2.0.4");/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const P=globalThis,k=P.trustedTypes,tt=k?k.createPolicy("lit-html",{createHTML:i=>i}):void 0,at="$lit$",m=`lit$${Math.random().toFixed(9).slice(2)}$`,ct="?"+m,Et=`<${ct}>`,v=document,M=()=>v.createComment(""),N=i=>i===null||typeof i!="object"&&typeof i!="function",F=Array.isArray,bt=i=>F(i)||typeof(i==null?void 0:i[Symbol.iterator])=="function",B=`[
+\f\r]`,w=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,et=/-->/g,st=/>/g,y=RegExp(`>|${B}(?:([^\\s"'>=/]+)(${B}*=${B}*(?:[^
+\f\r"'\`<>=]|("|')|))|$)`,"g"),it=/'/g,rt=/"/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"),nt=new WeakMap,S=v.createTreeWalker(v,129);function dt(i,t){if(!F(i)||!i.hasOwnProperty("raw"))throw Error("invalid template strings array");return tt!==void 0?tt.createHTML(t):t}const Ut=(i,t)=>{const e=i.length-1,s=[];let r,o=t===2?"":t===3?"":"",n=w;for(let a=0;a"?(n=r??w,c=-1):u[1]===void 0?c=-2:(c=n.lastIndex-u[2].length,d=u[1],n=u[3]===void 0?y:u[3]==='"'?rt:it):n===rt||n===it?n=y:n===et||n===st?n=w:(n=y,r=void 0);const f=n===y&&i[a+1].startsWith("/>")?" ":"";o+=n===w?h+Et:c>=0?(s.push(d),h.slice(0,c)+at+h.slice(c)+m+f):h+m+(c===-2?a:f)}return[dt(i,o+(i[e]||">")+(t===2?" ":t===3?"":"")),s]};class R{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=R.createElement(d,s),S.currentNode=this.el.content,e===2||e===3){const c=this.el.content.firstChild;c.replaceWith(...c.childNodes)}for(;(r=S.nextNode())!==null&&h.length0){r.textContent=k?k.emptyScript:"";for(let f=0;f2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=l}_$AI(t,e=this,s,r){const o=this.strings;let n=!1;if(o===void 0)t=C(this,t,e,0),n=!N(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 I(t.insertBefore(M(),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=Rt(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 ot;O._$litElement$=!0,O.finalized=!0,(ot=globalThis.litElementHydrateSupport)==null||ot.call(globalThis,{LitElement:O});const G=globalThis.litElementPolyfillSupport;G==null||G({LitElement:O});(globalThis.litElementVersions??(globalThis.litElementVersions=[])).push("4.1.1");/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const It=i=>(t,e)=>{e!==void 0?e.addInitializer(()=>{customElements.define(i,t)}):customElements.define(i,t)};/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const xt={attribute:!0,type:String,converter:L,reflect:!1,hasChanged:K},Ht=(i=xt,t,e)=>{const{kind:s,metadata:r}=e;let o=globalThis.litPropertyMetadata.get(r);if(o===void 0&&globalThis.litPropertyMetadata.set(r,o=new Map),o.set(e.name,i),s==="accessor"){const{name:n}=e;return{set(a){const h=t.get.call(this);t.set.call(this,a),this.requestUpdate(n,h,i)},init(a){return a!==void 0&&this.P(n,void 0,i),a}}}if(s==="setter"){const{name:n}=e;return function(a){const h=this[n];t.call(this,a),this.requestUpdate(n,h,i)}}throw Error("Unsupported decorator location: "+s)};function _(i){return(t,e)=>typeof e=="object"?Ht(i,t,e):((s,r,o)=>{const n=r.hasOwnProperty(o);return r.constructor.createProperty(o,n?{...s,wrapped:!0}:s),n?Object.getOwnPropertyDescriptor(r,o):void 0})(i,t,e)}/**
+ * @license
+ * Copyright 2020 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const Lt=i=>i.strings===void 0;/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const kt={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},Dt=i=>(...t)=>({_$litDirective$:i,values:t});let zt=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,s){this._$Ct=t,this._$AM=e,this._$Ci=s}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const 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},D=i=>{let t,e;do{if((t=i._$AM)===void 0)break;e=t._$AN,e.delete(i),i=t}while((e==null?void 0:e.size)===0)},pt=i=>{for(let t;t=i._$AM;i=t){let e=t._$AN;if(e===void 0)t._$AN=e=new Set;else if(e.has(i))break;e.add(i),jt(t)}};function Yt(i){this._$AN!==void 0?(D(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=Yt))};class Gt extends zt{constructor(){super(...arguments),this._$AN=void 0}_$AT(t,e,s){super._$AT(t,e,s),pt(this),this.isConnected=t._$AU}_$AO(t,e=!0){var s,r;t!==this.isConnected&&(this.isConnected=t,t?(s=this.reconnected)==null||s.call(this):(r=this.disconnected)==null||r.call(this)),e&&(T(this,t),D(this))}setValue(t){if(Lt(this._$Ct))this._$Ct._$AI(t,this);else{const e=[...this._$Ct._$AH];e[this._$Ci]=t,this._$Ct._$AI(e,this,0)}}disconnected(){}reconnected(){}}/**
+ * @license
+ * Copyright 2020 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const Wt=()=>new Vt;class Vt{}const W=new WeakMap,qt=Dt(class extends Gt{render(i){return l}update(i,[t]){var s;const e=t!==this.Y;return e&&this.Y!==void 0&&this.rt(void 0),(e||this.lt!==this.ct)&&(this.Y=t,this.ht=(s=i.options)==null?void 0:s.host,this.rt(this.ct=i.element)),l}rt(i){if(this.isConnected||(i=void 0),typeof this.Y=="function"){const t=this.ht??globalThis;let e=W.get(t);e===void 0&&(e=new WeakMap,W.set(t,e)),e.get(this.Y)!==void 0&&this.Y.call(this.ht,void 0),e.set(this.Y,i),i!==void 0&&this.Y.call(this.ht,i)}else this.Y.value=i}get lt(){var i,t;return typeof this.Y=="function"?(i=W.get(this.ht??globalThis))==null?void 0:i.get(this.Y):(t=this.Y)==null?void 0:t.value}disconnected(){this.lt===this.ct&&this.rt(void 0)}reconnected(){this.rt(this.ct)}});var Kt=Object.defineProperty,Ft=Object.getOwnPropertyDescriptor,$=(i,t,e,s)=>{for(var r=s>1?void 0:s?Ft(t,e):t,o=i.length-1,n;o>=0;o--)(n=i[o])&&(r=(s?n(t,e,r):n(r))||r);return s&&r&&Kt(t,e,r),r};function Jt(i){return customElements.get(i)?t=>t:It(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=Wt(),this.messageEventHandler=this.handleMessageEvent.bind(this),this.hasLoaded=!1,this.host=this.GISCUS_DEFAULT_HOST,this.strict="0",this.reactionsEnabled="1",this.emitMetadata="0",this.inputPosition="bottom",this.theme="light",this.lang="en",this.loading="eager",this.setupSession(),window.addEventListener("message",this.messageEventHandler)}get iframeRef(){var i;return(i=this._iframeRef)==null?void 0:i.value}get _host(){try{return new URL(this.host),this.host}catch{return this.GISCUS_DEFAULT_HOST}}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("message",this.messageEventHandler)}_formatError(i){return`[giscus] An error occurred. Error message: "${i}".`}setupSession(){const i=location.href,t=new URL(i),e=localStorage.getItem(this.GISCUS_SESSION_KEY),s=t.searchParams.get("giscus")??"";if(this.__session="",s){localStorage.setItem(this.GISCUS_SESSION_KEY,JSON.stringify(s)),this.__session=s,t.searchParams.delete("giscus"),t.hash="",history.replaceState(void 0,document.title,t.toString());return}if(e)try{this.__session=JSON.parse(e)}catch(r){localStorage.removeItem(this.GISCUS_SESSION_KEY),console.warn(`${this._formatError(r==null?void 0:r.message)} Session has been cleared.`)}}signOut(){localStorage.removeItem(this.GISCUS_SESSION_KEY),this.__session="",this.update(new Map)}handleMessageEvent(i){if(i.origin!==this._host)return;const{data:t}=i;if(!(typeof t=="object"&&t.giscus))return;if(this.iframeRef&&t.giscus.resizeHeight&&(this.iframeRef.style.height=`${t.giscus.resizeHeight}px`),t.giscus.signOut){console.info("[giscus] User has logged out. Session has been cleared."),this.signOut();return}if(!t.giscus.error)return;const e=t.giscus.error;if(e.includes("Bad credentials")||e.includes("Invalid state value")||e.includes("State has expired")){if(localStorage.getItem(this.GISCUS_SESSION_KEY)!==null){console.warn(`${this._formatError(e)} Session has been cleared.`),this.signOut();return}console.error(`${this._formatError(e)} No session is stored initially. ${this.ERROR_SUGGESTION}`)}if(e.includes("Discussion not found")){console.warn(`[giscus] ${e}. A new discussion will be created if a comment/reaction is submitted.`);return}console.error(`${this._formatError(e)} ${this.ERROR_SUGGESTION}`)}sendMessage(i){var t;!((t=this.iframeRef)!=null&&t.contentWindow)||!this.hasLoaded||this.iframeRef.contentWindow.postMessage({giscus:i},this._host)}updateConfig(){const i={setConfig:{repo:this.repo,repoId:this.repoId,category:this.category,categoryId:this.categoryId,term:this.getTerm(),number:+this.getNumber(),strict:this.strict==="1",reactionsEnabled:this.reactionsEnabled==="1",emitMetadata:this.emitMetadata==="1",inputPosition:this.inputPosition,theme:this.theme,lang:this.lang}};this.sendMessage(i)}firstUpdated(){var i;(i=this.iframeRef)==null||i.addEventListener("load",()=>{var t;(t=this.iframeRef)==null||t.classList.remove("loading"),this.hasLoaded=!0,this.updateConfig()})}requestUpdate(i,t,e){if(!this.hasUpdated||i==="host"){super.requestUpdate(i,t,e);return}this.updateConfig()}getMetaContent(i,t=!1){const e=t?`meta[property='og:${i}'],`:"",s=document.querySelector(e+`meta[name='${i}']`);return s?s.content:""}_getCleanedUrl(){const i=new URL(location.href);return i.searchParams.delete("giscus"),i.hash="",i}getTerm(){switch(this.mapping){case"url":return this._getCleanedUrl().toString();case"title":return document.title;case"og:title":return this.getMetaContent("title",!0);case"specific":return this.term??"";case"number":return"";case"pathname":default:return location.pathname.length<2?"index":location.pathname.substring(1).replace(/\.\w+$/,"")}}getNumber(){return this.mapping==="number"?this.term??"":""}getIframeSrc(){const i=this._getCleanedUrl().toString(),t=`${i}${this.id?"#"+this.id:""}`,e=this.getMetaContent("description",!0),s=this.getMetaContent("giscus:backlink")||i,r={origin:t,session:this.__session,repo:this.repo,repoId:this.repoId??"",category:this.category??"",categoryId:this.categoryId??"",term:this.getTerm(),number:this.getNumber(),strict:this.strict,reactionsEnabled:this.reactionsEnabled,emitMetadata:this.emitMetadata,inputPosition:this.inputPosition,theme:this.theme,description:e,backLink:s},o=this._host,n=this.lang?`/${this.lang}`:"",a=new URLSearchParams(r);return`${o}${n}/widget?${a.toString()}`}render(){return wt`
+
+ `}};p.styles=$t`
+ :host,
+ iframe {
+ width: 100%;
+ border: none;
+ min-height: 150px;
+ color-scheme: light dark;
+ }
+
+ iframe.loading {
+ opacity: 0;
+ }
+ `;$([_({reflect:!0})],p.prototype,"host",2);$([_({reflect:!0})],p.prototype,"repo",2);$([_({reflect:!0})],p.prototype,"repoId",2);$([_({reflect:!0})],p.prototype,"category",2);$([_({reflect:!0})],p.prototype,"categoryId",2);$([_({reflect:!0})],p.prototype,"mapping",2);$([_({reflect:!0})],p.prototype,"term",2);$([_({reflect:!0})],p.prototype,"strict",2);$([_({reflect:!0})],p.prototype,"reactionsEnabled",2);$([_({reflect:!0})],p.prototype,"emitMetadata",2);$([_({reflect:!0})],p.prototype,"inputPosition",2);$([_({reflect:!0})],p.prototype,"theme",2);$([_({reflect:!0})],p.prototype,"lang",2);$([_({reflect:!0})],p.prototype,"loading",2);p=$([Jt("giscus-widget")],p);export{p as GiscusWidget};
diff --git a/assets/icon/apple-icon-152.png b/assets/icon/apple-icon-152.png
new file mode 100644
index 00000000..f53c6c55
Binary files /dev/null and b/assets/icon/apple-icon-152.png differ
diff --git a/assets/icon/chrome-192.png b/assets/icon/chrome-192.png
new file mode 100644
index 00000000..57096280
Binary files /dev/null and b/assets/icon/chrome-192.png differ
diff --git a/assets/icon/chrome-512.png b/assets/icon/chrome-512.png
new file mode 100644
index 00000000..2db62c29
Binary files /dev/null and b/assets/icon/chrome-512.png differ
diff --git a/assets/icon/chrome-mask-192.png b/assets/icon/chrome-mask-192.png
new file mode 100644
index 00000000..77c39a2a
Binary files /dev/null and b/assets/icon/chrome-mask-192.png differ
diff --git a/assets/icon/chrome-mask-512.png b/assets/icon/chrome-mask-512.png
new file mode 100644
index 00000000..b8349f4e
Binary files /dev/null and b/assets/icon/chrome-mask-512.png differ
diff --git a/assets/icon/guide-maskable.png b/assets/icon/guide-maskable.png
new file mode 100644
index 00000000..230798a3
Binary files /dev/null and b/assets/icon/guide-maskable.png differ
diff --git a/assets/icon/guide-monochrome.png b/assets/icon/guide-monochrome.png
new file mode 100644
index 00000000..e12403e2
Binary files /dev/null and b/assets/icon/guide-monochrome.png differ
diff --git a/assets/icon/ms-icon-144.png b/assets/icon/ms-icon-144.png
new file mode 100644
index 00000000..681cde6f
Binary files /dev/null and b/assets/icon/ms-icon-144.png differ
diff --git "a/assets/idea\350\256\276\347\275\256.html-BThIkzaw.js" "b/assets/idea\350\256\276\347\275\256.html-BThIkzaw.js"
new file mode 100644
index 00000000..dc1d414f
--- /dev/null
+++ "b/assets/idea\350\256\276\347\275\256.html-BThIkzaw.js"
@@ -0,0 +1,17 @@
+import{_ as s,c as a,d as e,o as t}from"./app-ftEjETWs.js";const n={};function l(h,i){return t(),a("div",null,i[0]||(i[0]=[e(`想要在生成类的时候,自动带上author和时间,效果如下:
/**
+ * @author zhihuaiwen
+ * @since 2024/5/12 00:22
+ */
+public class EFE {
+}
放到File Header里统一下即可,当然,也可以去Files里定义Class File或者其他:
image-20240512002500812 想让自动给方法生成注释,以及参数的默认注释:
/**
+ * 获取首页商品列表
+ *
+ * @param type 类型 【1 精品推荐 2 热门榜单 3首发新品 4促销单品】
+ * @param pageParamRequest 分页参数
+ * @return List
+ */
+ @ Override
+ public CommonPage < IndexProductResponse > findIndexProductList ( Integer type , PageParamRequest pageParamRequest) {
去settings里面找到Live Templates,新建一个Template Group叫做user,然后再新建一个Live Template。
image-20240512001636936 Abbreviation填*,Description随便填,然后再Template text填下:
*
+$ VAR1 $
+ * @ return $returns$
+ */
编辑变量,Edit Variables:
image-20240512001711420.png VAR1:
groovyScript ( "def result=''; def params= \\" \${ _1 } \\" .replaceAll('[ \\\\\\\\ [| \\\\\\\\ ]| \\\\\\\\ s]', '').split(',').toList(); for(i = 0; i < params.size(); i++) {result+=' * @param ' + params[i] + ' ' + params[i] + ((i < params.size() - 1) ? ' \\\\ n' : '')}; return result" , methodParameters ())
returns:
Idea这个太烦了,总是不小心误点,想把右侧的两个都给去掉,网上查了有些比较旧,无法解决,下面特别声明下:
image-20240512001050312 位置:settings直接搜Inlay Hints,把右侧的Usages、Code author给取消勾选即可
image-20240512001010797 上面的设置放到百度网盘里了,可以下载后导入到Idea
链接: https://pan.baidu.com/s/1-3uhY1jssyMWyRbvBLQ2FQ?pwd=epw2 提取码: epw2 复制这段内容后打开百度网盘手机App,操作更方便哦
`,27)]))}const r=s(n,[["render",l],["__file","idea设置.html.vue"]]),k=JSON.parse('{"path":"/interesting/idea%E8%AE%BE%E7%BD%AE.html","title":"Jetbrains Idea设置","lang":"zh-CN","frontmatter":{"description":"Jetbrains Idea设置 一、类注释 想要在生成类的时候,自动带上author和时间,效果如下: 放到File Header里统一下即可,当然,也可以去Files里定义Class File或者其他: image-20240512002500812image-20240512002500812 二、方法注释 想让自动给方法生成注释,以及参数的默认...","head":[["meta",{"property":"og:url","content":"http://www.wenzhihuai.com/interesting/idea%E8%AE%BE%E7%BD%AE.html"}],["meta",{"property":"og:site_name","content":"个人博客"}],["meta",{"property":"og:title","content":"Jetbrains Idea设置"}],["meta",{"property":"og:description","content":"Jetbrains Idea设置 一、类注释 想要在生成类的时候,自动带上author和时间,效果如下: 放到File Header里统一下即可,当然,也可以去Files里定义Class File或者其他: image-20240512002500812image-20240512002500812 二、方法注释 想让自动给方法生成注释,以及参数的默认..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://github-images.wenzhihuai.com/images/image-20240512002500812.png"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-05-12T03:58:39.000Z"}],["meta",{"property":"article:modified_time","content":"2024-05-12T03:58:39.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Jetbrains Idea设置\\",\\"image\\":[\\"https://github-images.wenzhihuai.com/images/image-20240512002500812.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240512001636936.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240512001711420.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240512001050312.png\\",\\"https://github-images.wenzhihuai.com/images/image-20240512001010797.png\\"],\\"dateModified\\":\\"2024-05-12T03:58:39.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":"三、关闭Annotate With Git Blame","slug":"三、关闭annotate-with-git-blame","link":"#三、关闭annotate-with-git-blame","children":[]}],"git":{"createdTime":1715445447000,"updatedTime":1715486319000,"contributors":[{"name":"zhihuaiwen","email":"zhihuaiwen@tencent.com","commits":2}]},"readingTime":{"minutes":1.33,"words":399},"filePathRelative":"interesting/idea设置.md","localizedDate":"2024年5月11日","excerpt":"\\n一、类注释 \\n想要在生成类的时候,自动带上author和时间,效果如下:
","autoDesc":true}');export{r as comp,k as data};
diff --git a/assets/index-AN989yVn.js b/assets/index-AN989yVn.js
new file mode 100644
index 00000000..a0b535fa
--- /dev/null
+++ b/assets/index-AN989yVn.js
@@ -0,0 +1,61 @@
+/*! *****************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */var _p=function(r,e){return _p=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,a){t.__proto__=a}||function(t,a){for(var n in a)Object.prototype.hasOwnProperty.call(a,n)&&(t[n]=a[n])},_p(r,e)};function k(r,e){if(typeof e!="function"&&e!==null)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");_p(r,e);function t(){this.constructor=r}r.prototype=e===null?Object.create(e):(t.prototype=e.prototype,new t)}var oL=function(){function r(){this.firefox=!1,this.ie=!1,this.edge=!1,this.newEdge=!1,this.weChat=!1}return r}(),sL=function(){function r(){this.browser=new oL,this.node=!1,this.wxa=!1,this.worker=!1,this.svgSupported=!1,this.touchEventsSupported=!1,this.pointerEventsSupported=!1,this.domSupported=!1,this.transformSupported=!1,this.transform3dSupported=!1,this.hasGlobalWindow=typeof window<"u"}return r}(),_t=new sL;typeof wx=="object"&&typeof wx.getSystemInfoSync=="function"?(_t.wxa=!0,_t.touchEventsSupported=!0):typeof document>"u"&&typeof self<"u"?_t.worker=!0:typeof navigator>"u"||navigator.userAgent.indexOf("Node.js")===0?(_t.node=!0,_t.svgSupported=!0):lL(navigator.userAgent,_t);function lL(r,e){var t=e.browser,a=r.match(/Firefox\/([\d.]+)/),n=r.match(/MSIE\s([\d.]+)/)||r.match(/Trident\/.+?rv:(([\d.]+))/),i=r.match(/Edge?\/([\d.]+)/),o=/micromessenger/i.test(r);a&&(t.firefox=!0,t.version=a[1]),n&&(t.ie=!0,t.version=n[1]),i&&(t.edge=!0,t.version=i[1],t.newEdge=+i[1].split(".")[0]>18),o&&(t.weChat=!0),e.svgSupported=typeof SVGRect<"u",e.touchEventsSupported="ontouchstart"in window&&!t.ie&&!t.edge,e.pointerEventsSupported="onpointerdown"in window&&(t.edge||t.ie&&+t.version>=11),e.domSupported=typeof document<"u";var s=document.documentElement.style;e.transform3dSupported=(t.ie&&"transition"in s||t.edge||"WebKitCSSMatrix"in window&&"m11"in new WebKitCSSMatrix||"MozPerspective"in s)&&!("OTransition"in s),e.transformSupported=e.transform3dSupported||t.ie&&+t.version>=9}var sg=12,Sw="sans-serif",Ka=sg+"px "+Sw,uL=20,fL=100,hL="007LLmW'55;N0500LLLLLLLLLL00NNNLzWW\\\\WQb\\0FWLg\\bWb\\WQ\\WrWWQ000CL5LLFLL0LL**F*gLLLL5F0LF\\FFF5.5N";function vL(r){var e={};if(typeof JSON>"u")return e;for(var t=0;t=0)s=o*t.length;else for(var l=0;l>1)%2;s.cssText=["position: absolute","visibility: hidden","padding: 0","margin: 0","border-width: 0","user-select: none","width:0","height:0",a[l]+":0",n[u]+":0",a[1-l]+":auto",n[1-u]+":auto",""].join("!important;"),r.appendChild(o),t.push(o)}return t}function EL(r,e,t){for(var a=t?"invTrans":"trans",n=e[a],i=e.srcCoords,o=[],s=[],l=!0,u=0;u<4;u++){var f=r[u].getBoundingClientRect(),h=2*u,v=f.left,c=f.top;o.push(v,c),l=l&&i&&v===i[h]&&c===i[h+1],s.push(r[u].offsetLeft,r[u].offsetTop)}return l&&n?n:(e.srcCoords=o,e[a]=t?Tm(s,o):Tm(o,s))}function Pw(r){return r.nodeName.toUpperCase()==="CANVAS"}var kL=/([&<>"'])/g,OL={"&":"&","<":"<",">":">",'"':""","'":"'"};function Me(r){return r==null?"":(r+"").replace(kL,function(e,t){return OL[t]})}var NL=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Jh=[],BL=_t.browser.firefox&&+_t.browser.version.split(".")[0]<39;function Tp(r,e,t,a){return t=t||{},a?Cm(r,e,t):BL&&e.layerX!=null&&e.layerX!==e.offsetX?(t.zrX=e.layerX,t.zrY=e.layerY):e.offsetX!=null?(t.zrX=e.offsetX,t.zrY=e.offsetY):Cm(r,e,t),t}function Cm(r,e,t){if(_t.domSupported&&r.getBoundingClientRect){var a=e.clientX,n=e.clientY;if(Pw(r)){var i=r.getBoundingClientRect();t.zrX=a-i.left,t.zrY=n-i.top;return}else if(wp(Jh,r,a,n)){t.zrX=Jh[0],t.zrY=Jh[1];return}}t.zrX=t.zrY=0}function pg(r){return r||window.event}function Je(r,e,t){if(e=pg(e),e.zrX!=null)return e;var a=e.type,n=a&&a.indexOf("touch")>=0;if(n){var o=a!=="touchend"?e.targetTouches[0]:e.changedTouches[0];o&&Tp(r,o,e,t)}else{Tp(r,e,e,t);var i=VL(e);e.zrDelta=i?i/120:-(e.detail||0)/3}var s=e.button;return e.which==null&&s!==void 0&&NL.test(e.type)&&(e.which=s&1?1:s&2?3:s&4?2:0),e}function VL(r){var e=r.wheelDelta;if(e)return e;var t=r.deltaX,a=r.deltaY;if(t==null||a==null)return e;var n=Math.abs(a!==0?a:t),i=a>0?-1:a<0?1:t>0?-1:1;return 3*n*i}function Ap(r,e,t,a){r.addEventListener(e,t,a)}function zL(r,e,t,a){r.removeEventListener(e,t,a)}var pa=function(r){r.preventDefault(),r.stopPropagation(),r.cancelBubble=!0};function Dm(r){return r.which===2||r.which===3}var GL=function(){function r(){this._track=[]}return r.prototype.recognize=function(e,t,a){return this._doTrack(e,t,a),this._recognize(e)},r.prototype.clear=function(){return this._track.length=0,this},r.prototype._doTrack=function(e,t,a){var n=e.touches;if(n){for(var i={points:[],touches:[],target:t,event:e},o=0,s=n.length;o1&&a&&a.length>1){var i=Mm(a)/Mm(n);!isFinite(i)&&(i=1),e.pinchScale=i;var o=FL(a);return e.pinchX=o[0],e.pinchY=o[1],{type:"pinch",target:r[0].target,event:e}}}}};function Ge(){return[1,0,0,1,0,0]}function Sl(r){return r[0]=1,r[1]=0,r[2]=0,r[3]=1,r[4]=0,r[5]=0,r}function ph(r,e){return r[0]=e[0],r[1]=e[1],r[2]=e[2],r[3]=e[3],r[4]=e[4],r[5]=e[5],r}function Yr(r,e,t){var a=e[0]*t[0]+e[2]*t[1],n=e[1]*t[0]+e[3]*t[1],i=e[0]*t[2]+e[2]*t[3],o=e[1]*t[2]+e[3]*t[3],s=e[0]*t[4]+e[2]*t[5]+e[4],l=e[1]*t[4]+e[3]*t[5]+e[5];return r[0]=a,r[1]=n,r[2]=i,r[3]=o,r[4]=s,r[5]=l,r}function Dr(r,e,t){return r[0]=e[0],r[1]=e[1],r[2]=e[2],r[3]=e[3],r[4]=e[4]+t[0],r[5]=e[5]+t[1],r}function an(r,e,t,a){a===void 0&&(a=[0,0]);var n=e[0],i=e[2],o=e[4],s=e[1],l=e[3],u=e[5],f=Math.sin(t),h=Math.cos(t);return r[0]=n*h+s*f,r[1]=-n*f+s*h,r[2]=i*h+l*f,r[3]=-i*f+h*l,r[4]=h*(o-a[0])+f*(u-a[1])+a[0],r[5]=h*(u-a[1])-f*(o-a[0])+a[1],r}function dh(r,e,t){var a=t[0],n=t[1];return r[0]=e[0]*a,r[1]=e[1]*n,r[2]=e[2]*a,r[3]=e[3]*n,r[4]=e[4]*a,r[5]=e[5]*n,r}function vi(r,e){var t=e[0],a=e[2],n=e[4],i=e[1],o=e[3],s=e[5],l=t*o-i*a;return l?(l=1/l,r[0]=o*l,r[1]=-i*l,r[2]=-a*l,r[3]=t*l,r[4]=(a*s-o*n)*l,r[5]=(i*n-t*s)*l,r):null}function Rw(r){var e=Ge();return ph(e,r),e}const a7=Object.freeze(Object.defineProperty({__proto__:null,clone:Rw,copy:ph,create:Ge,identity:Sl,invert:vi,mul:Yr,rotate:an,scale:dh,translate:Dr},Symbol.toStringTag,{value:"Module"}));var ft=function(){function r(e,t){this.x=e||0,this.y=t||0}return r.prototype.copy=function(e){return this.x=e.x,this.y=e.y,this},r.prototype.clone=function(){return new r(this.x,this.y)},r.prototype.set=function(e,t){return this.x=e,this.y=t,this},r.prototype.equal=function(e){return e.x===this.x&&e.y===this.y},r.prototype.add=function(e){return this.x+=e.x,this.y+=e.y,this},r.prototype.scale=function(e){this.x*=e,this.y*=e},r.prototype.scaleAndAdd=function(e,t){this.x+=e.x*t,this.y+=e.y*t},r.prototype.sub=function(e){return this.x-=e.x,this.y-=e.y,this},r.prototype.dot=function(e){return this.x*e.x+this.y*e.y},r.prototype.len=function(){return Math.sqrt(this.x*this.x+this.y*this.y)},r.prototype.lenSquare=function(){return this.x*this.x+this.y*this.y},r.prototype.normalize=function(){var e=this.len();return this.x/=e,this.y/=e,this},r.prototype.distance=function(e){var t=this.x-e.x,a=this.y-e.y;return Math.sqrt(t*t+a*a)},r.prototype.distanceSquare=function(e){var t=this.x-e.x,a=this.y-e.y;return t*t+a*a},r.prototype.negate=function(){return this.x=-this.x,this.y=-this.y,this},r.prototype.transform=function(e){if(e){var t=this.x,a=this.y;return this.x=e[0]*t+e[2]*a+e[4],this.y=e[1]*t+e[3]*a+e[5],this}},r.prototype.toArray=function(e){return e[0]=this.x,e[1]=this.y,e},r.prototype.fromArray=function(e){this.x=e[0],this.y=e[1]},r.set=function(e,t,a){e.x=t,e.y=a},r.copy=function(e,t){e.x=t.x,e.y=t.y},r.len=function(e){return Math.sqrt(e.x*e.x+e.y*e.y)},r.lenSquare=function(e){return e.x*e.x+e.y*e.y},r.dot=function(e,t){return e.x*t.x+e.y*t.y},r.add=function(e,t,a){e.x=t.x+a.x,e.y=t.y+a.y},r.sub=function(e,t,a){e.x=t.x-a.x,e.y=t.y-a.y},r.scale=function(e,t,a){e.x=t.x*a,e.y=t.y*a},r.scaleAndAdd=function(e,t,a,n){e.x=t.x+a.x*n,e.y=t.y+a.y*n},r.lerp=function(e,t,a,n){var i=1-n;e.x=i*t.x+n*a.x,e.y=i*t.y+n*a.y},r}(),Wl=Math.min,Ul=Math.max,sn=new ft,ln=new ft,un=new ft,fn=new ft,Bo=new ft,Vo=new ft,ht=function(){function r(e,t,a,n){a<0&&(e=e+a,a=-a),n<0&&(t=t+n,n=-n),this.x=e,this.y=t,this.width=a,this.height=n}return r.prototype.union=function(e){var t=Wl(e.x,this.x),a=Wl(e.y,this.y);isFinite(this.x)&&isFinite(this.width)?this.width=Ul(e.x+e.width,this.x+this.width)-t:this.width=e.width,isFinite(this.y)&&isFinite(this.height)?this.height=Ul(e.y+e.height,this.y+this.height)-a:this.height=e.height,this.x=t,this.y=a},r.prototype.applyTransform=function(e){r.applyTransform(this,this,e)},r.prototype.calculateTransform=function(e){var t=this,a=e.width/t.width,n=e.height/t.height,i=Ge();return Dr(i,i,[-t.x,-t.y]),dh(i,i,[a,n]),Dr(i,i,[e.x,e.y]),i},r.prototype.intersect=function(e,t){if(!e)return!1;e instanceof r||(e=r.create(e));var a=this,n=a.x,i=a.x+a.width,o=a.y,s=a.y+a.height,l=e.x,u=e.x+e.width,f=e.y,h=e.y+e.height,v=!(ip&&(p=_,dp&&(p=S,y=a.x&&e<=a.x+a.width&&t>=a.y&&t<=a.y+a.height},r.prototype.clone=function(){return new r(this.x,this.y,this.width,this.height)},r.prototype.copy=function(e){r.copy(this,e)},r.prototype.plain=function(){return{x:this.x,y:this.y,width:this.width,height:this.height}},r.prototype.isFinite=function(){return isFinite(this.x)&&isFinite(this.y)&&isFinite(this.width)&&isFinite(this.height)},r.prototype.isZero=function(){return this.width===0||this.height===0},r.create=function(e){return new r(e.x,e.y,e.width,e.height)},r.copy=function(e,t){e.x=t.x,e.y=t.y,e.width=t.width,e.height=t.height},r.applyTransform=function(e,t,a){if(!a){e!==t&&r.copy(e,t);return}if(a[1]<1e-5&&a[1]>-1e-5&&a[2]<1e-5&&a[2]>-1e-5){var n=a[0],i=a[3],o=a[4],s=a[5];e.x=t.x*n+o,e.y=t.y*i+s,e.width=t.width*n,e.height=t.height*i,e.width<0&&(e.x+=e.width,e.width=-e.width),e.height<0&&(e.y+=e.height,e.height=-e.height);return}sn.x=un.x=t.x,sn.y=fn.y=t.y,ln.x=fn.x=t.x+t.width,ln.y=un.y=t.y+t.height,sn.transform(a),fn.transform(a),ln.transform(a),un.transform(a),e.x=Wl(sn.x,ln.x,un.x,fn.x),e.y=Wl(sn.y,ln.y,un.y,fn.y);var l=Ul(sn.x,ln.x,un.x,fn.x),u=Ul(sn.y,ln.y,un.y,fn.y);e.width=l-e.x,e.height=u-e.y},r}(),Ew="silent";function HL(r,e,t){return{type:r,event:t,target:e.target,topTarget:e.topTarget,cancelBubble:!1,offsetX:t.zrX,offsetY:t.zrY,gestureEvent:t.gestureEvent,pinchX:t.pinchX,pinchY:t.pinchY,pinchScale:t.pinchScale,wheelDelta:t.zrDelta,zrByTouch:t.zrByTouch,which:t.which,stop:WL}}function WL(){pa(this.event)}var UL=function(r){k(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.handler=null,t}return e.prototype.dispose=function(){},e.prototype.setCursor=function(){},e}(fr),zo=function(){function r(e,t){this.x=e,this.y=t}return r}(),YL=["click","dblclick","mousewheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],ev=new ht(0,0,0,0),kw=function(r){k(e,r);function e(t,a,n,i,o){var s=r.call(this)||this;return s._hovered=new zo(0,0),s.storage=t,s.painter=a,s.painterRoot=i,s._pointerSize=o,n=n||new UL,s.proxy=null,s.setHandlerProxy(n),s._draggingMgr=new IL(s),s}return e.prototype.setHandlerProxy=function(t){this.proxy&&this.proxy.dispose(),t&&(C(YL,function(a){t.on&&t.on(a,this[a],this)},this),t.handler=this),this.proxy=t},e.prototype.mousemove=function(t){var a=t.zrX,n=t.zrY,i=Ow(this,a,n),o=this._hovered,s=o.target;s&&!s.__zr&&(o=this.findHover(o.x,o.y),s=o.target);var l=this._hovered=i?new zo(a,n):this.findHover(a,n),u=l.target,f=this.proxy;f.setCursor&&f.setCursor(u?u.cursor:"default"),s&&u!==s&&this.dispatchToElement(o,"mouseout",t),this.dispatchToElement(l,"mousemove",t),u&&u!==s&&this.dispatchToElement(l,"mouseover",t)},e.prototype.mouseout=function(t){var a=t.zrEventControl;a!=="only_globalout"&&this.dispatchToElement(this._hovered,"mouseout",t),a!=="no_globalout"&&this.trigger("globalout",{type:"globalout",event:t})},e.prototype.resize=function(){this._hovered=new zo(0,0)},e.prototype.dispatch=function(t,a){var n=this[t];n&&n.call(this,a)},e.prototype.dispose=function(){this.proxy.dispose(),this.storage=null,this.proxy=null,this.painter=null},e.prototype.setCursorStyle=function(t){var a=this.proxy;a.setCursor&&a.setCursor(t)},e.prototype.dispatchToElement=function(t,a,n){t=t||{};var i=t.target;if(!(i&&i.silent)){for(var o="on"+a,s=HL(a,t,n);i&&(i[o]&&(s.cancelBubble=!!i[o].call(i,s)),i.trigger(a,s),i=i.__hostTarget?i.__hostTarget:i.parent,!s.cancelBubble););s.cancelBubble||(this.trigger(a,s),this.painter&&this.painter.eachOtherLayer&&this.painter.eachOtherLayer(function(l){typeof l[o]=="function"&&l[o].call(l,s),l.trigger&&l.trigger(a,s)}))}},e.prototype.findHover=function(t,a,n){var i=this.storage.getDisplayList(),o=new zo(t,a);if(Im(i,o,t,a,n),this._pointerSize&&!o.target){for(var s=[],l=this._pointerSize,u=l/2,f=new ht(t-u,a-u,l,l),h=i.length-1;h>=0;h--){var v=i[h];v!==n&&!v.ignore&&!v.ignoreCoarsePointer&&(!v.parent||!v.parent.ignoreCoarsePointer)&&(ev.copy(v.getBoundingRect()),v.transform&&ev.applyTransform(v.transform),ev.intersect(f)&&s.push(v))}if(s.length)for(var c=4,p=Math.PI/12,d=Math.PI*2,g=0;g4)return;this._downPoint=null}this.dispatchToElement(i,r,e)}});function XL(r,e,t){if(r[r.rectHover?"rectContain":"contain"](e,t)){for(var a=r,n=void 0,i=!1;a;){if(a.ignoreClip&&(i=!0),!i){var o=a.getClipPath();if(o&&!o.contain(e,t))return!1}a.silent&&(n=!0);var s=a.__hostTarget;a=s||a.parent}return n?Ew:!0}return!1}function Im(r,e,t,a,n){for(var i=r.length-1;i>=0;i--){var o=r[i],s=void 0;if(o!==n&&!o.ignore&&(s=XL(o,t,a))&&(!e.topTarget&&(e.topTarget=o),s!==Ew)){e.target=o;break}}}function Ow(r,e,t){var a=r.painter;return e<0||e>a.getWidth()||t<0||t>a.getHeight()}var Nw=32,Go=7;function $L(r){for(var e=0;r>=Nw;)e|=r&1,r>>=1;return r+e}function Lm(r,e,t,a){var n=e+1;if(n===t)return 1;if(a(r[n++],r[e])<0){for(;n=0;)n++;return n-e}function ZL(r,e,t){for(t--;e>>1,n(i,r[l])<0?s=l:o=l+1;var u=a-o;switch(u){case 3:r[o+3]=r[o+2];case 2:r[o+2]=r[o+1];case 1:r[o+1]=r[o];break;default:for(;u>0;)r[o+u]=r[o+u-1],u--}r[o]=i}}function rv(r,e,t,a,n,i){var o=0,s=0,l=1;if(i(r,e[t+n])>0){for(s=a-n;l0;)o=l,l=(l<<1)+1,l<=0&&(l=s);l>s&&(l=s),o+=n,l+=n}else{for(s=n+1;ls&&(l=s);var u=o;o=n-l,l=n-u}for(o++;o>>1);i(r,e[t+f])>0?o=f+1:l=f}return l}function av(r,e,t,a,n,i){var o=0,s=0,l=1;if(i(r,e[t+n])<0){for(s=n+1;ls&&(l=s);var u=o;o=n-l,l=n-u}else{for(s=a-n;l=0;)o=l,l=(l<<1)+1,l<=0&&(l=s);l>s&&(l=s),o+=n,l+=n}for(o++;o>>1);i(r,e[t+f])<0?l=f:o=f+1}return l}function qL(r,e){var t=Go,a,n,i=0,o=[];a=[],n=[];function s(c,p){a[i]=c,n[i]=p,i+=1}function l(){for(;i>1;){var c=i-2;if(c>=1&&n[c-1]<=n[c]+n[c+1]||c>=2&&n[c-2]<=n[c]+n[c-1])n[c-1]n[c+1])break;f(c)}}function u(){for(;i>1;){var c=i-2;c>0&&n[c-1]=Go||w>=Go);if(T)break;b<0&&(b=0),b+=2}if(t=b,t<1&&(t=1),p===1){for(y=0;y=0;y--)r[x+y]=r[b+y];r[S]=o[_];return}for(var w=t;;){var T=0,A=0,D=!1;do if(e(o[_],r[m])<0){if(r[S--]=r[m--],T++,A=0,--p===0){D=!0;break}}else if(r[S--]=o[_--],A++,T=0,--g===1){D=!0;break}while((T|A)=0;y--)r[x+y]=r[b+y];if(p===0){D=!0;break}}if(r[S--]=o[_--],--g===1){D=!0;break}if(A=g-rv(r[m],o,0,g,g-1,e),A!==0){for(S-=A,_-=A,g-=A,x=S+1,b=_+1,y=0;y=Go||A>=Go);if(D)break;w<0&&(w=0),w+=2}if(t=w,t<1&&(t=1),g===1){for(S-=p,m-=p,x=S+1,b=m+1,y=p-1;y>=0;y--)r[x+y]=r[b+y];r[S]=o[_]}else{if(g===0)throw new Error;for(b=S-(g-1),y=0;ys&&(l=s),Pm(r,t,t+l,t+i,e),i=l}o.pushRun(t,i),o.mergeRuns(),n-=i,t+=i}while(n!==0);o.forceMergeRuns()}}var He=1,vs=2,Fi=4,Rm=!1;function nv(){Rm||(Rm=!0,console.warn("z / z2 / zlevel of displayable is invalid, which may cause unexpected errors"))}function Em(r,e){return r.zlevel===e.zlevel?r.z===e.z?r.z2-e.z2:r.z-e.z:r.zlevel-e.zlevel}var KL=function(){function r(){this._roots=[],this._displayList=[],this._displayListLen=0,this.displayableSortFunc=Em}return r.prototype.traverse=function(e,t){for(var a=0;a0&&(f.__clipPaths=[]),isNaN(f.z)&&(nv(),f.z=0),isNaN(f.z2)&&(nv(),f.z2=0),isNaN(f.zlevel)&&(nv(),f.zlevel=0),this._displayList[this._displayListLen++]=f}var h=e.getDecalElement&&e.getDecalElement();h&&this._updateAndAddDisplayable(h,t,a);var v=e.getTextGuideLine();v&&this._updateAndAddDisplayable(v,t,a);var c=e.getTextContent();c&&this._updateAndAddDisplayable(c,t,a)}},r.prototype.addRoot=function(e){e.__zr&&e.__zr.storage===this||this._roots.push(e)},r.prototype.delRoot=function(e){if(e instanceof Array){for(var t=0,a=e.length;t=0&&this._roots.splice(n,1)},r.prototype.delAllRoots=function(){this._roots=[],this._displayList=[],this._displayListLen=0},r.prototype.getRoots=function(){return this._roots},r.prototype.dispose=function(){this._displayList=null,this._roots=null},r}(),pf;pf=_t.hasGlobalWindow&&(window.requestAnimationFrame&&window.requestAnimationFrame.bind(window)||window.msRequestAnimationFrame&&window.msRequestAnimationFrame.bind(window)||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame)||function(r){return setTimeout(r,16)};var Ds={linear:function(r){return r},quadraticIn:function(r){return r*r},quadraticOut:function(r){return r*(2-r)},quadraticInOut:function(r){return(r*=2)<1?.5*r*r:-.5*(--r*(r-2)-1)},cubicIn:function(r){return r*r*r},cubicOut:function(r){return--r*r*r+1},cubicInOut:function(r){return(r*=2)<1?.5*r*r*r:.5*((r-=2)*r*r+2)},quarticIn:function(r){return r*r*r*r},quarticOut:function(r){return 1- --r*r*r*r},quarticInOut:function(r){return(r*=2)<1?.5*r*r*r*r:-.5*((r-=2)*r*r*r-2)},quinticIn:function(r){return r*r*r*r*r},quinticOut:function(r){return--r*r*r*r*r+1},quinticInOut:function(r){return(r*=2)<1?.5*r*r*r*r*r:.5*((r-=2)*r*r*r*r+2)},sinusoidalIn:function(r){return 1-Math.cos(r*Math.PI/2)},sinusoidalOut:function(r){return Math.sin(r*Math.PI/2)},sinusoidalInOut:function(r){return .5*(1-Math.cos(Math.PI*r))},exponentialIn:function(r){return r===0?0:Math.pow(1024,r-1)},exponentialOut:function(r){return r===1?1:1-Math.pow(2,-10*r)},exponentialInOut:function(r){return r===0?0:r===1?1:(r*=2)<1?.5*Math.pow(1024,r-1):.5*(-Math.pow(2,-10*(r-1))+2)},circularIn:function(r){return 1-Math.sqrt(1-r*r)},circularOut:function(r){return Math.sqrt(1- --r*r)},circularInOut:function(r){return(r*=2)<1?-.5*(Math.sqrt(1-r*r)-1):.5*(Math.sqrt(1-(r-=2)*r)+1)},elasticIn:function(r){var e,t=.1,a=.4;return r===0?0:r===1?1:(!t||t<1?(t=1,e=a/4):e=a*Math.asin(1/t)/(2*Math.PI),-(t*Math.pow(2,10*(r-=1))*Math.sin((r-e)*(2*Math.PI)/a)))},elasticOut:function(r){var e,t=.1,a=.4;return r===0?0:r===1?1:(!t||t<1?(t=1,e=a/4):e=a*Math.asin(1/t)/(2*Math.PI),t*Math.pow(2,-10*r)*Math.sin((r-e)*(2*Math.PI)/a)+1)},elasticInOut:function(r){var e,t=.1,a=.4;return r===0?0:r===1?1:(!t||t<1?(t=1,e=a/4):e=a*Math.asin(1/t)/(2*Math.PI),(r*=2)<1?-.5*(t*Math.pow(2,10*(r-=1))*Math.sin((r-e)*(2*Math.PI)/a)):t*Math.pow(2,-10*(r-=1))*Math.sin((r-e)*(2*Math.PI)/a)*.5+1)},backIn:function(r){var e=1.70158;return r*r*((e+1)*r-e)},backOut:function(r){var e=1.70158;return--r*r*((e+1)*r+e)+1},backInOut:function(r){var e=2.5949095;return(r*=2)<1?.5*(r*r*((e+1)*r-e)):.5*((r-=2)*r*((e+1)*r+e)+2)},bounceIn:function(r){return 1-Ds.bounceOut(1-r)},bounceOut:function(r){return r<1/2.75?7.5625*r*r:r<2/2.75?7.5625*(r-=1.5/2.75)*r+.75:r<2.5/2.75?7.5625*(r-=2.25/2.75)*r+.9375:7.5625*(r-=2.625/2.75)*r+.984375},bounceInOut:function(r){return r<.5?Ds.bounceIn(r*2)*.5:Ds.bounceOut(r*2-1)*.5+.5}},Yl=Math.pow,Ua=Math.sqrt,df=1e-8,Bw=1e-4,km=Ua(3),Xl=1/3,zr=rn(),ar=rn(),ji=rn();function Ba(r){return r>-df&&rdf||r<-df}function te(r,e,t,a,n){var i=1-n;return i*i*(i*r+3*n*e)+n*n*(n*a+3*i*t)}function Om(r,e,t,a,n){var i=1-n;return 3*(((e-r)*i+2*(t-e)*n)*i+(a-t)*n*n)}function gf(r,e,t,a,n,i){var o=a+3*(e-t)-r,s=3*(t-e*2+r),l=3*(e-r),u=r-n,f=s*s-3*o*l,h=s*l-9*o*u,v=l*l-3*s*u,c=0;if(Ba(f)&&Ba(h))if(Ba(s))i[0]=0;else{var p=-l/s;p>=0&&p<=1&&(i[c++]=p)}else{var d=h*h-4*f*v;if(Ba(d)){var g=h/f,p=-s/o+g,y=-g/2;p>=0&&p<=1&&(i[c++]=p),y>=0&&y<=1&&(i[c++]=y)}else if(d>0){var m=Ua(d),_=f*s+1.5*o*(-h+m),S=f*s+1.5*o*(-h-m);_<0?_=-Yl(-_,Xl):_=Yl(_,Xl),S<0?S=-Yl(-S,Xl):S=Yl(S,Xl);var p=(-s-(_+S))/(3*o);p>=0&&p<=1&&(i[c++]=p)}else{var b=(2*f*s-3*o*h)/(2*Ua(f*f*f)),x=Math.acos(b)/3,w=Ua(f),T=Math.cos(x),p=(-s-2*w*T)/(3*o),y=(-s+w*(T+km*Math.sin(x)))/(3*o),A=(-s+w*(T-km*Math.sin(x)))/(3*o);p>=0&&p<=1&&(i[c++]=p),y>=0&&y<=1&&(i[c++]=y),A>=0&&A<=1&&(i[c++]=A)}}return c}function zw(r,e,t,a,n){var i=6*t-12*e+6*r,o=9*e+3*a-3*r-9*t,s=3*e-3*r,l=0;if(Ba(o)){if(Vw(i)){var u=-s/i;u>=0&&u<=1&&(n[l++]=u)}}else{var f=i*i-4*o*s;if(Ba(f))n[0]=-i/(2*o);else if(f>0){var h=Ua(f),u=(-i+h)/(2*o),v=(-i-h)/(2*o);u>=0&&u<=1&&(n[l++]=u),v>=0&&v<=1&&(n[l++]=v)}}return l}function ja(r,e,t,a,n,i){var o=(e-r)*n+r,s=(t-e)*n+e,l=(a-t)*n+t,u=(s-o)*n+o,f=(l-s)*n+s,h=(f-u)*n+u;i[0]=r,i[1]=o,i[2]=u,i[3]=h,i[4]=h,i[5]=f,i[6]=l,i[7]=a}function Gw(r,e,t,a,n,i,o,s,l,u,f){var h,v=.005,c=1/0,p,d,g,y;zr[0]=l,zr[1]=u;for(var m=0;m<1;m+=.05)ar[0]=te(r,t,n,o,m),ar[1]=te(e,a,i,s,m),g=Wa(zr,ar),g=0&&g=0&&u<=1&&(n[l++]=u)}}else{var f=o*o-4*i*s;if(Ba(f)){var u=-o/(2*i);u>=0&&u<=1&&(n[l++]=u)}else if(f>0){var h=Ua(f),u=(-o+h)/(2*i),v=(-o-h)/(2*i);u>=0&&u<=1&&(n[l++]=u),v>=0&&v<=1&&(n[l++]=v)}}return l}function Fw(r,e,t){var a=r+t-2*e;return a===0?.5:(r-e)/a}function Us(r,e,t,a,n){var i=(e-r)*a+r,o=(t-e)*a+e,s=(o-i)*a+i;n[0]=r,n[1]=i,n[2]=s,n[3]=s,n[4]=o,n[5]=t}function Hw(r,e,t,a,n,i,o,s,l){var u,f=.005,h=1/0;zr[0]=o,zr[1]=s;for(var v=0;v<1;v+=.05){ar[0]=se(r,t,n,v),ar[1]=se(e,a,i,v);var c=Wa(zr,ar);c=0&&c=1?1:gf(0,a,i,1,l,s)&&te(0,n,o,1,s[0])}}}var e2=function(){function r(e){this._inited=!1,this._startTime=0,this._pausedTime=0,this._paused=!1,this._life=e.life||1e3,this._delay=e.delay||0,this.loop=e.loop||!1,this.onframe=e.onframe||Yt,this.ondestroy=e.ondestroy||Yt,this.onrestart=e.onrestart||Yt,e.easing&&this.setEasing(e.easing)}return r.prototype.step=function(e,t){if(this._inited||(this._startTime=e+this._delay,this._inited=!0),this._paused){this._pausedTime+=t;return}var a=this._life,n=e-this._startTime-this._pausedTime,i=n/a;i<0&&(i=0),i=Math.min(i,1);var o=this.easingFunc,s=o?o(i):i;if(this.onframe(s),i===1)if(this.loop){var l=n%a;this._startTime=e-l,this._pausedTime=0,this.onrestart()}else return!0;return!1},r.prototype.pause=function(){this._paused=!0},r.prototype.resume=function(){this._paused=!1},r.prototype.setEasing=function(e){this.easing=e,this.easingFunc=K(e)?e:Ds[e]||dg(e)},r}(),Ww=function(){function r(e){this.value=e}return r}(),r2=function(){function r(){this._len=0}return r.prototype.insert=function(e){var t=new Ww(e);return this.insertEntry(t),t},r.prototype.insertEntry=function(e){this.head?(this.tail.next=e,e.prev=this.tail,e.next=null,this.tail=e):this.head=this.tail=e,this._len++},r.prototype.remove=function(e){var t=e.prev,a=e.next;t?t.next=a:this.head=a,a?a.prev=t:this.tail=t,e.next=e.prev=null,this._len--},r.prototype.len=function(){return this._len},r.prototype.clear=function(){this.head=this.tail=null,this._len=0},r}(),xl=function(){function r(e){this._list=new r2,this._maxSize=10,this._map={},this._maxSize=e}return r.prototype.put=function(e,t){var a=this._list,n=this._map,i=null;if(n[e]==null){var o=a.len(),s=this._lastRemovedEntry;if(o>=this._maxSize&&o>0){var l=a.head;a.remove(l),delete n[l.key],i=l.value,this._lastRemovedEntry=l}s?s.value=t:s=new Ww(t),s.key=e,a.insertEntry(s),n[e]=s}return i},r.prototype.get=function(e){var t=this._map[e],a=this._list;if(t!=null)return t!==a.tail&&(a.remove(t),a.insertEntry(t)),t.value},r.prototype.clear=function(){this._list.clear(),this._map={}},r.prototype.len=function(){return this._list.len()},r}(),Nm={transparent:[0,0,0,0],aliceblue:[240,248,255,1],antiquewhite:[250,235,215,1],aqua:[0,255,255,1],aquamarine:[127,255,212,1],azure:[240,255,255,1],beige:[245,245,220,1],bisque:[255,228,196,1],black:[0,0,0,1],blanchedalmond:[255,235,205,1],blue:[0,0,255,1],blueviolet:[138,43,226,1],brown:[165,42,42,1],burlywood:[222,184,135,1],cadetblue:[95,158,160,1],chartreuse:[127,255,0,1],chocolate:[210,105,30,1],coral:[255,127,80,1],cornflowerblue:[100,149,237,1],cornsilk:[255,248,220,1],crimson:[220,20,60,1],cyan:[0,255,255,1],darkblue:[0,0,139,1],darkcyan:[0,139,139,1],darkgoldenrod:[184,134,11,1],darkgray:[169,169,169,1],darkgreen:[0,100,0,1],darkgrey:[169,169,169,1],darkkhaki:[189,183,107,1],darkmagenta:[139,0,139,1],darkolivegreen:[85,107,47,1],darkorange:[255,140,0,1],darkorchid:[153,50,204,1],darkred:[139,0,0,1],darksalmon:[233,150,122,1],darkseagreen:[143,188,143,1],darkslateblue:[72,61,139,1],darkslategray:[47,79,79,1],darkslategrey:[47,79,79,1],darkturquoise:[0,206,209,1],darkviolet:[148,0,211,1],deeppink:[255,20,147,1],deepskyblue:[0,191,255,1],dimgray:[105,105,105,1],dimgrey:[105,105,105,1],dodgerblue:[30,144,255,1],firebrick:[178,34,34,1],floralwhite:[255,250,240,1],forestgreen:[34,139,34,1],fuchsia:[255,0,255,1],gainsboro:[220,220,220,1],ghostwhite:[248,248,255,1],gold:[255,215,0,1],goldenrod:[218,165,32,1],gray:[128,128,128,1],green:[0,128,0,1],greenyellow:[173,255,47,1],grey:[128,128,128,1],honeydew:[240,255,240,1],hotpink:[255,105,180,1],indianred:[205,92,92,1],indigo:[75,0,130,1],ivory:[255,255,240,1],khaki:[240,230,140,1],lavender:[230,230,250,1],lavenderblush:[255,240,245,1],lawngreen:[124,252,0,1],lemonchiffon:[255,250,205,1],lightblue:[173,216,230,1],lightcoral:[240,128,128,1],lightcyan:[224,255,255,1],lightgoldenrodyellow:[250,250,210,1],lightgray:[211,211,211,1],lightgreen:[144,238,144,1],lightgrey:[211,211,211,1],lightpink:[255,182,193,1],lightsalmon:[255,160,122,1],lightseagreen:[32,178,170,1],lightskyblue:[135,206,250,1],lightslategray:[119,136,153,1],lightslategrey:[119,136,153,1],lightsteelblue:[176,196,222,1],lightyellow:[255,255,224,1],lime:[0,255,0,1],limegreen:[50,205,50,1],linen:[250,240,230,1],magenta:[255,0,255,1],maroon:[128,0,0,1],mediumaquamarine:[102,205,170,1],mediumblue:[0,0,205,1],mediumorchid:[186,85,211,1],mediumpurple:[147,112,219,1],mediumseagreen:[60,179,113,1],mediumslateblue:[123,104,238,1],mediumspringgreen:[0,250,154,1],mediumturquoise:[72,209,204,1],mediumvioletred:[199,21,133,1],midnightblue:[25,25,112,1],mintcream:[245,255,250,1],mistyrose:[255,228,225,1],moccasin:[255,228,181,1],navajowhite:[255,222,173,1],navy:[0,0,128,1],oldlace:[253,245,230,1],olive:[128,128,0,1],olivedrab:[107,142,35,1],orange:[255,165,0,1],orangered:[255,69,0,1],orchid:[218,112,214,1],palegoldenrod:[238,232,170,1],palegreen:[152,251,152,1],paleturquoise:[175,238,238,1],palevioletred:[219,112,147,1],papayawhip:[255,239,213,1],peachpuff:[255,218,185,1],peru:[205,133,63,1],pink:[255,192,203,1],plum:[221,160,221,1],powderblue:[176,224,230,1],purple:[128,0,128,1],red:[255,0,0,1],rosybrown:[188,143,143,1],royalblue:[65,105,225,1],saddlebrown:[139,69,19,1],salmon:[250,128,114,1],sandybrown:[244,164,96,1],seagreen:[46,139,87,1],seashell:[255,245,238,1],sienna:[160,82,45,1],silver:[192,192,192,1],skyblue:[135,206,235,1],slateblue:[106,90,205,1],slategray:[112,128,144,1],slategrey:[112,128,144,1],snow:[255,250,250,1],springgreen:[0,255,127,1],steelblue:[70,130,180,1],tan:[210,180,140,1],teal:[0,128,128,1],thistle:[216,191,216,1],tomato:[255,99,71,1],turquoise:[64,224,208,1],violet:[238,130,238,1],wheat:[245,222,179,1],white:[255,255,255,1],whitesmoke:[245,245,245,1],yellow:[255,255,0,1],yellowgreen:[154,205,50,1]};function wr(r){return r=Math.round(r),r<0?0:r>255?255:r}function a2(r){return r=Math.round(r),r<0?0:r>360?360:r}function Ys(r){return r<0?0:r>1?1:r}function iv(r){var e=r;return e.length&&e.charAt(e.length-1)==="%"?wr(parseFloat(e)/100*255):wr(parseInt(e,10))}function qn(r){var e=r;return e.length&&e.charAt(e.length-1)==="%"?Ys(parseFloat(e)/100):Ys(parseFloat(e))}function ov(r,e,t){return t<0?t+=1:t>1&&(t-=1),t*6<1?r+(e-r)*t*6:t*2<1?e:t*3<2?r+(e-r)*(2/3-t)*6:r}function Va(r,e,t){return r+(e-r)*t}function Qe(r,e,t,a,n){return r[0]=e,r[1]=t,r[2]=a,r[3]=n,r}function Dp(r,e){return r[0]=e[0],r[1]=e[1],r[2]=e[2],r[3]=e[3],r}var Uw=new xl(20),$l=null;function xi(r,e){$l&&Dp($l,e),$l=Uw.put(r,$l||e.slice())}function Ie(r,e){if(r){e=e||[];var t=Uw.get(r);if(t)return Dp(e,t);r=r+"";var a=r.replace(/ /g,"").toLowerCase();if(a in Nm)return Dp(e,Nm[a]),xi(r,e),e;var n=a.length;if(a.charAt(0)==="#"){if(n===4||n===5){var i=parseInt(a.slice(1,4),16);if(!(i>=0&&i<=4095)){Qe(e,0,0,0,1);return}return Qe(e,(i&3840)>>4|(i&3840)>>8,i&240|(i&240)>>4,i&15|(i&15)<<4,n===5?parseInt(a.slice(4),16)/15:1),xi(r,e),e}else if(n===7||n===9){var i=parseInt(a.slice(1,7),16);if(!(i>=0&&i<=16777215)){Qe(e,0,0,0,1);return}return Qe(e,(i&16711680)>>16,(i&65280)>>8,i&255,n===9?parseInt(a.slice(7),16)/255:1),xi(r,e),e}return}var o=a.indexOf("("),s=a.indexOf(")");if(o!==-1&&s+1===n){var l=a.substr(0,o),u=a.substr(o+1,s-(o+1)).split(","),f=1;switch(l){case"rgba":if(u.length!==4)return u.length===3?Qe(e,+u[0],+u[1],+u[2],1):Qe(e,0,0,0,1);f=qn(u.pop());case"rgb":if(u.length>=3)return Qe(e,iv(u[0]),iv(u[1]),iv(u[2]),u.length===3?f:qn(u[3])),xi(r,e),e;Qe(e,0,0,0,1);return;case"hsla":if(u.length!==4){Qe(e,0,0,0,1);return}return u[3]=qn(u[3]),Mp(u,e),xi(r,e),e;case"hsl":if(u.length!==3){Qe(e,0,0,0,1);return}return Mp(u,e),xi(r,e),e;default:return}}Qe(e,0,0,0,1)}}function Mp(r,e){var t=(parseFloat(r[0])%360+360)%360/360,a=qn(r[1]),n=qn(r[2]),i=n<=.5?n*(a+1):n+a-n*a,o=n*2-i;return e=e||[],Qe(e,wr(ov(o,i,t+1/3)*255),wr(ov(o,i,t)*255),wr(ov(o,i,t-1/3)*255),1),r.length===4&&(e[3]=r[3]),e}function n2(r){if(r){var e=r[0]/255,t=r[1]/255,a=r[2]/255,n=Math.min(e,t,a),i=Math.max(e,t,a),o=i-n,s=(i+n)/2,l,u;if(o===0)l=0,u=0;else{s<.5?u=o/(i+n):u=o/(2-i-n);var f=((i-e)/6+o/2)/o,h=((i-t)/6+o/2)/o,v=((i-a)/6+o/2)/o;e===i?l=v-h:t===i?l=1/3+f-v:a===i&&(l=2/3+h-f),l<0&&(l+=1),l>1&&(l-=1)}var c=[l*360,u,s];return r[3]!=null&&c.push(r[3]),c}}function yf(r,e){var t=Ie(r);if(t){for(var a=0;a<3;a++)e<0?t[a]=t[a]*(1-e)|0:t[a]=(255-t[a])*e+t[a]|0,t[a]>255?t[a]=255:t[a]<0&&(t[a]=0);return Tr(t,t.length===4?"rgba":"rgb")}}function i2(r){var e=Ie(r);if(e)return((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1)}function Ms(r,e,t){if(!(!(e&&e.length)||!(r>=0&&r<=1))){t=t||[];var a=r*(e.length-1),n=Math.floor(a),i=Math.ceil(a),o=e[n],s=e[i],l=a-n;return t[0]=wr(Va(o[0],s[0],l)),t[1]=wr(Va(o[1],s[1],l)),t[2]=wr(Va(o[2],s[2],l)),t[3]=Ys(Va(o[3],s[3],l)),t}}var o2=Ms;function gg(r,e,t){if(!(!(e&&e.length)||!(r>=0&&r<=1))){var a=r*(e.length-1),n=Math.floor(a),i=Math.ceil(a),o=Ie(e[n]),s=Ie(e[i]),l=a-n,u=Tr([wr(Va(o[0],s[0],l)),wr(Va(o[1],s[1],l)),wr(Va(o[2],s[2],l)),Ys(Va(o[3],s[3],l))],"rgba");return t?{color:u,leftIndex:n,rightIndex:i,value:a}:u}}var s2=gg;function Qi(r,e,t,a){var n=Ie(r);if(r)return n=n2(n),e!=null&&(n[0]=a2(e)),t!=null&&(n[1]=qn(t)),a!=null&&(n[2]=qn(a)),Tr(Mp(n),"rgba")}function Xs(r,e){var t=Ie(r);if(t&&e!=null)return t[3]=Ys(e),Tr(t,"rgba")}function Tr(r,e){if(!(!r||!r.length)){var t=r[0]+","+r[1]+","+r[2];return(e==="rgba"||e==="hsva"||e==="hsla")&&(t+=","+r[3]),e+"("+t+")"}}function $s(r,e){var t=Ie(r);return t?(.299*t[0]+.587*t[1]+.114*t[2])*t[3]/255+(1-t[3])*e:0}function l2(){return Tr([Math.round(Math.random()*255),Math.round(Math.random()*255),Math.round(Math.random()*255)],"rgb")}var Bm=new xl(100);function mf(r){if(U(r)){var e=Bm.get(r);return e||(e=yf(r,-.1),Bm.put(r,e)),e}else if(ml(r)){var t=V({},r);return t.colorStops=G(r.colorStops,function(a){return{offset:a.offset,color:yf(a.color,-.1)}}),t}return r}const n7=Object.freeze(Object.defineProperty({__proto__:null,fastLerp:Ms,fastMapToColor:o2,lerp:gg,lift:yf,liftColor:mf,lum:$s,mapToColor:s2,modifyAlpha:Xs,modifyHSL:Qi,parse:Ie,random:l2,stringify:Tr,toHex:i2},Symbol.toStringTag,{value:"Module"}));var _f=Math.round;function Zs(r){var e;if(!r||r==="transparent")r="none";else if(typeof r=="string"&&r.indexOf("rgba")>-1){var t=Ie(r);t&&(r="rgb("+t[0]+","+t[1]+","+t[2]+")",e=t[3])}return{color:r,opacity:e??1}}var Vm=1e-4;function za(r){return r-Vm}function Zl(r){return _f(r*1e3)/1e3}function Ip(r){return _f(r*1e4)/1e4}function u2(r){return"matrix("+Zl(r[0])+","+Zl(r[1])+","+Zl(r[2])+","+Zl(r[3])+","+Ip(r[4])+","+Ip(r[5])+")"}var f2={left:"start",right:"end",center:"middle",middle:"middle"};function h2(r,e,t){return t==="top"?r+=e/2:t==="bottom"&&(r-=e/2),r}function v2(r){return r&&(r.shadowBlur||r.shadowOffsetX||r.shadowOffsetY)}function c2(r){var e=r.style,t=r.getGlobalScale();return[e.shadowColor,(e.shadowBlur||0).toFixed(2),(e.shadowOffsetX||0).toFixed(2),(e.shadowOffsetY||0).toFixed(2),t[0],t[1]].join(",")}function Yw(r){return r&&!!r.image}function p2(r){return r&&!!r.svgElement}function yg(r){return Yw(r)||p2(r)}function Xw(r){return r.type==="linear"}function $w(r){return r.type==="radial"}function Zw(r){return r&&(r.type==="linear"||r.type==="radial")}function gh(r){return"url(#"+r+")"}function qw(r){var e=r.getGlobalScale(),t=Math.max(e[0],e[1]);return Math.max(Math.ceil(Math.log(t)/Math.log(10)),1)}function Kw(r){var e=r.x||0,t=r.y||0,a=(r.rotation||0)*Ts,n=ot(r.scaleX,1),i=ot(r.scaleY,1),o=r.skewX||0,s=r.skewY||0,l=[];return(e||t)&&l.push("translate("+e+"px,"+t+"px)"),a&&l.push("rotate("+a+")"),(n!==1||i!==1)&&l.push("scale("+n+","+i+")"),(o||s)&&l.push("skew("+_f(o*Ts)+"deg, "+_f(s*Ts)+"deg)"),l.join(" ")}var d2=function(){return _t.hasGlobalWindow&&K(window.btoa)?function(r){return window.btoa(unescape(encodeURIComponent(r)))}:typeof Buffer<"u"?function(r){return Buffer.from(r).toString("base64")}:function(r){return null}}(),Lp=Array.prototype.slice;function ia(r,e,t){return(e-r)*t+r}function sv(r,e,t,a){for(var n=e.length,i=0;ia?e:r,i=Math.min(t,a),o=n[i-1]||{color:[0,0,0,0],offset:0},s=i;so;if(s)a.length=o;else for(var l=i;l=1},r.prototype.getAdditiveTrack=function(){return this._additiveTrack},r.prototype.addKeyframe=function(e,t,a){this._needsSort=!0;var n=this.keyframes,i=n.length,o=!1,s=Gm,l=t;if(fe(t)){var u=_2(t);s=u,(u===1&&!Ct(t[0])||u===2&&!Ct(t[0][0]))&&(o=!0)}else if(Ct(t)&&!no(t))s=Kl;else if(U(t))if(!isNaN(+t))s=Kl;else{var f=Ie(t);f&&(l=f,s=cs)}else if(ml(t)){var h=V({},l);h.colorStops=G(t.colorStops,function(c){return{offset:c.offset,color:Ie(c.color)}}),Xw(t)?s=Pp:$w(t)&&(s=Rp),l=h}i===0?this.valType=s:(s!==this.valType||s===Gm)&&(o=!0),this.discrete=this.discrete||o;var v={time:e,value:l,rawValue:t,percent:0};return a&&(v.easing=a,v.easingFunc=K(a)?a:Ds[a]||dg(a)),n.push(v),v},r.prototype.prepare=function(e,t){var a=this.keyframes;this._needsSort&&a.sort(function(d,g){return d.time-g.time});for(var n=this.valType,i=a.length,o=a[i-1],s=this.discrete,l=jl(n),u=Fm(n),f=0;f=0&&!(o[f].percent<=t);f--);f=v(f,s-2)}else{for(f=h;ft);f++);f=v(f-1,s-2)}p=o[f+1],c=o[f]}if(c&&p){this._lastFr=f,this._lastFrP=t;var g=p.percent-c.percent,y=g===0?1:v((t-c.percent)/g,1);p.easingFunc&&(y=p.easingFunc(y));var m=a?this._additiveValue:u?Fo:e[l];if((jl(i)||u)&&!m&&(m=this._additiveValue=[]),this.discrete)e[l]=y<1?c.rawValue:p.rawValue;else if(jl(i))i===$u?sv(m,c[n],p[n],y):g2(m,c[n],p[n],y);else if(Fm(i)){var _=c[n],S=p[n],b=i===Pp;e[l]={type:b?"linear":"radial",x:ia(_.x,S.x,y),y:ia(_.y,S.y,y),colorStops:G(_.colorStops,function(w,T){var A=S.colorStops[T];return{offset:ia(w.offset,A.offset,y),color:Xu(sv([],w.color,A.color,y))}}),global:S.global},b?(e[l].x2=ia(_.x2,S.x2,y),e[l].y2=ia(_.y2,S.y2,y)):e[l].r=ia(_.r,S.r,y)}else if(u)sv(m,c[n],p[n],y),a||(e[l]=Xu(m));else{var x=ia(c[n],p[n],y);a?this._additiveValue=x:e[l]=x}a&&this._addToTarget(e)}}},r.prototype._addToTarget=function(e){var t=this.valType,a=this.propName,n=this._additiveValue;t===Kl?e[a]=e[a]+n:t===cs?(Ie(e[a],Fo),ql(Fo,Fo,n,1),e[a]=Xu(Fo)):t===$u?ql(e[a],e[a],n,1):t===jw&&zm(e[a],e[a],n,1)},r}(),mg=function(){function r(e,t,a,n){if(this._tracks={},this._trackKeys=[],this._maxTime=0,this._started=0,this._clip=null,this._target=e,this._loop=t,t&&n){fh("Can' use additive animation on looped animation.");return}this._additiveAnimators=n,this._allowDiscrete=a}return r.prototype.getMaxTime=function(){return this._maxTime},r.prototype.getDelay=function(){return this._delay},r.prototype.getLoop=function(){return this._loop},r.prototype.getTarget=function(){return this._target},r.prototype.changeTarget=function(e){this._target=e},r.prototype.when=function(e,t,a){return this.whenWithKeys(e,t,St(t),a)},r.prototype.whenWithKeys=function(e,t,a,n){for(var i=this._tracks,o=0;o0&&l.addKeyframe(0,Is(u),n),this._trackKeys.push(s)}l.addKeyframe(e,Is(t[s]),n)}return this._maxTime=Math.max(this._maxTime,e),this},r.prototype.pause=function(){this._clip.pause(),this._paused=!0},r.prototype.resume=function(){this._clip.resume(),this._paused=!1},r.prototype.isPaused=function(){return!!this._paused},r.prototype.duration=function(e){return this._maxTime=e,this._force=!0,this},r.prototype._doneCallback=function(){this._setTracksFinished(),this._clip=null;var e=this._doneCbs;if(e)for(var t=e.length,a=0;a0)){this._started=1;for(var t=this,a=[],n=this._maxTime||0,i=0;i1){var s=o.pop();i.addKeyframe(s.time,e[n]),i.prepare(this._maxTime,i.getAdditiveTrack())}}}},r}();function Xi(){return new Date().getTime()}var x2=function(r){k(e,r);function e(t){var a=r.call(this)||this;return a._running=!1,a._time=0,a._pausedTime=0,a._pauseStart=0,a._paused=!1,t=t||{},a.stage=t.stage||{},a}return e.prototype.addClip=function(t){t.animation&&this.removeClip(t),this._head?(this._tail.next=t,t.prev=this._tail,t.next=null,this._tail=t):this._head=this._tail=t,t.animation=this},e.prototype.addAnimator=function(t){t.animation=this;var a=t.getClip();a&&this.addClip(a)},e.prototype.removeClip=function(t){if(t.animation){var a=t.prev,n=t.next;a?a.next=n:this._head=n,n?n.prev=a:this._tail=a,t.next=t.prev=t.animation=null}},e.prototype.removeAnimator=function(t){var a=t.getClip();a&&this.removeClip(a),t.animation=null},e.prototype.update=function(t){for(var a=Xi()-this._pausedTime,n=a-this._time,i=this._head;i;){var o=i.next,s=i.step(a,n);s&&(i.ondestroy(),this.removeClip(i)),i=o}this._time=a,t||(this.trigger("frame",n),this.stage.update&&this.stage.update())},e.prototype._startLoop=function(){var t=this;this._running=!0;function a(){t._running&&(pf(a),!t._paused&&t.update())}pf(a)},e.prototype.start=function(){this._running||(this._time=Xi(),this._pausedTime=0,this._startLoop())},e.prototype.stop=function(){this._running=!1},e.prototype.pause=function(){this._paused||(this._pauseStart=Xi(),this._paused=!0)},e.prototype.resume=function(){this._paused&&(this._pausedTime+=Xi()-this._pauseStart,this._paused=!1)},e.prototype.clear=function(){for(var t=this._head;t;){var a=t.next;t.prev=t.next=t.animation=null,t=a}this._head=this._tail=null},e.prototype.isFinished=function(){return this._head==null},e.prototype.animate=function(t,a){a=a||{},this.start();var n=new mg(t,a.loop);return this.addAnimator(n),n},e}(fr),b2=300,lv=_t.domSupported,uv=function(){var r=["click","dblclick","mousewheel","wheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],e=["touchstart","touchend","touchmove"],t={pointerdown:1,pointerup:1,pointermove:1,pointerout:1},a=G(r,function(n){var i=n.replace("mouse","pointer");return t.hasOwnProperty(i)?i:n});return{mouse:r,touch:e,pointer:a}}(),Hm={mouse:["mousemove","mouseup"],pointer:["pointermove","pointerup"]},Wm=!1;function Ep(r){var e=r.pointerType;return e==="pen"||e==="touch"}function w2(r){r.touching=!0,r.touchTimer!=null&&(clearTimeout(r.touchTimer),r.touchTimer=null),r.touchTimer=setTimeout(function(){r.touching=!1,r.touchTimer=null},700)}function fv(r){r&&(r.zrByTouch=!0)}function T2(r,e){return Je(r.dom,new A2(r,e),!0)}function Qw(r,e){for(var t=e,a=!1;t&&t.nodeType!==9&&!(a=t.domBelongToZr||t!==e&&t===r.painterRoot);)t=t.parentNode;return a}var A2=function(){function r(e,t){this.stopPropagation=Yt,this.stopImmediatePropagation=Yt,this.preventDefault=Yt,this.type=t.type,this.target=this.currentTarget=e.dom,this.pointerType=t.pointerType,this.clientX=t.clientX,this.clientY=t.clientY}return r}(),yr={mousedown:function(r){r=Je(this.dom,r),this.__mayPointerCapture=[r.zrX,r.zrY],this.trigger("mousedown",r)},mousemove:function(r){r=Je(this.dom,r);var e=this.__mayPointerCapture;e&&(r.zrX!==e[0]||r.zrY!==e[1])&&this.__togglePointerCapture(!0),this.trigger("mousemove",r)},mouseup:function(r){r=Je(this.dom,r),this.__togglePointerCapture(!1),this.trigger("mouseup",r)},mouseout:function(r){r=Je(this.dom,r);var e=r.toElement||r.relatedTarget;Qw(this,e)||(this.__pointerCapturing&&(r.zrEventControl="no_globalout"),this.trigger("mouseout",r))},wheel:function(r){Wm=!0,r=Je(this.dom,r),this.trigger("mousewheel",r)},mousewheel:function(r){Wm||(r=Je(this.dom,r),this.trigger("mousewheel",r))},touchstart:function(r){r=Je(this.dom,r),fv(r),this.__lastTouchMoment=new Date,this.handler.processGesture(r,"start"),yr.mousemove.call(this,r),yr.mousedown.call(this,r)},touchmove:function(r){r=Je(this.dom,r),fv(r),this.handler.processGesture(r,"change"),yr.mousemove.call(this,r)},touchend:function(r){r=Je(this.dom,r),fv(r),this.handler.processGesture(r,"end"),yr.mouseup.call(this,r),+new Date-+this.__lastTouchMomentXm||r<-Xm}var vn=[],bi=[],vv=Ge(),cv=Math.abs,fa=function(){function r(){}return r.prototype.getLocalTransform=function(e){return r.getLocalTransform(this,e)},r.prototype.setPosition=function(e){this.x=e[0],this.y=e[1]},r.prototype.setScale=function(e){this.scaleX=e[0],this.scaleY=e[1]},r.prototype.setSkew=function(e){this.skewX=e[0],this.skewY=e[1]},r.prototype.setOrigin=function(e){this.originX=e[0],this.originY=e[1]},r.prototype.needLocalTransform=function(){return hn(this.rotation)||hn(this.x)||hn(this.y)||hn(this.scaleX-1)||hn(this.scaleY-1)||hn(this.skewX)||hn(this.skewY)},r.prototype.updateTransform=function(){var e=this.parent&&this.parent.transform,t=this.needLocalTransform(),a=this.transform;if(!(t||e)){a&&(Ym(a),this.invTransform=null);return}a=a||Ge(),t?this.getLocalTransform(a):Ym(a),e&&(t?Yr(a,e,a):ph(a,e)),this.transform=a,this._resolveGlobalScaleRatio(a)},r.prototype._resolveGlobalScaleRatio=function(e){var t=this.globalScaleRatio;if(t!=null&&t!==1){this.getGlobalScale(vn);var a=vn[0]<0?-1:1,n=vn[1]<0?-1:1,i=((vn[0]-a)*t+a)/vn[0]||0,o=((vn[1]-n)*t+n)/vn[1]||0;e[0]*=i,e[1]*=i,e[2]*=o,e[3]*=o}this.invTransform=this.invTransform||Ge(),vi(this.invTransform,e)},r.prototype.getComputedTransform=function(){for(var e=this,t=[];e;)t.push(e),e=e.parent;for(;e=t.pop();)e.updateTransform();return this.transform},r.prototype.setLocalTransform=function(e){if(e){var t=e[0]*e[0]+e[1]*e[1],a=e[2]*e[2]+e[3]*e[3],n=Math.atan2(e[1],e[0]),i=Math.PI/2+n-Math.atan2(e[3],e[2]);a=Math.sqrt(a)*Math.cos(i),t=Math.sqrt(t),this.skewX=i,this.skewY=0,this.rotation=-n,this.x=+e[4],this.y=+e[5],this.scaleX=t,this.scaleY=a,this.originX=0,this.originY=0}},r.prototype.decomposeTransform=function(){if(this.transform){var e=this.parent,t=this.transform;e&&e.transform&&(e.invTransform=e.invTransform||Ge(),Yr(bi,e.invTransform,t),t=bi);var a=this.originX,n=this.originY;(a||n)&&(vv[4]=a,vv[5]=n,Yr(bi,t,vv),bi[4]-=a,bi[5]-=n,t=bi),this.setLocalTransform(t)}},r.prototype.getGlobalScale=function(e){var t=this.transform;return e=e||[],t?(e[0]=Math.sqrt(t[0]*t[0]+t[1]*t[1]),e[1]=Math.sqrt(t[2]*t[2]+t[3]*t[3]),t[0]<0&&(e[0]=-e[0]),t[3]<0&&(e[1]=-e[1]),e):(e[0]=1,e[1]=1,e)},r.prototype.transformCoordToLocal=function(e,t){var a=[e,t],n=this.invTransform;return n&&le(a,a,n),a},r.prototype.transformCoordToGlobal=function(e,t){var a=[e,t],n=this.transform;return n&&le(a,a,n),a},r.prototype.getLineScale=function(){var e=this.transform;return e&&cv(e[0]-1)>1e-10&&cv(e[3]-1)>1e-10?Math.sqrt(cv(e[0]*e[3]-e[2]*e[1])):1},r.prototype.copyTransform=function(e){tT(this,e)},r.getLocalTransform=function(e,t){t=t||[];var a=e.originX||0,n=e.originY||0,i=e.scaleX,o=e.scaleY,s=e.anchorX,l=e.anchorY,u=e.rotation||0,f=e.x,h=e.y,v=e.skewX?Math.tan(e.skewX):0,c=e.skewY?Math.tan(-e.skewY):0;if(a||n||s||l){var p=a+s,d=n+l;t[4]=-p*i-v*d*o,t[5]=-d*o-c*p*i}else t[4]=t[5]=0;return t[0]=i,t[3]=o,t[1]=c*i,t[2]=v*o,u&&an(t,t,u),t[4]+=a+f,t[5]+=n+h,t},r.initDefaultProps=function(){var e=r.prototype;e.scaleX=e.scaleY=e.globalScaleRatio=1,e.x=e.y=e.originX=e.originY=e.skewX=e.skewY=e.rotation=e.anchorX=e.anchorY=0}(),r}(),$r=["x","y","originX","originY","anchorX","anchorY","rotation","scaleX","scaleY","skewX","skewY"];function tT(r,e){for(var t=0;t<$r.length;t++){var a=$r[t];r[a]=e[a]}}var $m={};function Xe(r,e){e=e||Ka;var t=$m[e];t||(t=$m[e]=new xl(500));var a=t.get(r);return a==null&&(a=Cr.measureText(r,e).width,t.put(r,a)),a}function Zm(r,e,t,a){var n=Xe(r,e),i=yh(e),o=ps(0,n,t),s=Hi(0,i,a),l=new ht(o,s,n,i);return l}function bl(r,e,t,a){var n=((r||"")+"").split(`
+`),i=n.length;if(i===1)return Zm(n[0],e,t,a);for(var o=new ht(0,0,0,0),s=0;s=0?parseFloat(r)/100*e:parseFloat(r):r}function xf(r,e,t){var a=e.position||"inside",n=e.distance!=null?e.distance:5,i=t.height,o=t.width,s=i/2,l=t.x,u=t.y,f="left",h="top";if(a instanceof Array)l+=Mr(a[0],t.width),u+=Mr(a[1],t.height),f=null,h=null;else switch(a){case"left":l-=n,u+=s,f="right",h="middle";break;case"right":l+=n+o,u+=s,h="middle";break;case"top":l+=o/2,u-=n,f="center",h="bottom";break;case"bottom":l+=o/2,u+=i+n,f="center";break;case"inside":l+=o/2,u+=s,f="center",h="middle";break;case"insideLeft":l+=n,u+=s,h="middle";break;case"insideRight":l+=o-n,u+=s,f="right",h="middle";break;case"insideTop":l+=o/2,u+=n,f="center";break;case"insideBottom":l+=o/2,u+=i-n,f="center",h="bottom";break;case"insideTopLeft":l+=n,u+=n;break;case"insideTopRight":l+=o-n,u+=n,f="right";break;case"insideBottomLeft":l+=n,u+=i-n,h="bottom";break;case"insideBottomRight":l+=o-n,u+=i-n,f="right",h="bottom";break}return r=r||{},r.x=l,r.y=u,r.align=f,r.verticalAlign=h,r}var pv="__zr_normal__",dv=$r.concat(["ignore"]),L2=lr($r,function(r,e){return r[e]=!0,r},{ignore:!1}),wi={},P2=new ht(0,0,0,0),mh=function(){function r(e){this.id=fg(),this.animators=[],this.currentStates=[],this.states={},this._init(e)}return r.prototype._init=function(e){this.attr(e)},r.prototype.drift=function(e,t,a){switch(this.draggable){case"horizontal":t=0;break;case"vertical":e=0;break}var n=this.transform;n||(n=this.transform=[1,0,0,1,0,0]),n[4]+=e,n[5]+=t,this.decomposeTransform(),this.markRedraw()},r.prototype.beforeUpdate=function(){},r.prototype.afterUpdate=function(){},r.prototype.update=function(){this.updateTransform(),this.__dirty&&this.updateInnerText()},r.prototype.updateInnerText=function(e){var t=this._textContent;if(t&&(!t.ignore||e)){this.textConfig||(this.textConfig={});var a=this.textConfig,n=a.local,i=t.innerTransformable,o=void 0,s=void 0,l=!1;i.parent=n?this:null;var u=!1;if(i.copyTransform(t),a.position!=null){var f=P2;a.layoutRect?f.copy(a.layoutRect):f.copy(this.getBoundingRect()),n||f.applyTransform(this.transform),this.calculateTextPosition?this.calculateTextPosition(wi,a,f):xf(wi,a,f),i.x=wi.x,i.y=wi.y,o=wi.align,s=wi.verticalAlign;var h=a.origin;if(h&&a.rotation!=null){var v=void 0,c=void 0;h==="center"?(v=f.width*.5,c=f.height*.5):(v=Mr(h[0],f.width),c=Mr(h[1],f.height)),u=!0,i.originX=-i.x+v+(n?0:f.x),i.originY=-i.y+c+(n?0:f.y)}}a.rotation!=null&&(i.rotation=a.rotation);var p=a.offset;p&&(i.x+=p[0],i.y+=p[1],u||(i.originX=-p[0],i.originY=-p[1]));var d=a.inside==null?typeof a.position=="string"&&a.position.indexOf("inside")>=0:a.inside,g=this._innerTextDefaultStyle||(this._innerTextDefaultStyle={}),y=void 0,m=void 0,_=void 0;d&&this.canBeInsideText()?(y=a.insideFill,m=a.insideStroke,(y==null||y==="auto")&&(y=this.getInsideTextFill()),(m==null||m==="auto")&&(m=this.getInsideTextStroke(y),_=!0)):(y=a.outsideFill,m=a.outsideStroke,(y==null||y==="auto")&&(y=this.getOutsideFill()),(m==null||m==="auto")&&(m=this.getOutsideStroke(y),_=!0)),y=y||"#000",(y!==g.fill||m!==g.stroke||_!==g.autoStroke||o!==g.align||s!==g.verticalAlign)&&(l=!0,g.fill=y,g.stroke=m,g.autoStroke=_,g.align=o,g.verticalAlign=s,t.setDefaultTextStyle(g)),t.__dirty|=He,l&&t.dirtyStyle(!0)}},r.prototype.canBeInsideText=function(){return!0},r.prototype.getInsideTextFill=function(){return"#fff"},r.prototype.getInsideTextStroke=function(e){return"#000"},r.prototype.getOutsideFill=function(){return this.__zr&&this.__zr.isDarkMode()?Bp:Np},r.prototype.getOutsideStroke=function(e){var t=this.__zr&&this.__zr.getBackgroundColor(),a=typeof t=="string"&&Ie(t);a||(a=[255,255,255,1]);for(var n=a[3],i=this.__zr.isDarkMode(),o=0;o<3;o++)a[o]=a[o]*n+(i?0:255)*(1-n);return a[3]=1,Tr(a,"rgba")},r.prototype.traverse=function(e,t){},r.prototype.attrKV=function(e,t){e==="textConfig"?this.setTextConfig(t):e==="textContent"?this.setTextContent(t):e==="clipPath"?this.setClipPath(t):e==="extra"?(this.extra=this.extra||{},V(this.extra,t)):this[e]=t},r.prototype.hide=function(){this.ignore=!0,this.markRedraw()},r.prototype.show=function(){this.ignore=!1,this.markRedraw()},r.prototype.attr=function(e,t){if(typeof e=="string")this.attrKV(e,t);else if(tt(e))for(var a=e,n=St(a),i=0;i0},r.prototype.getState=function(e){return this.states[e]},r.prototype.ensureState=function(e){var t=this.states;return t[e]||(t[e]={}),t[e]},r.prototype.clearStates=function(e){this.useState(pv,!1,e)},r.prototype.useState=function(e,t,a,n){var i=e===pv,o=this.hasState();if(!(!o&&i)){var s=this.currentStates,l=this.stateTransition;if(!(vt(s,e)>=0&&(t||s.length===1))){var u;if(this.stateProxy&&!i&&(u=this.stateProxy(e)),u||(u=this.states&&this.states[e]),!u&&!i){fh("State "+e+" not exists.");return}i||this.saveCurrentToNormalState(u);var f=!!(u&&u.hoverLayer||n);f&&this._toggleHoverLayerFlag(!0),this._applyStateObj(e,u,this._normalState,t,!a&&!this.__inHover&&l&&l.duration>0,l);var h=this._textContent,v=this._textGuide;return h&&h.useState(e,t,a,f),v&&v.useState(e,t,a,f),i?(this.currentStates=[],this._normalState={}):t?this.currentStates.push(e):this.currentStates=[e],this._updateAnimationTargets(),this.markRedraw(),!f&&this.__inHover&&(this._toggleHoverLayerFlag(!1),this.__dirty&=~He),u}}},r.prototype.useStates=function(e,t,a){if(!e.length)this.clearStates();else{var n=[],i=this.currentStates,o=e.length,s=o===i.length;if(s){for(var l=0;l0,p);var d=this._textContent,g=this._textGuide;d&&d.useStates(e,t,v),g&&g.useStates(e,t,v),this._updateAnimationTargets(),this.currentStates=e.slice(),this.markRedraw(),!v&&this.__inHover&&(this._toggleHoverLayerFlag(!1),this.__dirty&=~He)}},r.prototype.isSilent=function(){for(var e=this.silent,t=this.parent;!e&&t;){if(t.silent){e=!0;break}t=t.parent}return e},r.prototype._updateAnimationTargets=function(){for(var e=0;e=0){var a=this.currentStates.slice();a.splice(t,1),this.useStates(a)}},r.prototype.replaceState=function(e,t,a){var n=this.currentStates.slice(),i=vt(n,e),o=vt(n,t)>=0;i>=0?o?n.splice(i,1):n[i]=t:a&&!o&&n.push(t),this.useStates(n)},r.prototype.toggleState=function(e,t){t?this.useState(e,!0):this.removeState(e)},r.prototype._mergeStates=function(e){for(var t={},a,n=0;n=0&&i.splice(o,1)}),this.animators.push(e),a&&a.animation.addAnimator(e),a&&a.wakeUp()},r.prototype.updateDuringAnimation=function(e){this.markRedraw()},r.prototype.stopAnimation=function(e,t){for(var a=this.animators,n=a.length,i=[],o=0;o0&&t.during&&i[0].during(function(p,d){t.during(d)});for(var v=0;v0||n.force&&!o.length){var T=void 0,A=void 0,D=void 0;if(s){A={},v&&(T={});for(var S=0;S<_;S++){var y=d[S];A[y]=t[y],v?T[y]=a[y]:t[y]=a[y]}}else if(v){D={};for(var S=0;S<_;S++){var y=d[S];D[y]=Is(t[y]),E2(t,a,y)}}var b=new mg(t,!1,!1,h?Pt(p,function(I){return I.targetName===e}):null);b.targetName=e,n.scope&&(b.scope=n.scope),v&&T&&b.whenWithKeys(0,T,d),D&&b.whenWithKeys(0,D,d),b.whenWithKeys(u??500,s?A:a,d).delay(f||0),r.addAnimator(b,e),o.push(b)}}var at=function(r){k(e,r);function e(t){var a=r.call(this)||this;return a.isGroup=!0,a._children=[],a.attr(t),a}return e.prototype.childrenRef=function(){return this._children},e.prototype.children=function(){return this._children.slice()},e.prototype.childAt=function(t){return this._children[t]},e.prototype.childOfName=function(t){for(var a=this._children,n=0;n=0&&(n.splice(i,0,t),this._doAdd(t))}return this},e.prototype.replace=function(t,a){var n=vt(this._children,t);return n>=0&&this.replaceAt(a,n),this},e.prototype.replaceAt=function(t,a){var n=this._children,i=n[a];if(t&&t!==this&&t.parent!==this&&t!==i){n[a]=t,i.parent=null;var o=this.__zr;o&&i.removeSelfFromZr(o),this._doAdd(t)}return this},e.prototype._doAdd=function(t){t.parent&&t.parent.remove(t),t.parent=this;var a=this.__zr;a&&a!==t.__zr&&t.addSelfToZr(a),a&&a.refresh()},e.prototype.remove=function(t){var a=this.__zr,n=this._children,i=vt(n,t);return i<0?this:(n.splice(i,1),t.parent=null,a&&t.removeSelfFromZr(a),a&&a.refresh(),this)},e.prototype.removeAll=function(){for(var t=this._children,a=this.__zr,n=0;n0&&(this._stillFrameAccum++,this._stillFrameAccum>this._sleepAfterStill&&this.animation.stop())},r.prototype.setSleepAfterStill=function(e){this._sleepAfterStill=e},r.prototype.wakeUp=function(){this._disposed||(this.animation.start(),this._stillFrameAccum=0)},r.prototype.refreshHover=function(){this._needsRefreshHover=!0},r.prototype.refreshHoverImmediately=function(){this._disposed||(this._needsRefreshHover=!1,this.painter.refreshHover&&this.painter.getType()==="canvas"&&this.painter.refreshHover())},r.prototype.resize=function(e){this._disposed||(e=e||{},this.painter.resize(e.width,e.height),this.handler.resize())},r.prototype.clearAnimation=function(){this._disposed||this.animation.clear()},r.prototype.getWidth=function(){if(!this._disposed)return this.painter.getWidth()},r.prototype.getHeight=function(){if(!this._disposed)return this.painter.getHeight()},r.prototype.setCursorStyle=function(e){this._disposed||this.handler.setCursorStyle(e)},r.prototype.findHover=function(e,t){if(!this._disposed)return this.handler.findHover(e,t)},r.prototype.on=function(e,t,a){return this._disposed||this.handler.on(e,t,a),this},r.prototype.off=function(e,t){this._disposed||this.handler.off(e,t)},r.prototype.trigger=function(e,t){this._disposed||this.handler.trigger(e,t)},r.prototype.clear=function(){if(!this._disposed){for(var e=this.storage.getRoots(),t=0;t0){if(r<=n)return o;if(r>=i)return s}else{if(r>=n)return o;if(r<=i)return s}else{if(r===n)return o;if(r===i)return s}return(r-n)/l*u+o}function W(r,e){switch(r){case"center":case"middle":r="50%";break;case"left":case"top":r="0%";break;case"right":case"bottom":r="100%";break}return U(r)?W2(r).match(/%$/)?parseFloat(r)/100*e:parseFloat(r):r==null?NaN:+r}function Ht(r,e,t){return e==null&&(e=10),e=Math.min(Math.max(0,e),iT),r=(+r).toFixed(e),t?r:+r}function Ue(r){return r.sort(function(e,t){return e-t}),r}function Sr(r){if(r=+r,isNaN(r))return 0;if(r>1e-14){for(var e=1,t=0;t<15;t++,e*=10)if(Math.round(r*e)/e===r)return t}return oT(r)}function oT(r){var e=r.toString().toLowerCase(),t=e.indexOf("e"),a=t>0?+e.slice(t+1):0,n=t>0?t:e.length,i=e.indexOf("."),o=i<0?0:n-1-i;return Math.max(0,o-a)}function _g(r,e){var t=Math.log,a=Math.LN10,n=Math.floor(t(r[1]-r[0])/a),i=Math.round(t(Math.abs(e[1]-e[0]))/a),o=Math.min(Math.max(-n+i,0),20);return isFinite(o)?o:20}function U2(r,e,t){if(!r[e])return 0;var a=sT(r,t);return a[e]||0}function sT(r,e){var t=lr(r,function(c,p){return c+(isNaN(p)?0:p)},0);if(t===0)return[];for(var a=Math.pow(10,e),n=G(r,function(c){return(isNaN(c)?0:c)/t*a*100}),i=a*100,o=G(n,function(c){return Math.floor(c)}),s=lr(o,function(c,p){return c+p},0),l=G(n,function(c,p){return c-o[p]});su&&(u=l[h],f=h);++o[f],l[f]=0,++s}return G(o,function(c){return c/a})}function Y2(r,e){var t=Math.max(Sr(r),Sr(e)),a=r+e;return t>iT?a:Ht(a,t)}var Gp=9007199254740991;function Sg(r){var e=Math.PI*2;return(r%e+e)%e}function io(r){return r>-qm&&r=10&&e++,e}function xg(r,e){var t=_h(r),a=Math.pow(10,t),n=r/a,i;return e?n<1.5?i=1:n<2.5?i=2:n<4?i=3:n<7?i=5:i=10:n<1?i=1:n<2?i=2:n<3?i=3:n<5?i=5:i=10,r=i*a,t>=-20?+r.toFixed(t<0?-t:0):r}function Ku(r,e){var t=(r.length-1)*e+1,a=Math.floor(t),n=+r[a-1],i=t-a;return i?n+i*(r[a]-n):n}function Fp(r){r.sort(function(l,u){return s(l,u,0)?-1:1});for(var e=-1/0,t=1,a=0;a=0||i&&vt(i,l)<0)){var u=a.getShallow(l,e);u!=null&&(o[r[s][0]]=u)}}return o}}var gP=[["fill","color"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["opacity"],["shadowColor"]],yP=ii(gP),mP=function(){function r(){}return r.prototype.getAreaStyle=function(e,t){return yP(this,e,t)},r}(),Wp=new xl(50);function _P(r){if(typeof r=="string"){var e=Wp.get(r);return e&&e.image}else return r}function Cg(r,e,t,a,n){if(r)if(typeof r=="string"){if(e&&e.__zrImageSrc===r||!t)return e;var i=Wp.get(r),o={hostEl:t,cb:a,cbPayload:n};return i?(e=i.image,!xh(e)&&i.pending.push(o)):(e=Cr.loadImage(r,Jm,Jm),e.__zrImageSrc=r,Wp.put(r,e.__cachedImgObj={image:e,pending:[o]})),e}else return r;else return e}function Jm(){var r=this.__cachedImgObj;this.onload=this.onerror=this.__cachedImgObj=null;for(var e=0;e=o;l++)s-=o;var u=Xe(t,e);return u>s&&(t="",u=0),s=r-u,n.ellipsis=t,n.ellipsisWidth=u,n.contentWidth=s,n.containerWidth=r,n}function xT(r,e){var t=e.containerWidth,a=e.font,n=e.contentWidth;if(!t)return"";var i=Xe(r,a);if(i<=t)return r;for(var o=0;;o++){if(i<=n||o>=e.maxIterations){r+=e.ellipsis;break}var s=o===0?SP(r,n,e.ascCharWidth,e.cnCharWidth):i>0?Math.floor(r.length*n/i):0;r=r.substr(0,s),i=Xe(r,a)}return r===""&&(r=e.placeholder),r}function SP(r,e,t,a){for(var n=0,i=0,o=r.length;ic&&u){var p=Math.floor(c/s);h=h.slice(0,p)}if(r&&i&&f!=null)for(var d=ST(f,n,e.ellipsis,{minChar:e.truncateMinChar,placeholder:e.placeholder}),g=0;gs&&_v(t,r.substring(s,u),e,o),_v(t,l[2],e,o,l[1]),s=mv.lastIndex}sn){b>0?(m.tokens=m.tokens.slice(0,b),g(m,S,_),t.lines=t.lines.slice(0,y+1)):t.lines=t.lines.slice(0,y);break t}var I=w.width,L=I==null||I==="auto";if(typeof I=="string"&&I.charAt(I.length-1)==="%")x.percentWidth=I,f.push(x),x.contentWidth=Xe(x.text,D);else{if(L){var P=w.backgroundColor,R=P&&P.image;R&&(R=_P(R),xh(R)&&(x.width=Math.max(x.width,R.width*M/R.height)))}var E=p&&a!=null?a-S:null;E!=null&&E0&&p+a.accumWidth>a.width&&(f=e.split(`
+`),u=!0),a.accumWidth=p}else{var d=bT(e,l,a.width,a.breakAll,a.accumWidth);a.accumWidth=d.accumWidth+c,h=d.linesWidths,f=d.lines}}else f=e.split(`
+`);for(var g=0;g=32&&e<=591||e>=880&&e<=4351||e>=4608&&e<=5119||e>=7680&&e<=8303}var CP=lr(",&?/;] ".split(""),function(r,e){return r[e]=!0,r},{});function DP(r){return AP(r)?!!CP[r]:!0}function bT(r,e,t,a,n){for(var i=[],o=[],s="",l="",u=0,f=0,h=0;ht:n+f+c>t){f?(s||l)&&(p?(s||(s=l,l="",u=0,f=u),i.push(s),o.push(f-u),l+=v,u+=c,s="",f=u):(l&&(s+=l,l="",u=0),i.push(s),o.push(f),s=v,f=c)):p?(i.push(l),o.push(u),l=v,u=c):(i.push(v),o.push(c));continue}f+=c,p?(l+=v,u+=c):(l&&(s+=l,l="",u=0),s+=v)}return!i.length&&!s&&(s=r,l="",u=0),l&&(s+=l),s&&(i.push(s),o.push(f)),i.length===1&&(f+=n),{accumWidth:f,lines:i,linesWidths:o}}var Up="__zr_style_"+Math.round(Math.random()*10),Kn={shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,shadowColor:"#000",opacity:1,blend:"source-over"},bh={style:{shadowBlur:!0,shadowOffsetX:!0,shadowOffsetY:!0,shadowColor:!0,opacity:!0}};Kn[Up]=!0;var e0=["z","z2","invisible"],MP=["invisible"],ur=function(r){k(e,r);function e(t){return r.call(this,t)||this}return e.prototype._init=function(t){for(var a=St(t),n=0;n1e-4){s[0]=r-t,s[1]=e-a,l[0]=r+t,l[1]=e+a;return}if(Ql[0]=wv(n)*t+r,Ql[1]=bv(n)*a+e,Jl[0]=wv(i)*t+r,Jl[1]=bv(i)*a+e,u(s,Ql,Jl),f(l,Ql,Jl),n=n%pn,n<0&&(n=n+pn),i=i%pn,i<0&&(i=i+pn),n>i&&!o?i+=pn:nn&&(tu[0]=wv(c)*t+r,tu[1]=bv(c)*a+e,u(s,tu,s),f(l,tu,l))}var Ot={M:1,L:2,C:3,Q:4,A:5,Z:6,R:7},dn=[],gn=[],Pr=[],Ta=[],Rr=[],Er=[],Tv=Math.min,Av=Math.max,yn=Math.cos,mn=Math.sin,ra=Math.abs,Yp=Math.PI,Ra=Yp*2,Cv=typeof Float32Array<"u",Ho=[];function Dv(r){var e=Math.round(r/Yp*1e8)/1e8;return e%2*Yp}function Dg(r,e){var t=Dv(r[0]);t<0&&(t+=Ra);var a=t-r[0],n=r[1];n+=a,!e&&n-t>=Ra?n=t+Ra:e&&t-n>=Ra?n=t-Ra:!e&&t>n?n=t+(Ra-Dv(t-n)):e&&t0&&(this._ux=ra(a/Sf/e)||0,this._uy=ra(a/Sf/t)||0)},r.prototype.setDPR=function(e){this.dpr=e},r.prototype.setContext=function(e){this._ctx=e},r.prototype.getContext=function(){return this._ctx},r.prototype.beginPath=function(){return this._ctx&&this._ctx.beginPath(),this.reset(),this},r.prototype.reset=function(){this._saveData&&(this._len=0),this._pathSegLen&&(this._pathSegLen=null,this._pathLen=0),this._version++},r.prototype.moveTo=function(e,t){return this._drawPendingPt(),this.addData(Ot.M,e,t),this._ctx&&this._ctx.moveTo(e,t),this._x0=e,this._y0=t,this._xi=e,this._yi=t,this},r.prototype.lineTo=function(e,t){var a=ra(e-this._xi),n=ra(t-this._yi),i=a>this._ux||n>this._uy;if(this.addData(Ot.L,e,t),this._ctx&&i&&this._ctx.lineTo(e,t),i)this._xi=e,this._yi=t,this._pendingPtDist=0;else{var o=a*a+n*n;o>this._pendingPtDist&&(this._pendingPtX=e,this._pendingPtY=t,this._pendingPtDist=o)}return this},r.prototype.bezierCurveTo=function(e,t,a,n,i,o){return this._drawPendingPt(),this.addData(Ot.C,e,t,a,n,i,o),this._ctx&&this._ctx.bezierCurveTo(e,t,a,n,i,o),this._xi=i,this._yi=o,this},r.prototype.quadraticCurveTo=function(e,t,a,n){return this._drawPendingPt(),this.addData(Ot.Q,e,t,a,n),this._ctx&&this._ctx.quadraticCurveTo(e,t,a,n),this._xi=a,this._yi=n,this},r.prototype.arc=function(e,t,a,n,i,o){this._drawPendingPt(),Ho[0]=n,Ho[1]=i,Dg(Ho,o),n=Ho[0],i=Ho[1];var s=i-n;return this.addData(Ot.A,e,t,a,a,n,s,0,o?0:1),this._ctx&&this._ctx.arc(e,t,a,n,i,o),this._xi=yn(i)*a+e,this._yi=mn(i)*a+t,this},r.prototype.arcTo=function(e,t,a,n,i){return this._drawPendingPt(),this._ctx&&this._ctx.arcTo(e,t,a,n,i),this},r.prototype.rect=function(e,t,a,n){return this._drawPendingPt(),this._ctx&&this._ctx.rect(e,t,a,n),this.addData(Ot.R,e,t,a,n),this},r.prototype.closePath=function(){this._drawPendingPt(),this.addData(Ot.Z);var e=this._ctx,t=this._x0,a=this._y0;return e&&e.closePath(),this._xi=t,this._yi=a,this},r.prototype.fill=function(e){e&&e.fill(),this.toStatic()},r.prototype.stroke=function(e){e&&e.stroke(),this.toStatic()},r.prototype.len=function(){return this._len},r.prototype.setData=function(e){var t=e.length;!(this.data&&this.data.length===t)&&Cv&&(this.data=new Float32Array(t));for(var a=0;af.length&&(this._expandData(),f=this.data);for(var h=0;h0&&(this._ctx&&this._ctx.lineTo(this._pendingPtX,this._pendingPtY),this._pendingPtDist=0)},r.prototype._expandData=function(){if(!(this.data instanceof Array)){for(var e=[],t=0;t11&&(this.data=new Float32Array(e)))}},r.prototype.getBoundingRect=function(){Pr[0]=Pr[1]=Rr[0]=Rr[1]=Number.MAX_VALUE,Ta[0]=Ta[1]=Er[0]=Er[1]=-Number.MAX_VALUE;var e=this.data,t=0,a=0,n=0,i=0,o;for(o=0;oa||ra(_)>n||v===t-1)&&(d=Math.sqrt(m*m+_*_),i=g,o=y);break}case Ot.C:{var S=e[v++],b=e[v++],g=e[v++],y=e[v++],x=e[v++],w=e[v++];d=jL(i,o,S,b,g,y,x,w,10),i=x,o=w;break}case Ot.Q:{var S=e[v++],b=e[v++],g=e[v++],y=e[v++];d=JL(i,o,S,b,g,y,10),i=g,o=y;break}case Ot.A:var T=e[v++],A=e[v++],D=e[v++],M=e[v++],I=e[v++],L=e[v++],P=L+I;v+=1,p&&(s=yn(I)*D+T,l=mn(I)*M+A),d=Av(D,M)*Tv(Ra,Math.abs(L)),i=yn(P)*D+T,o=mn(P)*M+A;break;case Ot.R:{s=i=e[v++],l=o=e[v++];var R=e[v++],E=e[v++];d=R*2+E*2;break}case Ot.Z:{var m=s-i,_=l-o;d=Math.sqrt(m*m+_*_),i=s,o=l;break}}d>=0&&(u[h++]=d,f+=d)}return this._pathLen=f,f},r.prototype.rebuildPath=function(e,t){var a=this.data,n=this._ux,i=this._uy,o=this._len,s,l,u,f,h,v,c=t<1,p,d,g=0,y=0,m,_=0,S,b;if(!(c&&(this._pathSegLen||this._calculateLength(),p=this._pathSegLen,d=this._pathLen,m=t*d,!m)))t:for(var x=0;x0&&(e.lineTo(S,b),_=0),w){case Ot.M:s=u=a[x++],l=f=a[x++],e.moveTo(u,f);break;case Ot.L:{h=a[x++],v=a[x++];var A=ra(h-u),D=ra(v-f);if(A>n||D>i){if(c){var M=p[y++];if(g+M>m){var I=(m-g)/M;e.lineTo(u*(1-I)+h*I,f*(1-I)+v*I);break t}g+=M}e.lineTo(h,v),u=h,f=v,_=0}else{var L=A*A+D*D;L>_&&(S=h,b=v,_=L)}break}case Ot.C:{var P=a[x++],R=a[x++],E=a[x++],N=a[x++],O=a[x++],B=a[x++];if(c){var M=p[y++];if(g+M>m){var I=(m-g)/M;ja(u,P,E,O,I,dn),ja(f,R,N,B,I,gn),e.bezierCurveTo(dn[1],gn[1],dn[2],gn[2],dn[3],gn[3]);break t}g+=M}e.bezierCurveTo(P,R,E,N,O,B),u=O,f=B;break}case Ot.Q:{var P=a[x++],R=a[x++],E=a[x++],N=a[x++];if(c){var M=p[y++];if(g+M>m){var I=(m-g)/M;Us(u,P,E,I,dn),Us(f,R,N,I,gn),e.quadraticCurveTo(dn[1],gn[1],dn[2],gn[2]);break t}g+=M}e.quadraticCurveTo(P,R,E,N),u=E,f=N;break}case Ot.A:var F=a[x++],H=a[x++],Y=a[x++],j=a[x++],J=a[x++],ct=a[x++],xt=a[x++],pt=!a[x++],rt=Y>j?Y:j,dt=ra(Y-j)>.001,lt=J+ct,q=!1;if(c){var M=p[y++];g+M>m&&(lt=J+ct*(m-g)/M,q=!0),g+=M}if(dt&&e.ellipse?e.ellipse(F,H,Y,j,xt,J,lt,pt):e.arc(F,H,rt,J,lt,pt),q)break t;T&&(s=yn(J)*Y+F,l=mn(J)*j+H),u=yn(lt)*Y+F,f=mn(lt)*j+H;break;case Ot.R:s=u=a[x],l=f=a[x+1],h=a[x++],v=a[x++];var ut=a[x++],Gt=a[x++];if(c){var M=p[y++];if(g+M>m){var At=m-g;e.moveTo(h,v),e.lineTo(h+Tv(At,ut),v),At-=ut,At>0&&e.lineTo(h+ut,v+Tv(At,Gt)),At-=Gt,At>0&&e.lineTo(h+Av(ut-At,0),v+Gt),At-=ut,At>0&&e.lineTo(h,v+Av(Gt-At,0));break t}g+=M}e.rect(h,v,ut,Gt);break;case Ot.Z:if(c){var M=p[y++];if(g+M>m){var I=(m-g)/M;e.lineTo(u*(1-I)+s*I,f*(1-I)+l*I);break t}g+=M}e.closePath(),u=s,f=l}}},r.prototype.clone=function(){var e=new r,t=this.data;return e.data=t.slice?t.slice():Array.prototype.slice.call(t),e._len=this._len,e},r.CMD=Ot,r.initDefaultProps=function(){var e=r.prototype;e._saveData=!0,e._ux=0,e._uy=0,e._pendingPtDist=0,e._version=0}(),r}();function ka(r,e,t,a,n,i,o){if(n===0)return!1;var s=n,l=0,u=r;if(o>e+s&&o>a+s||or+s&&i>t+s||ie+h&&f>a+h&&f>i+h&&f>s+h||fr+h&&u>t+h&&u>n+h&&u>o+h||ue+u&&l>a+u&&l>i+u||lr+u&&s>t+u&&s>n+u||st||f+un&&(n+=Wo);var v=Math.atan2(l,s);return v<0&&(v+=Wo),v>=a&&v<=n||v+Wo>=a&&v+Wo<=n}function oa(r,e,t,a,n,i){if(i>e&&i>a||in?s:0}var Aa=qr.CMD,_n=Math.PI*2,OP=1e-4;function NP(r,e){return Math.abs(r-e)e&&u>a&&u>i&&u>s||u1&&BP(),c=te(e,a,i,s,er[0]),v>1&&(p=te(e,a,i,s,er[1]))),v===2?ge&&s>a&&s>i||s=0&&u<=1){for(var f=0,h=se(e,a,i,u),v=0;vt||s<-t)return 0;var l=Math.sqrt(t*t-s*s);Ae[0]=-l,Ae[1]=l;var u=Math.abs(a-n);if(u<1e-4)return 0;if(u>=_n-1e-4){a=0,n=_n;var f=i?1:-1;return o>=Ae[0]+r&&o<=Ae[1]+r?f:0}if(a>n){var h=a;a=n,n=h}a<0&&(a+=_n,n+=_n);for(var v=0,c=0;c<2;c++){var p=Ae[c];if(p+r>o){var d=Math.atan2(s,p),f=i?1:-1;d<0&&(d=_n+d),(d>=a&&d<=n||d+_n>=a&&d+_n<=n)&&(d>Math.PI/2&&d1&&(t||(s+=oa(l,u,f,h,a,n))),g&&(l=i[p],u=i[p+1],f=l,h=u),d){case Aa.M:f=i[p++],h=i[p++],l=f,u=h;break;case Aa.L:if(t){if(ka(l,u,i[p],i[p+1],e,a,n))return!0}else s+=oa(l,u,i[p],i[p+1],a,n)||0;l=i[p++],u=i[p++];break;case Aa.C:if(t){if(EP(l,u,i[p++],i[p++],i[p++],i[p++],i[p],i[p+1],e,a,n))return!0}else s+=VP(l,u,i[p++],i[p++],i[p++],i[p++],i[p],i[p+1],a,n)||0;l=i[p++],u=i[p++];break;case Aa.Q:if(t){if(wT(l,u,i[p++],i[p++],i[p],i[p+1],e,a,n))return!0}else s+=zP(l,u,i[p++],i[p++],i[p],i[p+1],a,n)||0;l=i[p++],u=i[p++];break;case Aa.A:var y=i[p++],m=i[p++],_=i[p++],S=i[p++],b=i[p++],x=i[p++];p+=1;var w=!!(1-i[p++]);v=Math.cos(b)*_+y,c=Math.sin(b)*S+m,g?(f=v,h=c):s+=oa(l,u,v,c,a,n);var T=(a-y)*S/_+y;if(t){if(kP(y,m,S,b,b+x,w,e,T,n))return!0}else s+=GP(y,m,S,b,b+x,w,T,n);l=Math.cos(b+x)*_+y,u=Math.sin(b+x)*S+m;break;case Aa.R:f=l=i[p++],h=u=i[p++];var A=i[p++],D=i[p++];if(v=f+A,c=h+D,t){if(ka(f,h,v,h,e,a,n)||ka(v,h,v,c,e,a,n)||ka(v,c,f,c,e,a,n)||ka(f,c,f,h,e,a,n))return!0}else s+=oa(v,h,v,c,a,n),s+=oa(f,c,f,h,a,n);break;case Aa.Z:if(t){if(ka(l,u,f,h,e,a,n))return!0}else s+=oa(l,u,f,h,a,n);l=f,u=h;break}}return!t&&!NP(u,h)&&(s+=oa(l,u,f,h,a,n)||0),s!==0}function FP(r,e,t){return TT(r,0,!1,e,t)}function HP(r,e,t,a){return TT(r,e,!0,t,a)}var bf=Q({fill:"#000",stroke:null,strokePercent:1,fillOpacity:1,strokeOpacity:1,lineDashOffset:0,lineWidth:1,lineCap:"butt",miterLimit:10,strokeNoScale:!1,strokeFirst:!1},Kn),WP={style:Q({fill:!0,stroke:!0,strokePercent:!0,fillOpacity:!0,strokeOpacity:!0,lineDashOffset:!0,lineWidth:!0,miterLimit:!0},bh.style)},Mv=$r.concat(["invisible","culling","z","z2","zlevel","parent"]),yt=function(r){k(e,r);function e(t){return r.call(this,t)||this}return e.prototype.update=function(){var t=this;r.prototype.update.call(this);var a=this.style;if(a.decal){var n=this._decalEl=this._decalEl||new e;n.buildPath===e.prototype.buildPath&&(n.buildPath=function(l){t.buildPath(l,t.shape)}),n.silent=!0;var i=n.style;for(var o in a)i[o]!==a[o]&&(i[o]=a[o]);i.fill=a.fill?a.decal:null,i.decal=null,i.shadowColor=null,a.strokeFirst&&(i.stroke=null);for(var s=0;s.5?Np:a>.2?I2:Bp}else if(t)return Bp}return Np},e.prototype.getInsideTextStroke=function(t){var a=this.style.fill;if(U(a)){var n=this.__zr,i=!!(n&&n.isDarkMode()),o=$s(t,0)0))},e.prototype.hasFill=function(){var t=this.style,a=t.fill;return a!=null&&a!=="none"},e.prototype.getBoundingRect=function(){var t=this._rect,a=this.style,n=!t;if(n){var i=!1;this.path||(i=!0,this.createPathProxy());var o=this.path;(i||this.__dirty&Fi)&&(o.beginPath(),this.buildPath(o,this.shape,!1),this.pathUpdated()),t=o.getBoundingRect()}if(this._rect=t,this.hasStroke()&&this.path&&this.path.len()>0){var s=this._rectStroke||(this._rectStroke=t.clone());if(this.__dirty||n){s.copy(t);var l=a.strokeNoScale?this.getLineScale():1,u=a.lineWidth;if(!this.hasFill()){var f=this.strokeContainThreshold;u=Math.max(u,f??4)}l>1e-10&&(s.width+=u/l,s.height+=u/l,s.x-=u/l/2,s.y-=u/l/2)}return s}return t},e.prototype.contain=function(t,a){var n=this.transformCoordToLocal(t,a),i=this.getBoundingRect(),o=this.style;if(t=n[0],a=n[1],i.contain(t,a)){var s=this.path;if(this.hasStroke()){var l=o.lineWidth,u=o.strokeNoScale?this.getLineScale():1;if(u>1e-10&&(this.hasFill()||(l=Math.max(l,this.strokeContainThreshold)),HP(s,l/u,t,a)))return!0}if(this.hasFill())return FP(s,t,a)}return!1},e.prototype.dirtyShape=function(){this.__dirty|=Fi,this._rect&&(this._rect=null),this._decalEl&&this._decalEl.dirtyShape(),this.markRedraw()},e.prototype.dirty=function(){this.dirtyStyle(),this.dirtyShape()},e.prototype.animateShape=function(t){return this.animate("shape",t)},e.prototype.updateDuringAnimation=function(t){t==="style"?this.dirtyStyle():t==="shape"?this.dirtyShape():this.markRedraw()},e.prototype.attrKV=function(t,a){t==="shape"?this.setShape(a):r.prototype.attrKV.call(this,t,a)},e.prototype.setShape=function(t,a){var n=this.shape;return n||(n=this.shape={}),typeof t=="string"?n[t]=a:V(n,t),this.dirtyShape(),this},e.prototype.shapeChanged=function(){return!!(this.__dirty&Fi)},e.prototype.createStyle=function(t){return _l(bf,t)},e.prototype._innerSaveToNormal=function(t){r.prototype._innerSaveToNormal.call(this,t);var a=this._normalState;t.shape&&!a.shape&&(a.shape=V({},this.shape))},e.prototype._applyStateObj=function(t,a,n,i,o,s){r.prototype._applyStateObj.call(this,t,a,n,i,o,s);var l=!(a&&i),u;if(a&&a.shape?o?i?u=a.shape:(u=V({},n.shape),V(u,a.shape)):(u=V({},i?this.shape:n.shape),V(u,a.shape)):l&&(u=n.shape),u)if(o){this.shape=V({},this.shape);for(var f={},h=St(u),v=0;v0},e.prototype.hasFill=function(){var t=this.style,a=t.fill;return a!=null&&a!=="none"},e.prototype.createStyle=function(t){return _l(UP,t)},e.prototype.setBoundingRect=function(t){this._rect=t},e.prototype.getBoundingRect=function(){var t=this.style;if(!this._rect){var a=t.text;a!=null?a+="":a="";var n=bl(a,t.font,t.textAlign,t.textBaseline);if(n.x+=t.x||0,n.y+=t.y||0,this.hasStroke()){var i=t.lineWidth;n.x-=i/2,n.y-=i/2,n.width+=i,n.height+=i}this._rect=n}return this._rect},e.initDefaultProps=function(){var t=e.prototype;t.dirtyRectTolerance=10}(),e}(ur);oo.prototype.type="tspan";var YP=Q({x:0,y:0},Kn),XP={style:Q({x:!0,y:!0,width:!0,height:!0,sx:!0,sy:!0,sWidth:!0,sHeight:!0},bh.style)};function $P(r){return!!(r&&typeof r!="string"&&r.width&&r.height)}var oe=function(r){k(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.createStyle=function(t){return _l(YP,t)},e.prototype._getSize=function(t){var a=this.style,n=a[t];if(n!=null)return n;var i=$P(a.image)?a.image:this.__image;if(!i)return 0;var o=t==="width"?"height":"width",s=a[o];return s==null?i[t]:i[t]/i[o]*s},e.prototype.getWidth=function(){return this._getSize("width")},e.prototype.getHeight=function(){return this._getSize("height")},e.prototype.getAnimationStyleProps=function(){return XP},e.prototype.getBoundingRect=function(){var t=this.style;return this._rect||(this._rect=new ht(t.x||0,t.y||0,this.getWidth(),this.getHeight())),this._rect},e}(ur);oe.prototype.type="image";function ZP(r,e){var t=e.x,a=e.y,n=e.width,i=e.height,o=e.r,s,l,u,f;n<0&&(t=t+n,n=-n),i<0&&(a=a+i,i=-i),typeof o=="number"?s=l=u=f=o:o instanceof Array?o.length===1?s=l=u=f=o[0]:o.length===2?(s=u=o[0],l=f=o[1]):o.length===3?(s=o[0],l=f=o[1],u=o[2]):(s=o[0],l=o[1],u=o[2],f=o[3]):s=l=u=f=0;var h;s+l>n&&(h=s+l,s*=n/h,l*=n/h),u+f>n&&(h=u+f,u*=n/h,f*=n/h),l+u>i&&(h=l+u,l*=i/h,u*=i/h),s+f>i&&(h=s+f,s*=i/h,f*=i/h),r.moveTo(t+s,a),r.lineTo(t+n-l,a),l!==0&&r.arc(t+n-l,a+l,l,-Math.PI/2,0),r.lineTo(t+n,a+i-u),u!==0&&r.arc(t+n-u,a+i-u,u,0,Math.PI/2),r.lineTo(t+f,a+i),f!==0&&r.arc(t+f,a+i-f,f,Math.PI/2,Math.PI),r.lineTo(t,a+s),s!==0&&r.arc(t+s,a+s,s,Math.PI,Math.PI*1.5)}var $i=Math.round;function AT(r,e,t){if(e){var a=e.x1,n=e.x2,i=e.y1,o=e.y2;r.x1=a,r.x2=n,r.y1=i,r.y2=o;var s=t&&t.lineWidth;return s&&($i(a*2)===$i(n*2)&&(r.x1=r.x2=Hn(a,s,!0)),$i(i*2)===$i(o*2)&&(r.y1=r.y2=Hn(i,s,!0))),r}}function CT(r,e,t){if(e){var a=e.x,n=e.y,i=e.width,o=e.height;r.x=a,r.y=n,r.width=i,r.height=o;var s=t&&t.lineWidth;return s&&(r.x=Hn(a,s,!0),r.y=Hn(n,s,!0),r.width=Math.max(Hn(a+i,s,!1)-r.x,i===0?0:1),r.height=Math.max(Hn(n+o,s,!1)-r.y,o===0?0:1)),r}}function Hn(r,e,t){if(!e)return r;var a=$i(r*2);return(a+$i(e))%2===0?a/2:(a+(t?1:-1))/2}var qP=function(){function r(){this.x=0,this.y=0,this.width=0,this.height=0}return r}(),KP={},wt=function(r){k(e,r);function e(t){return r.call(this,t)||this}return e.prototype.getDefaultShape=function(){return new qP},e.prototype.buildPath=function(t,a){var n,i,o,s;if(this.subPixelOptimize){var l=CT(KP,a,this.style);n=l.x,i=l.y,o=l.width,s=l.height,l.r=a.r,a=l}else n=a.x,i=a.y,o=a.width,s=a.height;a.r?ZP(t,a):t.rect(n,i,o,s)},e.prototype.isZeroArea=function(){return!this.shape.width||!this.shape.height},e}(yt);wt.prototype.type="rect";var o0={fill:"#000"},s0=2,jP={style:Q({fill:!0,stroke:!0,fillOpacity:!0,strokeOpacity:!0,lineWidth:!0,fontSize:!0,lineHeight:!0,width:!0,height:!0,textShadowColor:!0,textShadowBlur:!0,textShadowOffsetX:!0,textShadowOffsetY:!0,backgroundColor:!0,padding:!0,borderColor:!0,borderWidth:!0,borderRadius:!0},bh.style)},bt=function(r){k(e,r);function e(t){var a=r.call(this)||this;return a.type="text",a._children=[],a._defaultStyle=o0,a.attr(t),a}return e.prototype.childrenRef=function(){return this._children},e.prototype.update=function(){r.prototype.update.call(this),this.styleChanged()&&this._updateSubTexts();for(var t=0;t0,I=t.width!=null&&(t.overflow==="truncate"||t.overflow==="break"||t.overflow==="breakAll"),L=o.calculatedLineHeight,P=0;P=0&&(P=x[L],P.align==="right");)this._placeToken(P,t,T,y,I,"right",_),A-=P.width,I-=P.width,L--;for(M+=(i-(M-g)-(m-I)-A)/2;D<=L;)P=x[D],this._placeToken(P,t,T,y,M+P.width/2,"center",_),M+=P.width,D++;y+=T}},e.prototype._placeToken=function(t,a,n,i,o,s,l){var u=a.rich[t.styleName]||{};u.text=t.text;var f=t.verticalAlign,h=i+n/2;f==="top"?h=i+t.height/2:f==="bottom"&&(h=i+n-t.height/2);var v=!t.isLineHolder&&Iv(u);v&&this._renderBackground(u,a,s==="right"?o-t.width:s==="center"?o-t.width/2:o,h-t.height/2,t.width,t.height);var c=!!u.backgroundColor,p=t.textPadding;p&&(o=c0(o,s,p),h-=t.height/2-p[0]-t.innerHeight/2);var d=this._getOrCreateChild(oo),g=d.createStyle();d.useStyle(g);var y=this._defaultStyle,m=!1,_=0,S=v0("fill"in u?u.fill:"fill"in a?a.fill:(m=!0,y.fill)),b=h0("stroke"in u?u.stroke:"stroke"in a?a.stroke:!c&&!l&&(!y.autoStroke||m)?(_=s0,y.stroke):null),x=u.textShadowBlur>0||a.textShadowBlur>0;g.text=t.text,g.x=o,g.y=h,x&&(g.shadowBlur=u.textShadowBlur||a.textShadowBlur||0,g.shadowColor=u.textShadowColor||a.textShadowColor||"transparent",g.shadowOffsetX=u.textShadowOffsetX||a.textShadowOffsetX||0,g.shadowOffsetY=u.textShadowOffsetY||a.textShadowOffsetY||0),g.textAlign=s,g.textBaseline="middle",g.font=t.font||Ka,g.opacity=br(u.opacity,a.opacity,1),u0(g,u),b&&(g.lineWidth=br(u.lineWidth,a.lineWidth,_),g.lineDash=ot(u.lineDash,a.lineDash),g.lineDashOffset=a.lineDashOffset||0,g.stroke=b),S&&(g.fill=S);var w=t.contentWidth,T=t.contentHeight;d.setBoundingRect(new ht(ps(g.x,w,g.textAlign),Hi(g.y,T,g.textBaseline),w,T))},e.prototype._renderBackground=function(t,a,n,i,o,s){var l=t.backgroundColor,u=t.borderWidth,f=t.borderColor,h=l&&l.image,v=l&&!h,c=t.borderRadius,p=this,d,g;if(v||t.lineHeight||u&&f){d=this._getOrCreateChild(wt),d.useStyle(d.createStyle()),d.style.fill=null;var y=d.shape;y.x=n,y.y=i,y.width=o,y.height=s,y.r=c,d.dirtyShape()}if(v){var m=d.style;m.fill=l||null,m.fillOpacity=ot(t.fillOpacity,1)}else if(h){g=this._getOrCreateChild(oe),g.onload=function(){p.dirtyStyle()};var _=g.style;_.image=l.image,_.x=n,_.y=i,_.width=o,_.height=s}if(u&&f){var m=d.style;m.lineWidth=u,m.stroke=f,m.strokeOpacity=ot(t.strokeOpacity,1),m.lineDash=t.borderDash,m.lineDashOffset=t.borderDashOffset||0,d.strokeContainThreshold=0,d.hasFill()&&d.hasStroke()&&(m.strokeFirst=!0,m.lineWidth*=2)}var S=(d||g).style;S.shadowBlur=t.shadowBlur||0,S.shadowColor=t.shadowColor||"transparent",S.shadowOffsetX=t.shadowOffsetX||0,S.shadowOffsetY=t.shadowOffsetY||0,S.opacity=br(t.opacity,a.opacity,1)},e.makeFont=function(t){var a="";return MT(t)&&(a=[t.fontStyle,t.fontWeight,DT(t.fontSize),t.fontFamily||"sans-serif"].join(" ")),a&&or(a)||t.textFont||t.font},e}(ur),QP={left:!0,right:1,center:1},JP={top:1,bottom:1,middle:1},l0=["fontStyle","fontWeight","fontSize","fontFamily"];function DT(r){return typeof r=="string"&&(r.indexOf("px")!==-1||r.indexOf("rem")!==-1||r.indexOf("em")!==-1)?r:isNaN(+r)?sg+"px":r+"px"}function u0(r,e){for(var t=0;t=0,i=!1;if(r instanceof yt){var o=IT(r),s=n&&o.selectFill||o.normalFill,l=n&&o.selectStroke||o.normalStroke;if(Ti(s)||Ti(l)){a=a||{};var u=a.style||{};u.fill==="inherit"?(i=!0,a=V({},a),u=V({},u),u.fill=s):!Ti(u.fill)&&Ti(s)?(i=!0,a=V({},a),u=V({},u),u.fill=mf(s)):!Ti(u.stroke)&&Ti(l)&&(i||(a=V({},a),u=V({},u)),u.stroke=mf(l)),a.style=u}}if(a&&a.z2==null){i||(a=V({},a));var f=r.z2EmphasisLift;a.z2=r.z2+(f??mo)}return a}function oR(r,e,t){if(t&&t.z2==null){t=V({},t);var a=r.z2SelectLift;t.z2=r.z2+(a??eR)}return t}function sR(r,e,t){var a=vt(r.currentStates,e)>=0,n=r.style.opacity,i=a?null:nR(r,["opacity"],e,{opacity:1});t=t||{};var o=t.style||{};return o.opacity==null&&(t=V({},t),o=V({opacity:a?n:i.opacity*.1},o),t.style=o),t}function Lv(r,e){var t=this.states[r];if(this.style){if(r==="emphasis")return iR(this,r,e,t);if(r==="blur")return sR(this,r,t);if(r==="select")return oR(this,r,t)}return t}function oi(r){r.stateProxy=Lv;var e=r.getTextContent(),t=r.getTextGuideLine();e&&(e.stateProxy=Lv),t&&(t.stateProxy=Lv)}function m0(r,e){!NT(r,e)&&!r.__highByOuter&&ba(r,LT)}function _0(r,e){!NT(r,e)&&!r.__highByOuter&&ba(r,PT)}function da(r,e){r.__highByOuter|=1<<(e||0),ba(r,LT)}function ga(r,e){!(r.__highByOuter&=~(1<<(e||0)))&&ba(r,PT)}function ET(r){ba(r,Lg)}function Pg(r){ba(r,RT)}function kT(r){ba(r,rR)}function OT(r){ba(r,aR)}function NT(r,e){return r.__highDownSilentOnTouch&&e.zrByTouch}function BT(r){var e=r.getModel(),t=[],a=[];e.eachComponent(function(n,i){var o=Mg(i),s=n==="series",l=s?r.getViewOfSeriesModel(i):r.getViewOfComponentModel(i);!s&&a.push(l),o.isBlured&&(l.group.traverse(function(u){RT(u)}),s&&t.push(i)),o.isBlured=!1}),C(a,function(n){n&&n.toggleBlurSeries&&n.toggleBlurSeries(t,!1,e)})}function $p(r,e,t,a){var n=a.getModel();t=t||"coordinateSystem";function i(u,f){for(var h=0;h0){var s={dataIndex:o,seriesIndex:t.seriesIndex};i!=null&&(s.dataType=i),e.push(s)}})}),e}function Ya(r,e,t){Wn(r,!0),ba(r,oi),qp(r,e,t)}function cR(r){Wn(r,!1)}function Wt(r,e,t,a){a?cR(r):Ya(r,e,t)}function qp(r,e,t){var a=nt(r);e!=null?(a.focus=e,a.blurScope=t):a.focus&&(a.focus=null)}var x0=["emphasis","blur","select"],pR={itemStyle:"getItemStyle",lineStyle:"getLineStyle",areaStyle:"getAreaStyle"};function he(r,e,t,a){t=t||"itemStyle";for(var n=0;n1&&(o*=Pv(p),s*=Pv(p));var d=(n===i?-1:1)*Pv((o*o*(s*s)-o*o*(c*c)-s*s*(v*v))/(o*o*(c*c)+s*s*(v*v)))||0,g=d*o*c/s,y=d*-s*v/o,m=(r+t)/2+ru(h)*g-eu(h)*y,_=(e+a)/2+eu(h)*g+ru(h)*y,S=A0([1,0],[(v-g)/o,(c-y)/s]),b=[(v-g)/o,(c-y)/s],x=[(-1*v-g)/o,(-1*c-y)/s],w=A0(b,x);if(jp(b,x)<=-1&&(w=Uo),jp(b,x)>=1&&(w=0),w<0){var T=Math.round(w/Uo*1e6)/1e6;w=Uo*2+T%2*Uo}f.addData(u,m,_,o,s,S,w,h,i)}var SR=/([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig,xR=/-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;function bR(r){var e=new qr;if(!r)return e;var t=0,a=0,n=t,i=a,o,s=qr.CMD,l=r.match(SR);if(!l)return e;for(var u=0;uP*P+R*R&&(T=D,A=M),{cx:T,cy:A,x0:-f,y0:-h,x1:T*(n/b-1),y1:A*(n/b-1)}}function IR(r){var e;if(z(r)){var t=r.length;if(!t)return r;t===1?e=[r[0],r[0],0,0]:t===2?e=[r[0],r[0],r[1],r[1]]:t===3?e=r.concat(r[2]):e=r}else e=[r,r,r,r];return e}function LR(r,e){var t,a=ds(e.r,0),n=ds(e.r0||0,0),i=a>0,o=n>0;if(!(!i&&!o)){if(i||(a=n,n=0),n>a){var s=a;a=n,n=s}var l=e.startAngle,u=e.endAngle;if(!(isNaN(l)||isNaN(u))){var f=e.cx,h=e.cy,v=!!e.clockwise,c=D0(u-l),p=c>Rv&&c%Rv;if(p>gr&&(c=p),!(a>gr))r.moveTo(f,h);else if(c>Rv-gr)r.moveTo(f+a*Ci(l),h+a*Sn(l)),r.arc(f,h,a,l,u,!v),n>gr&&(r.moveTo(f+n*Ci(u),h+n*Sn(u)),r.arc(f,h,n,u,l,v));else{var d=void 0,g=void 0,y=void 0,m=void 0,_=void 0,S=void 0,b=void 0,x=void 0,w=void 0,T=void 0,A=void 0,D=void 0,M=void 0,I=void 0,L=void 0,P=void 0,R=a*Ci(l),E=a*Sn(l),N=n*Ci(u),O=n*Sn(u),B=c>gr;if(B){var F=e.cornerRadius;F&&(t=IR(F),d=t[0],g=t[1],y=t[2],m=t[3]);var H=D0(a-n)/2;if(_=kr(H,y),S=kr(H,m),b=kr(H,d),x=kr(H,g),A=w=ds(_,S),D=T=ds(b,x),(w>gr||T>gr)&&(M=a*Ci(u),I=a*Sn(u),L=n*Ci(l),P=n*Sn(l),cgr){var dt=kr(y,A),lt=kr(m,A),q=au(L,P,R,E,a,dt,v),ut=au(M,I,N,O,a,lt,v);r.moveTo(f+q.cx+q.x0,h+q.cy+q.y0),A0&&r.arc(f+q.cx,h+q.cy,dt,pe(q.y0,q.x0),pe(q.y1,q.x1),!v),r.arc(f,h,a,pe(q.cy+q.y1,q.cx+q.x1),pe(ut.cy+ut.y1,ut.cx+ut.x1),!v),lt>0&&r.arc(f+ut.cx,h+ut.cy,lt,pe(ut.y1,ut.x1),pe(ut.y0,ut.x0),!v))}else r.moveTo(f+R,h+E),r.arc(f,h,a,l,u,!v);if(!(n>gr)||!B)r.lineTo(f+N,h+O);else if(D>gr){var dt=kr(d,D),lt=kr(g,D),q=au(N,O,M,I,n,-lt,v),ut=au(R,E,L,P,n,-dt,v);r.lineTo(f+q.cx+q.x0,h+q.cy+q.y0),D0&&r.arc(f+q.cx,h+q.cy,lt,pe(q.y0,q.x0),pe(q.y1,q.x1),!v),r.arc(f,h,n,pe(q.cy+q.y1,q.cx+q.x1),pe(ut.cy+ut.y1,ut.cx+ut.x1),v),dt>0&&r.arc(f+ut.cx,h+ut.cy,dt,pe(ut.y1,ut.x1),pe(ut.y0,ut.x0),!v))}else r.lineTo(f+N,h+O),r.arc(f,h,n,u,l,v)}r.closePath()}}}var PR=function(){function r(){this.cx=0,this.cy=0,this.r0=0,this.r=0,this.startAngle=0,this.endAngle=Math.PI*2,this.clockwise=!0,this.cornerRadius=0}return r}(),_e=function(r){k(e,r);function e(t){return r.call(this,t)||this}return e.prototype.getDefaultShape=function(){return new PR},e.prototype.buildPath=function(t,a){LR(t,a)},e.prototype.isZeroArea=function(){return this.shape.startAngle===this.shape.endAngle||this.shape.r===this.shape.r0},e}(yt);_e.prototype.type="sector";var RR=function(){function r(){this.cx=0,this.cy=0,this.r=0,this.r0=0}return r}(),_o=function(r){k(e,r);function e(t){return r.call(this,t)||this}return e.prototype.getDefaultShape=function(){return new RR},e.prototype.buildPath=function(t,a){var n=a.cx,i=a.cy,o=Math.PI*2;t.moveTo(n+a.r,i),t.arc(n,i,a.r,0,o,!1),t.moveTo(n+a.r0,i),t.arc(n,i,a.r0,0,o,!0)},e}(yt);_o.prototype.type="ring";function ER(r,e,t,a){var n=[],i=[],o=[],s=[],l,u,f,h;if(a){f=[1/0,1/0],h=[-1/0,-1/0];for(var v=0,c=r.length;v=2){if(a){var i=ER(n,a,t,e.smoothConstraint);r.moveTo(n[0][0],n[0][1]);for(var o=n.length,s=0;s<(t?o:o-1);s++){var l=i[s*2],u=i[s*2+1],f=n[(s+1)%o];r.bezierCurveTo(l[0],l[1],u[0],u[1],f[0],f[1])}}else{r.moveTo(n[0][0],n[0][1]);for(var s=1,h=n.length;sbn[1]){if(s=!1,i)return s;var f=Math.abs(bn[0]-xn[1]),h=Math.abs(xn[0]-bn[1]);Math.min(f,h)>n.len()&&(f0){var h=f.duration,v=f.delay,c=f.easing,p={duration:h,delay:v||0,easing:c,done:i,force:!!i||!!o,setToFinal:!u,scope:r,during:o};s?e.animateFrom(t,p):e.animateTo(t,p)}else e.stopAnimation(),!s&&e.attr(t),o&&o(1),i&&i()}function Dt(r,e,t,a,n,i){Og("update",r,e,t,a,n,i)}function Vt(r,e,t,a,n,i){Og("enter",r,e,t,a,n,i)}function Ji(r){if(!r.__zr)return!0;for(var e=0;eMath.abs(i[1])?i[0]>0?"right":"left":i[1]>0?"bottom":"top"}function L0(r){return!r.isGroup}function UR(r){return r.shape!=null}function Ml(r,e,t){if(!r||!e)return;function a(o){var s={};return o.traverse(function(l){L0(l)&&l.anid&&(s[l.anid]=l)}),s}function n(o){var s={x:o.x,y:o.y,rotation:o.rotation};return UR(o)&&(s.shape=V({},o.shape)),s}var i=a(r);e.traverse(function(o){if(L0(o)&&o.anid){var s=i[o.anid];if(s){var l=n(o);o.attr(n(s)),Dt(o,l,t,nt(o).dataIndex)}}})}function Vg(r,e){return G(r,function(t){var a=t[0];a=Af(a,e.x),a=Cf(a,e.x+e.width);var n=t[1];return n=Af(n,e.y),n=Cf(n,e.y+e.height),[a,n]})}function jT(r,e){var t=Af(r.x,e.x),a=Cf(r.x+r.width,e.x+e.width),n=Af(r.y,e.y),i=Cf(r.y+r.height,e.y+e.height);if(a>=t&&i>=n)return{x:t,y:n,width:a-t,height:i-n}}function wo(r,e,t){var a=V({rectHover:!0},e),n=a.style={strokeNoScale:!0};if(t=t||{x:-1,y:-1,width:2,height:2},r)return r.indexOf("image://")===0?(n.image=r.slice(8),Q(n,t),new oe(a)):Dl(r.replace("path://",""),a,t,"center")}function gs(r,e,t,a,n){for(var i=0,o=n[n.length-1];i1)return!1;var g=Ev(c,p,f,h)/v;return!(g<0||g>1)}function Ev(r,e,t,a){return r*a-t*e}function YR(r){return r<=1e-6&&r>=-1e-6}function To(r){var e=r.itemTooltipOption,t=r.componentModel,a=r.itemName,n=U(e)?{formatter:e}:e,i=t.mainType,o=t.componentIndex,s={componentType:i,name:a,$vars:["name"]};s[i+"Index"]=o;var l=r.formatterParamsExtra;l&&C(St(l),function(f){$(s,f)||(s[f]=l[f],s.$vars.push(f))});var u=nt(r.el);u.componentMainType=i,u.componentIndex=o,u.tooltipConfig={name:a,option:Q({content:a,encodeHTMLContent:!0,formatterParams:s},n)}}function P0(r,e){var t;r.isGroup&&(t=e(r)),t||r.traverse(e)}function nn(r,e){if(r)if(z(r))for(var t=0;t=0&&s.push(l)}),s}}function on(r,e){return st(st({},r,!0),e,!0)}const aE={time:{month:["January","February","March","April","May","June","July","August","September","October","November","December"],monthAbbr:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayOfWeek:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayOfWeekAbbr:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]},legend:{selector:{all:"All",inverse:"Inv"}},toolbox:{brush:{title:{rect:"Box Select",polygon:"Lasso Select",lineX:"Horizontally Select",lineY:"Vertically Select",keep:"Keep Selections",clear:"Clear Selections"}},dataView:{title:"Data View",lang:["Data View","Close","Refresh"]},dataZoom:{title:{zoom:"Zoom",back:"Zoom Reset"}},magicType:{title:{line:"Switch to Line Chart",bar:"Switch to Bar Chart",stack:"Stack",tiled:"Tile"}},restore:{title:"Restore"},saveAsImage:{title:"Save as Image",lang:["Right Click to Save Image"]}},series:{typeNames:{pie:"Pie chart",bar:"Bar chart",line:"Line chart",scatter:"Scatter plot",effectScatter:"Ripple scatter plot",radar:"Radar chart",tree:"Tree",treemap:"Treemap",boxplot:"Boxplot",candlestick:"Candlestick",k:"K line chart",heatmap:"Heat map",map:"Map",parallel:"Parallel coordinate map",lines:"Line graph",graph:"Relationship graph",sankey:"Sankey diagram",funnel:"Funnel chart",gauge:"Gauge",pictorialBar:"Pictorial bar",themeRiver:"Theme River Map",sunburst:"Sunburst",custom:"Custom chart",chart:"Chart"}},aria:{general:{withTitle:'This is a chart about "{title}"',withoutTitle:"This is a chart"},series:{single:{prefix:"",withName:" with type {seriesType} named {seriesName}.",withoutName:" with type {seriesType}."},multiple:{prefix:". It consists of {seriesCount} series count.",withName:" The {seriesId} series is a {seriesType} representing {seriesName}.",withoutName:" The {seriesId} series is a {seriesType}.",separator:{middle:"",end:""}}},data:{allData:"The data is as follows: ",partialData:"The first {displayCnt} items are: ",withName:"the data for {name} is {value}",withoutName:"{value}",separator:{middle:", ",end:". "}}}},nE={time:{month:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthAbbr:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],dayOfWeek:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayOfWeekAbbr:["日","一","二","三","四","五","六"]},legend:{selector:{all:"全选",inverse:"反选"}},toolbox:{brush:{title:{rect:"矩形选择",polygon:"圈选",lineX:"横向选择",lineY:"纵向选择",keep:"保持选择",clear:"清除选择"}},dataView:{title:"数据视图",lang:["数据视图","关闭","刷新"]},dataZoom:{title:{zoom:"区域缩放",back:"区域缩放还原"}},magicType:{title:{line:"切换为折线图",bar:"切换为柱状图",stack:"切换为堆叠",tiled:"切换为平铺"}},restore:{title:"还原"},saveAsImage:{title:"保存为图片",lang:["右键另存为图片"]}},series:{typeNames:{pie:"饼图",bar:"柱状图",line:"折线图",scatter:"散点图",effectScatter:"涟漪散点图",radar:"雷达图",tree:"树图",treemap:"矩形树图",boxplot:"箱型图",candlestick:"K线图",k:"K线图",heatmap:"热力图",map:"地图",parallel:"平行坐标图",lines:"线图",graph:"关系图",sankey:"桑基图",funnel:"漏斗图",gauge:"仪表盘图",pictorialBar:"象形柱图",themeRiver:"主题河流图",sunburst:"旭日图",custom:"自定义图表",chart:"图表"}},aria:{general:{withTitle:"这是一个关于“{title}”的图表。",withoutTitle:"这是一个图表,"},series:{single:{prefix:"",withName:"图表类型是{seriesType},表示{seriesName}。",withoutName:"图表类型是{seriesType}。"},multiple:{prefix:"它由{seriesCount}个图表系列组成。",withName:"第{seriesId}个系列是一个表示{seriesName}的{seriesType},",withoutName:"第{seriesId}个系列是一个{seriesType},",separator:{middle:";",end:"。"}}},data:{allData:"其数据是——",partialData:"其中,前{displayCnt}项是——",withName:"{name}的数据是{value}",withoutName:"{value}",separator:{middle:",",end:""}}}};var Mf="ZH",Gg="EN",to=Gg,tf={},Fg={},nA=_t.domSupported?function(){var r=(document.documentElement.lang||navigator.language||navigator.browserLanguage||to).toUpperCase();return r.indexOf(Mf)>-1?Mf:to}():to;function iA(r,e){r=r.toUpperCase(),Fg[r]=new Mt(e),tf[r]=e}function iE(r){if(U(r)){var e=tf[r.toUpperCase()]||{};return r===Mf||r===Gg?et(e):st(et(e),et(tf[to]),!1)}else return st(et(r),et(tf[to]),!1)}function td(r){return Fg[r]}function oE(){return Fg[to]}iA(Gg,aE);iA(Mf,nE);var Hg=1e3,Wg=Hg*60,Os=Wg*60,ir=Os*24,N0=ir*365,ys={year:"{yyyy}",month:"{MMM}",day:"{d}",hour:"{HH}:{mm}",minute:"{HH}:{mm}",second:"{HH}:{mm}:{ss}",millisecond:"{HH}:{mm}:{ss} {SSS}",none:"{yyyy}-{MM}-{dd} {HH}:{mm}:{ss} {SSS}"},ou="{yyyy}-{MM}-{dd}",B0={year:"{yyyy}",month:"{yyyy}-{MM}",day:ou,hour:ou+" "+ys.hour,minute:ou+" "+ys.minute,second:ou+" "+ys.second,millisecond:ys.none},Nv=["year","month","day","hour","minute","second","millisecond"],oA=["year","half-year","quarter","month","week","half-week","day","half-day","quarter-day","hour","minute","second","millisecond"];function Ce(r,e){return r+="","0000".substr(0,e-r.length)+r}function eo(r){switch(r){case"half-year":case"quarter":return"month";case"week":case"half-week":return"day";case"half-day":case"quarter-day":return"hour";default:return r}}function sE(r){return r===eo(r)}function lE(r){switch(r){case"year":case"month":return"day";case"millisecond":return"millisecond";default:return"second"}}function Il(r,e,t,a){var n=$e(r),i=n[Ug(t)](),o=n[ro(t)]()+1,s=Math.floor((o-1)/3)+1,l=n[Lh(t)](),u=n["get"+(t?"UTC":"")+"Day"](),f=n[Js(t)](),h=(f-1)%12+1,v=n[Ph(t)](),c=n[Rh(t)](),p=n[Eh(t)](),d=f>=12?"pm":"am",g=d.toUpperCase(),y=a instanceof Mt?a:td(a||nA)||oE(),m=y.getModel("time"),_=m.get("month"),S=m.get("monthAbbr"),b=m.get("dayOfWeek"),x=m.get("dayOfWeekAbbr");return(e||"").replace(/{a}/g,d+"").replace(/{A}/g,g+"").replace(/{yyyy}/g,i+"").replace(/{yy}/g,Ce(i%100+"",2)).replace(/{Q}/g,s+"").replace(/{MMMM}/g,_[o-1]).replace(/{MMM}/g,S[o-1]).replace(/{MM}/g,Ce(o,2)).replace(/{M}/g,o+"").replace(/{dd}/g,Ce(l,2)).replace(/{d}/g,l+"").replace(/{eeee}/g,b[u]).replace(/{ee}/g,x[u]).replace(/{e}/g,u+"").replace(/{HH}/g,Ce(f,2)).replace(/{H}/g,f+"").replace(/{hh}/g,Ce(h+"",2)).replace(/{h}/g,h+"").replace(/{mm}/g,Ce(v,2)).replace(/{m}/g,v+"").replace(/{ss}/g,Ce(c,2)).replace(/{s}/g,c+"").replace(/{SSS}/g,Ce(p,3)).replace(/{S}/g,p+"")}function uE(r,e,t,a,n){var i=null;if(U(t))i=t;else if(K(t))i=t(r.value,e,{level:r.level});else{var o=V({},ys);if(r.level>0)for(var s=0;s=0;--s)if(l[u]){i=l[u];break}i=i||o.none}if(z(i)){var h=r.level==null?0:r.level>=0?r.level:i.length+r.level;h=Math.min(h,i.length-1),i=i[h]}}return Il(new Date(r.value),i,n,a)}function sA(r,e){var t=$e(r),a=t[ro(e)]()+1,n=t[Lh(e)](),i=t[Js(e)](),o=t[Ph(e)](),s=t[Rh(e)](),l=t[Eh(e)](),u=l===0,f=u&&s===0,h=f&&o===0,v=h&&i===0,c=v&&n===1,p=c&&a===1;return p?"year":c?"month":v?"day":h?"hour":f?"minute":u?"second":"millisecond"}function V0(r,e,t){var a=Ct(r)?$e(r):r;switch(e=e||sA(r,t),e){case"year":return a[Ug(t)]();case"half-year":return a[ro(t)]()>=6?1:0;case"quarter":return Math.floor((a[ro(t)]()+1)/4);case"month":return a[ro(t)]();case"day":return a[Lh(t)]();case"half-day":return a[Js(t)]()/24;case"hour":return a[Js(t)]();case"minute":return a[Ph(t)]();case"second":return a[Rh(t)]();case"millisecond":return a[Eh(t)]()}}function Ug(r){return r?"getUTCFullYear":"getFullYear"}function ro(r){return r?"getUTCMonth":"getMonth"}function Lh(r){return r?"getUTCDate":"getDate"}function Js(r){return r?"getUTCHours":"getHours"}function Ph(r){return r?"getUTCMinutes":"getMinutes"}function Rh(r){return r?"getUTCSeconds":"getSeconds"}function Eh(r){return r?"getUTCMilliseconds":"getMilliseconds"}function fE(r){return r?"setUTCFullYear":"setFullYear"}function lA(r){return r?"setUTCMonth":"setMonth"}function uA(r){return r?"setUTCDate":"setDate"}function fA(r){return r?"setUTCHours":"setHours"}function hA(r){return r?"setUTCMinutes":"setMinutes"}function vA(r){return r?"setUTCSeconds":"setSeconds"}function cA(r){return r?"setUTCMilliseconds":"setMilliseconds"}function hE(r,e,t,a,n,i,o,s){var l=new bt({style:{text:r,font:e,align:t,verticalAlign:a,padding:n,rich:i,overflow:o?"truncate":null,lineHeight:s}});return l.getBoundingRect()}function Yg(r){if(!bg(r))return U(r)?r:"-";var e=(r+"").split(".");return e[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(e.length>1?"."+e[1]:"")}function Xg(r,e){return r=(r||"").toLowerCase().replace(/-(.)/g,function(t,a){return a.toUpperCase()}),e&&r&&(r=r.charAt(0).toUpperCase()+r.slice(1)),r}var pi=ch;function ed(r,e,t){var a="{yyyy}-{MM}-{dd} {HH}:{mm}:{ss}";function n(f){return f&&or(f)?f:"-"}function i(f){return!!(f!=null&&!isNaN(f)&&isFinite(f))}var o=e==="time",s=r instanceof Date;if(o||s){var l=o?$e(r):r;if(isNaN(+l)){if(s)return"-"}else return Il(l,a,t)}if(e==="ordinal")return hf(r)?n(r):Ct(r)&&i(r)?r+"":"-";var u=Zr(r);return i(u)?Yg(u):hf(r)?n(r):typeof r=="boolean"?r+"":"-"}var z0=["a","b","c","d","e","f","g"],Bv=function(r,e){return"{"+r+(e??"")+"}"};function $g(r,e,t){z(e)||(e=[e]);var a=e.length;if(!a)return"";for(var n=e[0].$vars||[],i=0;i':' ';var o=t.markerId||"markerX";return{renderMode:i,content:"{"+o+"|} ",style:n==="subItem"?{width:4,height:4,borderRadius:2,backgroundColor:a}:{width:10,height:10,borderRadius:5,backgroundColor:a}}}function cE(r,e,t){(r==="week"||r==="month"||r==="quarter"||r==="half-year"||r==="year")&&(r=`MM-dd
+yyyy`);var a=$e(e),n=t?"getUTC":"get",i=a[n+"FullYear"](),o=a[n+"Month"]()+1,s=a[n+"Date"](),l=a[n+"Hours"](),u=a[n+"Minutes"](),f=a[n+"Seconds"](),h=a[n+"Milliseconds"]();return r=r.replace("MM",Ce(o,2)).replace("M",o).replace("yyyy",i).replace("yy",Ce(i%100+"",2)).replace("dd",Ce(s,2)).replace("d",s).replace("hh",Ce(l,2)).replace("h",l).replace("mm",Ce(u,2)).replace("m",u).replace("ss",Ce(f,2)).replace("s",f).replace("SSS",Ce(h,3)),r}function pE(r){return r&&r.charAt(0).toUpperCase()+r.substr(1)}function si(r,e){return e=e||"transparent",U(r)?r:tt(r)&&r.colorStops&&(r.colorStops[0]||{}).color||e}function If(r,e){if(e==="_blank"||e==="blank"){var t=window.open();t.opener=null,t.location.href=r}else window.open(r,e)}var ef=C,dA=["left","right","top","bottom","width","height"],Un=[["width","left","right"],["height","top","bottom"]];function Zg(r,e,t,a,n){var i=0,o=0;a==null&&(a=1/0),n==null&&(n=1/0);var s=0;e.eachChild(function(l,u){var f=l.getBoundingRect(),h=e.childAt(u+1),v=h&&h.getBoundingRect(),c,p;if(r==="horizontal"){var d=f.width+(v?-v.x+f.x:0);c=i+d,c>a||l.newline?(i=0,c=d,o+=s+t,s=f.height):s=Math.max(s,f.height)}else{var g=f.height+(v?-v.y+f.y:0);p=o+g,p>n||l.newline?(i+=s+t,o=0,p=g,s=f.width):s=Math.max(s,f.width)}l.newline||(l.x=i,l.y=o,l.markRedraw(),r==="horizontal"?i=c+t:o=p+t)})}var Qn=Zg;it(Zg,"vertical");it(Zg,"horizontal");function dE(r,e,t){var a=e.width,n=e.height,i=W(r.left,a),o=W(r.top,n),s=W(r.right,a),l=W(r.bottom,n);return(isNaN(i)||isNaN(parseFloat(r.left)))&&(i=0),(isNaN(s)||isNaN(parseFloat(r.right)))&&(s=a),(isNaN(o)||isNaN(parseFloat(r.top)))&&(o=0),(isNaN(l)||isNaN(parseFloat(r.bottom)))&&(l=n),t=pi(t||0),{width:Math.max(s-i-t[1]-t[3],0),height:Math.max(l-o-t[0]-t[2],0)}}function jt(r,e,t){t=pi(t||0);var a=e.width,n=e.height,i=W(r.left,a),o=W(r.top,n),s=W(r.right,a),l=W(r.bottom,n),u=W(r.width,a),f=W(r.height,n),h=t[2]+t[0],v=t[1]+t[3],c=r.aspect;switch(isNaN(u)&&(u=a-s-v-i),isNaN(f)&&(f=n-l-h-o),c!=null&&(isNaN(u)&&isNaN(f)&&(c>a/n?u=a*.8:f=n*.8),isNaN(u)&&(u=c*f),isNaN(f)&&(f=u/c)),isNaN(i)&&(i=a-s-u-v),isNaN(o)&&(o=n-l-f-h),r.left||r.right){case"center":i=a/2-u/2-t[3];break;case"right":i=a-u-v;break}switch(r.top||r.bottom){case"middle":case"center":o=n/2-f/2-t[0];break;case"bottom":o=n-f-h;break}i=i||0,o=o||0,isNaN(u)&&(u=a-v-i-(s||0)),isNaN(f)&&(f=n-h-o-(l||0));var p=new ht(i+t[3],o+t[0],u,f);return p.margin=t,p}function kh(r,e,t,a,n,i){var o=!n||!n.hv||n.hv[0],s=!n||!n.hv||n.hv[1],l=n&&n.boundingMode||"all";if(i=i||r,i.x=r.x,i.y=r.y,!o&&!s)return!1;var u;if(l==="raw")u=r.type==="group"?new ht(0,0,+e.width||0,+e.height||0):r.getBoundingRect();else if(u=r.getBoundingRect(),r.needLocalTransform()){var f=r.getLocalTransform();u=u.clone(),u.applyTransform(f)}var h=jt(Q({width:u.width,height:u.height},e),t,a),v=o?h.x-u.x:0,c=s?h.y-u.y:0;return l==="raw"?(i.x=v,i.y=c):(i.x+=v,i.y+=c),i===r&&r.markRedraw(),!0}function gE(r,e){return r[Un[e][0]]!=null||r[Un[e][1]]!=null&&r[Un[e][2]]!=null}function tl(r){var e=r.layoutMode||r.constructor.layoutMode;return tt(e)?e:e?{type:e}:null}function Ja(r,e,t){var a=t&&t.ignoreSize;!z(a)&&(a=[a,a]);var n=o(Un[0],0),i=o(Un[1],1);u(Un[0],r,n),u(Un[1],r,i);function o(f,h){var v={},c=0,p={},d=0,g=2;if(ef(f,function(_){p[_]=r[_]}),ef(f,function(_){s(e,_)&&(v[_]=p[_]=e[_]),l(v,_)&&c++,l(p,_)&&d++}),a[h])return l(e,f[1])?p[f[2]]=null:l(e,f[2])&&(p[f[1]]=null),p;if(d===g||!c)return p;if(c>=g)return v;for(var y=0;y=0;l--)s=st(s,n[l],!0);a.defaultOption=s}return a.defaultOption},e.prototype.getReferringComponents=function(t,a){var n=t+"Index",i=t+"Id";return wl(this.ecModel,t,{index:this.get(n,!0),id:this.get(i,!0)},a)},e.prototype.getBoxLayoutParams=function(){var t=this;return{left:t.get("left"),top:t.get("top"),right:t.get("right"),bottom:t.get("bottom"),width:t.get("width"),height:t.get("height")}},e.prototype.getZLevelKey=function(){return""},e.prototype.setZLevel=function(t){this.option.zlevel=t},e.protoInitialize=function(){var t=e.prototype;t.type="component",t.id="",t.name="",t.mainType="",t.subType="",t.componentIndex=0}(),e}(Mt);mT(mt,Mt);Sh(mt);eE(mt);rE(mt,mE);function mE(r){var e=[];return C(mt.getClassesByMainType(r),function(t){e=e.concat(t.dependencies||t.prototype.dependencies||[])}),e=G(e,function(t){return Fr(t).main}),r!=="dataset"&&vt(e,"dataset")<=0&&e.unshift("dataset"),e}var yA="";typeof navigator<"u"&&(yA=navigator.platform||"");var Di="rgba(0, 0, 0, 0.2)";const _E={darkMode:"auto",colorBy:"series",color:["#5470c6","#91cc75","#fac858","#ee6666","#73c0de","#3ba272","#fc8452","#9a60b4","#ea7ccc"],gradientColor:["#f6efa6","#d88273","#bf444c"],aria:{decal:{decals:[{color:Di,dashArrayX:[1,0],dashArrayY:[2,5],symbolSize:1,rotation:Math.PI/6},{color:Di,symbol:"circle",dashArrayX:[[8,8],[0,8,8,0]],dashArrayY:[6,0],symbolSize:.8},{color:Di,dashArrayX:[1,0],dashArrayY:[4,3],rotation:-Math.PI/4},{color:Di,dashArrayX:[[6,6],[0,6,6,0]],dashArrayY:[6,0]},{color:Di,dashArrayX:[[1,0],[1,6]],dashArrayY:[1,0,6,0],rotation:Math.PI/4},{color:Di,symbol:"triangle",dashArrayX:[[9,9],[0,9,9,0]],dashArrayY:[7,2],symbolSize:.75}]}},textStyle:{fontFamily:yA.match(/^Win/)?"Microsoft YaHei":"sans-serif",fontSize:12,fontStyle:"normal",fontWeight:"normal"},blendMode:null,stateAnimation:{duration:300,easing:"cubicOut"},animation:"auto",animationDuration:1e3,animationDurationUpdate:500,animationEasing:"cubicInOut",animationEasingUpdate:"cubicInOut",animationThreshold:2e3,progressiveThreshold:3e3,progressive:400,hoverLayerThreshold:3e3,useUTC:!1};var mA=Z(["tooltip","label","itemName","itemId","itemGroupId","itemChildGroupId","seriesName"]),vr="original",xe="arrayRows",cr="objectRows",jr="keyedColumns",$a="typedArray",_A="unknown",Xr="column",Mo="row",ue={Must:1,Might:2,Not:3},SA=Tt();function SE(r){SA(r).datasetMap=Z()}function xA(r,e,t){var a={},n=Kg(e);if(!n||!r)return a;var i=[],o=[],s=e.ecModel,l=SA(s).datasetMap,u=n.uid+"_"+t.seriesLayoutBy,f,h;r=r.slice(),C(r,function(d,g){var y=tt(d)?d:r[g]={name:d};y.type==="ordinal"&&f==null&&(f=g,h=p(y)),a[y.name]=[]});var v=l.get(u)||l.set(u,{categoryWayDim:h,valueWayDim:0});C(r,function(d,g){var y=d.name,m=p(d);if(f==null){var _=v.valueWayDim;c(a[y],_,m),c(o,_,m),v.valueWayDim+=m}else if(f===g)c(a[y],0,m),c(i,0,m);else{var _=v.categoryWayDim;c(a[y],_,m),c(o,_,m),v.categoryWayDim+=m}});function c(d,g,y){for(var m=0;me)return r[a];return r[t-1]}function TA(r,e,t,a,n,i,o){i=i||r;var s=e(i),l=s.paletteIdx||0,u=s.paletteNameMap=s.paletteNameMap||{};if(u.hasOwnProperty(n))return u[n];var f=o==null||!a?t:AE(a,o);if(f=f||t,!(!f||!f.length)){var h=f[l];return n&&(u[n]=h),s.paletteIdx=(l+1)%f.length,h}}function CE(r,e){e(r).paletteIdx=0,e(r).paletteNameMap={}}var su,Yo,F0,H0="\0_ec_inner",DE=1,Qg=function(r){k(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.init=function(t,a,n,i,o,s){i=i||{},this.option=null,this._theme=new Mt(i),this._locale=new Mt(o),this._optionManager=s},e.prototype.setOption=function(t,a,n){var i=Y0(a);this._optionManager.setOption(t,n,i),this._resetOption(null,i)},e.prototype.resetOption=function(t,a){return this._resetOption(t,Y0(a))},e.prototype._resetOption=function(t,a){var n=!1,i=this._optionManager;if(!t||t==="recreate"){var o=i.mountOption(t==="recreate");!this.option||t==="recreate"?F0(this,o):(this.restoreData(),this._mergeOption(o,a)),n=!0}if((t==="timeline"||t==="media")&&this.restoreData(),!t||t==="recreate"||t==="timeline"){var s=i.getTimelineOption(this);s&&(n=!0,this._mergeOption(s,a))}if(!t||t==="recreate"||t==="media"){var l=i.getMediaOption(this);l.length&&C(l,function(u){n=!0,this._mergeOption(u,a)},this)}return n},e.prototype.mergeOption=function(t){this._mergeOption(t,null)},e.prototype._mergeOption=function(t,a){var n=this.option,i=this._componentsMap,o=this._componentsCount,s=[],l=Z(),u=a&&a.replaceMergeMainTypeMap;SE(this),C(t,function(h,v){h!=null&&(mt.hasClass(v)?v&&(s.push(v),l.set(v,!0)):n[v]=n[v]==null?et(h):st(n[v],h,!0))}),u&&u.each(function(h,v){mt.hasClass(v)&&!l.get(v)&&(s.push(v),l.set(v,!0))}),mt.topologicalTravel(s,mt.getAllClassMainTypes(),f,this);function f(h){var v=wE(this,h,Et(t[h])),c=i.get(h),p=c?u&&u.get(h)?"replaceMerge":"normalMerge":"replaceAll",d=cT(c,v,p);eP(d,h,mt),n[h]=null,i.set(h,null),o.set(h,0);var g=[],y=[],m=0,_;C(d,function(S,b){var x=S.existing,w=S.newOption;if(!w)x&&(x.mergeOption({},this),x.optionUpdated({},!1));else{var T=h==="series",A=mt.getClass(h,S.keyInfo.subType,!T);if(!A)return;if(h==="tooltip"){if(_)return;_=!0}if(x&&x.constructor===A)x.name=S.keyInfo.name,x.mergeOption(w,this),x.optionUpdated(w,!1);else{var D=V({componentIndex:b},S.keyInfo);x=new A(w,this,this,D),V(x,D),S.brandNew&&(x.__requireNewView=!0),x.init(w,this,this),x.optionUpdated(null,!0)}}x?(g.push(x.option),y.push(x),m++):(g.push(void 0),y.push(void 0))},this),n[h]=g,i.set(h,y),o.set(h,m),h==="series"&&su(this)}this._seriesIndices||su(this)},e.prototype.getOption=function(){var t=et(this.option);return C(t,function(a,n){if(mt.hasClass(n)){for(var i=Et(a),o=i.length,s=!1,l=o-1;l>=0;l--)i[l]&&!qs(i[l])?s=!0:(i[l]=null,!s&&o--);i.length=o,t[n]=i}}),delete t[H0],t},e.prototype.getTheme=function(){return this._theme},e.prototype.getLocaleModel=function(){return this._locale},e.prototype.setUpdatePayload=function(t){this._payload=t},e.prototype.getUpdatePayload=function(){return this._payload},e.prototype.getComponent=function(t,a){var n=this._componentsMap.get(t);if(n){var i=n[a||0];if(i)return i;if(a==null){for(var o=0;o=e:t==="max"?r<=e:r===e}function NE(r,e){return r.join(",")===e.join(",")}var pr=C,el=tt,X0=["areaStyle","lineStyle","nodeStyle","linkStyle","chordStyle","label","labelLine"];function zv(r){var e=r&&r.itemStyle;if(e)for(var t=0,a=X0.length;t=0;g--){var y=r[g];if(s||(p=y.data.rawIndexOf(y.stackedByDimension,c)),p>=0){var m=y.data.getByRawIndex(y.stackResultDimension,p);if(l==="all"||l==="positive"&&m>0||l==="negative"&&m<0||l==="samesign"&&v>=0&&m>0||l==="samesign"&&v<=0&&m<0){v=Y2(v,m),d=m;break}}}return a[0]=v,a[1]=d,a})})}var Oh=function(){function r(e){this.data=e.data||(e.sourceFormat===jr?{}:[]),this.sourceFormat=e.sourceFormat||_A,this.seriesLayoutBy=e.seriesLayoutBy||Xr,this.startIndex=e.startIndex||0,this.dimensionsDetectedCount=e.dimensionsDetectedCount,this.metaRawOption=e.metaRawOption;var t=this.dimensionsDefine=e.dimensionsDefine;if(t)for(var a=0;ad&&(d=_)}c[0]=p,c[1]=d}},n=function(){return this._data?this._data.length/this._dimSize:0};J0=(e={},e[xe+"_"+Xr]={pure:!0,appendData:i},e[xe+"_"+Mo]={pure:!0,appendData:function(){throw new Error('Do not support appendData when set seriesLayoutBy: "row".')}},e[cr]={pure:!0,appendData:i},e[jr]={pure:!0,appendData:function(o){var s=this._data;C(o,function(l,u){for(var f=s[u]||(s[u]=[]),h=0;h<(l||[]).length;h++)f.push(l[h])})}},e[vr]={appendData:i},e[$a]={persistent:!1,pure:!0,appendData:function(o){this._data=o},clean:function(){this._offset+=this.count(),this._data=null}},e);function i(o){for(var s=0;s=0&&(d=o.interpolatedValue[g])}return d!=null?d+"":""})}},r.prototype.getRawValue=function(e,t){return lo(this.getData(t),e)},r.prototype.formatTooltip=function(e,t,a){},r}();function a_(r){var e,t;return tt(r)?r.type&&(t=r):e=r,{text:e,frag:t}}function Ns(r){return new JE(r)}var JE=function(){function r(e){e=e||{},this._reset=e.reset,this._plan=e.plan,this._count=e.count,this._onDirty=e.onDirty,this._dirty=!0}return r.prototype.perform=function(e){var t=this._upstream,a=e&&e.skip;if(this._dirty&&t){var n=this.context;n.data=n.outputData=t.context.outputData}this.__pipeline&&(this.__pipeline.currentTask=this);var i;this._plan&&!a&&(i=this._plan(this.context));var o=f(this._modBy),s=this._modDataCount||0,l=f(e&&e.modBy),u=e&&e.modDataCount||0;(o!==l||s!==u)&&(i="reset");function f(m){return!(m>=1)&&(m=1),m}var h;(this._dirty||i==="reset")&&(this._dirty=!1,h=this._doReset(a)),this._modBy=l,this._modDataCount=u;var v=e&&e.step;if(t?this._dueEnd=t._outputDueEnd:this._dueEnd=this._count?this._count(this.context):1/0,this._progress){var c=this._dueIndex,p=Math.min(v!=null?this._dueIndex+v:1/0,this._dueEnd);if(!a&&(h||c1&&a>0?s:o}};return i;function o(){return e=r?null:le},gte:function(r,e){return r>=e}},ek=function(){function r(e,t){if(!Ct(t)){var a="";It(a)}this._opFn=OA[e],this._rvalFloat=Zr(t)}return r.prototype.evaluate=function(e){return Ct(e)?this._opFn(e,this._rvalFloat):this._opFn(Zr(e),this._rvalFloat)},r}(),NA=function(){function r(e,t){var a=e==="desc";this._resultLT=a?1:-1,t==null&&(t=a?"min":"max"),this._incomparable=t==="min"?-1/0:1/0}return r.prototype.evaluate=function(e,t){var a=Ct(e)?e:Zr(e),n=Ct(t)?t:Zr(t),i=isNaN(a),o=isNaN(n);if(i&&(a=this._incomparable),o&&(n=this._incomparable),i&&o){var s=U(e),l=U(t);s&&(a=l?e:0),l&&(n=s?t:0)}return an?-this._resultLT:0},r}(),rk=function(){function r(e,t){this._rval=t,this._isEQ=e,this._rvalTypeof=typeof t,this._rvalFloat=Zr(t)}return r.prototype.evaluate=function(e){var t=e===this._rval;if(!t){var a=typeof e;a!==this._rvalTypeof&&(a==="number"||this._rvalTypeof==="number")&&(t=Zr(e)===this._rvalFloat)}return this._isEQ?t:!t},r}();function ak(r,e){return r==="eq"||r==="ne"?new rk(r==="eq",e):$(OA,r)?new ek(r,e):null}var nk=function(){function r(){}return r.prototype.getRawData=function(){throw new Error("not supported")},r.prototype.getRawDataItem=function(e){throw new Error("not supported")},r.prototype.cloneRawData=function(){},r.prototype.getDimensionInfo=function(e){},r.prototype.cloneAllDimensionInfo=function(){},r.prototype.count=function(){},r.prototype.retrieveValue=function(e,t){},r.prototype.retrieveValueFromItem=function(e,t){},r.prototype.convertValue=function(e,t){return Za(e,t)},r}();function ik(r,e){var t=new nk,a=r.data,n=t.sourceFormat=r.sourceFormat,i=r.startIndex,o="";r.seriesLayoutBy!==Xr&&It(o);var s=[],l={},u=r.dimensionsDefine;if(u)C(u,function(d,g){var y=d.name,m={index:g,name:y,displayName:d.displayName};if(s.push(m),y!=null){var _="";$(l,y)&&It(_),l[y]=m}});else for(var f=0;f65535?ck:pk}function Mi(){return[1/0,-1/0]}function dk(r){var e=r.constructor;return e===Array?r.slice():new e(r)}function o_(r,e,t,a,n){var i=zA[t||"float"];if(n){var o=r[e],s=o&&o.length;if(s!==a){for(var l=new i(a),u=0;ug[1]&&(g[1]=d)}return this._rawCount=this._count=l,{start:s,end:l}},r.prototype._initDataFromProvider=function(e,t,a){for(var n=this._provider,i=this._chunks,o=this._dimensions,s=o.length,l=this._rawExtent,u=G(o,function(m){return m.property}),f=0;fy[1]&&(y[1]=g)}}!n.persistent&&n.clean&&n.clean(),this._rawCount=this._count=t,this._extent=[]},r.prototype.count=function(){return this._count},r.prototype.get=function(e,t){if(!(t>=0&&t=0&&t=this._rawCount||e<0)return-1;if(!this._indices)return e;var t=this._indices,a=t[e];if(a!=null&&ae)i=o-1;else return o}return-1},r.prototype.indicesOfNearest=function(e,t,a){var n=this._chunks,i=n[e],o=[];if(!i)return o;a==null&&(a=1/0);for(var s=1/0,l=-1,u=0,f=0,h=this.count();f=0&&l<0)&&(s=p,l=c,u=0),c===l&&(o[u++]=f))}return o.length=u,o},r.prototype.getIndices=function(){var e,t=this._indices;if(t){var a=t.constructor,n=this._count;if(a===Array){e=new a(n);for(var i=0;i=h&&m<=v||isNaN(m))&&(l[u++]=d),d++}p=!0}else if(i===2){for(var g=c[n[0]],_=c[n[1]],S=e[n[1]][0],b=e[n[1]][1],y=0;y=h&&m<=v||isNaN(m))&&(x>=S&&x<=b||isNaN(x))&&(l[u++]=d),d++}p=!0}}if(!p)if(i===1)for(var y=0;y=h&&m<=v||isNaN(m))&&(l[u++]=w)}else for(var y=0;ye[D][1])&&(T=!1)}T&&(l[u++]=t.getRawIndex(y))}return uy[1]&&(y[1]=g)}}}},r.prototype.lttbDownSample=function(e,t){var a=this.clone([e],!0),n=a._chunks,i=n[e],o=this.count(),s=0,l=Math.floor(1/t),u=this.getRawIndex(0),f,h,v,c=new($o(this._rawCount))(Math.min((Math.ceil(o/l)+2)*2,o));c[s++]=u;for(var p=1;pf&&(f=h,v=S)}M>0&&Mf-p&&(l=f-p,s.length=l);for(var d=0;dh[1]&&(h[1]=y),v[c++]=m}return i._count=c,i._indices=v,i._updateGetRawIdx(),i},r.prototype.each=function(e,t){if(this._count)for(var a=e.length,n=this._chunks,i=0,o=this.count();il&&(l=h)}return o=[s,l],this._extent[e]=o,o},r.prototype.getRawDataItem=function(e){var t=this.getRawIndex(e);if(this._provider.persistent)return this._provider.getItem(t);for(var a=[],n=this._chunks,i=0;i=0?this._indices[e]:-1},r.prototype._updateGetRawIdx=function(){this.getRawIndex=this._indices?this._getRawIdx:this._getRawIdxIdentity},r.internalField=function(){function e(t,a,n,i){return Za(t[i],this._dimensions[i])}Hv={arrayRows:e,objectRows:function(t,a,n,i){return Za(t[a],this._dimensions[i])},keyedColumns:e,original:function(t,a,n,i){var o=t&&(t.value==null?t:t.value);return Za(o instanceof Array?o[i]:o,this._dimensions[i])},typedArray:function(t,a,n,i){return t[i]}}}(),r}(),GA=function(){function r(e){this._sourceList=[],this._storeList=[],this._upstreamSignList=[],this._versionSignBase=0,this._dirty=!0,this._sourceHost=e}return r.prototype.dirty=function(){this._setLocalSource([],[]),this._storeList=[],this._dirty=!0},r.prototype._setLocalSource=function(e,t){this._sourceList=e,this._upstreamSignList=t,this._versionSignBase++,this._versionSignBase>9e10&&(this._versionSignBase=0)},r.prototype._getVersionSign=function(){return this._sourceHost.uid+"_"+this._versionSignBase},r.prototype.prepareSource=function(){this._isDirty()&&(this._createSource(),this._dirty=!1)},r.prototype._createSource=function(){this._setLocalSource([],[]);var e=this._sourceHost,t=this._getUpstreamSourceManagers(),a=!!t.length,n,i;if(lu(e)){var o=e,s=void 0,l=void 0,u=void 0;if(a){var f=t[0];f.prepareSource(),u=f.getSource(),s=u.data,l=u.sourceFormat,i=[f._getVersionSign()]}else s=o.get("data",!0),l=Re(s)?$a:vr,i=[];var h=this._getSourceMetaRawOption()||{},v=u&&u.metaRawOption||{},c=ot(h.seriesLayoutBy,v.seriesLayoutBy)||null,p=ot(h.sourceHeader,v.sourceHeader),d=ot(h.dimensions,v.dimensions),g=c!==v.seriesLayoutBy||!!p!=!!v.sourceHeader||d;n=g?[nd(s,{seriesLayoutBy:c,sourceHeader:p,dimensions:d},l)]:[]}else{var y=e;if(a){var m=this._applyTransform(t);n=m.sourceList,i=m.upstreamSignList}else{var _=y.get("source",!0);n=[nd(_,this._getSourceMetaRawOption(),null)],i=[]}}this._setLocalSource(n,i)},r.prototype._applyTransform=function(e){var t=this._sourceHost,a=t.get("transform",!0),n=t.get("fromTransformResult",!0);if(n!=null){var i="";e.length!==1&&l_(i)}var o,s=[],l=[];return C(e,function(u){u.prepareSource();var f=u.getSource(n||0),h="";n!=null&&!f&&l_(h),s.push(f),l.push(u._getVersionSign())}),a?o=hk(a,s,{datasetIndex:t.componentIndex}):n!=null&&(o=[XE(s[0])]),{sourceList:o,upstreamSignList:l}},r.prototype._isDirty=function(){if(this._dirty)return!0;for(var e=this._getUpstreamSourceManagers(),t=0;t1||t>0&&!r.noHeader;return C(r.blocks,function(n){var i=UA(n);i>=e&&(e=i+ +(a&&(!i||od(n)&&!n.noHeader)))}),e}return 0}function mk(r,e,t,a){var n=e.noHeader,i=Sk(UA(e)),o=[],s=e.blocks||[];me(!s||z(s)),s=s||[];var l=r.orderMode;if(e.sortBlocks&&l){s=s.slice();var u={valueAsc:"asc",valueDesc:"desc"};if($(u,l)){var f=new NA(u[l],null);s.sort(function(p,d){return f.evaluate(p.sortParam,d.sortParam)})}else l==="seriesDesc"&&s.reverse()}C(s,function(p,d){var g=e.valueFormatter,y=WA(p)(g?V(V({},r),{valueFormatter:g}):r,p,d>0?i.html:0,a);y!=null&&o.push(y)});var h=r.renderMode==="richText"?o.join(i.richText):sd(o.join(""),n?t:i.html);if(n)return h;var v=ed(e.header,"ordinal",r.useUTC),c=HA(a,r.renderMode).nameStyle;return r.renderMode==="richText"?YA(r,v,c)+i.richText+h:sd(''+Me(v)+"
"+h,t)}function _k(r,e,t,a){var n=r.renderMode,i=e.noName,o=e.noValue,s=!e.markerType,l=e.name,u=r.useUTC,f=e.valueFormatter||r.valueFormatter||function(S){return S=z(S)?S:[S],G(S,function(b,x){return ed(b,z(c)?c[x]:c,u)})};if(!(i&&o)){var h=s?"":r.markupStyleCreator.makeTooltipMarker(e.markerType,e.markerColor||"#333",n),v=i?"":ed(l,"ordinal",u),c=e.valueType,p=o?[]:f(e.value,e.dataIndex),d=!s||!i,g=!s&&i,y=HA(a,n),m=y.nameStyle,_=y.valueStyle;return n==="richText"?(s?"":h)+(i?"":YA(r,v,m))+(o?"":wk(r,p,d,g,_)):sd((s?"":h)+(i?"":xk(v,!s,m))+(o?"":bk(p,d,g,_)),t)}}function u_(r,e,t,a,n,i){if(r){var o=WA(r),s={useUTC:n,renderMode:t,orderMode:a,markupStyleCreator:e,valueFormatter:r.valueFormatter};return o(s,r,0,i)}}function Sk(r){return{html:gk[r],richText:yk[r]}}function sd(r,e){var t='
',a="margin: "+e+"px 0 0";return''+r+t+"
"}function xk(r,e,t){var a=e?"margin-left:2px":"";return''+Me(r)+" "}function bk(r,e,t,a){var n=t?"10px":"20px",i=e?"float:right;margin-left:"+n:"";return r=z(r)?r:[r],''+G(r,function(o){return Me(o)}).join(" ")+" "}function YA(r,e,t){return r.markupStyleCreator.wrapRichTextStyle(e,t)}function wk(r,e,t,a,n){var i=[n],o=a?10:20;return t&&i.push({padding:[0,0,0,o],align:"right"}),r.markupStyleCreator.wrapRichTextStyle(z(e)?e.join(" "):e,i)}function XA(r,e){var t=r.getData().getItemVisual(e,"style"),a=t[r.visualDrawType];return si(a)}function $A(r,e){var t=r.get("padding");return t??(e==="richText"?[8,10]:10)}var Wv=function(){function r(){this.richTextStyles={},this._nextStyleNameId=uT()}return r.prototype._generateStyleName=function(){return"__EC_aUTo_"+this._nextStyleNameId++},r.prototype.makeTooltipMarker=function(e,t,a){var n=a==="richText"?this._generateStyleName():null,i=pA({color:t,type:e,renderMode:a,markerId:n});return U(i)?i:(this.richTextStyles[n]=i.style,i.content)},r.prototype.wrapRichTextStyle=function(e,t){var a={};z(t)?C(t,function(i){return V(a,i)}):V(a,t);var n=this._generateStyleName();return this.richTextStyles[n]=a,"{"+n+"|"+e+"}"},r}();function ZA(r){var e=r.series,t=r.dataIndex,a=r.multipleSeries,n=e.getData(),i=n.mapDimensionsAll("defaultedTooltip"),o=i.length,s=e.getRawValue(t),l=z(s),u=XA(e,t),f,h,v,c;if(o>1||l&&!o){var p=Tk(s,e,t,i,u);f=p.inlineValues,h=p.inlineValueTypes,v=p.blocks,c=p.inlineValues[0]}else if(o){var d=n.getDimensionInfo(i[0]);c=f=lo(n,t,i[0]),h=d.type}else c=f=l?s[0]:s;var g=wg(e),y=g&&e.name||"",m=n.getName(t),_=a?y:m;return ie("section",{header:y,noHeader:a||!g,sortParam:c,blocks:[ie("nameValue",{markerType:"item",markerColor:u,name:_,noName:!or(_),value:f,valueType:h,dataIndex:t})].concat(v||[])})}function Tk(r,e,t,a,n){var i=e.getData(),o=lr(r,function(h,v,c){var p=i.getDimensionInfo(c);return h=h||p&&p.tooltip!==!1&&p.displayName!=null},!1),s=[],l=[],u=[];a.length?C(a,function(h){f(lo(i,t,h),h)}):C(r,f);function f(h,v){var c=i.getDimensionInfo(v);!c||c.otherDims.tooltip===!1||(o?u.push(ie("nameValue",{markerType:"subItem",markerColor:n,name:c.displayName,value:h,valueType:c.type})):(s.push(h),l.push(c.type)))}return{inlineValues:s,inlineValueTypes:l,blocks:u}}var Ca=Tt();function uu(r,e){return r.getName(e)||r.getId(e)}var rf="__universalTransitionEnabled",kt=function(r){k(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t._selectedDataIndicesMap={},t}return e.prototype.init=function(t,a,n){this.seriesIndex=this.componentIndex,this.dataTask=Ns({count:Ck,reset:Dk}),this.dataTask.context={model:this},this.mergeDefaultAndTheme(t,n);var i=Ca(this).sourceManager=new GA(this);i.prepareSource();var o=this.getInitialData(t,n);h_(o,this),this.dataTask.context.data=o,Ca(this).dataBeforeProcessed=o,f_(this),this._initSelectedMapFromData(o)},e.prototype.mergeDefaultAndTheme=function(t,a){var n=tl(this),i=n?Do(t):{},o=this.subType;mt.hasClass(o)&&(o+="Series"),st(t,a.getTheme().get(this.subType)),st(t,this.getDefaultOption()),ai(t,"label",["show"]),this.fillDataTextStyle(t.data),n&&Ja(t,i,n)},e.prototype.mergeOption=function(t,a){t=st(this.option,t,!0),this.fillDataTextStyle(t.data);var n=tl(this);n&&Ja(this.option,t,n);var i=Ca(this).sourceManager;i.dirty(),i.prepareSource();var o=this.getInitialData(t,a);h_(o,this),this.dataTask.dirty(),this.dataTask.context.data=o,Ca(this).dataBeforeProcessed=o,f_(this),this._initSelectedMapFromData(o)},e.prototype.fillDataTextStyle=function(t){if(t&&!Re(t))for(var a=["show"],n=0;nthis.getShallow("animationThreshold")&&(a=!1),!!a},e.prototype.restoreData=function(){this.dataTask.dirty()},e.prototype.getColorFromPalette=function(t,a,n){var i=this.ecModel,o=jg.prototype.getColorFromPalette.call(this,t,a,n);return o||(o=i.getColorFromPalette(t,a,n)),o},e.prototype.coordDimToDataDim=function(t){return this.getRawData().mapDimensionsAll(t)},e.prototype.getProgressive=function(){return this.get("progressive")},e.prototype.getProgressiveThreshold=function(){return this.get("progressiveThreshold")},e.prototype.select=function(t,a){this._innerSelect(this.getData(a),t)},e.prototype.unselect=function(t,a){var n=this.option.selectedMap;if(n){var i=this.option.selectedMode,o=this.getData(a);if(i==="series"||n==="all"){this.option.selectedMap={},this._selectedDataIndicesMap={};return}for(var s=0;s=0&&n.push(o)}return n},e.prototype.isSelected=function(t,a){var n=this.option.selectedMap;if(!n)return!1;var i=this.getData(a);return(n==="all"||n[uu(i,t)])&&!i.getItemModel(t).get(["select","disabled"])},e.prototype.isUniversalTransitionEnabled=function(){if(this[rf])return!0;var t=this.option.universalTransition;return t?t===!0?!0:t&&t.enabled:!1},e.prototype._innerSelect=function(t,a){var n,i,o=this.option,s=o.selectedMode,l=a.length;if(!(!s||!l)){if(s==="series")o.selectedMap="all";else if(s==="multiple"){tt(o.selectedMap)||(o.selectedMap={});for(var u=o.selectedMap,f=0;f0&&this._innerSelect(t,a)}},e.registerClass=function(t){return mt.registerClass(t)},e.protoInitialize=function(){var t=e.prototype;t.type="series.__base__",t.seriesIndex=0,t.ignoreStyleOnData=!1,t.hasSymbolVisual=!1,t.defaultSymbol="circle",t.visualStyleAccessPath="itemStyle",t.visualDrawType="fill"}(),e}(mt);Xt(kt,Nh);Xt(kt,jg);mT(kt,mt);function f_(r){var e=r.name;wg(r)||(r.name=Ak(r)||e)}function Ak(r){var e=r.getRawData(),t=e.mapDimensionsAll("seriesName"),a=[];return C(t,function(n){var i=e.getDimensionInfo(n);i.displayName&&a.push(i.displayName)}),a.join(" ")}function Ck(r){return r.model.getRawData().count()}function Dk(r){var e=r.model;return e.setData(e.getRawData().cloneShallow()),Mk}function Mk(r,e){e.outputData&&r.end>e.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function h_(r,e){C(Hs(r.CHANGABLE_METHODS,r.DOWNSAMPLE_METHODS),function(t){r.wrapMethod(t,it(Ik,e))})}function Ik(r,e){var t=ld(r);return t&&t.setOutputEnd((e||this).count()),e}function ld(r){var e=(r.ecModel||{}).scheduler,t=e&&e.getPipeline(r.uid);if(t){var a=t.currentTask;if(a){var n=a.agentStubMap;n&&(a=n.get(r.uid))}return a}}var zt=function(){function r(){this.group=new at,this.uid=Co("viewComponent")}return r.prototype.init=function(e,t){},r.prototype.render=function(e,t,a,n){},r.prototype.dispose=function(e,t){},r.prototype.updateView=function(e,t,a,n){},r.prototype.updateLayout=function(e,t,a,n){},r.prototype.updateVisual=function(e,t,a,n){},r.prototype.toggleBlurSeries=function(e,t,a){},r.prototype.eachRendered=function(e){var t=this.group;t&&t.traverse(e)},r}();Ag(zt);Sh(zt);function Lo(){var r=Tt();return function(e){var t=r(e),a=e.pipelineContext,n=!!t.large,i=!!t.progressiveRender,o=t.large=!!(a&&a.large),s=t.progressiveRender=!!(a&&a.progressiveRender);return(n!==o||i!==s)&&"reset"}}var qA=Tt(),Lk=Lo(),Rt=function(){function r(){this.group=new at,this.uid=Co("viewChart"),this.renderTask=Ns({plan:Pk,reset:Rk}),this.renderTask.context={view:this}}return r.prototype.init=function(e,t){},r.prototype.render=function(e,t,a,n){},r.prototype.highlight=function(e,t,a,n){var i=e.getData(n&&n.dataType);i&&c_(i,n,"emphasis")},r.prototype.downplay=function(e,t,a,n){var i=e.getData(n&&n.dataType);i&&c_(i,n,"normal")},r.prototype.remove=function(e,t){this.group.removeAll()},r.prototype.dispose=function(e,t){},r.prototype.updateView=function(e,t,a,n){this.render(e,t,a,n)},r.prototype.updateLayout=function(e,t,a,n){this.render(e,t,a,n)},r.prototype.updateVisual=function(e,t,a,n){this.render(e,t,a,n)},r.prototype.eachRendered=function(e){nn(this.group,e)},r.markUpdateMethod=function(e,t){qA(e).updateMethod=t},r.protoInitialize=function(){var e=r.prototype;e.type="chart"}(),r}();function v_(r,e,t){r&&js(r)&&(e==="emphasis"?da:ga)(r,t)}function c_(r,e,t){var a=ni(r,e),n=e&&e.highlightKey!=null?gR(e.highlightKey):null;a!=null?C(Et(a),function(i){v_(r.getItemGraphicEl(i),t,n)}):r.eachItemGraphicEl(function(i){v_(i,t,n)})}Ag(Rt);Sh(Rt);function Pk(r){return Lk(r.model)}function Rk(r){var e=r.model,t=r.ecModel,a=r.api,n=r.payload,i=e.pipelineContext.progressiveRender,o=r.view,s=n&&qA(n).updateMethod,l=i?"incrementalPrepareRender":s&&o[s]?s:"render";return l!=="render"&&o[l](e,t,a,n),Ek[l]}var Ek={incrementalPrepareRender:{progress:function(r,e){e.view.incrementalRender(r,e.model,e.ecModel,e.api,e.payload)}},render:{forceFirstProgress:!0,progress:function(r,e){e.view.render(e.model,e.ecModel,e.api,e.payload)}}},Lf="\0__throttleOriginMethod",p_="\0__throttleRate",d_="\0__throttleType";function ay(r,e,t){var a,n=0,i=0,o=null,s,l,u,f;e=e||0;function h(){i=new Date().getTime(),o=null,r.apply(l,u||[])}var v=function(){for(var c=[],p=0;p=0?h():o=setTimeout(h,-s),n=a};return v.clear=function(){o&&(clearTimeout(o),o=null)},v.debounceNextCall=function(c){f=c},v}function Po(r,e,t,a){var n=r[e];if(n){var i=n[Lf]||n,o=n[d_],s=n[p_];if(s!==t||o!==a){if(t==null||!a)return r[e]=i;n=r[e]=ay(i,t,a==="debounce"),n[Lf]=i,n[d_]=a,n[p_]=t}return n}}function rl(r,e){var t=r[e];t&&t[Lf]&&(t.clear&&t.clear(),r[e]=t[Lf])}var g_=Tt(),y_={itemStyle:ii(aA,!0),lineStyle:ii(rA,!0)},kk={lineStyle:"stroke",itemStyle:"fill"};function KA(r,e){var t=r.visualStyleMapper||y_[e];return t||(console.warn("Unknown style type '"+e+"'."),y_.itemStyle)}function jA(r,e){var t=r.visualDrawType||kk[e];return t||(console.warn("Unknown style type '"+e+"'."),"fill")}var Ok={createOnAllSeries:!0,performRawSeries:!0,reset:function(r,e){var t=r.getData(),a=r.visualStyleAccessPath||"itemStyle",n=r.getModel(a),i=KA(r,a),o=i(n),s=n.getShallow("decal");s&&(t.setVisual("decal",s),s.dirty=!0);var l=jA(r,a),u=o[l],f=K(u)?u:null,h=o.fill==="auto"||o.stroke==="auto";if(!o[l]||f||h){var v=r.getColorFromPalette(r.name,null,e.getSeriesCount());o[l]||(o[l]=v,t.setVisual("colorFromPalette",!0)),o.fill=o.fill==="auto"||K(o.fill)?v:o.fill,o.stroke=o.stroke==="auto"||K(o.stroke)?v:o.stroke}if(t.setVisual("style",o),t.setVisual("drawType",l),!e.isSeriesFiltered(r)&&f)return t.setVisual("colorFromPalette",!1),{dataEach:function(c,p){var d=r.getDataParams(p),g=V({},o);g[l]=f(d),c.setItemVisual(p,"style",g)}}}},Zo=new Mt,Nk={createOnAllSeries:!0,performRawSeries:!0,reset:function(r,e){if(!(r.ignoreStyleOnData||e.isSeriesFiltered(r))){var t=r.getData(),a=r.visualStyleAccessPath||"itemStyle",n=KA(r,a),i=t.getVisual("drawType");return{dataEach:t.hasItemOption?function(o,s){var l=o.getRawDataItem(s);if(l&&l[a]){Zo.option=l[a];var u=n(Zo),f=o.ensureUniqueItemVisual(s,"style");V(f,u),Zo.option.decal&&(o.setItemVisual(s,"decal",Zo.option.decal),Zo.option.decal.dirty=!0),i in u&&o.setItemVisual(s,"colorFromPalette",!1)}}:null}}}},Bk={performRawSeries:!0,overallReset:function(r){var e=Z();r.eachSeries(function(t){var a=t.getColorBy();if(!t.isColorBySeries()){var n=t.type+"-"+a,i=e.get(n);i||(i={},e.set(n,i)),g_(t).scope=i}}),r.eachSeries(function(t){if(!(t.isColorBySeries()||r.isSeriesFiltered(t))){var a=t.getRawData(),n={},i=t.getData(),o=g_(t).scope,s=t.visualStyleAccessPath||"itemStyle",l=jA(t,s);i.each(function(u){var f=i.getRawIndex(u);n[f]=u}),a.each(function(u){var f=n[u],h=i.getItemVisual(f,"colorFromPalette");if(h){var v=i.ensureUniqueItemVisual(f,"style"),c=a.getName(u)||u+"",p=a.count();v[l]=t.getColorFromPalette(c,o,p)}})}})}},fu=Math.PI;function Vk(r,e){e=e||{},Q(e,{text:"loading",textColor:"#000",fontSize:12,fontWeight:"normal",fontStyle:"normal",fontFamily:"sans-serif",maskColor:"rgba(255, 255, 255, 0.8)",showSpinner:!0,color:"#5470c6",spinnerRadius:10,lineWidth:5,zlevel:0});var t=new at,a=new wt({style:{fill:e.maskColor},zlevel:e.zlevel,z:1e4});t.add(a);var n=new bt({style:{text:e.text,fill:e.textColor,fontSize:e.fontSize,fontWeight:e.fontWeight,fontStyle:e.fontStyle,fontFamily:e.fontFamily},zlevel:e.zlevel,z:10001}),i=new wt({style:{fill:"none"},textContent:n,textConfig:{position:"right",distance:10},zlevel:e.zlevel,z:10001});t.add(i);var o;return e.showSpinner&&(o=new Cl({shape:{startAngle:-fu/2,endAngle:-fu/2+.1,r:e.spinnerRadius},style:{stroke:e.color,lineCap:"round",lineWidth:e.lineWidth},zlevel:e.zlevel,z:10001}),o.animateShape(!0).when(1e3,{endAngle:fu*3/2}).start("circularInOut"),o.animateShape(!0).when(1e3,{startAngle:fu*3/2}).delay(300).start("circularInOut"),t.add(o)),t.resize=function(){var s=n.getBoundingRect().width,l=e.showSpinner?e.spinnerRadius:0,u=(r.getWidth()-l*2-(e.showSpinner&&s?10:0)-s)/2-(e.showSpinner&&s?0:5+s/2)+(e.showSpinner?0:s/2)+(s?0:l),f=r.getHeight()/2;e.showSpinner&&o.setShape({cx:u,cy:f}),i.setShape({x:u-l,y:f-l,width:l*2,height:l*2}),a.setShape({x:0,y:0,width:r.getWidth(),height:r.getHeight()})},t.resize(),t}var QA=function(){function r(e,t,a,n){this._stageTaskMap=Z(),this.ecInstance=e,this.api=t,a=this._dataProcessorHandlers=a.slice(),n=this._visualHandlers=n.slice(),this._allHandlers=a.concat(n)}return r.prototype.restoreData=function(e,t){e.restoreData(t),this._stageTaskMap.each(function(a){var n=a.overallTask;n&&n.dirty()})},r.prototype.getPerformArgs=function(e,t){if(e.__pipeline){var a=this._pipelineMap.get(e.__pipeline.id),n=a.context,i=!t&&a.progressiveEnabled&&(!n||n.progressiveRender)&&e.__idxInPipeline>a.blockIndex,o=i?a.step:null,s=n&&n.modDataCount,l=s!=null?Math.ceil(s/o):null;return{step:o,modBy:l,modDataCount:s}}},r.prototype.getPipeline=function(e){return this._pipelineMap.get(e)},r.prototype.updateStreamModes=function(e,t){var a=this._pipelineMap.get(e.uid),n=e.getData(),i=n.count(),o=a.progressiveEnabled&&t.incrementalPrepareRender&&i>=a.threshold,s=e.get("large")&&i>=e.get("largeThreshold"),l=e.get("progressiveChunkMode")==="mod"?i:null;e.pipelineContext=a.context={progressiveRender:o,modDataCount:l,large:s}},r.prototype.restorePipelines=function(e){var t=this,a=t._pipelineMap=Z();e.eachSeries(function(n){var i=n.getProgressive(),o=n.uid;a.set(o,{id:o,head:null,tail:null,threshold:n.getProgressiveThreshold(),progressiveEnabled:i&&!(n.preventIncremental&&n.preventIncremental()),blockIndex:-1,step:Math.round(i||700),count:0}),t._pipe(n,n.dataTask)})},r.prototype.prepareStageTasks=function(){var e=this._stageTaskMap,t=this.api.getModel(),a=this.api;C(this._allHandlers,function(n){var i=e.get(n.uid)||e.set(n.uid,{}),o="";me(!(n.reset&&n.overallReset),o),n.reset&&this._createSeriesStageTask(n,i,t,a),n.overallReset&&this._createOverallStageTask(n,i,t,a)},this)},r.prototype.prepareView=function(e,t,a,n){var i=e.renderTask,o=i.context;o.model=t,o.ecModel=a,o.api=n,i.__block=!e.incrementalPrepareRender,this._pipe(t,i)},r.prototype.performDataProcessorTasks=function(e,t){this._performStageTasks(this._dataProcessorHandlers,e,t,{block:!0})},r.prototype.performVisualTasks=function(e,t,a){this._performStageTasks(this._visualHandlers,e,t,a)},r.prototype._performStageTasks=function(e,t,a,n){n=n||{};var i=!1,o=this;C(e,function(l,u){if(!(n.visualType&&n.visualType!==l.visualType)){var f=o._stageTaskMap.get(l.uid),h=f.seriesTaskMap,v=f.overallTask;if(v){var c,p=v.agentStubMap;p.each(function(g){s(n,g)&&(g.dirty(),c=!0)}),c&&v.dirty(),o.updatePayload(v,a);var d=o.getPerformArgs(v,n.block);p.each(function(g){g.perform(d)}),v.perform(d)&&(i=!0)}else h&&h.each(function(g,y){s(n,g)&&g.dirty();var m=o.getPerformArgs(g,n.block);m.skip=!l.performRawSeries&&t.isSeriesFiltered(g.context.model),o.updatePayload(g,a),g.perform(m)&&(i=!0)})}});function s(l,u){return l.setDirty&&(!l.dirtyMap||l.dirtyMap.get(u.__pipeline.id))}this.unfinished=i||this.unfinished},r.prototype.performSeriesTasks=function(e){var t;e.eachSeries(function(a){t=a.dataTask.perform()||t}),this.unfinished=t||this.unfinished},r.prototype.plan=function(){this._pipelineMap.each(function(e){var t=e.tail;do{if(t.__block){e.blockIndex=t.__idxInPipeline;break}t=t.getUpstream()}while(t)})},r.prototype.updatePayload=function(e,t){t!=="remain"&&(e.context.payload=t)},r.prototype._createSeriesStageTask=function(e,t,a,n){var i=this,o=t.seriesTaskMap,s=t.seriesTaskMap=Z(),l=e.seriesType,u=e.getTargetSeries;e.createOnAllSeries?a.eachRawSeries(f):l?a.eachRawSeriesByType(l,f):u&&u(a,n).each(f);function f(h){var v=h.uid,c=s.set(v,o&&o.get(v)||Ns({plan:Wk,reset:Uk,count:Xk}));c.context={model:h,ecModel:a,api:n,useClearVisual:e.isVisual&&!e.isLayout,plan:e.plan,reset:e.reset,scheduler:i},i._pipe(h,c)}},r.prototype._createOverallStageTask=function(e,t,a,n){var i=this,o=t.overallTask=t.overallTask||Ns({reset:zk});o.context={ecModel:a,api:n,overallReset:e.overallReset,scheduler:i};var s=o.agentStubMap,l=o.agentStubMap=Z(),u=e.seriesType,f=e.getTargetSeries,h=!0,v=!1,c="";me(!e.createOnAllSeries,c),u?a.eachRawSeriesByType(u,p):f?f(a,n).each(p):(h=!1,C(a.getSeries(),p));function p(d){var g=d.uid,y=l.set(g,s&&s.get(g)||(v=!0,Ns({reset:Gk,onDirty:Hk})));y.context={model:d,overallProgress:h},y.agent=o,y.__block=h,i._pipe(d,y)}v&&o.dirty()},r.prototype._pipe=function(e,t){var a=e.uid,n=this._pipelineMap.get(a);!n.head&&(n.head=t),n.tail&&n.tail.pipe(t),n.tail=t,t.__idxInPipeline=n.count++,t.__pipeline=n},r.wrapStageHandler=function(e,t){return K(e)&&(e={overallReset:e,seriesType:$k(e)}),e.uid=Co("stageHandler"),t&&(e.visualType=t),e},r}();function zk(r){r.overallReset(r.ecModel,r.api,r.payload)}function Gk(r){return r.overallProgress&&Fk}function Fk(){this.agent.dirty(),this.getDownstream().dirty()}function Hk(){this.agent&&this.agent.dirty()}function Wk(r){return r.plan?r.plan(r.model,r.ecModel,r.api,r.payload):null}function Uk(r){r.useClearVisual&&r.data.clearAllVisual();var e=r.resetDefines=Et(r.reset(r.model,r.ecModel,r.api,r.payload));return e.length>1?G(e,function(t,a){return JA(a)}):Yk}var Yk=JA(0);function JA(r){return function(e,t){var a=t.data,n=t.resetDefines[r];if(n&&n.dataEach)for(var i=e.start;i0&&c===u.length-v.length){var p=u.slice(0,c);p!=="data"&&(t.mainType=p,t[v.toLowerCase()]=l,f=!0)}}s.hasOwnProperty(u)&&(a[u]=l,f=!0),f||(n[u]=l)})}return{cptQuery:t,dataQuery:a,otherQuery:n}},r.prototype.filter=function(e,t){var a=this.eventInfo;if(!a)return!0;var n=a.targetEl,i=a.packedEvent,o=a.model,s=a.view;if(!o||!s)return!0;var l=t.cptQuery,u=t.dataQuery;return f(l,o,"mainType")&&f(l,o,"subType")&&f(l,o,"index","componentIndex")&&f(l,o,"name")&&f(l,o,"id")&&f(u,i,"name")&&f(u,i,"dataIndex")&&f(u,i,"dataType")&&(!s.filterForExposedEvent||s.filterForExposedEvent(e,t.otherQuery,n,i));function f(h,v,c,p){return h[c]==null||v[p||c]===h[c]}},r.prototype.afterTrigger=function(){this.eventInfo=null},r}(),ud=["symbol","symbolSize","symbolRotate","symbolOffset"],x_=ud.concat(["symbolKeepAspect"]),Kk={createOnAllSeries:!0,performRawSeries:!0,reset:function(r,e){var t=r.getData();if(r.legendIcon&&t.setVisual("legendIcon",r.legendIcon),!r.hasSymbolVisual)return;for(var a={},n={},i=!1,o=0;o=0&&Xn(l)?l:.5;var u=r.createRadialGradient(o,s,0,o,s,l);return u}function fd(r,e,t){for(var a=e.type==="radial"?hO(r,e,t):fO(r,e,t),n=e.colorStops,i=0;i0)?null:r==="dashed"?[4*e,2*e]:r==="dotted"?[e]:Ct(r)?[r]:z(r)?r:null}function iy(r){var e=r.style,t=e.lineDash&&e.lineWidth>0&&cO(e.lineDash,e.lineWidth),a=e.lineDashOffset;if(t){var n=e.strokeNoScale&&r.getLineScale?r.getLineScale():1;n&&n!==1&&(t=G(t,function(i){return i/n}),a/=n)}return[t,a]}var pO=new qr(!0);function Ef(r){var e=r.stroke;return!(e==null||e==="none"||!(r.lineWidth>0))}function b_(r){return typeof r=="string"&&r!=="none"}function kf(r){var e=r.fill;return e!=null&&e!=="none"}function w_(r,e){if(e.fillOpacity!=null&&e.fillOpacity!==1){var t=r.globalAlpha;r.globalAlpha=e.fillOpacity*e.opacity,r.fill(),r.globalAlpha=t}else r.fill()}function T_(r,e){if(e.strokeOpacity!=null&&e.strokeOpacity!==1){var t=r.globalAlpha;r.globalAlpha=e.strokeOpacity*e.opacity,r.stroke(),r.globalAlpha=t}else r.stroke()}function hd(r,e,t){var a=Cg(e.image,e.__image,t);if(xh(a)){var n=r.createPattern(a,e.repeat||"repeat");if(typeof DOMMatrix=="function"&&n&&n.setTransform){var i=new DOMMatrix;i.translateSelf(e.x||0,e.y||0),i.rotateSelf(0,0,(e.rotation||0)*Ts),i.scaleSelf(e.scaleX||1,e.scaleY||1),n.setTransform(i)}return n}}function dO(r,e,t,a){var n,i=Ef(t),o=kf(t),s=t.strokePercent,l=s<1,u=!e.path;(!e.silent||l)&&u&&e.createPathProxy();var f=e.path||pO,h=e.__dirty;if(!a){var v=t.fill,c=t.stroke,p=o&&!!v.colorStops,d=i&&!!c.colorStops,g=o&&!!v.image,y=i&&!!c.image,m=void 0,_=void 0,S=void 0,b=void 0,x=void 0;(p||d)&&(x=e.getBoundingRect()),p&&(m=h?fd(r,v,x):e.__canvasFillGradient,e.__canvasFillGradient=m),d&&(_=h?fd(r,c,x):e.__canvasStrokeGradient,e.__canvasStrokeGradient=_),g&&(S=h||!e.__canvasFillPattern?hd(r,v,e):e.__canvasFillPattern,e.__canvasFillPattern=S),y&&(b=h||!e.__canvasStrokePattern?hd(r,c,e):e.__canvasStrokePattern,e.__canvasStrokePattern=S),p?r.fillStyle=m:g&&(S?r.fillStyle=S:o=!1),d?r.strokeStyle=_:y&&(b?r.strokeStyle=b:i=!1)}var w=e.getGlobalScale();f.setScale(w[0],w[1],e.segmentIgnoreThreshold);var T,A;r.setLineDash&&t.lineDash&&(n=iy(e),T=n[0],A=n[1]);var D=!0;(u||h&Fi)&&(f.setDPR(r.dpr),l?f.setContext(null):(f.setContext(r),D=!1),f.reset(),e.buildPath(f,e.shape,a),f.toStatic(),e.pathUpdated()),D&&f.rebuildPath(r,l?s:1),T&&(r.setLineDash(T),r.lineDashOffset=A),a||(t.strokeFirst?(i&&T_(r,t),o&&w_(r,t)):(o&&w_(r,t),i&&T_(r,t))),T&&r.setLineDash([])}function gO(r,e,t){var a=e.__image=Cg(t.image,e.__image,e,e.onload);if(!(!a||!xh(a))){var n=t.x||0,i=t.y||0,o=e.getWidth(),s=e.getHeight(),l=a.width/a.height;if(o==null&&s!=null?o=s*l:s==null&&o!=null?s=o/l:o==null&&s==null&&(o=a.width,s=a.height),t.sWidth&&t.sHeight){var u=t.sx||0,f=t.sy||0;r.drawImage(a,u,f,t.sWidth,t.sHeight,n,i,o,s)}else if(t.sx&&t.sy){var u=t.sx,f=t.sy,h=o-u,v=s-f;r.drawImage(a,u,f,h,v,n,i,o,s)}else r.drawImage(a,n,i,o,s)}}function yO(r,e,t){var a,n=t.text;if(n!=null&&(n+=""),n){r.font=t.font||Ka,r.textAlign=t.textAlign,r.textBaseline=t.textBaseline;var i=void 0,o=void 0;r.setLineDash&&t.lineDash&&(a=iy(e),i=a[0],o=a[1]),i&&(r.setLineDash(i),r.lineDashOffset=o),t.strokeFirst?(Ef(t)&&r.strokeText(n,t.x,t.y),kf(t)&&r.fillText(n,t.x,t.y)):(kf(t)&&r.fillText(n,t.x,t.y),Ef(t)&&r.strokeText(n,t.x,t.y)),i&&r.setLineDash([])}}var A_=["shadowBlur","shadowOffsetX","shadowOffsetY"],C_=[["lineCap","butt"],["lineJoin","miter"],["miterLimit",10]];function iC(r,e,t,a,n){var i=!1;if(!a&&(t=t||{},e===t))return!1;if(a||e.opacity!==t.opacity){ze(r,n),i=!0;var o=Math.max(Math.min(e.opacity,1),0);r.globalAlpha=isNaN(o)?Kn.opacity:o}(a||e.blend!==t.blend)&&(i||(ze(r,n),i=!0),r.globalCompositeOperation=e.blend||Kn.blend);for(var s=0;s0&&t.unfinished);t.unfinished||this._zr.flush()}}},e.prototype.getDom=function(){return this._dom},e.prototype.getId=function(){return this.id},e.prototype.getZr=function(){return this._zr},e.prototype.isSSR=function(){return this._ssr},e.prototype.setOption=function(t,a,n){if(!this[de]){if(this._disposed){this.id;return}var i,o,s;if(tt(a)&&(n=a.lazyUpdate,i=a.silent,o=a.replaceMerge,s=a.transition,a=a.notMerge),this[de]=!0,!this._model||a){var l=new RE(this._api),u=this._theme,f=this._model=new Qg;f.scheduler=this._scheduler,f.ssr=this._ssr,f.init(null,null,null,u,this._locale,l)}this._model.setOption(t,{replaceMerge:o},cd);var h={seriesTransition:s,optionChanged:!0};if(n)this[Ne]={silent:i,updateParams:h},this[de]=!1,this.getZr().wakeUp();else{try{Li(this),Da.update.call(this,null,h)}catch(v){throw this[Ne]=null,this[de]=!1,v}this._ssr||this._zr.flush(),this[Ne]=null,this[de]=!1,qo.call(this,i),Ko.call(this,i)}}},e.prototype.setTheme=function(){},e.prototype.getModel=function(){return this._model},e.prototype.getOption=function(){return this._model&&this._model.getOption()},e.prototype.getWidth=function(){return this._zr.getWidth()},e.prototype.getHeight=function(){return this._zr.getHeight()},e.prototype.getDevicePixelRatio=function(){return this._zr.painter.dpr||_t.hasGlobalWindow&&window.devicePixelRatio||1},e.prototype.getRenderedCanvas=function(t){return this.renderToCanvas(t)},e.prototype.renderToCanvas=function(t){t=t||{};var a=this._zr.painter;return a.getRenderedCanvas({backgroundColor:t.backgroundColor||this._model.get("backgroundColor"),pixelRatio:t.pixelRatio||this.getDevicePixelRatio()})},e.prototype.renderToSVGString=function(t){t=t||{};var a=this._zr.painter;return a.renderToString({useViewBox:t.useViewBox})},e.prototype.getSvgDataURL=function(){if(_t.svgSupported){var t=this._zr,a=t.storage.getDisplayList();return C(a,function(n){n.stopAnimation(null,!0)}),t.painter.toDataURL()}},e.prototype.getDataURL=function(t){if(this._disposed){this.id;return}t=t||{};var a=t.excludeComponents,n=this._model,i=[],o=this;C(a,function(l){n.eachComponent({mainType:l},function(u){var f=o._componentsMap[u.__viewId];f.group.ignore||(i.push(f),f.group.ignore=!0)})});var s=this._zr.painter.getType()==="svg"?this.getSvgDataURL():this.renderToCanvas(t).toDataURL("image/"+(t&&t.type||"png"));return C(i,function(l){l.group.ignore=!1}),s},e.prototype.getConnectedDataURL=function(t){if(this._disposed){this.id;return}var a=t.type==="svg",n=this.group,i=Math.min,o=Math.max,s=1/0;if(Vf[n]){var l=s,u=s,f=-s,h=-s,v=[],c=t&&t.pixelRatio||this.getDevicePixelRatio();C(Jn,function(_,S){if(_.group===n){var b=a?_.getZr().painter.getSvgDom().innerHTML:_.renderToCanvas(et(t)),x=_.getDom().getBoundingClientRect();l=i(x.left,l),u=i(x.top,u),f=o(x.right,f),h=o(x.bottom,h),v.push({dom:b,left:x.left,top:x.top})}}),l*=c,u*=c,f*=c,h*=c;var p=f-l,d=h-u,g=Cr.createCanvas(),y=Vp(g,{renderer:a?"svg":"canvas"});if(y.resize({width:p,height:d}),a){var m="";return C(v,function(_){var S=_.left-l,b=_.top-u;m+=''+_.dom+" "}),y.painter.getSvgRoot().innerHTML=m,t.connectedBackgroundColor&&y.painter.setBackgroundColor(t.connectedBackgroundColor),y.refreshImmediately(),y.painter.toDataURL()}else return t.connectedBackgroundColor&&y.add(new wt({shape:{x:0,y:0,width:p,height:d},style:{fill:t.connectedBackgroundColor}})),C(v,function(_){var S=new oe({style:{x:_.left*c-l,y:_.top*c-u,image:_.dom}});y.add(S)}),y.refreshImmediately(),g.toDataURL("image/"+(t&&t.type||"png"))}else return this.getDataURL(t)},e.prototype.convertToPixel=function(t,a){return Zv(this,"convertToPixel",t,a)},e.prototype.convertFromPixel=function(t,a){return Zv(this,"convertFromPixel",t,a)},e.prototype.containPixel=function(t,a){if(this._disposed){this.id;return}var n=this._model,i,o=Ps(n,t);return C(o,function(s,l){l.indexOf("Models")>=0&&C(s,function(u){var f=u.coordinateSystem;if(f&&f.containPoint)i=i||!!f.containPoint(a);else if(l==="seriesModels"){var h=this._chartsMap[u.__viewId];h&&h.containPoint&&(i=i||h.containPoint(a,u))}},this)},this),!!i},e.prototype.getVisual=function(t,a){var n=this._model,i=Ps(n,t,{defaultMainType:"series"}),o=i.seriesModel,s=o.getData(),l=i.hasOwnProperty("dataIndexInside")?i.dataIndexInside:i.hasOwnProperty("dataIndex")?s.indexOfRawIndex(i.dataIndex):null;return l!=null?ny(s,l,a):Ll(s,a)},e.prototype.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},e.prototype.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]},e.prototype._initEvents=function(){var t=this;C(FO,function(a){var n=function(i){var o=t.getModel(),s=i.target,l,u=a==="globalout";if(u?l={}:s&&Yn(s,function(p){var d=nt(p);if(d&&d.dataIndex!=null){var g=d.dataModel||o.getSeriesByIndex(d.seriesIndex);return l=g&&g.getDataParams(d.dataIndex,d.dataType,s)||{},!0}else if(d.eventData)return l=V({},d.eventData),!0},!0),l){var f=l.componentType,h=l.componentIndex;(f==="markLine"||f==="markPoint"||f==="markArea")&&(f="series",h=l.seriesIndex);var v=f&&h!=null&&o.getComponent(f,h),c=v&&t[v.mainType==="series"?"_chartsMap":"_componentsMap"][v.__viewId];l.event=i,l.type=a,t._$eventProcessor.eventInfo={targetEl:s,packedEvent:l,model:v,view:c},t.trigger(a,l)}};n.zrEventfulCallAtLast=!0,t._zr.on(a,n,t)}),C(Bs,function(a,n){t._messageCenter.on(n,function(i){this.trigger(n,i)},t)}),C(["selectchanged"],function(a){t._messageCenter.on(a,function(n){this.trigger(a,n)},t)}),Qk(this._messageCenter,this,this._api)},e.prototype.isDisposed=function(){return this._disposed},e.prototype.clear=function(){if(this._disposed){this.id;return}this.setOption({series:[]},!0)},e.prototype.dispose=function(){if(this._disposed){this.id;return}this._disposed=!0;var t=this.getDom();t&&dT(this.getDom(),ly,"");var a=this,n=a._api,i=a._model;C(a._componentsViews,function(o){o.dispose(i,n)}),C(a._chartsViews,function(o){o.dispose(i,n)}),a._zr.dispose(),a._dom=a._model=a._chartsMap=a._componentsMap=a._chartsViews=a._componentsViews=a._scheduler=a._api=a._zr=a._throttledZrFlush=a._theme=a._coordSysMgr=a._messageCenter=null,delete Jn[a.id]},e.prototype.resize=function(t){if(!this[de]){if(this._disposed){this.id;return}this._zr.resize(t);var a=this._model;if(this._loadingFX&&this._loadingFX.resize(),!!a){var n=a.resetOption("media"),i=t&&t.silent;this[Ne]&&(i==null&&(i=this[Ne].silent),n=!0,this[Ne]=null),this[de]=!0;try{n&&Li(this),Da.update.call(this,{type:"resize",animation:V({duration:0},t&&t.animation)})}catch(o){throw this[de]=!1,o}this[de]=!1,qo.call(this,i),Ko.call(this,i)}}},e.prototype.showLoading=function(t,a){if(this._disposed){this.id;return}if(tt(t)&&(a=t,t=""),t=t||"default",this.hideLoading(),!!pd[t]){var n=pd[t](this._api,a),i=this._zr;this._loadingFX=n,i.add(n)}},e.prototype.hideLoading=function(){if(this._disposed){this.id;return}this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null},e.prototype.makeActionFromEvent=function(t){var a=V({},t);return a.type=Bs[t.type],a},e.prototype.dispatchAction=function(t,a){if(this._disposed){this.id;return}if(tt(a)||(a={silent:!!a}),!!Nf[t.type]&&this._model){if(this[de]){this._pendingActions.push(t);return}var n=a.silent;Kv.call(this,t,n);var i=a.flush;i?this._zr.flush():i!==!1&&_t.browser.weChat&&this._throttledZrFlush(),qo.call(this,n),Ko.call(this,n)}},e.prototype.updateLabelLayout=function(){mr.trigger("series:layoutlabels",this._model,this._api,{updatedSeries:[]})},e.prototype.appendData=function(t){if(this._disposed){this.id;return}var a=t.seriesIndex,n=this.getModel(),i=n.getSeriesByIndex(a);i.appendData(t),this._scheduler.unfinished=!0,this.getZr().wakeUp()},e.internalField=function(){Li=function(h){var v=h._scheduler;v.restorePipelines(h._model),v.prepareStageTasks(),$v(h,!0),$v(h,!1),v.plan()},$v=function(h,v){for(var c=h._model,p=h._scheduler,d=v?h._componentsViews:h._chartsViews,g=v?h._componentsMap:h._chartsMap,y=h._zr,m=h._api,_=0;_v.get("hoverLayerThreshold")&&!_t.node&&!_t.worker&&v.eachSeries(function(g){if(!g.preventUsingHoverLayer){var y=h._chartsMap[g.__viewId];y.__alive&&y.eachRendered(function(m){m.states.emphasis&&(m.states.emphasis.hoverLayer=!0)})}})}function o(h,v){var c=h.get("blendMode")||null;v.eachRendered(function(p){p.isGroup||(p.style.blend=c)})}function s(h,v){if(!h.preventAutoZ){var c=h.get("z")||0,p=h.get("zlevel")||0;v.eachRendered(function(d){return l(d,c,p,-1/0),!0})}}function l(h,v,c,p){var d=h.getTextContent(),g=h.getTextGuideLine(),y=h.isGroup;if(y)for(var m=h.childrenRef(),_=0;_0?{duration:d,delay:c.get("delay"),easing:c.get("easing")}:null;v.eachRendered(function(y){if(y.states&&y.states.emphasis){if(Ji(y))return;if(y instanceof yt&&yR(y),y.__dirty){var m=y.prevStates;m&&y.useStates(m)}if(p){y.stateTransition=g;var _=y.getTextContent(),S=y.getTextGuideLine();_&&(_.stateTransition=g),S&&(S.stateTransition=g)}y.__dirty&&n(y)}})}z_=function(h){return new(function(v){k(c,v);function c(){return v!==null&&v.apply(this,arguments)||this}return c.prototype.getCoordinateSystems=function(){return h._coordSysMgr.getCoordinateSystems()},c.prototype.getComponentByElement=function(p){for(;p;){var d=p.__ecComponentInfo;if(d!=null)return h._model.getComponent(d.mainType,d.index);p=p.parent}},c.prototype.enterEmphasis=function(p,d){da(p,d),Ze(h)},c.prototype.leaveEmphasis=function(p,d){ga(p,d),Ze(h)},c.prototype.enterBlur=function(p){ET(p),Ze(h)},c.prototype.leaveBlur=function(p){Pg(p),Ze(h)},c.prototype.enterSelect=function(p){kT(p),Ze(h)},c.prototype.leaveSelect=function(p){OT(p),Ze(h)},c.prototype.getModel=function(){return h.getModel()},c.prototype.getViewOfComponentModel=function(p){return h.getViewOfComponentModel(p)},c.prototype.getViewOfSeriesModel=function(p){return h.getViewOfSeriesModel(p)},c}(AA))(h)},xC=function(h){function v(c,p){for(var d=0;d=0)){F_.push(t);var i=QA.wrapStageHandler(t,n);i.__prio=e,i.__raw=t,r.push(i)}}function DC(r,e){pd[r]=e}function p7(r){pL({createCanvas:r})}function qO(r,e,t){var a=vC("registerMap");a&&a(r,e,t)}function d7(r){var e=vC("getMap");return e&&e(r)}var KO=fk;gi(oy,Ok);gi(Vh,Nk);gi(Vh,Bk);gi(oy,Kk);gi(Vh,jk);gi(dC,AO);AC(DA);CC(IO,UE);DC("default",Vk);Qr({type:jn,event:jn,update:jn},Yt);Qr({type:ju,event:ju,update:ju},Yt);Qr({type:Rs,event:Rs,update:Rs},Yt);Qr({type:Qu,event:Qu,update:Qu},Yt);Qr({type:Es,event:Es,update:Es},Yt);TC("light",Zk);TC("dark",rC);var g7={},H_=[],jO={registerPreprocessor:AC,registerProcessor:CC,registerPostInit:YO,registerPostUpdate:XO,registerUpdateLifecycle:uy,registerAction:Qr,registerCoordinateSystem:$O,registerLayout:ZO,registerVisual:gi,registerTransform:KO,registerLoading:DC,registerMap:qO,registerImpl:CO,PRIORITY:VO,ComponentModel:mt,ComponentView:zt,SeriesModel:kt,ChartView:Rt,registerComponentModel:function(r){mt.registerClass(r)},registerComponentView:function(r){zt.registerClass(r)},registerSeriesModel:function(r){kt.registerClass(r)},registerChartView:function(r){Rt.registerClass(r)},registerSubTypeDefaulter:function(r,e){mt.registerSubTypeDefaulter(r,e)},registerPainter:function(r,e){rT(r,e)}};function gt(r){if(z(r)){C(r,function(e){gt(e)});return}vt(H_,r)>=0||(H_.push(r),K(r)&&(r={install:r}),r.install(jO))}function jo(r){return r==null?0:r.length||1}function W_(r){return r}var ya=function(){function r(e,t,a,n,i,o){this._old=e,this._new=t,this._oldKeyGetter=a||W_,this._newKeyGetter=n||W_,this.context=i,this._diffModeMultiple=o==="multiple"}return r.prototype.add=function(e){return this._add=e,this},r.prototype.update=function(e){return this._update=e,this},r.prototype.updateManyToOne=function(e){return this._updateManyToOne=e,this},r.prototype.updateOneToMany=function(e){return this._updateOneToMany=e,this},r.prototype.updateManyToMany=function(e){return this._updateManyToMany=e,this},r.prototype.remove=function(e){return this._remove=e,this},r.prototype.execute=function(){this[this._diffModeMultiple?"_executeMultiple":"_executeOneToOne"]()},r.prototype._executeOneToOne=function(){var e=this._old,t=this._new,a={},n=new Array(e.length),i=new Array(t.length);this._initIndexMap(e,null,n,"_oldKeyGetter"),this._initIndexMap(t,a,i,"_newKeyGetter");for(var o=0;o1){var f=l.shift();l.length===1&&(a[s]=l[0]),this._update&&this._update(f,o)}else u===1?(a[s]=null,this._update&&this._update(l,o)):this._remove&&this._remove(o)}this._performRestAdd(i,a)},r.prototype._executeMultiple=function(){var e=this._old,t=this._new,a={},n={},i=[],o=[];this._initIndexMap(e,a,i,"_oldKeyGetter"),this._initIndexMap(t,n,o,"_newKeyGetter");for(var s=0;s1&&v===1)this._updateManyToOne&&this._updateManyToOne(f,u),n[l]=null;else if(h===1&&v>1)this._updateOneToMany&&this._updateOneToMany(f,u),n[l]=null;else if(h===1&&v===1)this._update&&this._update(f,u),n[l]=null;else if(h>1&&v>1)this._updateManyToMany&&this._updateManyToMany(f,u),n[l]=null;else if(h>1)for(var c=0;c1)for(var s=0;s30}var Qo=tt,Ma=G,aN=typeof Int32Array>"u"?Array:Int32Array,nN="e\0\0",U_=-1,iN=["hasItemOption","_nameList","_idList","_invertedIndicesMap","_dimSummary","userOutput","_rawData","_dimValueGetter","_nameDimIdx","_idDimIdx","_nameRepeatCount"],oN=["_approximateExtent"],Y_,du,Jo,ts,Jv,gu,tc,Le=function(){function r(e,t){this.type="list",this._dimOmitted=!1,this._nameList=[],this._idList=[],this._visual={},this._layout={},this._itemVisuals=[],this._itemLayouts=[],this._graphicEls=[],this._approximateExtent={},this._calculationInfo={},this.hasItemOption=!1,this.TRANSFERABLE_METHODS=["cloneShallow","downSample","lttbDownSample","map"],this.CHANGABLE_METHODS=["filterSelf","selectRange"],this.DOWNSAMPLE_METHODS=["downSample","lttbDownSample"];var a,n=!1;IC(e)?(a=e.dimensions,this._dimOmitted=e.isDimensionOmitted(),this._schema=e):(n=!0,a=e),a=a||["x","y"];for(var i={},o=[],s={},l=!1,u={},f=0;f=t)){var a=this._store,n=a.getProvider();this._updateOrdinalMeta();var i=this._nameList,o=this._idList,s=n.getSource().sourceFormat,l=s===vr;if(l&&!n.pure)for(var u=[],f=e;f0},r.prototype.ensureUniqueItemVisual=function(e,t){var a=this._itemVisuals,n=a[e];n||(n=a[e]={});var i=n[t];return i==null&&(i=this.getVisual(t),z(i)?i=i.slice():Qo(i)&&(i=V({},i)),n[t]=i),i},r.prototype.setItemVisual=function(e,t,a){var n=this._itemVisuals[e]||{};this._itemVisuals[e]=n,Qo(t)?V(n,t):n[t]=a},r.prototype.clearAllVisual=function(){this._visual={},this._itemVisuals=[]},r.prototype.setLayout=function(e,t){Qo(e)?V(this._layout,e):this._layout[e]=t},r.prototype.getLayout=function(e){return this._layout[e]},r.prototype.getItemLayout=function(e){return this._itemLayouts[e]},r.prototype.setItemLayout=function(e,t,a){this._itemLayouts[e]=a?V(this._itemLayouts[e]||{},t):t},r.prototype.clearItemLayouts=function(){this._itemLayouts.length=0},r.prototype.setItemGraphicEl=function(e,t){var a=this.hostModel&&this.hostModel.seriesIndex;Xp(a,this.dataType,e,t),this._graphicEls[e]=t},r.prototype.getItemGraphicEl=function(e){return this._graphicEls[e]},r.prototype.eachItemGraphicEl=function(e,t){C(this._graphicEls,function(a,n){a&&e&&e.call(t,a,n)})},r.prototype.cloneShallow=function(e){return e||(e=new r(this._schema?this._schema:Ma(this.dimensions,this._getDimInfo,this),this.hostModel)),Jv(e,this),e._store=this._store,e},r.prototype.wrapMethod=function(e,t){var a=this[e];K(a)&&(this.__wrappedMethods=this.__wrappedMethods||[],this.__wrappedMethods.push(e),this[e]=function(){var n=a.apply(this,arguments);return t.apply(this,[n].concat(vh(arguments)))})},r.internalField=function(){Y_=function(e){var t=e._invertedIndicesMap;C(t,function(a,n){var i=e._dimInfos[n],o=i.ordinalMeta,s=e._store;if(o){a=t[n]=new aN(o.categories.length);for(var l=0;l1&&(l+="__ec__"+f),n[t]=l}}}(),r}();function sN(r,e){return Eo(r,e).dimensions}function Eo(r,e){Jg(r)||(r=ty(r)),e=e||{};var t=e.coordDimensions||[],a=e.dimensionsDefine||r.dimensionsDefine||[],n=Z(),i=[],o=uN(r,t,a,e.dimensionsCount),s=e.canOmitUnusedDimensions&&RC(o),l=a===r.dimensionsDefine,u=l?PC(r):LC(a),f=e.encodeDefine;!f&&e.encodeDefaulter&&(f=e.encodeDefaulter(r,o));for(var h=Z(f),v=new VA(o),c=0;c0&&(a.name=n+(i-1)),i++,e.set(n,i)}}function uN(r,e,t,a){var n=Math.max(r.dimensionsDetectedCount||1,e.length,t.length,a||0);return C(e,function(i){var o;tt(i)&&(o=i.dimsDef)&&(n=Math.max(n,o.length))}),n}function fN(r,e,t){if(t||e.hasKey(r)){for(var a=0;e.hasKey(r+a);)a++;r+=a}return e.set(r,!0),r}var hN=function(){function r(e){this.coordSysDims=[],this.axisMap=Z(),this.categoryAxisMap=Z(),this.coordSysName=e}return r}();function vN(r){var e=r.get("coordinateSystem"),t=new hN(e),a=cN[e];if(a)return a(r,t,t.axisMap,t.categoryAxisMap),t}var cN={cartesian2d:function(r,e,t,a){var n=r.getReferringComponents("xAxis",Kt).models[0],i=r.getReferringComponents("yAxis",Kt).models[0];e.coordSysDims=["x","y"],t.set("x",n),t.set("y",i),Pi(n)&&(a.set("x",n),e.firstCategoryDimIndex=0),Pi(i)&&(a.set("y",i),e.firstCategoryDimIndex==null&&(e.firstCategoryDimIndex=1))},singleAxis:function(r,e,t,a){var n=r.getReferringComponents("singleAxis",Kt).models[0];e.coordSysDims=["single"],t.set("single",n),Pi(n)&&(a.set("single",n),e.firstCategoryDimIndex=0)},polar:function(r,e,t,a){var n=r.getReferringComponents("polar",Kt).models[0],i=n.findAxisModel("radiusAxis"),o=n.findAxisModel("angleAxis");e.coordSysDims=["radius","angle"],t.set("radius",i),t.set("angle",o),Pi(i)&&(a.set("radius",i),e.firstCategoryDimIndex=0),Pi(o)&&(a.set("angle",o),e.firstCategoryDimIndex==null&&(e.firstCategoryDimIndex=1))},geo:function(r,e,t,a){e.coordSysDims=["lng","lat"]},parallel:function(r,e,t,a){var n=r.ecModel,i=n.getComponent("parallel",r.get("parallelIndex")),o=e.coordSysDims=i.dimensions.slice();C(i.parallelAxisIndex,function(s,l){var u=n.getComponent("parallelAxis",s),f=o[l];t.set(f,u),Pi(u)&&(a.set(f,u),e.firstCategoryDimIndex==null&&(e.firstCategoryDimIndex=l))})}};function Pi(r){return r.get("type")==="category"}function EC(r,e,t){t=t||{};var a=t.byIndex,n=t.stackedCoordDimension,i,o,s;pN(e)?i=e:(o=e.schema,i=o.dimensions,s=e.store);var l=!!(r&&r.get("stack")),u,f,h,v;if(C(i,function(m,_){U(m)&&(i[_]=m={name:m}),l&&!m.isExtraCoord&&(!a&&!u&&m.ordinalMeta&&(u=m),!f&&m.type!=="ordinal"&&m.type!=="time"&&(!n||n===m.coordDim)&&(f=m))}),f&&!a&&!u&&(a=!0),f){h="__\0ecstackresult_"+r.id,v="__\0ecstackedover_"+r.id,u&&(u.createInvertedIndices=!0);var c=f.coordDim,p=f.type,d=0;C(i,function(m){m.coordDim===c&&d++});var g={name:h,coordDim:c,coordDimIndex:d,type:p,isExtraCoord:!0,isCalculationCoord:!0,storeDimIndex:i.length},y={name:v,coordDim:v,coordDimIndex:d+1,type:p,isExtraCoord:!0,isCalculationCoord:!0,storeDimIndex:i.length+1};o?(s&&(g.storeDimIndex=s.ensureCalculationDimension(v,p),y.storeDimIndex=s.ensureCalculationDimension(h,p)),o.appendCalculationDimension(g),o.appendCalculationDimension(y)):(i.push(g),i.push(y))}return{stackedDimension:f&&f.name,stackedByDimension:u&&u.name,isStackedByIndex:a,stackedOverDimension:v,stackResultDimension:h}}function pN(r){return!IC(r.schema)}function ma(r,e){return!!e&&e===r.getCalculationInfo("stackedDimension")}function hy(r,e){return ma(r,e)?r.getCalculationInfo("stackResultDimension"):e}function dN(r,e){var t=r.get("coordinateSystem"),a=Io.get(t),n;return e&&e.coordSysDims&&(n=G(e.coordSysDims,function(i){var o={name:i},s=e.axisMap.get(i);if(s){var l=s.get("type");o.type=zf(l)}return o})),n||(n=a&&(a.getDimensionsInfo?a.getDimensionsInfo():a.dimensions.slice())||["x","y"]),n}function gN(r,e,t){var a,n;return t&&C(r,function(i,o){var s=i.coordDim,l=t.categoryAxisMap.get(s);l&&(a==null&&(a=o),i.ordinalMeta=l.getOrdinalMeta(),e&&(i.createInvertedIndices=!0)),i.otherDims.itemName!=null&&(n=!0)}),!n&&a!=null&&(r[a].otherDims.itemName=0),a}function Jr(r,e,t){t=t||{};var a=e.getSourceManager(),n,i=!1;r?(i=!0,n=ty(r)):(n=a.getSource(),i=n.sourceFormat===vr);var o=vN(e),s=dN(e,o),l=t.useEncodeDefaulter,u=K(l)?l:l?it(xA,s,e):null,f={coordDimensions:s,generateCoord:t.generateCoord,encodeDefine:e.getEncode(),encodeDefaulter:u,canOmitUnusedDimensions:!i},h=Eo(n,f),v=gN(h.dimensions,t.createInvertedIndices,o),c=i?null:a.getSharedDataStore(h),p=EC(e,{schema:h,store:c}),d=new Le(h,e);d.setCalculationInfo(p);var g=v!=null&&yN(n)?function(y,m,_,S){return S===v?_:this.defaultDimValueGetter(y,m,_,S)}:null;return d.hasItemOption=!1,d.initData(i?n:c,null,g),d}function yN(r){if(r.sourceFormat===vr){var e=mN(r.data||[]);return!z(yo(e))}}function mN(r){for(var e=0;et[1]&&(t[1]=e[1])},r.prototype.unionExtentFromData=function(e,t){this.unionExtent(e.getApproximateExtent(t))},r.prototype.getExtent=function(){return this._extent.slice()},r.prototype.setExtent=function(e,t){var a=this._extent;isNaN(e)||(a[0]=e),isNaN(t)||(a[1]=t)},r.prototype.isInExtentRange=function(e){return this._extent[0]<=e&&this._extent[1]>=e},r.prototype.isBlank=function(){return this._isBlank},r.prototype.setBlank=function(e){this._isBlank=e},r}();Sh(ta);var _N=0,dd=function(){function r(e){this.categories=e.categories||[],this._needCollect=e.needCollect,this._deduplication=e.deduplication,this.uid=++_N}return r.createByAxisModel=function(e){var t=e.option,a=t.data,n=a&&G(a,SN);return new r({categories:n,needCollect:!n,deduplication:t.dedplication!==!1})},r.prototype.getOrdinal=function(e){return this._getOrCreateMap().get(e)},r.prototype.parseAndCollect=function(e){var t,a=this._needCollect;if(!U(e)&&!a)return e;if(a&&!this._deduplication)return t=this.categories.length,this.categories[t]=e,t;var n=this._getOrCreateMap();return t=n.get(e),t==null&&(a?(t=this.categories.length,this.categories[t]=e,n.set(e,t)):t=NaN),t},r.prototype._getOrCreateMap=function(){return this._map||(this._map=Z(this.categories))},r}();function SN(r){return tt(r)&&r.value!=null?r.value:r+""}function gd(r){return r.type==="interval"||r.type==="log"}function xN(r,e,t,a){var n={},i=r[1]-r[0],o=n.interval=xg(i/e,!0);t!=null&&oa&&(o=n.interval=a);var s=n.intervalPrecision=kC(o),l=n.niceTickExtent=[Ht(Math.ceil(r[0]/o)*o,s),Ht(Math.floor(r[1]/o)*o,s)];return bN(l,r),n}function ec(r){var e=Math.pow(10,_h(r)),t=r/e;return t?t===2?t=3:t===3?t=5:t*=2:t=1,Ht(t*e)}function kC(r){return Sr(r)+2}function X_(r,e,t){r[e]=Math.max(Math.min(r[e],t[1]),t[0])}function bN(r,e){!isFinite(r[0])&&(r[0]=e[0]),!isFinite(r[1])&&(r[1]=e[1]),X_(r,0,e),X_(r,1,e),r[0]>r[1]&&(r[0]=r[1])}function zh(r,e){return r>=e[0]&&r<=e[1]}function Gh(r,e){return e[1]===e[0]?.5:(r-e[0])/(e[1]-e[0])}function Fh(r,e){return r*(e[1]-e[0])+e[0]}var Hh=function(r){k(e,r);function e(t){var a=r.call(this,t)||this;a.type="ordinal";var n=a.getSetting("ordinalMeta");return n||(n=new dd({})),z(n)&&(n=new dd({categories:G(n,function(i){return tt(i)?i.value:i})})),a._ordinalMeta=n,a._extent=a.getSetting("extent")||[0,n.categories.length-1],a}return e.prototype.parse=function(t){return t==null?NaN:U(t)?this._ordinalMeta.getOrdinal(t):Math.round(t)},e.prototype.contain=function(t){return t=this.parse(t),zh(t,this._extent)&&this._ordinalMeta.categories[t]!=null},e.prototype.normalize=function(t){return t=this._getTickNumber(this.parse(t)),Gh(t,this._extent)},e.prototype.scale=function(t){return t=Math.round(Fh(t,this._extent)),this.getRawOrdinalNumber(t)},e.prototype.getTicks=function(){for(var t=[],a=this._extent,n=a[0];n<=a[1];)t.push({value:n}),n++;return t},e.prototype.getMinorTicks=function(t){},e.prototype.setSortInfo=function(t){if(t==null){this._ordinalNumbersByTick=this._ticksByOrdinalNumber=null;return}for(var a=t.ordinalNumbers,n=this._ordinalNumbersByTick=[],i=this._ticksByOrdinalNumber=[],o=0,s=this._ordinalMeta.categories.length,l=Math.min(s,a.length);o=0&&t=0&&t=t},e.prototype.getOrdinalMeta=function(){return this._ordinalMeta},e.prototype.calcNiceTicks=function(){},e.prototype.calcNiceExtent=function(){},e.type="ordinal",e}(ta);ta.registerClass(Hh);var Cn=Ht,_a=function(r){k(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.type="interval",t._interval=0,t._intervalPrecision=2,t}return e.prototype.parse=function(t){return t},e.prototype.contain=function(t){return zh(t,this._extent)},e.prototype.normalize=function(t){return Gh(t,this._extent)},e.prototype.scale=function(t){return Fh(t,this._extent)},e.prototype.setExtent=function(t,a){var n=this._extent;isNaN(t)||(n[0]=parseFloat(t)),isNaN(a)||(n[1]=parseFloat(a))},e.prototype.unionExtent=function(t){var a=this._extent;t[0]a[1]&&(a[1]=t[1]),this.setExtent(a[0],a[1])},e.prototype.getInterval=function(){return this._interval},e.prototype.setInterval=function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=kC(t)},e.prototype.getTicks=function(t){var a=this._interval,n=this._extent,i=this._niceExtent,o=this._intervalPrecision,s=[];if(!a)return s;var l=1e4;n[0]l)return[];var f=s.length?s[s.length-1].value:i[1];return n[1]>f&&(t?s.push({value:Cn(f+a,o)}):s.push({value:n[1]})),s},e.prototype.getMinorTicks=function(t){for(var a=this.getTicks(!0),n=[],i=this.getExtent(),o=1;oi[0]&&c0&&(i=i===null?s:Math.min(i,s))}t[a]=i}}return t}function BC(r){var e=AN(r),t=[];return C(r,function(a){var n=a.coordinateSystem,i=n.getBaseAxis(),o=i.getExtent(),s;if(i.type==="category")s=i.getBandWidth();else if(i.type==="value"||i.type==="time"){var l=i.dim+"_"+i.index,u=e[l],f=Math.abs(o[1]-o[0]),h=i.scale.getExtent(),v=Math.abs(h[1]-h[0]);s=u?f/v*u:f}else{var c=a.getData();s=Math.abs(o[1]-o[0])/c.count()}var p=W(a.get("barWidth"),s),d=W(a.get("barMaxWidth"),s),g=W(a.get("barMinWidth")||(HC(a)?.5:1),s),y=a.get("barGap"),m=a.get("barCategoryGap");t.push({bandWidth:s,barWidth:p,barMaxWidth:d,barMinWidth:g,barGap:y,barCategoryGap:m,axisKey:cy(i),stackId:vy(a)})}),VC(t)}function VC(r){var e={};C(r,function(a,n){var i=a.axisKey,o=a.bandWidth,s=e[i]||{bandWidth:o,remainedWidth:o,autoWidthCount:0,categoryGap:null,gap:"20%",stacks:{}},l=s.stacks;e[i]=s;var u=a.stackId;l[u]||s.autoWidthCount++,l[u]=l[u]||{width:0,maxWidth:0};var f=a.barWidth;f&&!l[u].width&&(l[u].width=f,f=Math.min(s.remainedWidth,f),s.remainedWidth-=f);var h=a.barMaxWidth;h&&(l[u].maxWidth=h);var v=a.barMinWidth;v&&(l[u].minWidth=v);var c=a.barGap;c!=null&&(s.gap=c);var p=a.barCategoryGap;p!=null&&(s.categoryGap=p)});var t={};return C(e,function(a,n){t[n]={};var i=a.stacks,o=a.bandWidth,s=a.categoryGap;if(s==null){var l=St(i).length;s=Math.max(35-l*4,15)+"%"}var u=W(s,o),f=W(a.gap,1),h=a.remainedWidth,v=a.autoWidthCount,c=(h-u)/(v+(v-1)*f);c=Math.max(c,0),C(i,function(y){var m=y.maxWidth,_=y.minWidth;if(y.width){var S=y.width;m&&(S=Math.min(S,m)),_&&(S=Math.max(S,_)),y.width=S,h-=S+f*S,v--}else{var S=c;m&&mS&&(S=_),S!==c&&(y.width=S,h-=S+f*S,v--)}}),c=(h-u)/(v+(v-1)*f),c=Math.max(c,0);var p=0,d;C(i,function(y,m){y.width||(y.width=c),d=y,p+=y.width*(1+f)}),d&&(p-=d.width*f);var g=-p/2;C(i,function(y,m){t[n][m]=t[n][m]||{bandWidth:o,offset:g,width:y.width},g+=y.width*(1+f)})}),t}function CN(r,e,t){if(r&&e){var a=r[cy(e)];return a!=null&&t!=null?a[vy(t)]:a}}function zC(r,e){var t=NC(r,e),a=BC(t);C(t,function(n){var i=n.getData(),o=n.coordinateSystem,s=o.getBaseAxis(),l=vy(n),u=a[cy(s)][l],f=u.offset,h=u.width;i.setLayout({bandWidth:u.bandWidth,offset:f,size:h})})}function GC(r){return{seriesType:r,plan:Lo(),reset:function(e){if(FC(e)){var t=e.getData(),a=e.coordinateSystem,n=a.getBaseAxis(),i=a.getOtherAxis(n),o=t.getDimensionIndex(t.mapDimension(i.dim)),s=t.getDimensionIndex(t.mapDimension(n.dim)),l=e.get("showBackground",!0),u=t.mapDimension(i.dim),f=t.getCalculationInfo("stackResultDimension"),h=ma(t,u)&&!!t.getCalculationInfo("stackedOnSeries"),v=i.isHorizontal(),c=DN(n,i),p=HC(e),d=e.get("barMinHeight")||0,g=f&&t.getDimensionIndex(f),y=t.getLayout("size"),m=t.getLayout("offset");return{progress:function(_,S){for(var b=_.count,x=p&&Hr(b*3),w=p&&l&&Hr(b*3),T=p&&Hr(b),A=a.master.getRect(),D=v?A.width:A.height,M,I=S.getStore(),L=0;(M=_.next())!=null;){var P=I.get(h?g:o,M),R=I.get(s,M),E=c,N=void 0;h&&(N=+P-I.get(o,M));var O=void 0,B=void 0,F=void 0,H=void 0;if(v){var Y=a.dataToPoint([P,R]);if(h){var j=a.dataToPoint([N,R]);E=j[0]}O=E,B=Y[1]+m,F=Y[0]-E,H=y,Math.abs(F)0?t:1:t))}var MN=function(r,e,t,a){for(;t>>1;r[n][1]n&&(this._approxInterval=n);var s=yu.length,l=Math.min(MN(yu,this._approxInterval,0,s),s-1);this._interval=yu[l][1],this._minLevelUnit=yu[Math.max(l-1,0)][0]},e.prototype.parse=function(t){return Ct(t)?t:+$e(t)},e.prototype.contain=function(t){return zh(this.parse(t),this._extent)},e.prototype.normalize=function(t){return Gh(this.parse(t),this._extent)},e.prototype.scale=function(t){return Fh(t,this._extent)},e.type="time",e}(_a),yu=[["second",Hg],["minute",Wg],["hour",Os],["quarter-day",Os*6],["half-day",Os*12],["day",ir*1.2],["half-week",ir*3.5],["week",ir*7],["month",ir*31],["quarter",ir*95],["half-year",N0/2],["year",N0]];function IN(r,e,t,a){var n=$e(e),i=$e(t),o=function(p){return V0(n,p,a)===V0(i,p,a)},s=function(){return o("year")},l=function(){return s()&&o("month")},u=function(){return l()&&o("day")},f=function(){return u()&&o("hour")},h=function(){return f()&&o("minute")},v=function(){return h()&&o("second")},c=function(){return v()&&o("millisecond")};switch(r){case"year":return s();case"month":return l();case"day":return u();case"hour":return f();case"minute":return h();case"second":return v();case"millisecond":return c()}}function LN(r,e){return r/=ir,r>16?16:r>7.5?7:r>3.5?4:r>1.5?2:1}function PN(r){var e=30*ir;return r/=e,r>6?6:r>3?3:r>2?2:1}function RN(r){return r/=Os,r>12?12:r>6?6:r>3.5?4:r>2?2:1}function $_(r,e){return r/=e?Wg:Hg,r>30?30:r>20?20:r>15?15:r>10?10:r>5?5:r>2?2:1}function EN(r){return xg(r,!0)}function kN(r,e,t){var a=new Date(r);switch(eo(e)){case"year":case"month":a[lA(t)](0);case"day":a[uA(t)](1);case"hour":a[fA(t)](0);case"minute":a[hA(t)](0);case"second":a[vA(t)](0),a[cA(t)](0)}return a.getTime()}function ON(r,e,t,a){var n=1e4,i=oA,o=0;function s(D,M,I,L,P,R,E){for(var N=new Date(M),O=M,B=N[L]();O1&&R===0&&I.unshift({value:I[0].value-O})}}for(var R=0;R=a[0]&&m<=a[1]&&h++)}var _=(a[1]-a[0])/e;if(h>_*1.5&&v>_/1.5||(u.push(g),h>_||r===i[c]))break}f=[]}}}for(var S=Pt(G(u,function(D){return Pt(D,function(M){return M.value>=a[0]&&M.value<=a[1]&&!M.notAdd})}),function(D){return D.length>0}),b=[],x=S.length-1,c=0;c0;)i*=10;var s=[Ht(VN(a[0]/i)*i),Ht(BN(a[1]/i)*i)];this._interval=i,this._niceExtent=s}},e.prototype.calcNiceExtent=function(t){Vs.calcNiceExtent.call(this,t),this._fixMin=t.fixMin,this._fixMax=t.fixMax},e.prototype.parse=function(t){return t},e.prototype.contain=function(t){return t=dr(t)/dr(this.base),zh(t,this._extent)},e.prototype.normalize=function(t){return t=dr(t)/dr(this.base),Gh(t,this._extent)},e.prototype.scale=function(t){return t=Fh(t,this._extent),mu(this.base,t)},e.type="log",e}(ta),WC=dy.prototype;WC.getMinorTicks=Vs.getMinorTicks;WC.getLabel=Vs.getLabel;function _u(r,e){return NN(r,Sr(e))}ta.registerClass(dy);var zN=function(){function r(e,t,a){this._prepareParams(e,t,a)}return r.prototype._prepareParams=function(e,t,a){a[1]0&&l>0&&!u&&(s=0),s<0&&l<0&&!f&&(l=0));var v=this._determinedMin,c=this._determinedMax;return v!=null&&(s=v,u=!0),c!=null&&(l=c,f=!0),{min:s,max:l,minFixed:u,maxFixed:f,isBlank:h}},r.prototype.modifyDataMinMax=function(e,t){this[FN[e]]=t},r.prototype.setDeterminedMinMax=function(e,t){var a=GN[e];this[a]=t},r.prototype.freeze=function(){this.frozen=!0},r}(),GN={min:"_determinedMin",max:"_determinedMax"},FN={min:"_dataMin",max:"_dataMax"};function UC(r,e,t){var a=r.rawExtentInfo;return a||(a=new zN(r,e,t),r.rawExtentInfo=a,a)}function Su(r,e){return e==null?null:no(e)?NaN:r.parse(e)}function YC(r,e){var t=r.type,a=UC(r,e,r.getExtent()).calculate();r.setBlank(a.isBlank);var n=a.min,i=a.max,o=e.ecModel;if(o&&t==="time"){var s=NC("bar",o),l=!1;if(C(s,function(h){l=l||h.getBaseAxis()===e.axis}),l){var u=BC(s),f=HN(n,i,e,u);n=f.min,i=f.max}}return{extent:[n,i],fixMin:a.minFixed,fixMax:a.maxFixed}}function HN(r,e,t,a){var n=t.axis.getExtent(),i=n[1]-n[0],o=CN(a,t.axis);if(o===void 0)return{min:r,max:e};var s=1/0;C(o,function(c){s=Math.min(c.offset,s)});var l=-1/0;C(o,function(c){l=Math.max(c.offset+c.width,l)}),s=Math.abs(s),l=Math.abs(l);var u=s+l,f=e-r,h=1-(s+l)/i,v=f/h-f;return e+=v*(l/u),r-=v*(s/u),{min:r,max:e}}function li(r,e){var t=e,a=YC(r,t),n=a.extent,i=t.get("splitNumber");r instanceof dy&&(r.base=t.get("logBase"));var o=r.type,s=t.get("interval"),l=o==="interval"||o==="time";r.setExtent(n[0],n[1]),r.calcNiceExtent({splitNumber:i,fixMin:a.fixMin,fixMax:a.fixMax,minInterval:l?t.get("minInterval"):null,maxInterval:l?t.get("maxInterval"):null}),s!=null&&r.setInterval&&r.setInterval(s)}function Pl(r,e){if(e=e||r.get("type"),e)switch(e){case"category":return new Hh({ordinalMeta:r.getOrdinalMeta?r.getOrdinalMeta():r.getCategories(),extent:[1/0,-1/0]});case"time":return new py({locale:r.ecModel.getLocaleModel(),useUTC:r.ecModel.get("useUTC")});default:return new(ta.getClass(e)||_a)}}function WN(r){var e=r.scale.getExtent(),t=e[0],a=e[1];return!(t>0&&a>0||t<0&&a<0)}function ko(r){var e=r.getLabelModel().get("formatter"),t=r.type==="category"?r.scale.getExtent()[0]:null;return r.scale.type==="time"?function(a){return function(n,i){return r.scale.getFormattedLabel(n,i,a)}}(e):U(e)?function(a){return function(n){var i=r.scale.getLabel(n),o=a.replace("{value}",i??"");return o}}(e):K(e)?function(a){return function(n,i){return t!=null&&(i=n.value-t),a(gy(r,n),i,n.level!=null?{level:n.level}:null)}}(e):function(a){return r.scale.getLabel(a)}}function gy(r,e){return r.type==="category"?r.scale.getLabel(e):e.value}function UN(r){var e=r.model,t=r.scale;if(!(!e.get(["axisLabel","show"])||t.isBlank())){var a,n,i=t.getExtent();t instanceof Hh?n=t.count():(a=t.getTicks(),n=a.length);var o=r.getLabelModel(),s=ko(r),l,u=1;n>40&&(u=Math.ceil(n/40));for(var f=0;fr[1]&&(r[1]=n[1])})}var Oo=function(){function r(){}return r.prototype.getNeedCrossZero=function(){var e=this.option;return!e.scale},r.prototype.getCoordSysModel=function(){},r}();function $N(r){return Jr(null,r)}var ZN={isDimensionStacked:ma,enableDataStack:EC,getStackedDimension:hy};function qN(r,e){var t=e;e instanceof Mt||(t=new Mt(e));var a=Pl(t);return a.setExtent(r[0],r[1]),li(a,t),a}function KN(r){Xt(r,Oo)}function jN(r,e){return e=e||{},Nt(r,null,null,e.state!=="normal")}const y7=Object.freeze(Object.defineProperty({__proto__:null,createDimensions:sN,createList:$N,createScale:qN,createSymbol:Zt,createTextStyle:jN,dataStack:ZN,enableHoverEmphasis:Ya,getECData:nt,getLayoutRect:jt,mixinAxisModelCommonMethods:KN},Symbol.toStringTag,{value:"Module"}));var QN=1e-8;function q_(r,e){return Math.abs(r-e)n&&(a=o,n=l)}if(a)return tB(a.exterior);var u=this.getBoundingRect();return[u.x+u.width/2,u.y+u.height/2]},e.prototype.getBoundingRect=function(t){var a=this._rect;if(a&&!t)return a;var n=[1/0,1/0],i=[-1/0,-1/0],o=this.geometries;return C(o,function(s){s.type==="polygon"?K_(s.exterior,n,i,t):C(s.points,function(l){K_(l,n,i,t)})}),isFinite(n[0])&&isFinite(n[1])&&isFinite(i[0])&&isFinite(i[1])||(n[0]=n[1]=i[0]=i[1]=0),a=new ht(n[0],n[1],i[0]-n[0],i[1]-n[1]),t||(this._rect=a),a},e.prototype.contain=function(t){var a=this.getBoundingRect(),n=this.geometries;if(!a.contain(t[0],t[1]))return!1;t:for(var i=0,o=n.length;i>1^-(s&1),l=l>>1^-(l&1),s+=n,l+=i,n=s,i=l,a.push([s/t,l/t])}return a}function aB(r,e){return r=rB(r),G(Pt(r.features,function(t){return t.geometry&&t.properties&&t.geometry.coordinates.length>0}),function(t){var a=t.properties,n=t.geometry,i=[];switch(n.type){case"Polygon":var o=n.coordinates;i.push(new j_(o[0],o.slice(1)));break;case"MultiPolygon":C(n.coordinates,function(l){l[0]&&i.push(new j_(l[0],l.slice(1)))});break;case"LineString":i.push(new Q_([n.coordinates]));break;case"MultiLineString":i.push(new Q_(n.coordinates))}var s=new ZC(a[e||"name"],i,a.cp);return s.properties=a,s})}const m7=Object.freeze(Object.defineProperty({__proto__:null,MAX_SAFE_INTEGER:Gp,asc:Ue,getPercentWithPrecision:U2,getPixelPrecision:_g,getPrecision:Sr,getPrecisionSafe:oT,isNumeric:bg,isRadianAroundZero:io,linearMap:Lt,nice:xg,numericToNumber:Zr,parseDate:$e,quantile:Ku,quantity:lT,quantityExponent:_h,reformIntervals:Fp,remRadian:Sg,round:Ht},Symbol.toStringTag,{value:"Module"})),_7=Object.freeze(Object.defineProperty({__proto__:null,format:Il,parse:$e},Symbol.toStringTag,{value:"Module"})),S7=Object.freeze(Object.defineProperty({__proto__:null,Arc:Cl,BezierCurve:So,BoundingRect:ht,Circle:Kr,CompoundPath:Ch,Ellipse:Al,Group:at,Image:oe,IncrementalDisplayable:XT,Line:Jt,LinearGradient:xo,Polygon:Se,Polyline:be,RadialGradient:kg,Rect:wt,Ring:_o,Sector:_e,Text:bt,clipPointsByRect:Vg,clipRectByRect:jT,createIcon:wo,extendPath:qT,extendShape:ZT,getShapeClass:Dh,getTransform:Xa,initProps:Vt,makeImage:Ng,makePath:Dl,mergePath:We,registerShape:hr,resizePath:Bg,updateProps:Dt},Symbol.toStringTag,{value:"Module"})),x7=Object.freeze(Object.defineProperty({__proto__:null,addCommas:Yg,capitalFirst:pE,encodeHTML:Me,formatTime:cE,formatTpl:$g,getTextRect:hE,getTooltipMarker:pA,normalizeCssArray:pi,toCamelCase:Xg,truncateText:_T},Symbol.toStringTag,{value:"Module"})),b7=Object.freeze(Object.defineProperty({__proto__:null,bind:X,clone:et,curry:it,defaults:Q,each:C,extend:V,filter:Pt,indexOf:vt,inherits:hg,isArray:z,isFunction:K,isObject:tt,isString:U,map:G,merge:st,reduce:lr},Symbol.toStringTag,{value:"Module"}));var il=Tt();function KC(r,e){var t=G(e,function(a){return r.scale.parse(a)});return r.type==="time"&&t.length>0&&(t.sort(),t.unshift(t[0]),t.push(t[t.length-1])),t}function nB(r){var e=r.getLabelModel().get("customValues");if(e){var t=ko(r);return{labels:KC(r,e).map(function(a){var n={value:a};return{formattedLabel:t(n),rawLabel:r.scale.getLabel(n),tickValue:a}})}}return r.type==="category"?oB(r):lB(r)}function iB(r,e){var t=r.getTickModel().get("customValues");return t?{ticks:KC(r,t)}:r.type==="category"?sB(r,e):{ticks:G(r.scale.getTicks(),function(a){return a.value})}}function oB(r){var e=r.getLabelModel(),t=jC(r,e);return!e.get("show")||r.scale.isBlank()?{labels:[],labelCategoryInterval:t.labelCategoryInterval}:t}function jC(r,e){var t=QC(r,"labels"),a=yy(e),n=JC(t,a);if(n)return n;var i,o;return K(a)?i=rD(r,a):(o=a==="auto"?uB(r):a,i=eD(r,o)),tD(t,a,{labels:i,labelCategoryInterval:o})}function sB(r,e){var t=QC(r,"ticks"),a=yy(e),n=JC(t,a);if(n)return n;var i,o;if((!e.get("show")||r.scale.isBlank())&&(i=[]),K(a))i=rD(r,a,!0);else if(a==="auto"){var s=jC(r,r.getLabelModel());o=s.labelCategoryInterval,i=G(s.labels,function(l){return l.tickValue})}else o=a,i=eD(r,o,!0);return tD(t,a,{ticks:i,tickCategoryInterval:o})}function lB(r){var e=r.scale.getTicks(),t=ko(r);return{labels:G(e,function(a,n){return{level:a.level,formattedLabel:t(a,n),rawLabel:r.scale.getLabel(a),tickValue:a.value}})}}function QC(r,e){return il(r)[e]||(il(r)[e]=[])}function JC(r,e){for(var t=0;t40&&(s=Math.max(1,Math.floor(o/40)));for(var l=i[0],u=r.dataToCoord(l+1)-r.dataToCoord(l),f=Math.abs(u*Math.cos(a)),h=Math.abs(u*Math.sin(a)),v=0,c=0;l<=i[1];l+=s){var p=0,d=0,g=bl(t({value:l}),e.font,"center","top");p=g.width*1.3,d=g.height*1.3,v=Math.max(v,p,7),c=Math.max(c,d,7)}var y=v/f,m=c/h;isNaN(y)&&(y=1/0),isNaN(m)&&(m=1/0);var _=Math.max(0,Math.floor(Math.min(y,m))),S=il(r.model),b=r.getExtent(),x=S.lastAutoInterval,w=S.lastTickCount;return x!=null&&w!=null&&Math.abs(x-_)<=1&&Math.abs(w-o)<=1&&x>_&&S.axisExtent0===b[0]&&S.axisExtent1===b[1]?_=x:(S.lastTickCount=o,S.lastAutoInterval=_,S.axisExtent0=b[0],S.axisExtent1=b[1]),_}function hB(r){var e=r.getLabelModel();return{axisRotate:r.getRotate?r.getRotate():r.isHorizontal&&!r.isHorizontal()?90:0,labelRotate:e.get("rotate")||0,font:e.getFont()}}function eD(r,e,t){var a=ko(r),n=r.scale,i=n.getExtent(),o=r.getLabelModel(),s=[],l=Math.max((e||0)+1,1),u=i[0],f=n.count();u!==0&&l>1&&f/l>2&&(u=Math.round(Math.ceil(u/l)*l));var h=XC(r),v=o.get("showMinLabel")||h,c=o.get("showMaxLabel")||h;v&&u!==i[0]&&d(i[0]);for(var p=u;p<=i[1];p+=l)d(p);c&&p-l!==i[1]&&d(i[1]);function d(g){var y={value:g};s.push(t?g:{formattedLabel:a(y),rawLabel:n.getLabel(y),tickValue:g})}return s}function rD(r,e,t){var a=r.scale,n=ko(r),i=[];return C(a.getTicks(),function(o){var s=a.getLabel(o),l=o.value;e(o.value,s)&&i.push(t?l:{formattedLabel:n(o),rawLabel:s,tickValue:l})}),i}var J_=[0,1],Lr=function(){function r(e,t,a){this.onBand=!1,this.inverse=!1,this.dim=e,this.scale=t,this._extent=a||[0,0]}return r.prototype.contain=function(e){var t=this._extent,a=Math.min(t[0],t[1]),n=Math.max(t[0],t[1]);return e>=a&&e<=n},r.prototype.containData=function(e){return this.scale.contain(e)},r.prototype.getExtent=function(){return this._extent.slice()},r.prototype.getPixelPrecision=function(e){return _g(e||this.scale.getExtent(),this._extent)},r.prototype.setExtent=function(e,t){var a=this._extent;a[0]=e,a[1]=t},r.prototype.dataToCoord=function(e,t){var a=this._extent,n=this.scale;return e=n.normalize(e),this.onBand&&n.type==="ordinal"&&(a=a.slice(),t1(a,n.count())),Lt(e,J_,a,t)},r.prototype.coordToData=function(e,t){var a=this._extent,n=this.scale;this.onBand&&n.type==="ordinal"&&(a=a.slice(),t1(a,n.count()));var i=Lt(e,a,J_,t);return this.scale.scale(i)},r.prototype.pointToData=function(e,t){},r.prototype.getTicksCoords=function(e){e=e||{};var t=e.tickModel||this.getTickModel(),a=iB(this,t),n=a.ticks,i=G(n,function(s){return{coord:this.dataToCoord(this.scale.type==="ordinal"?this.scale.getRawOrdinalNumber(s):s),tickValue:s}},this),o=t.get("alignWithLabel");return vB(this,i,o,e.clamp),i},r.prototype.getMinorTicksCoords=function(){if(this.scale.type==="ordinal")return[];var e=this.model.getModel("minorTick"),t=e.get("splitNumber");t>0&&t<100||(t=5);var a=this.scale.getMinorTicks(t),n=G(a,function(i){return G(i,function(o){return{coord:this.dataToCoord(o),tickValue:o}},this)},this);return n},r.prototype.getViewLabels=function(){return nB(this).labels},r.prototype.getLabelModel=function(){return this.model.getModel("axisLabel")},r.prototype.getTickModel=function(){return this.model.getModel("axisTick")},r.prototype.getBandWidth=function(){var e=this._extent,t=this.scale.getExtent(),a=t[1]-t[0]+(this.onBand?1:0);a===0&&(a=1);var n=Math.abs(e[1]-e[0]);return Math.abs(n)/a},r.prototype.calculateCategoryInterval=function(){return fB(this)},r}();function t1(r,e){var t=r[1]-r[0],a=e,n=t/a/2;r[0]+=n,r[1]-=n}function vB(r,e,t,a){var n=e.length;if(!r.onBand||t||!n)return;var i=r.getExtent(),o,s;if(n===1)e[0].coord=i[0],o=e[1]={coord:i[1]};else{var l=e[n-1].tickValue-e[0].tickValue,u=(e[n-1].coord-e[0].coord)/l;C(e,function(c){c.coord-=u/2});var f=r.scale.getExtent();s=1+f[1]-e[n-1].tickValue,o={coord:e[n-1].coord+u*s},e.push(o)}var h=i[0]>i[1];v(e[0].coord,i[0])&&(a?e[0].coord=i[0]:e.shift()),a&&v(i[0],e[0].coord)&&e.unshift({coord:i[0]}),v(i[1],o.coord)&&(a?o.coord=i[1]:e.pop()),a&&v(o.coord,i[1])&&e.push({coord:i[1]});function v(c,p){return c=Ht(c),p=Ht(p),h?c>p:cn&&(n+=es);var c=Math.atan2(s,o);if(c<0&&(c+=es),c>=a&&c<=n||c+es>=a&&c+es<=n)return l[0]=f,l[1]=h,u-t;var p=t*Math.cos(a)+r,d=t*Math.sin(a)+e,g=t*Math.cos(n)+r,y=t*Math.sin(n)+e,m=(p-o)*(p-o)+(d-s)*(d-s),_=(g-o)*(g-o)+(y-s)*(y-s);return m<_?(l[0]=p,l[1]=d,Math.sqrt(m)):(l[0]=g,l[1]=y,Math.sqrt(_))}function Ff(r,e,t,a,n,i,o,s){var l=n-r,u=i-e,f=t-r,h=a-e,v=Math.sqrt(f*f+h*h);f/=v,h/=v;var c=l*f+u*h,p=c/v;s&&(p=Math.min(Math.max(p,0),1)),p*=v;var d=o[0]=r+p*f,g=o[1]=e+p*h;return Math.sqrt((d-n)*(d-n)+(g-i)*(g-i))}function aD(r,e,t,a,n,i,o){t<0&&(r=r+t,t=-t),a<0&&(e=e+a,a=-a);var s=r+t,l=e+a,u=o[0]=Math.min(Math.max(n,r),s),f=o[1]=Math.min(Math.max(i,e),l);return Math.sqrt((u-n)*(u-n)+(f-i)*(f-i))}var _r=[];function gB(r,e,t){var a=aD(e.x,e.y,e.width,e.height,r.x,r.y,_r);return t.set(_r[0],_r[1]),a}function yB(r,e,t){for(var a=0,n=0,i=0,o=0,s,l,u=1/0,f=e.data,h=r.x,v=r.y,c=0;c