文章列表

联邦查询神器Trino初体验 →

作者:微信小助手

<p><span style="font-size: 14px;letter-spacing: 0.578px;text-indent: 0em;">Trino是一个分布式SQL查询引擎,设计用来查询大规模的数据集存储在Hadoop、SQL和NoSQL数据库、对象存储等多种数据源中。它支持跨多个数据源的联合查询,对数据的位置透明,使得用户可以在一个系统中分析所有的数据。Trino的设计目标是提供快速(即时)的分析查询,它使用了许多优化技术来实现高查询性能。</span><br></p> <section style="line-height: 1.6em;text-align: justify;margin: 0px 0px 24px;text-indent: 0em;"> <span style="letter-spacing: 0.578px;text-decoration: none solid rgba(0, 0, 0, 0.9);font-size: 14px;">Trino官网:https://trino.io/</span> </section> <section style="line-height: 1.6em;text-align: justify;margin: 0px 0px 24px;text-indent: 0em;"> <img class="rich_pages wxw-img" data-galleryid="" data-imgfileid="100004064" data-ratio="0.5054151624548736" data-s="300,640" src="/upload/95f71423f5664c3e46abb25435be8150.png" data-type="png" data-w="554" style="text-align: center;font-size: var(--articleFontsize);letter-spacing: 0.034em;"> </section> <p><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">Trino</span>目前支持的数据源包括<span style="font-family: Calibri;">Accumulo</span>、<span style="font-family: Calibri;">Atop</span>、<span style="font-family: Calibri;">BigQuery</span>、<span style="font-family: Calibri;">Black Hole</span>、<span style="font-family: Calibri;">Cassandra</span>、<span style="font-family: Calibri;">ClickHouse</span>、<span style="font-family: Calibri;">Delta Lake</span>、<span style="font-family: Calibri;">Druid</span>、<span style="font-family: Calibri;">Elasticsearch</span>、<span style="font-family: Calibri;">Google Sheets</span>、<span style="font-family: Calibri;">Hive</span>、<span style="font-family: Calibri;">Hudi</span>、<span style="font-family: Calibri;">Iceberg</span>、<span style="font-family: Calibri;">Ignite</span>、<span style="font-family: Calibri;">JMX</span>、<span style="font-family: Calibri;">Kafka</span>、<span style="font-family: Calibri;">Kinesis</span>、<span style="font-family: Calibri;">Kudu</span>、<span style="font-family: Calibri;">Local File</span>、<span style="font-family: Calibri;">MariaDB</span>、<span style="font-family: Calibri;">Memory</span>、<span style="font-family: Calibri;">MongoDB</span>、<span style="font-family: Calibri;">MySQL</span>、<span style="font-family: Calibri;">OpenSearch</span>、<span style="font-family: Calibri;">Oracle</span>、<span style="font-family: Calibri;">Phoenix</span>、<span style="font-family: Calibri;">Pinot</span>、<span style="font-family: Calibri;">PostgreSQL</span>、<span style="font-family: Calibri;">Prometheus</span>、<span style="font-family: Calibri;">Redis</span>、<span style="font-family: Calibri;">Redshift</span>、<span style="font-family: Calibri;">SingleStore</span>、<span style="font-family: Calibri;">SQL Server</span>、<span style="font-family: Calibri;">System</span>、<span style="font-family: Calibri;">Thrift</span>、<span style="font-family: Calibri;">TPCDS</span>、<span style="font-family: Calibri;">TPCH</span>。 <o:p></o:p></span></p> <p><span style="font-size: 14px;"><span style="font-family: 等线;"><span style="font-family: 等线;">本文介绍</span><span style="font-family: Calibri;">trino</span><span style="font-family: 等线;">安装及使用Trino进行联邦查询</span><span style="font-family: Calibri;">mysql</span><span style="font-family: 等线;">和</span><span style="font-family: Calibri;">sqlserver</span><span style="font-family: 等线;">中的数据。</span></span><span style="font-family: Calibri;"> <o:p></o:p></span></span></p> <p><strong><span style="font-size: 14px;font-family: 等线;">1.<span style="font-family: Calibri;">Trino</span><span style="font-family: 等线;">安装</span></span></strong><span style="font-size: 14px;font-family: Calibri;"> <o:p></o:p></span></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.1 </span><span style="font-family: 等线;">设置</span><span style="font-family: Calibri;">java17</span></span></strong><span style="font-size: 14px;font-family: Calibri;"> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;">Trino 400 <span style="font-family: 等线;">需要 </span><span style="font-family: Calibri;">64 </span><span style="font-family: 等线;">位版本的 </span><span style="font-family: Calibri;">Java 17</span><span style="font-family: 等线;">,最低版本要求为 </span><span style="font-family: Calibri;">17.0.3</span><span style="font-family: 等线;">。早期的主要版本(例如 </span><span style="font-family: Calibri;">Java 8 </span><span style="font-family: 等线;">或 </span><span style="font-family: Calibri;">Java 11</span><span style="font-family: 等线;">)不起作用。</span> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: 等线;"><span style="font-family: 等线;">如果你安装的是</span><span style="font-family: Calibri;">java8</span><span style="font-family: 等线;">,可以使用以下方式同时安装</span><span style="font-family: Calibri;">java17+</span></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer">update-alternatives --install /usr/bin/java java /opt/software/jdk-18/bin/java 1</span></code></pre> </section> <p><span style="font-size: 14px;letter-spacing: 0.034em;font-family: 等线;">其中 </span><span style="font-size: 14px;letter-spacing: 0.034em;font-family: Calibri;">/opt/software/jdk-18</span><span style="font-size: 14px;letter-spacing: 0.034em;font-family: 等线;">&nbsp;是<span style="font-family: Calibri;">jdk-18</span>的安装目录</span><br></p> <p><span style="font-family: 等线;font-size: 14px;">需要切换到<span style="font-family: Calibri;">jdk-18</span>可以使用<span style="font-family: Calibri;">update-alternatives --config java </span>命令进行切换,选择对用的<span style="font-family: Calibri;">jdk</span>版本就可以</span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="37" data-backw="503" data-galleryid="" data-imgfileid="100004066" data-ratio="0.073558648111332" data-s="300,640" src="/upload/9ad4423aa3805a0497930290b8f53b08.png" data-type="png" data-w="503" style="width: 100%;height: auto;"></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.2 </span><span style="font-family: 等线;">安装</span><span style="font-family: Calibri;">python2.6+</span></span></strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;"></span> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: 等线;"><span style="font-family: 等线;">这里建议使用</span><span style="font-family: Calibri;">anaconda</span><span style="font-family: 等线;">安装</span> <o:p></o:p></span></p> <p><a href="https://mp.weixin.qq.com/s?__biz=Mzg5Mzg3MzkwNA==&amp;mid=2247484316&amp;idx=1&amp;sn=dd571faa66971d97f999b7d9b0dfb288&amp;scene=21#wechat_redirect" style="font-family: Calibri;color: rgb(0, 0, 255);text-decoration: underline;font-size: 14px;" data-linktype="2"><span style="font-family: Calibri;color: rgb(0, 0, 255);text-decoration: underline;font-size: 14px;">https://mp.weixin.qq.com/s/PWaPQhftDnd64mHn-W3X9Q</span></a><span style="font-family: Calibri;font-size: 14px;"> <o:p></o:p></span></p> <p><a href="https://mp.weixin.qq.com/s?__biz=Mzg5Mzg3MzkwNA==&amp;mid=2247484344&amp;idx=1&amp;sn=b88558dc8646cd7dc293eb5a76faa665&amp;scene=21#wechat_redirect" style="font-family: Calibri;color: rgb(0, 0, 255);text-decoration: underline;font-size: 14px;" data-linktype="2"><span style="font-family: Calibri;color: rgb(0, 0, 255);text-decoration: underline;font-size: 14px;">https://mp.weixin.qq.com/s/FC1QyWvzpWNUwAS7QS62RQ</span></a><span style="mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:等线;mso-bidi-font-family:'Times New Roman';"> <o:p></o:p></span></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.3 </span><span style="font-family: 等线;">下载</span><span style="font-family: Calibri;">Trino</span></span></strong><span style="font-size: 14px;font-family: Calibri;"> <o:p></o:p></span></p> <p><span style="font-family: Calibri;font-size: 14px;">下载地址:</span><span style="font-family: Calibri;color: rgb(0, 0, 255);text-decoration: underline;font-size: 14px;">https://repo.maven.apache.org/maven2/io/trino/trino-server/</span><span style="mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:等线;mso-bidi-font-family:'Times New Roman';"> <o:p></o:p></span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="275" data-backw="515" data-galleryid="" data-imgfileid="100004067" data-ratio="0.5339805825242718" data-s="300,640" src="/upload/7210eadeef95f8b80f72d3314de55be4.png" data-type="png" data-w="515" style="width: 100%;height: auto;"></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.4 </span><span style="font-family: 等线;">解压</span><span style="font-family: Calibri;">Trino</span></span></strong><span style="font-size: 14px;font-family: 等线;"> <o:p></o:p></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="nginx"><code><span class="code-snippet_outer">tar -zxvf trino-server-392.tar.gz -C /opt/software</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="164" data-backw="518" data-galleryid="" data-imgfileid="100004068" data-ratio="0.3166023166023166" data-s="300,640" src="/upload/0ead3c56555b5372412ee7185802a919.png" data-type="png" data-w="518" style="width: 100%;height: auto;"></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.5 </span><span style="font-family: 等线;">配置 </span><span style="font-family: Calibri;">Trino</span></span></strong><span style="font-size: 14px;font-family: 等线;"> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;"><span style="font-family: 等线;">在安装目录中创建一个</span>etc<span style="font-family: 等线;">目录,我们会在该目录中配置以下:</span> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;">trino<span style="font-family: 等线;">节点配置:配置每个</span><span style="font-family: Calibri;">trino</span><span style="font-family: 等线;">节点的环境。</span> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;">JVM<span style="font-family: 等线;">配置:配置</span><span style="font-family: Calibri;">JVM</span><span style="font-family: 等线;">的相关参数。</span> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;">Config<span style="font-family: 等线;">属性:配置</span><span style="font-family: Calibri;">trino</span><span style="font-family: 等线;">服务器。</span> <o:p></o:p></span></p> <p><span style="font-family: Calibri;font-size: 14px;">Catalog<span style="font-family: 等线;">属性:配置</span>trino<span style="font-family: 等线;">的</span>connector<span style="font-family: 等线;">(数据源)</span></span><span style="mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:等线;mso-bidi-font-family:'Times New Roman';"> <o:p></o:p></span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="249" data-backw="466" data-galleryid="" data-imgfileid="100004069" data-ratio="0.5343347639484979" data-s="300,640" src="/upload/8c438110bbe8acec30cd9d12b8b22dd9.png" data-type="png" data-w="466" style="width: 100%;height: auto;"></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.5.1 </span><span style="font-family: 等线;">创建配置目录</span></span></strong><span style="font-size: 14px;font-family: 等线;"> <o:p></o:p></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="nginx"><code><span class="code-snippet_outer">mkdir /opt/software/trino-server-392/etc</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="250" data-backw="469" data-galleryid="" data-imgfileid="100004070" data-ratio="0.5330490405117271" data-s="300,640" src="/upload/7f73f65b7ef27ab55dd1101f2eea35ac.png" data-type="png" data-w="469" style="width: 100%;height: auto;"></p> <p><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.5.2 </span><span style="font-family: 等线;">配置节点属性</span></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="ruby"><code><span class="code-snippet_outer">vi etc/node.properties</span></code><code><span class="code-snippet_outer"># 环境的名字。集群中所有的Trino节点必须具有相同的环境名称。</span></code><code><span class="code-snippet_outer">node.environment=test</span></code><code><span class="code-snippet_outer"># 此Trino安装的唯一标识符。这对于每个节点都必须是唯一的。</span></code><code><span class="code-snippet_outer">node.id=ffffffff-ffff-ffff-ffff-ffffffffffff</span></code><code><span class="code-snippet_outer"># 数据目录的位置(文件系统路径)。Trino在这里存储日志和其他数据。</span></code><code><span class="code-snippet_outer">node.data-dir=/opt/software/trino/data</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="41" data-backw="472" data-galleryid="" data-imgfileid="100004071" data-ratio="0.08686440677966102" data-s="300,640" src="/upload/a55a792e391ac20fb167944b6d997d05.png" data-type="png" data-w="472" style="width: 100%;height: auto;"></p> <p><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.5.3 JVM</span><span style="font-family: 等线;">配置</span> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;"><span style="font-family: 等线;">每个节点可以配置不同的容量</span>,<span style="font-family: 等线;">根据服务器实际性能进行修改</span></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="diff"><code><span class="code-snippet_outer">vi etc/jvm.config</span></code><code><span class="code-snippet_outer">-server</span></code><code><span class="code-snippet_outer">-Xmx16G</span></code><code><span class="code-snippet_outer">-XX:InitialRAMPercentage=80</span></code><code><span class="code-snippet_outer">-XX:MaxRAMPercentage=80</span></code><code><span class="code-snippet_outer">-XX:G1HeapRegionSize=32M</span></code><code><span class="code-snippet_outer">-XX:+ExplicitGCInvokesConcurrent</span></code><code><span class="code-snippet_outer">-XX:+ExitOnOutOfMemoryError</span></code><code><span class="code-snippet_outer">-XX:+HeapDumpOnOutOfMemoryError</span></code><code><span class="code-snippet_outer">-XX:-OmitStackTraceInFastThrow</span></code><code><span class="code-snippet_outer">-XX:ReservedCodeCacheSize=512M</span></code><code><span class="code-snippet_outer">-XX:PerMethodRecompilationCutoff=10000</span></code><code><span class="code-snippet_outer">-XX:PerBytecodeRecompilationCutoff=10000</span></code><code><span class="code-snippet_outer">-Djdk.attach.allowAttachSelf=true</span></code><code><span class="code-snippet_outer">-Djdk.nio.maxCachedBufferSize=2000000</span></code><code><span class="code-snippet_outer">-XX:+UnlockDiagnosticVMOptions</span></code><code><span class="code-snippet_outer">-XX:+UseAESCTRIntrinsics</span></code><code><span class="code-snippet_outer"># Disable Preventive GC for performance reasons (JDK-8293861)</span></code><code><span class="code-snippet_outer">-XX:-G1UsePreventiveGC</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="131" data-backw="504" data-galleryid="" data-imgfileid="100004072" data-ratio="0.25992063492063494" data-s="300,640" src="/upload/055d834fcd884fd3b44160edb78d8815.png" data-type="png" data-w="504" style="width: 100%;height: auto;"></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.5.4 </span><span style="font-family: 等线;">配置</span><span style="font-family: Calibri;">Trino</span><span style="font-family: 等线;">服务器</span></span></strong></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="php"><code><span class="code-snippet_outer">vi etc/config.properties</span></code><code><span class="code-snippet_outer">#如果您要设置一台机器进行测试,它既充当协调器又充当工作人员,请使用以下配置:</span></code><code><span class="code-snippet_outer">coordinator=true</span></code><code><span class="code-snippet_outer">node-scheduler.include-coordinator=true</span></code><code><span class="code-snippet_outer">http-server.http.port=8080</span></code><code><span class="code-snippet_outer">discovery.uri=http://192.168.31.128:8080</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="57" data-backw="504" data-galleryid="" data-imgfileid="100004073" data-ratio="0.1130952380952381" data-s="300,640" src="/upload/b1e53c5715b25c3f7d9da35f5a790c36.png" data-type="png" data-w="504" style="width: 100%;height: auto;"></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.5.5 </span><span style="font-family: 等线;">配置日志级别</span></span></strong></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="cpp"><code><span class="code-snippet_outer">设置日志级别,有四个级别:DEBUG, INFO, WARN and ERROR</span></code><code><span class="code-snippet_outer">vi etc/log.properties</span></code><code><span class="code-snippet_outer">io.trino=INFO</span></code></pre> </section> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">1.5.6 </span><span style="font-family: 等线;">配置</span><span style="font-family: Calibri;">trino catalog</span></span></strong><span style="font-size: 14px;font-family: 等线;"> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;">Trino<span style="font-family: 等线;">访问数据通过</span><span style="font-family: Calibri;">connector,</span><span style="font-family: 等线;">它配置在</span><span style="font-family: Calibri;">catalog</span><span style="font-family: 等线;">目录内,我们创建</span><span style="font-family: Calibri;">etc/catalog</span><span style="font-family: 等线;">目录</span> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;">mysql<span style="font-family: 等线;">源配置如下,我们在</span><span style="font-family: Calibri;">catalog</span><span style="font-family: 等线;">目录下创建</span><span style="font-family: Calibri;">mysql.properties</span> <o:p></o:p></span></p> <p><span style="font-size: 14px;"><span style="font-family: 等线;"><span style="font-family: Calibri;">sqlserver</span><span style="font-family: 等线;">源配置如下,</span></span><span style="font-family: Calibri;"><span style="font-family: 等线;">我们在</span>catalog<span style="font-family: 等线;">目录下创建</span>sqlserver.properties <o:p></o:p></span></span></p> <p><span style="font-size: 14px;font-family: Calibri;"><span style="font-family: 等线;">不同的数据源参考这里</span>https://trino.io/docs/current/connector.html</span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer">mkdir etc/catalog</span></code><code><span class="code-snippet_outer">vi etc/catalog/mysql.properties</span></code><code><span class="code-snippet_outer">connector.name=mysql</span></code><code><span class="code-snippet_outer">connection-url=jdbc:mysql://192.168.154.128:3306?useUnicode=true&amp;useSSL=false&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC</span></code><code><span class="code-snippet_outer">connection-user=root</span></code><code><span class="code-snippet_outer">connection-password=Admin@123</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="53" data-backw="553" data-galleryid="" data-imgfileid="100004074" data-ratio="0.09584086799276673" data-s="300,640" src="/upload/6ec8acf36e4ad56e05bd68dc3bbdb46d.png" data-type="png" data-w="553" style="width: 100%;height: auto;"></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="javascript"><code><span class="code-snippet_outer">vi etc/catalog/sqlserver.properties</span></code><code><span class="code-snippet_outer">connector.name=sqlserver</span></code><code><span class="code-snippet_outer">connection-url=jdbc:sqlserver://192.168.154.128:1433;databaseName=exampledb;encrypt=false</span></code><code><span class="code-snippet_outer">connection-user=sa</span></code><code><span class="code-snippet_outer">connection-password=Wuzongyun0!</span></code></pre> </section> <p><strong><span style="font-size: 14px;font-family: Calibri;">2 Trino<span style="font-family: 等线;">启动命令</span></span></strong><span style="font-size: 14px;font-family: Calibri;"> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;"><span style="font-family: 等线;">启动</span>/<span style="font-family: 等线;">关闭</span><span style="font-family: Calibri;">/</span><span style="font-family: 等线;">查看运行状态</span></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer">bin/launcher start</span></code><code><span class="code-snippet_outer">bin/launcher stop</span></code><code><span class="code-snippet_outer">bin/launcher status</span></code><code><span class="code-snippet_outer">访问trino web页面</span></code></pre> </section> <p><span style="font-size: 14px;text-decoration: underline;"><span style="font-family: Calibri;color: rgb(0, 0, 255);">http://192.168.154.128:80</span><span style="color: rgb(0, 0, 255);font-family: Calibri;">80</span><span style="font-family: Calibri;color: rgb(0, 0, 255);">/</span></span><span style="mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:等线;mso-bidi-font-family:'Times New Roman';"> <o:p></o:p></span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="259" data-backw="514" data-galleryid="" data-imgfileid="100004075" data-ratio="0.5038910505836576" data-s="300,640" src="/upload/6ace6aa56b295456c6a7822d1123fd93.png" data-type="png" data-w="514" style="width: 100%;height: auto;"></p> <p><span style="font-family: 等线;font-size: 14px;">名称自定义,第一次输入什么,以后就用什么用户登录</span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="259" data-backw="512" data-galleryid="" data-imgfileid="100004076" data-ratio="0.505859375" data-s="300,640" src="/upload/7f7545af15be5e0e48b6bffb727f67c8.png" data-type="png" data-w="512" style="width: 100%;height: auto;"></p> <p><strong><span style="font-size: 14px;"><span style="font-family: 等线;"><span style="font-family: Calibri;">3 </span><span style="font-family: 等线;">安装</span></span><span style="font-family: Calibri;">Trino<span style="font-family: 等线;">客户端</span></span></span></strong><span style="font-size: 14px;font-family: Calibri;"> <o:p></o:p></span></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">3.1 </span><span style="font-family: 等线;">安装</span><span style="font-family: Calibri;">trino</span><span style="font-family: 等线;">客户端</span></span></strong><span style="font-size: 14px;font-family: 等线;"> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;"><span style="font-family: 等线;">下载地址</span>https://repo1.maven.org/maven2/io/trino/trino-cli/392/trino-cli-392-executable.jar <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: Calibri;"><span style="font-family: 等线;">将其重命名为</span>trino<span style="font-family: 等线;">,使用 使其可执行 ,然后运行它以显示</span></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="properties"><code><span class="code-snippet_outer">mv trino-cli-392-executable.jar trino-cli</span></code><code><span class="code-snippet_outer">chmod +x trino-cli</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="253" data-backw="473" data-galleryid="" data-imgfileid="100004077" data-ratio="0.5348837209302325" data-s="300,640" src="/upload/af554731edf48279a63ba8aa7feef13a.png" data-type="png" data-w="473" style="width: 100%;height: auto;"></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">3.1 </span><span style="font-family: 等线;">启动</span><span style="font-family: Calibri;">trino</span><span style="font-family: 等线;">客户端</span></span></strong><span style="font-size: 14px;font-family: 等线;"> <o:p></o:p></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer">./trino-cli --server 192.168.154.128:8080</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="89" data-backw="476" data-galleryid="" data-imgfileid="100004078" data-ratio="0.1869747899159664" data-s="300,640" src="/upload/2b578be98c666492e1b5cac980ddfbda.png" data-type="png" data-w="476" style="width: 100%;height: auto;"></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer">#常用命令</span></code><code><span class="code-snippet_outer">#显示所有的catalog</span></code><code><span class="code-snippet_outer">show catalogs;</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="109" data-backw="553" data-galleryid="" data-imgfileid="100004079" data-ratio="0.19710669077757687" data-s="300,640" src="/upload/1f655777d9e746a4e08edf879cb30755.png" data-type="png" data-w="553" style="width: 100%;height: auto;"></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer">#查看所有的schemas</span></code><code><span class="code-snippet_outer">show schemas from mysql;</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="178" data-backw="553" data-galleryid="" data-imgfileid="100004080" data-ratio="0.321880650994575" data-s="300,640" src="/upload/5591248d2a27ba48174eedc641b31dd2.png" data-type="png" data-w="553" style="width: 100%;height: auto;"></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="apache"><code><span class="code-snippet_outer">#退出客户端</span></code><code><span class="code-snippet_outer">quit;</span></code></pre> </section> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">4 </span><span style="font-family: 等线;">使用</span><span style="font-family: Calibri;">dbeaver</span><span style="font-family: 等线;">操作</span><span style="font-family: Calibri;">trino</span></span></strong><span style="font-size: 14px;font-family: Calibri;"> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: 等线;"><span style="font-family: 等线;">为了可以更方便的使用</span><span style="font-family: Calibri;">trino</span><span style="font-family: 等线;">,可以使用</span><span style="font-family: Calibri;">dbeaver</span><span style="font-family: 等线;">链接</span><span style="font-family: Calibri;">trino</span><span style="font-family: 等线;">进行数据处理</span> <o:p></o:p></span></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">4.1 </span><span style="font-family: 等线;">下载 </span><span style="font-family: Calibri;">jdbc</span><span style="font-family: 等线;">驱动</span></span></strong><span style="font-size: 14px;font-family: Calibri;"> <o:p></o:p></span></p> <p><span style="font-size: 14px;"><span style="font-family: 等线;">下载地址</span><span style="font-family: Calibri;">https://repo.maven.apache.org/maven2/io/trino/trino-jdbc</span><span style="font-family: 等线;"><span style="font-family: Calibri;">/trino-jdbc-392.jar</span> <o:p></o:p></span></span></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">4.2 dbeaver </span><span style="font-family: 等线;">安装 </span><span style="font-family: Calibri;">trino</span><span style="font-family: 等线;">驱动(如果</span><span style="font-family: Calibri;">dbeaver</span><span style="font-family: 等线;">没有</span><span style="font-family: Calibri;">trino</span><span style="font-family: 等线;">驱动)</span></span></strong><span style="font-size: 14px;font-family: 等线;"> <o:p></o:p></span></p> <p><span style="font-family: 等线;font-size: 14px;">数据库<span style="font-family: Calibri;">-&gt;</span>驱动管理器<span style="font-family: Calibri;">-&gt;</span>新建</span><span style="mso-spacerun:'yes';font-family:等线;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';"> <o:p></o:p></span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-imgfileid="100004082" data-ratio="0.5333333333333333" data-s="300,640" src="/upload/0944d22b19d3a3c24f9bfcc9e2b38888.png" data-type="png" data-w="1080" style=""></p> <p><span style="font-size: 14px;font-family: 等线;"><span style="font-family: 等线;">编辑信息:驱动名称、驱动类型、类名、</span><span style="font-family: Calibri;">URL</span><span style="font-family: 等线;">模板、端口</span> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: 等线;"><span style="font-family: 等线;">添加文件:选择到下载下来的</span><span style="font-family: Calibri;">jar</span><span style="font-family: 等线;">包</span> <o:p></o:p></span></p> <p><span style="font-family: 等线;font-size: 14px;">找到类:选择驱动类</span><span style="mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:等线;mso-bidi-font-family:'Times New Roman';"> <o:p></o:p></span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-imgfileid="100004083" data-ratio="0.5185185185185185" data-s="300,640" src="/upload/d35d1eda643e68b5a91298ebf366af92.png" data-type="png" data-w="1080" style=""></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">4.3 dbeaver</span><span style="font-family: 等线;">链接</span><span style="font-family: Calibri;">trino</span></span></strong><span style="font-size: 14px;font-family: 等线;"> <o:p></o:p></span></p> <p><span style="font-family: 等线;font-size: 14px;">填写<span style="font-family: Calibri;">jdbc-url</span>、主机、端口、用户名</span><span style="mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:等线;mso-bidi-font-family:'Times New Roman';"> <o:p></o:p></span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-imgfileid="100004084" data-ratio="0.5351851851851852" data-s="300,640" src="/upload/6fabd340e42fddff43bf4afe9077e267.png" data-type="png" data-w="1080" style=""></p> <p><strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: Calibri;">4.4 </span><span style="font-family: 等线;">查询数据</span></span></strong><span style="font-size: 14px;font-family: 等线;"><span style="font-family: 等线;"></span> <o:p></o:p></span></p> <p><span style="font-size: 14px;font-family: 等线;"><span style="font-family: 等线;">关联</span><span style="font-family: Calibri;">mysql</span><span style="font-family: 等线;">中的数据和</span><span style="font-family: Calibri;">sqlserver</span><span style="font-family: 等线;">中的数据进行联邦查询</span> <o:p></o:p></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">select</span> * <span class="code-snippet__keyword">from</span> mysql.x2ddl.x2ddl datamapping a <span class="code-snippet__keyword">inner</span> <span class="code-snippet__keyword">join</span> sqlserver.cdc.captured <span class="code-snippet__keyword">columns</span> b <span class="code-snippet__keyword">on</span> a.id = b.object <span class="code-snippet__keyword">id</span> ;</span></code></pre> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-imgfileid="100004085" data-ratio="0.5361111111111111" data-s="300,640" src="/upload/33b7f825b3a69607eacaa4d4caf70c64.png" data-type="png" data-w="1080" style=""></p> <p><span style="font-family: 等线;font-size: 14px;">查看执行任务详情,进入网页端</span><span style="mso-spacerun:'yes';font-family:等线;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';"> <o:p></o:p></span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="280" data-backw="554" data-galleryid="" data-imgfileid="100004086" data-ratio="0.5054151624548736" data-s="300,640" src="/upload/9598833219824420115e25ff4be646e2.png" data-type="png" data-w="554" style="width: 100%;height: auto;"></p> <p><span style="font-family: 等线;font-size: 14px;">点击任务<span style="font-family: Calibri;">ID</span></span><span style="mso-spacerun:'yes';font-family:等线;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';"> <o:p></o:p></span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="280" data-backw="554" data-galleryid="" data-imgfileid="100004087" data-ratio="0.5054151624548736" data-s="300,640" src="/upload/5abe5b8adad109af2796117ec5694cb7.png" data-type="png" data-w="554" style="width: 100%;height: auto;"></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="280" data-backw="554" data-galleryid="" data-imgfileid="100004088" data-ratio="0.5054151624548736" data-s="300,640" src="/upload/97537a9c4159501194701f32b3f5f001.png" data-type="png" data-w="554" style="width: 100%;height: auto;"></p> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="Mzg5Mzg3MzkwNA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/mZpqbZwlCSQ3SvW4umad8CibQ6YxFaicraoibJL4I9bxNVEkpsFcxcs4bibe1cJXiax5R2SLRblxmBea1L7meZbKnug/0?wx_fmt=png" data-nickname="大数据技能圈" data-alias="ByteTeach" data-signature="包含30+大数据组件;内容包含基础学习、项目实战、面试面经、源码解析、测试数据等;在同一个项目中完成所有组件的学习,保证学习的连贯性,助你快速成长为合格的大数据开发工程师" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>

Go 语言简明教程

作者:微信小助手

<blockquote style="box-sizing: border-box;margin: 10px 0px;padding: 0.5em 1em;color: rgb(102, 102, 102);border-left: 0.25em solid rgb(51, 122, 183);background-color: rgb(240, 248, 255);overflow: auto;font-family: &quot;Microsoft YaHei&quot;, Helvetica, &quot;Meiryo UI&quot;, &quot;Malgun Gothic&quot;, &quot;Segoe UI&quot;, &quot;Trebuchet MS&quot;, Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, &quot;Helvetica Neue&quot;, &quot;Droid Sans&quot;, &quot;wenquanyi micro hei&quot;, FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"> <p style="box-sizing: border-box;margin: 0px;padding: 0px;">Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。——&nbsp;Go - wikipedia.org</p> </blockquote> <p><span style="line-height: 0px;">‍</span><br></p> <h2 style="box-sizing: border-box;margin: -55px 0px 5px;padding: 60px 0px 0px;font-size: 1.5em;font-weight: 500;color: rgba(0, 0, 0, 0.9);font-family: &quot;Microsoft YaHei&quot;, Helvetica, &quot;Meiryo UI&quot;, &quot;Malgun Gothic&quot;, &quot;Segoe UI&quot;, &quot;Trebuchet MS&quot;, Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, &quot;Helvetica Neue&quot;, &quot;Droid Sans&quot;, &quot;wenquanyi micro hei&quot;, FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">1 Go 安装</h2> <p style="box-sizing: border-box;margin: 10px 0px;padding: 0px;color: rgba(0, 0, 0, 0.9);font-family: &quot;Microsoft YaHei&quot;, Helvetica, &quot;Meiryo UI&quot;, &quot;Malgun Gothic&quot;, &quot;Segoe UI&quot;, &quot;Trebuchet MS&quot;, Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, &quot;Helvetica Neue&quot;, &quot;Droid Sans&quot;, &quot;wenquanyi micro hei&quot;, FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">最新版本下载地址官方下载 golang.org,当前是 1.13.6。如无法访问,可以在&nbsp;<strong style="box-sizing: border-box;font-weight: 600;">studygolang.com/dl</strong>&nbsp;下载</p> <p style="box-sizing: border-box;margin: 10px 0px;padding: 0px;color: rgba(0, 0, 0, 0.9);font-family: &quot;Microsoft YaHei&quot;, Helvetica, &quot;Meiryo UI&quot;, &quot;Malgun Gothic&quot;, &quot;Segoe UI&quot;, &quot;Trebuchet MS&quot;, Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, &quot;Helvetica Neue&quot;, &quot;Droid Sans&quot;, &quot;wenquanyi micro hei&quot;, FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">使用 Linux,可以用如下方式快速安装。</p> <p><span style="line-height: 0px;"><br></span></p> <figure style="box-sizing: border-box;margin: 10px 0px 20px;padding: 15px;overflow: auto;font-size: 13px;color: rgb(36, 41, 46);background: rgb(246, 248, 250);line-height: 1.8;font-family: &quot;Microsoft YaHei&quot;, Helvetica, &quot;Meiryo UI&quot;, &quot;Malgun Gothic&quot;, &quot;Segoe UI&quot;, &quot;Trebuchet MS&quot;, Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, &quot;Helvetica Neue&quot;, &quot;Droid Sans&quot;, &quot;wenquanyi micro hei&quot;, FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"> <table style="box-sizing: border-box;border-collapse: collapse;border-spacing: 0px;margin: 0px;display: block;width: auto;overflow: auto;border-width: initial;border-style: none;border-color: initial;"> <tbody style="box-sizing: border-box;"> <tr style="box-sizing: border-box;background-color: transparent;border-top: none;"> <td style="box-sizing: border-box;padding: 0px;text-align: left;border-width: initial !important;border-style: none !important;border-color: initial !important;"><pre style="box-sizing: border-box;margin: 0px;padding: 1px 20px 1px 1px;font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;overflow-wrap: normal;overflow: auto;line-height: 1.8;background: rgb(246, 248, 250);border-radius: 3px;font-size: 13px;color: rgb(102, 102, 102);border-width: initial;border-style: none;border-color: initial;text-align: right;"><span style="box-sizing: border-box;height: 20px;">1</span><br style="box-sizing: border-box;"><span style="box-sizing: border-box;height: 20px;">2</span><br style="box-sizing: border-box;"><span style="box-sizing: border-box;height: 20px;">3</span><br style="box-sizing: border-box;"><span style="box-sizing: border-box;height: 20px;">4</span><br style="box-sizing: border-box;"><span style="box-sizing: border-box;height: 20px;">5</span><br style="box-sizing: border-box;"><span style="box-sizing: border-box;height: 20px;">6</span><br style="box-sizing: border-box;"></pre></td> <td style="box-sizing: border-box;padding: 0px;text-align: left;border-width: initial !important;border-style: none !import

Go:简单的优化笔记

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding: 0px 10px;line-height: 1.6;word-spacing: 0px;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;margin-bottom: 24px;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><br><em><span style="font-size: 15px;color: rgb(2, 30, 170);"></span></em></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">在云计算时代,我们经常创建 Serverless 应用(一种云原生开发模式,允许开发人员构建和运行应用程序,而无需管理服务器)。当我们的项目采用这种模式,那基础设施维护预算将排在首位。如果我们的服务负载很低,它实际上近乎是免费的。但是如果出现问题,你将为此付出很多!当谈到金钱时,你肯定会以某方式对它做出反应。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">当你的 VPS 运行着多个服务应用,但其中一个有时会占用所有的资源,以至于都无法通过 ssh 访问服务器。你转到使用 Kubernetes 集群,为所有应用程序设置限制。随后看到一些应用程序被重新启动,因为 OOM-killer 解决了内存”泄漏“问题。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">当然, OOM 并不总是泄漏问题,也可能是资源超支。泄漏问题大概率是由程序错误引起的,我们今天谈论的主题是如何尽量避免这种情况。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;"><em style="font-style: italic;color: black;">过多的资源消耗会伤害钱包,这意味着我们需要立即采取行动。</em></span></p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 22px;border-bottom: 4px rgba(160, 249, 176) solid;display: flex;padding: 0;"><span style="width: 100%;display: flex;color: rgba(160, 249, 176);padding: 0.5rem 1rem;border-top-left-radius: 4px;border-top-right-radius: 4px;background: #181a21 !important;">不要过早优化</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">现在让我们谈谈优化。希望你能明白为什么我们不要过早优化!</span></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">第一,优化可能是无用的工作。因为我们应该先研究整个应用程序,而你的代码很可能不会成为瓶颈。我们需要的是快速的结果,MVP(Minimum Viable Product,最简可行产品),然后才会考虑它的问题。</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">第二,优化都必须有所依据。也就是说,每次优化都应该建立在基准上,我们必须证明它给我们带来了多少利润。</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">第三,优化也许会带来复杂。你需要知道的是,大多数优化会使代码的可读性变差。你需要把握好这种平衡。</span> </section></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 22px;border-bottom: 4px rgba(160, 249, 176) solid;display: flex;padding: 0;"><span style="width: 100%;display: flex;color: rgba(160, 249, 176);padding: 0.5rem 1rem;border-top-left-radius: 4px;border-top-right-radius: 4px;background: #181a21 !important;">优化建议</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">现在我们按照 Go 中的标准实体分类,来给出一些实用建议。</span></p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 18px;">1. 数组与切片</h4> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">提前为切片分配内存</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">尽量使用第三个参数:</span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">make([]T, 0, len)</span></code></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">如果不知道元素确切的数量并且切片是短暂的,可以分配更大一点,保障切片在运行时不会增长。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">不要忘记使用 copy</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">尽量不要在复制时使用 append,例如在合并两个或多个切片时。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">正确迭代</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">一个包含许多元素或大元素的切片,使用 for 去获取单个元素。通过这种方法,将避免不必要的复制。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">复用切片</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">如果对传入的切片进行某种操作并返回已经修改的结果,我们可以返回它。这样能避免新的内存分配。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">不要留下不使用的切片部分</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">如果需要从切片中切下一小块并仅使用它,该切片的主要部分也将被保留。正确的做法是,为这小块切片使用新的副本,而将旧的切片扔给 GC。</span></p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 18px;">2. 字符串</h4> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">正确拼接</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">如果拼接字符串可以在一个语句中完成,那就使用 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">+</span></code><span style="font-size: 15px;"> 操作符。如果需要在循环中执行此操作,使用 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">string.Builder</span></code><span style="font-size: 15px;">,并使用它的 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">Grow</span></code><span style="font-size: 15px;"> 方法预先指定 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">Builder</span></code><span style="font-size: 15px;"> 的大小,减少内存分配次数。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">转换优化</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">string 和 []byte 在底层结构上非常相近,有时这两种类型之间可以通过强转换来避免内存分配。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">字符串驻留</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">可以池化字符串,从而帮助编译器只存储一次相同的字符串。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">避免分配</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">我们可以使用 map(级联)而不是复合键,我们可以使用字节切片。尽量不使用 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">fmt</span></code><span style="font-size: 15px;"> 包,因为它所有的方法都用到了反射。</span></p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 18px;">3. 结构体</h4> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">避免拷贝大结构体</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">我们理解的小结构体是不超过4个字段不超过一个机器字大小。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">一些典型的拷贝场景</span></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">投射到 interface</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">通道的接收和发送</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">替换 map 中的元素</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">向切片添加元素</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">迭代(range)</span> </section></li> </ul> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">避免通过指针访问结构体字段</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">解引用是昂贵的,我们应该尽可能少地这样做,尤其是在循环中。同时它也失去了使用快速寄存器的能力。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">处理小结构体</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">这项工作由编辑器进行优化,这意味着它很便宜。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">使用对齐减小结构体大小</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">我们可以对齐结构体(根据字段的大小,以正确的顺序排列它们),以此减小结构体本身的大小。</span></p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 18px;">4. 函数</h4> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">使用内联函数或自己内联它们</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">尝试编写可供编译器内联的小函数,它会很快,甚至快过自己在函数中嵌入代码。对于热路径(hot path)尤其如此。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">哪些不会内联</span></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">recovery</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">select 块</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">类型声明</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">defer</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">goroutine</span> </section></li> <li style="font-size: 15px;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"> <span style="font-size: 15px;">for-range</span> </section></li> </ul> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">合理地选择函数参数</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">尝试使用小参数,因为它们的复制将被优化。尝试复制和栈增长在GC负载保持平衡。避免大量参数,让你的程序使用快速寄存器(它们的数量是有限的)。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">命名返回值</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">这似乎比在函数体中声明这些变量更高效。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">保存中间结果</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">帮助编译器优化你的代码,保存中间结果,然后会有更多的选项来优化你的代码。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">仔细地使用 defer</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">尽量不要使用 defer,或者至少不要在循环中使用它。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">助力 hot path</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">避免在热路径分配内存,尤其是短生命对象。制作最常见分支(if,switch)</span></p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 18px;">5. Map</h4> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">提前分配内存</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">和 slice 一样,初始化 map 时,指定其大小。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">使用空结构体为值</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">struct{} 什么都不是(不占内存),因此例如传递信号时,使用它是非常有益的。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">清空 map</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">map 只能增长,不能缩小。我们需要重置 map 时,删除其所有元素是无济于事的。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">尽量不在键和值中使用指针</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">如果 map 中不包含指针,那么 GC 就不会在上面浪费宝贵的时间。字符串也使用了指针,因此应该使用字节数组而不是字符串作为键。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">减少修改次数</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">同样,我们不想使用指针,但我们可以使用 &nbsp;map 和 slice 的组合,将键存储在 map 中,将值存在 slice。这样我们就可以不受限制地更改值。</span></p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 18px;">6. Interface</h4> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">计算内存分配</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">请记住,要为接口分配值时,首先需要将其复制到某处,然后将指针黏贴给它。关键是复制。事实证明,接口的装箱和拆箱的成本将近似于结构体大小的一次分配。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">选择最优类型</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">在某些情况下,接口的装箱和拆箱期间没有分配。例如,变量和常量的小值或布尔值、具有一个简单字段的结构体、指针(包括 map、channel、func)</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">避免内存分配</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">与其他地方一样,尽量避免不必要的分配。例如将一个接口分配给另一个接口,而不是装箱两次。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">仅在需要时使用</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">避免在频繁调用的函数参数和返回结果中使用接口。我们不需要额外的拆装包操作。减少使用接口方法调用的频率,因为它会阻止内联。</span></p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 18px;">7. 指针、通道、边界检查</h4> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">避免不必要的解引用</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">尤其是在循环中,因为事实证明它太昂贵了。解引用是我们不想自费执行的操作。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">使用通道效率低下</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">channel 同步比其他同步原语方法慢。另外, select 中的 case 越多,我们的程序就越慢。但是,select,case 加 default 有被优化。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">避免不必要的边界检查</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">这也很昂贵,我们应该避免它。例如,只检查(获取)一次最大切片索引,而不是多次。最好立即尝试获得极端选项。</span></p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 22px;border-bottom: 4px rgba(160, 249, 176) solid;display: flex;padding: 0;"><span style="width: 100%;display: flex;color: rgba(160, 249, 176);padding: 0.5rem 1rem;border-top-left-radius: 4px;border-top-right-radius: 4px;background: #181a21 !important;">总结</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">在整篇文章中,我们看到了一些相同的优化规则。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">帮助编译器做出正确的决定,它会感谢你的。在编译时分配内存,使用中间结果,并尽量保持你的代码可读。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">我再次重申,对于隐式优化,基准是强制性的。如果因为编译器在不同版本之间变化太快,昨天工作的东西明天就不能工作,反之亦然。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">不要忘记使用 Go 内置的分析和跟踪工具。</span></p> <h6 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 16px;">译者有话说</h6> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;"><span style="font-size: 15px;">注意,作者的建议并不一定是对的。就像原文中有人评价,为什么不在每条建议下面列出优化代码。因为作者更希望开发人员把这些建议当做一张备忘单,知道这些瓶颈并主动去寻找如何做优化。</span></p> </section>

代码越写越乱?那是因为你没用责任链

作者:微信小助手

<p style="text-align: left;" data-mpa-powered-by="yiban.io"><strong style="letter-spacing: 0.034em;font-size: 16px;text-align: justify;">目录</strong><br></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 什么是责任链 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 使用场景 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 结语 </section></li> </ul> <section mpa-from-tpl="t"> <section data-mpa-category="模板" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <br> </section> </section> </section> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section style="width:100%;text-align:center;" data-width="100%" mpa-from-tpl="t"> <section style="display:inline-block;width:auto;" mpa-from-tpl="t"> <section style="width: 45px;margin-right: auto;margin-bottom: -12px;margin-left: auto;background-color: #fefefe;transform: translateZ(10px);-webkit-transform: translateZ(10px);-moz-transform: translateZ(10px);-ms-transform: translateZ(10px);-o-transform: translateZ(10px);" mpa-from-tpl="t"> <img class="rich_pages wxw-img" data-imgfileid="100126414" data-ratio="1" src="/upload/2f587a759a9336e658edf1970c0a8632.png" data-w="100" data-width="100%" style="display: block;width: 100%;"> </section> <section style="display:inline-block;width:auto;height:auto;" mpa-from-tpl="t"> <section style="border-width: 1px;border-style: solid;border-color: rgb(102, 102, 102);height: 40px;" mpa-from-tpl="t"> <br> </section> <section style="margin-top:-37px;margin-right:-3px;margin-bottom:-3px;margin-left:3px;" mpa-from-tpl="t"> <section style="display: inline-block;height: 40px;line-height: 40px;padding-right: 15px;padding-left: 15px;border-width: 1px;border-style: solid;border-color: rgb(255, 116, 128);width: 100%;" data-width="100%" mpa-from-tpl="t"> <p mpa-is-content="t">前言</p> </section> </section> </section> </section> </section> </section> </section> <p><br mpa-from-tpl="t"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">最近,我让团队内一位成员写了一个导入功能。他使用了责任链模式,代码堆的非常多,bug 也多,没有达到我预期的效果。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">实际上,针对导入功能,我认为模版方法更合适!为此,隔壁团队也拿出我们的案例,进行了集体 code review。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">学好设计模式,且不要为了练习,强行使用!让原本 100 行就能实现的功能,写了 3000 行!对错暂且不论,我们先一起看看责任链设计模式吧!</p> <section data-mid="" mpa-from-tpl="t" style="margin-bottom: 0px;"> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-category="模板" style="width: 100%;padding: 0 15px;" data-mid="" mpa-from-tpl="t"> <section style="width: 100%;padding: 15px 17px 20px;background: #ebf4ff;font-size: 14px;font-weight: 400;color: #6273aa;line-height: 20px;" data-mid="" mpa-from-tpl="t"> <p data-mid="" mpa-is-content="t" style="text-align: left;">文章来源:https://blog.csdn.net/q1472750149/article/details/121886327</p> </section> <section style="width: 100%;display: flex;justify-content: flex-end;align-items: flex-start;padding-right: 5px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t" style="width: 23px;height: 27px;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/dLHvdVqeWINyJQzMVmQzxIcFqDsaiaK6ATCCANPe11FbZKCApfz0TbDtfc5gfSQNgJpic86YejM6qcNU5gubeetQ/640&quot;) no-repeat;background-size: contain;background-position: center center;margin-top: -27px;z-index: 10;"> <br> </section> </section> <section style="width: 100%;display: flex;justify-content: flex-start;align-items: flex-start;" data-mid="" mpa-from-tpl="t"> <section style="width: 52.3%;height: 8px;background: #6273AA;margin-top: -6px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 10px;height: 8px;background: #6273AA;transform: skew(35deg);margin-left: -5px;margin-top: -6px;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="width: 100%;display: flex;justify-content: flex-end;align-items: flex-start;" data-mid="" mpa-from-tpl="t"> <section style="width: 10px;height: 3px;background: #6273AA;transform: skew(35deg);margin-right: -5px;margin-top: -3px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 42.2%;height: 3px;background: #6273AA;margin-top: -3px;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> </section> </section> </section> <section data-mid="" mpa-from-tpl="t" style="margin-bottom: 0px;"> <section data-mid="" mpa-from-tpl="t"> <br style="color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;letter-spacing: normal;text-align: left;text-wrap: wrap;"> </section> </section> <h2 data-tool="mdnice编辑器"><span style="display: none;"></span><br mpa-from-tpl="t"></h2> <section data-mpa-template="t" mpa-from-tpl="t"> <blockquote style="margin: 5px auto;padding: 0px;max-width: 100%;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;color: rgb(68, 153, 231);" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <blockquote style="margin: 5px auto;padding: 0px;max-width: 100%;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;text-align: center;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto -38px;padding: 0px 15px;max-width: 100%;display: inline-block;background-color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <p style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;clear: both;min-height: 1em;color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><span style="font-family: Arial, Helvetica, sans-serif;"><strong mpa-from-tpl="t"><span style="border-color: rgb(68, 153, 231);color: rgb(255, 255, 255);font-size: 16px;">什么是责任链</span></strong></span></p> </section> <section style="margin: -40px 25px 50px;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 3px 0px 0px;padding: 10px 0px;max-width: 100%;box-sizing: border-box;display: inline-block;width: 495px;color: rgb(68, 153, 231);float: left;border-color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 1em 0px 0px;padding: 0px;max-width: 100%;box-sizing: border-box;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);clear: both;color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px 0px -3px;padding: 0px;max-width: 100%;float: right;border-color: rgb(68, 153, 231);width: 6px;border-radius: 50%;background-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;height: 6px !important;" mpa-from-tpl="t"> <br> </section> <section style="margin: 0px 0px -2px;padding: 0px;max-width: 100%;text-align: left;border-color: rgb(68, 153, 231);width: 6px;border-radius: 50%;background-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;height: 6px !important;" mpa-from-tpl="t"> <br> </section> <section style="margin: -20px 0px 0px;padding: 0px;max-width: 100%;box-sizing: border-box;text-decoration: inherit;color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box;border-top: 1px solid rgb(68, 153, 231);width: 495px;float: left;border-right-color: rgb(68, 153, 231);border-bottom-color: rgb(68, 153, 231);border-left-color: rgb(68, 153, 231);color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <br> </section> </section> </section> </section> </section> </section> </blockquote> </section> </section> </blockquote> </section> <p><br mpa-from-tpl="t"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。</p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-imgfileid="100126415" data-ratio="0.2884333821376281" data-s="300,640" src="/upload/f76f6798384481d7850d3a3586a2b55a.png" data-type="png" data-w="683" style=""></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><span style="font-size: 16px;letter-spacing: 0px;"></span></p> <h2 data-tool="mdnice编辑器"><span style="display: none;"></span><br mpa-from-tpl="t"></h2> <section data-mpa-template="t" mpa-from-tpl="t"> <blockquote style="margin: 5px auto;padding: 0px;max-width: 100%;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;color: rgb(68, 153, 231);" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <blockquote style="margin: 5px auto;padding: 0px;max-width: 100%;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;text-align: center;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto -38px;padding: 0px 15px;max-width: 100%;display: inline-block;background-color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <p style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;clear: both;min-height: 1em;color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><span style="font-family: Arial, Helvetica, sans-serif;"><strong mpa-from-tpl="t"><span style="border-color: rgb(68, 153, 231);color: rgb(255, 255, 255);font-size: 16px;">使用场景</span></strong></span></p> </section> <section style="margin: -40px 25px 50px;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 3px 0px 0px;padding: 10px 0px;max-width: 100%;box-sizing: border-box;display: inline-block;width: 495px;color: rgb(68, 153, 231);float: left;border-color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 1em 0px 0px;padding: 0px;max-width: 100%;box-sizing: border-box;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);clear: both;color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px 0px -3px;padding: 0px;max-width: 100%;float: right;border-color: rgb(68, 153, 231);width: 6px;border-radius: 50%;background-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;height: 6px !important;" mpa-from-tpl="t"> <br> </section> <section style="margin: 0px 0px -2px;padding: 0px;max-width: 100%;text-align: left;border-color: rgb(68, 153, 231);width: 6px;border-radius: 50%;background-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;height: 6px !important;" mpa-from-tpl="t"> <br> </section> <section style="margin: -20px 0px 0px;padding: 0px;max-width: 100%;box-sizing: border-box;text-decoration: inherit;color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box;border-top: 1px solid rgb(68, 153, 231);width: 495px;float: left;border-right-color: rgb(68, 153, 231);border-bottom-color: rgb(68, 153, 231);border-left-color: rgb(68, 153, 231);color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <br> </section> </section> </section> </section> </section> </section> </blockquote> </section> </section> </blockquote> </section> <p><br mpa-from-tpl="t"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">责任链的使用场景还是比较多的:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 多条件流程判断:权限控制 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> ERP 系统流程审批:总经理、人事经理、项目经理 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);fon

Java Live Tmplates 设置/**注释

作者:じ☆ve宝贝

> idea 开发Java,注释使用不太方便,节后live template,打造一款方便的注释生成。 Editor -> Live Templates -> Java Abbreviation: * Description: 方法注释 Template text: ``` * * TODO $params$ $return$ */ ``` Expand with: Enter Reformat according to style: 勾选 Shorten FQ names: 勾选 Edit Variables: ``` name:params Expression:groovyScript( "if(\"${_1}\".length() == 2) { return '*'; } else { def result='*\\n'; def valid = 'false'; def params=\"${_1}\".replaceAll('[\\\\[|\\\\]|\\\\s]', '').split(',').toList(); for(i = 0; i < params.size(); i++) { valid = params[i]+'' == 'null' ? 'true' : 'false'; if(i<(params.size()-1)){ result+='* @param ' + params[i] + '\\n'; }else{ result+='* @param ' + params[i] } }; def res = valid == 'true' ? '*' : result; return res; }", methodParameters()); ----------------------------------------------------------- name:return Expression: groovyScript( "if(\"${_1}\" == 'void'){ def result = '' } else { def returnType = \"${_1}\"; def valid = returnType+'' == 'null' ? 'true' : 'false'; def result = valid == 'true' ? '' : '\\r\\n * @return ' + returnType; return result; }", methodReturnType()); ----------------------------------------------------------- name:returnName groovyScript("def result=''; def params=\"${_1}\".replaceAll('[\\\\[|\\\\]|\\\\s]', '').split('<').toList(); for(i = 0; i < params.size(); i++) {if(i!=0){result+='<';}; def p1=params[i].split(',').toList(); for(i2 = 0; i2 < p1.size(); i2++) { def p2=p1[i2].split('\\\\.').toList(); result+=p2[p2.size()-1]; if(i2!=p1.size()-1){result+=','} } ; }; return result", methodReturnType()); ``` 点击OK。 ## 测试 依次输入 /** 回车 即可查看效果

一次线上JVM GC 长暂停排查,加班搞了好久

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;" data-mpa-powered-by="yiban.io"> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="custom_select_card mp_profile_iframe mp_common_widget" data-pluginname="mpprofile" data-id="MzAwMTk4NjM1MA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/PxMzT0Oibf4gcBzLSUNh2cgXUsuLIsvQYJE1lzZd74qpC3iciaM6gcYIfOVV0KjDDkeN4CTLTn4ETPtaHOAuTWSWA/0?wx_fmt=png" data-nickname="JAVA日知录" data-alias="javadaily" data-signature="写代码的架构师,做架构的程序员! 实战、源码、数据库、架构...只要你来,你想了解的这里都有!" data-from="0"></mp-common-profile> </section> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">背景</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在高并发下,Java程序的GC问题属于很典型的一类问题,带来的影响往往会被进一步放大。不管是「GC频率过快」还是「GC耗时太长」,由于GC期间都存在Stop The World问题,因此很容易导致服务超时,引发性能问题。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">事情最初是线上某应用垃圾收集出现Full GC异常的现象,应用中个别实例Full GC时间特别长,持续时间约为15~30秒,平均每2周左右触发一次;</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035934" data-ratio="0.4083333333333333" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/cefc89ecf33644c16e68925421cdc4e6.png"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035933" data-ratio="0.4597222222222222" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/f107c99f17c44e19df841693a6014855.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">JVM参数配置:</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(239, 112, 96);background: rgb(255, 249, 249);"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;">-Xms2048M –Xmx2048M –Xmn1024M –XX:MaxPermSize=512M</p> </blockquote> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035935" data-ratio="0.30416666666666664" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/49e1ab065d516199bc361e78576cc665.png"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">排查过程</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>分析 GC 日志<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">GC 日志它记录了每一次的 GC 的执行时间和执行结果,通过分析 GC 日志可以调优堆设置和 GC 设置,或者改进应用程序的对象分配模式。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里Full GC的reason是Ergonomics,是因为开启了UseAdaptiveSizePolicy,jvm自己进行自适应调整引发的Full GC。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这份日志主要体现GC前后的变化,目前为止看不出个所以然来。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035937" data-ratio="0.5125" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/60cb355ee072db47bb97d248adcf376a.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">开启GC日志,需要添加如下 JVM 启动参数:</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(239, 112, 96);background: rgb(255, 249, 249);"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;">-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/export/log/risk_pillar/gc.log</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">常见的 Young GC、Full GC 日志含义如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035936" data-ratio="0.6194444444444445" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/d216a5617aa19528f7b963421f3e53c8.png"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>进一步查看服务器性能指标<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">获取到了GC耗时的时间后,通过监控平台获取到各个监控项,开始排查这个时点有异常的指标,最终分析发现,在5.06分左右(GC的时点),CPU占用显著提升,而SWAP出现了释放资源、memory资源增长出现拐点的情况(详见下图红色框,橙色框中的变化是因修改配置导致,后面会介绍,暂且可忽略)</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035941" data-ratio="0.4777777777777778" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/4fa8efcf5ae8b77bc77bc55684784a74.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">JVM用到了swap?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">是因为GC导致的CPU突然飙升,并且释放了swap交换区这部分内存到memory?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">为了验证JVM是否用到swap,我们通过检查proc下的进程内存资源占用情况</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/V0mhkIwf3EFGsyVp9XEqnn4iawLRHSs3AvCoIed6JIoHAOWD9z6rKxyUxWEpZuL0aTibiaqIyq7XiazJcIGZ56jUbl7Kssm4GJicT/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(248, 248, 248);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #333;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #f8f8f8;border-radius: 5px;"><span style="font-weight: bold;line-height: 26px;">for</span>&nbsp;i&nbsp;<span style="font-weight: bold;line-height: 26px;">in</span>&nbsp;(<span style="color: #0086b3;line-height: 26px;">cd</span>/proc;ls∣grep<span style="color: #d14;line-height: 26px;">"[0−9]"</span>∣awk′0&nbsp;&gt;100<span style="color: #d14;line-height: 26px;">');<br>do&nbsp;awk&nbsp;'</span>/Swap:/{a=a+2}END{<span style="color: #0086b3;line-height: 26px;">print</span>&nbsp;<span style="color: #d14;line-height: 26px;">'"i"'</span>,a/1024<span style="color: #d14;line-height: 26px;">"M"</span>}<span style="color: #d14;line-height: 26px;">'&nbsp;/proc/$i/smaps&nbsp;2&gt;/dev/null;<br>done&nbsp;|&nbsp;sort&nbsp;-k2nr&nbsp;|&nbsp;head&nbsp;-10&nbsp;<br><br>#&nbsp;head&nbsp;-10&nbsp;表示&nbsp;取出&nbsp;前10个内存占用高的进程&nbsp;<br>#&nbsp;取出的第一列为进程的id&nbsp;第二列进程占用swap大小<br></span></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">看到确实有用到305MB的swap</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035938" data-ratio="0.3597222222222222" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/46291ea27e8eba5c8b83b61aef056938.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里简单介绍下什么是swap?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">swap指的是一个交换分区或文件,主要是在内存使用存在压力时,触发内存回收,这时可能会将部分内存的数据交换到swap空间,以便让系统不会因为内存不够用而导致oom或者更致命的情况出现。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">当某进程向OS请求内存发现不足时,OS会把内存中暂时不用的数据交换出去,放在swap分区中,这个过程称为swap out。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">当某进程又需要这些数据且OS发现还有空闲物理内存时,又会把swap分区中的数据交换回物理内存中,这个过程称为swap in。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">为了验证GC耗时与swap操作有必然关系,我抽查了十几台机器,重点关注耗时长的GC日志,通过时间点确认到GC耗时的时间点与swap操作的时间点确实是一致的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">进一步查看虚拟机各实例 swappiness 参数,一个普遍现象是,凡是发生较长Full GC的实例都配置了参数 vm.swappiness = 30(值越大表示越倾向于使用swap);而GC时间相对正常的实例配置参数 vm.swappiness = 0(最大限度地降低使用swap)。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">swappiness 可以设置为 0 到 100 之间的值,它是Linux的一个内核参数,控制系统在进 行swap时,内存使用的相对权重。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> swappiness=0: 表示最大限度使用物理内存,然后才是 swap空间 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> swappiness=100: 表示积极的使用swap分区,并且把内存上的数据及时的交换到swap空间里面 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035939" data-ratio="0.3277777777777778" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/1d05d9145b6f8c1f461dd3ee609f7ab7.png"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035940" data-ratio="0.4625" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/69e077f94d105cfe31ee0abd3e3f33a6.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">对应的物理内存使用率和swap使用情况如下</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035942" data-ratio="0.13055555555555556" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/beec4051cf9a57b33d72fb436e2c2b3b.png"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035946" data-ratio="0.41388888888888886" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/5bb350e74fc88c280047f6d35bb85eec.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">至此,矛头似乎都指向了swap。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">问题分析</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">当内存使用率达到水位线(vm.swappiness)时,linux会把一部分暂时不使用的内存数据放到磁盘swap去,以便腾出更多可用内存空间;</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">当需要使用位于swap区的数据时,再将其换回内存中,当JVM进行GC时,需要对相应堆分区的已用内存进行遍历;</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">假如GC的时候,有堆的一部分内容被交换到swap空间中,遍历到这部分的时候就需要将其交换回内存,由于需要访问磁盘,所以相比物理内存,它的速度肯定慢的令人发指,GC停顿的时间一定会非常非常恐怖;</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">进而导致Linux对swap分区的回收滞后(内存到磁盘换入换出操作十分占用CPU与系统IO),在高并发/QPS服务中,这种滞后带来的结果是致命的(STW)。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">问题解决</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">至此,答案似乎很清晰,我们只需尝试把swap关闭或释放掉,看看能否解决问题?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>如何释放swap?</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">设置vm.swappiness=0(重启应用释放swap后生效),表示尽可能不使用交换内存</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">方案 a:临时设置方案,重启后不生效</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 设置vm.swappiness为0,sysctl vm.swappiness=0 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 查看swappiness值,cat /proc/sys/vm/swappiness </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">方案b:永久设置方案,重启后仍然生效</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> vi /etc/sysctl.conf </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 关闭交换分区swapoff –a(前提:首先要保证内存剩余要大于等于swap使用量,否则会报Cannot allocate memory!swap分区一旦释放,所有存放在swap分区的文件都会转存到物理内存上,可能会引发系统IO或者其他问题。) </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">查看当前swap分区挂载在哪:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035943" data-ratio="0.07398843930635839" data-type="png" data-w="865" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/99250e74089179b08abefe523bbab1ff.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">关停分区:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035944" data-ratio="0.12716763005780346" data-type="png" data-w="865" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/159c2d73c499b3b701963f201ff0af03.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">关闭swap交换区后的内存变化见下图橙色框,此时swap分区的文件都转存到了物理内存上</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035945" data-ratio="0.5347222222222222" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/5460d613b6aa463ee3526760bb464cbc.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">关闭Swap交换区后,于2.23再次发生Full GC,耗时190ms,问题得到解决。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035947" data-ratio="0.5069444444444444" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/118e14e6673587092936f8d4e350e4e2.png"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">疑惑</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 是不是只要开启了swap交换区的JVM,在GC的时候都会耗时较长呢? </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 既然JVM对swap如此不待见,为何JVM不明令禁止使用呢? </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> swap工作机制是怎样的?这台物理内存为8g的server,使用了交换区内存(swap),说明物理内存不够使用了,但是通过free命令查看内存使用情况,实际物理内存似乎并没有占用那么多,反而Swap已占近1G? </section></li> </ol> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035948" data-ratio="0.13108614232209737" data-type="png" data-w="801" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/73915807ac03ea76905287e9b9dfc961.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">free:除了buff/cache剩余了多少内存</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">shared:共享内存</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">buff/cache:缓冲、缓存区内存数(使用过高通常是程序频繁存取文件)</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">available:真实剩余的可用内存数</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">进一步思考</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">大家可以想想,关闭交换磁盘缓存意味着什么?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">其实大可不必如此激进,要知道这个世界永远不是非0即1的,大家都会或多或少选择走在中间,不过有些偏向0,有些偏向1而已。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">很显然,在swap这个问题上,JVM可以选择偏向尽量少用,从而降低swap影响,要降低swap影响有必要弄清楚Linux内存回收是怎么工作的,这样才能不遗漏任何可能的疑点。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>先来看看swap是如何触发的?</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">Linux会在两种场景下触发内存回收,一种是在内存分配时发现没有足够空闲内存时会立刻触发内存回收;另一种是开启了一个守护进程(kswapd进程)周期性对系统内存进行检查,在可用内存降低到特定阈值之后主动触发内存回收。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">通过如下图示可以很容易理解,详细信息参见:</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(239, 112, 96);background: rgb(255, 249, 249);"> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;">http://hbasefly.com/2017/05/24/hbase-linux/</p> </blockquote> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035952" data-ratio="0.4638888888888889" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/cbb7062fc9306b3d0b5f7cad01cedf0c.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">是不是只要开启了swap交换区的JVM,在GC的时候都会耗时较长?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">笔者去查了一下另外的一个应用,相关指标信息请见下图。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">实名服务的QPS是非常高的,同样能看到应用了swap,GC平均耗时 576ms,这是为什么呢?</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035950" data-ratio="0.4486111111111111" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/e60a1e41efa538c4a13cdfc5bde0a031.png"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035951" data-ratio="0.5138888888888888" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/eae037c835b017a2405fd20ec4c42ce6.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">通过把时间范围聚焦到发生GC的某一时间段,从监控指标图可以看到swapUsed没有任何变化,也就是说没有swap活动,进而没有影响到垃级回收的总耗时。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035949" data-ratio="0.41944444444444445" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/8d691e61decb205860edcbd778125da0.png"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035953" data-ratio="0.4722222222222222" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/63a1bee63a666cca01eb253246168f40.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">通过如下命令列举出各进程swap空间占用情况,很清楚的看到实名这个服务swap空间占用的较少(仅54.2MB)</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035956" data-ratio="0.5069444444444444" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/9d283b590923d17f3fc000def42fef1e.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">另一个显著的现象是实名服务Full GC间隔较短(几个小时一次),而我的服务平均间隔2周一次Full GC</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035954" data-ratio="0.5138888888888888" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/2ae8994c85e80628e5deca5bcb6a1371.png"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035957" data-ratio="0.44583333333333336" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/ffd170d4c571552fbb4d66abc2fd909a.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">基于以上推测</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 实名服务由于 GC 间隔较短,内存中的东西根本没有机会置换到swap中就被回收了,GC的时候不需要将swap分区中的数据交换回物理内存中,完全基于内存计算,所以要快很多 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 将哪些内存数据置换进swap交换区的筛选策略应该是类似于LRU算法(最近最少使用原则) </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">为了证实上述猜测,我们只需跟踪swap变更日志,监控数据变化即可得到答案,这里采用一段shell 脚本实现</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/V0mhkIwf3EFGsyVp9XEqnn4iawLRHSs3AvCoIed6JIoHAOWD9z6rKxyUxWEpZuL0aTibiaqIyq7XiazJcIGZ56jUbl7Kssm4GJicT/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(248, 248, 248);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #333;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #f8f8f8;border-radius: 5px;"><span style="color: #999;font-weight: bold;line-height: 26px;">#!/bin/bash&nbsp;</span><br><span style="color: #0086b3;line-height: 26px;">echo</span>&nbsp;-e&nbsp;`date&nbsp;+%y%m%d%H%M%S`&nbsp;<br><span style="color: #0086b3;line-height: 26px;">echo</span>&nbsp;-e&nbsp;<span style="color: #d14;line-height: 26px;">"PID\t\tSwap\t\tProc_Name"</span>&nbsp;<br><br><span style="color: #998;font-style: italic;line-height: 26px;">#拿出/proc目录下所有以数字为名的目录(进程名是数字才是进程,其他如sys,net等存放的是其他信息)&nbsp;</span><br><span style="font-weight: bold;line-height: 26px;">for</span>&nbsp;pid&nbsp;<span style="font-weight: bold;line-height: 26px;">in</span>&nbsp;`ls&nbsp;-l&nbsp;/proc&nbsp;|&nbsp;grep&nbsp;^d&nbsp;|&nbsp;awk&nbsp;<span style="color: #d14;line-height: 26px;">'{&nbsp;print&nbsp;$9&nbsp;}'</span>|&nbsp;grep&nbsp;-v&nbsp;[^0-9]`&nbsp;<br><span style="font-weight: bold;line-height: 26px;">do</span>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold;line-height: 26px;">if</span>&nbsp;[&nbsp;<span style="color: #008080;line-height: 26px;">$pid</span>&nbsp;-eq&nbsp;1&nbsp;];<span style="font-weight: bold;line-height: 26px;">then</span>&nbsp;<span style="color: #0086b3;line-height: 26px;">continue</span>;<span style="font-weight: bold;line-height: 26px;">fi</span>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;grep&nbsp;-q&nbsp;<span style="color: #d14;line-height: 26px;">"Swap"</span>&nbsp;/proc/<span style="color: #008080;line-height: 26px;">$pid</span>/smaps&nbsp;2&gt;/dev/null&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold;line-height: 26px;">if</span>&nbsp;[&nbsp;$?&nbsp;-eq&nbsp;0&nbsp;];<span style="font-weight: bold;line-height: 26px;">then</span>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;swap=$(gawk&nbsp;<span style="color: #d14;line-height: 26px;">'/Swap/{&nbsp;sum+=$2;}&nbsp;END{&nbsp;print&nbsp;sum&nbsp;}'</span>&nbsp;/proc/<span style="color: #008080;line-height: 26px;">$pid</span>/smaps)&nbsp;<span style="color: #998;font-style: italic;line-height: 26px;">#统计占用的swap分区的&nbsp;大小&nbsp;单位是KB&nbsp;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proc_name=$(ps&nbsp;aux&nbsp;|&nbsp;grep&nbsp;-w&nbsp;<span style="color: #d14;line-height: 26px;">"<span style="color: #008080;line-height: 26px;">$pid</span>"</span>&nbsp;|&nbsp;awk&nbsp;<span style="color: #d14;line-height: 26px;">'!/grep/{&nbsp;for(i=11;i&lt;=NF;i++){&nbsp;printf("%s&nbsp;",$i);&nbsp;}}'</span>)&nbsp;<span style="color: #998;font-style: italic;line-height: 26px;">#取出进程的名字&nbsp;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold;line-height: 26px;">if</span>&nbsp;[&nbsp;<span style="color: #008080;line-height: 26px;">$swap</span>&nbsp;-gt&nbsp;0&nbsp;];<span style="font-weight: bold;line-height: 26px;">then</span>&nbsp;<span style="color: #998;font-style: italic;line-height: 26px;">#判断是否占用swap&nbsp;只有占用才会输出&nbsp;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0086b3;line-height: 26px;">echo</span>&nbsp;-e&nbsp;<span style="color: #d14;line-height: 26px;">"<span style="color: #008080;line-height: 26px;">${pid}</span>\t<span style="color: #008080;line-height: 26px;">${swap}</span>\t<span style="color: #008080;line-height: 26px;">${proc_name:0:100}</span>"</span>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold;line-height: 26px;">fi</span>&nbsp;<br>&nbsp;&nbsp;&nbsp;<span style="font-weight: bold;line-height: 26px;">fi</span><br><span style="font-weight: bold;line-height: 26px;">done</span>&nbsp;|&nbsp;sort&nbsp;-k2nr&nbsp;|&nbsp;head&nbsp;-10&nbsp;|&nbsp;gawk&nbsp;-F<span style="color: #d14;line-height: 26px;">'\t'</span>&nbsp;<span style="color: #d14;line-height: 26px;">'{&nbsp;#排序取前&nbsp;10&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;pid[NR]=$1;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;size[NR]=$2;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;name[NR]=$3;&nbsp;<br>}&nbsp;<br>END{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;for(id=1;id&lt;=length(pid);id++)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;if(size[id]&lt;1024)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%-10s\t%15sKB\t%s\n",pid[id],size[id],name[id]);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(size[id]&lt;1048576)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%-10s\t%15.2fMB\t%s\n",pid[id],size[id]/1024,name[id]);<br>&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;printf("%-10s\t%15.2fGB\t%s\n",pid[id],size[id]/1048576,name[id]);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>}<br></span></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">由于上面图中 2022.3.2 19:57:00 至 2022.3.2 19:58:00 发生了一次Full GC,我们重点关注下这一分钟内swap交换区的变化即可,我这里每10s做一次信息采集,可以看到在GC时点前后,swap确实没有变化</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100035955" data-ratio="0.475" data-type="png" data-w="720" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;" src="/upload/0ee27d1d963cdac666cd7402e5dc294a.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">通过上述分析,回归本文核心问题上,现在看来我的处理方式过于激进了,其实也可以不用关闭swap,通过适当降低堆大小,也是能够解决问题的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这也侧面的说明,部署Java服务的Linux系统,在内存分配上并不是无脑大而全,需要综合考虑不同场景下JVM对Java永久代 、Java堆(新生代和老年代)、线程栈、Java NIO所使用内存的需求。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">总结</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">综上,我们得出结论,swap和GC同一时候发生会导致GC时间非常长,JVM严重卡顿,极端的情况下会导致服务崩溃。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">主要原因是:JVM进行GC时,需要对对应堆分区的已用内存进行遍历,假如GC的时候,有堆的一部分内容被交换到swap中,遍历到这部分的时候就须要将其交换回内存;更极端情况同一时刻因为内存空间不足,就需要把内存中堆的另外一部分换到SWAP中去,于是在遍历堆分区的过程中,会把整个堆分区轮流往SWAP写一遍,导致GC时间超长。线上应该限制swap区的大小,如果swap占用比例较高应该进行排查和解决,适当的时候可以通过降低堆大小,或者添加物理内存。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">因此,部署Java服务的Linux系统,在内存分配上要慎重。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">以上内容希望可以起到抛转引玉的作用,如有理解不到位的地方烦请指出。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">好了,本文的技术部分就到这里啦。</p> </section>

架构重构技巧

作者:微信小助手

<p data-mpa-powered-by="yiban.io"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">代码重构</span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.8044444444444444" data-s="300,640" src="/upload/195ad5e38849f5d5862591adac996902.png" data-type="png" data-w="450" style=""></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【定义】</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">对软件代码做任何改动以增加可读性或者简化结构而</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;font-size: 15px;letter-spacing: 0.034em;">不影响输出结果。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【目的】</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">增加可读性、增加可维护性、可扩展性。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(192, 0, 0);font-size: 15px;">【关键点】</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">1. 不影响输出;</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;font-size: 15px;letter-spacing: 0.034em;">2. 不修正错误;3. 不增加新的功能性</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">架构重构</span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.75" data-s="300,640" src="/upload/192c853030dd2c0cb988ef63f07ece5c.png" data-type="png" data-w="640" style=""></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【定义】</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">通过调整系统结构来修复系统质量问题而不</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;font-size: 15px;letter-spacing: 0.034em;">影响整体系统能力。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【目的】</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">修复质量问题(性能、可用性、可扩展……)。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(221, 56, 6);font-size: 15px;">【关键点】</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">1. 修复质量问题,提升架构质量;</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;font-size: 15px;letter-spacing: 0.034em;">2. 不影响整体系统功能;3. 架构本质没有发生变化。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">代码重构 vs 架构重构</span></p> <table> <tbody> <tr> <td width="172" valign="top" style="word-break: break-all;"><br></td> <td width="172" valign="top" style="word-break: break-all;"><span style="font-size: 15px;">代码重构<br></span></td> <td width="172" valign="top"><br></td> </tr> <tr> <td width="172" valign="top" style="word-break: break-all;"><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">基本做法</span></p></td> <td width="172" valign="top" style="word-break: break-all;"><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">调整代码</span></p><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;"><br></span></p></td> <td width="172" valign="top" style="word-break: break-all;"><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.578px;font-size: 15px;">调整架构</span></td> </tr> <tr> <td width="172" valign="top" style="word-break: break-all;"><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">目的</span></p></td> <td width="172" valign="top" style="word-break: break-all;"><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">优化代码,增加代码的可读性、可维护性、可扩展性</span></p></td> <td width="172" valign="top" style="word-break: break-all;"><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">修复架构质量问题</span></p></td> </tr> <tr> <td width="172" valign="top" style="word-break: break-all;"><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">是否修复问题</span></p></td> <td width="172" valign="top" style="word-break: break-all;"><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">否</span></p></td> <td width="172" valign="top" style="word-break: break-all;"><span style="font-size: 15px;">是<br></span></td> </tr> <tr> <td width="172" valign="top" style="word-break: break-all;"><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.578px;font-size: 15px;">是否改变系统能力</span></td> <td width="172" valign="top" style="word-break: break-all;"><span style="font-size: 15px;">否</span></td> <td width="172" valign="top" style="word-break: break-all;"><span style="font-size: 15px;">否<br></span></td> </tr> <tr> <td width="172" valign="top" style="word-break: break-all;"><span style="font-size: 15px;">手段<br></span></td> <td width="172" valign="top" style="word-break: break-all;"><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">引入设计模式</span></p></td> <td width="172" valign="top" style="word-break: break-all;"><p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">引入缓存,分库分表</span></p></td> </tr> </tbody> </table> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">架构重构手段</span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.4351851851851852" data-s="300,640" src="/upload/f5d67fe5482c28f8eccd7ef74ef9720c.png" data-type="png" data-w="1080" style=""></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">技巧1 - 先局部优化后架构重构</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">局部优化<br></span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【定义】</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">对部分业务或者功能进行优化,</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(221, 56, 6);">不影响</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">系统架构。</span></span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【常见手段】</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">1. 数据库添加索引,优化索引;</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">2. 某个数据缓存更新策略采用后台更新;</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">3. 增加负载均衡服务数量;</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">4. 优化代码里面并发的逻辑;</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">5. 修改 InnoDB buffer pool 配置,分配更多内存;</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">6. 服务间的某个接口增加1个参数。</span></p> <p><strong><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">架构重构<br></span></strong></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【定义】</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">优化系统架构,整体提升质量,架构重构</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(221, 56, 6);">会影响</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">架构的4R定义。</span></span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【常见手段】</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">1. 引入消息队列(增加 Role);</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">2. 去掉 ZooKeeper,改为内置 Raft 算法实现(删除 Role);</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">3. 将 Memcached 改为 Redis(改变 Role);</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">4. 按照稳定性拆分微服务(拆分 Role);</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">5. 将粒度太细的微服务合并(合并 Role);</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">6. 将服务间的通信方式由 HTTP 改为 gRPC(修改 Relation);</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">7. SDK 从读本地配置文件改为从管理系统读取配置(修改</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;font-size: 15px;letter-spacing: 0.034em;">Rule)</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">技巧2 - 有的放矢</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">1.明确目标:</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">不要试图解决所有的问题,</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;">抓住关键问题。</span></span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【技巧】</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(4, 50, 255);">问题分类</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">:问题收集列表可能有100条,</span></span><span style="font-size: 15px;letter-spacing: 0.034em;font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">不要全部想着通过架构重构解决,</span><span style="font-size: 15px;letter-spacing: 0.034em;font-family: AlibabaPuHuiTiR;color: rgb(192, 0, 0);">分门</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(192, 0, 0);">别类</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">,找出需要架构重构解决的问题。</span></span></p> <p><strong><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 17px;">2.明确时间:<br></span></strong></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">要有明确的时间点和里程碑,</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;font-size: 15px;letter-spacing: 0.034em;">不要说“慢慢优化”。需要有量化的指标来衡量,不能说“提升 xxx 质量。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【技巧】</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(4, 50, 255);">独立版本</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">:不要混在业务版本里面做</span></span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;font-size: 15px;letter-spacing: 0.034em;">架构重构,否则不好协调资源。</span></p> <p><strong><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;font-size: 17px;">3.明确目标:<br></span></strong></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">需要有量化的指标来衡量,</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;">不能说“提升 xxx 质量”。</span></span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">【技巧】</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">1. 先收集系统已有相关数据,适合项</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;font-size: 15px;letter-spacing: 0.034em;">目投入、时间等;</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">2. </span><span style="font-family: AlibabaPuHuiTiR;color: rgb(4, 50, 255);">调查问卷</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">:适合效率、复杂度等。</span></span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">技巧2 - 案例</span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.3148148148148148" data-s="300,640" src="/upload/975685b080d2777f190910a98e9ce7c4.png" data-type="png" data-w="1080" style=""></p> <p><br></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">技巧3 - 合纵连横</span></p> <p><strong><span style="font-size: 15px;font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">1.合纵:</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;font-size: 15px;">说服业务方和老板。</span></strong></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">1. 以数据说话</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">把“可扩展性”转换为“版本开发速度很慢”,</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;font-size: 15px;letter-spacing: 0.034em;">然后给出对应的项目数据。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">2. 以案例说话</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">如果没有数据,就举极端案例,例如某个小功能,</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;">开发测试只要5天,但是等了1个月才上线。</span></span></p> <p><strong><span style="font-size: 15px;letter-spacing: 0.034em;font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">1.联横:</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;font-size: 15px;">说服其它团队</span></strong></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">1. 换位思考</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">思考对其它团队的好处,才能让人配合。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(218, 104, 46);font-size: 15px;">2. 合作双赢</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">汇报和总结的时候,把其它团队也带上。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">技巧3 - 案例</span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.32407407407407407" data-s="300,640" src="/upload/e5630099f16d682e0dcebb7d365ce40f.png" data-type="png" data-w="1080" style=""></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">技巧4 - 运筹帷幄</span></p> <p><strong>1.问题分类:</strong></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">将问题分类,一段时间集中处理</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;">一类问题。</span></span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">避免对照 Excel 表格,一条一条</span><span style="color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;">的解决</span></span></p> <p><strong><span style="font-size: 15px;color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;">2.问题排序</span></strong><span style="font-size: 15px;color: rgb(0, 0, 0);font-family: AlibabaPuHuiTiR;letter-spacing: 0.034em;"><br></span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">分类后排序,按照优先级顺序来落地。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">避免见缝插针式的安排重构任务。</span></p> <p><strong><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">3.逐一攻破<br></span></strong></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">每一类问题里面先易后难。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">把容易的问题解决掉,增强信心。</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">技巧4 - 案例</span></p> <p style="text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.49166666666666664" data-s="300,640" src="/upload/4d7803c5e8f2c5339839f966448de5c6.png" data-type="png" data-w="1080" style=""></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-weight: bold;font-size: 17px;">架构重构的一些典型问题</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">架构重构是否可以引入新技术?</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">可以,但尽量少,架构重构要求</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(4, 50, 255);">快准</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">。</span></span></p> <hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"> <p><br></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">业务不给时间重构怎么办?</span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">会哭的孩子有奶吃。</span></p> <hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;"></span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">其它团队不配合怎么办?</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">学会利用</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(4, 50, 255);">上级力量。</span></span></p> <hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(4, 50, 255);"></span></span></p> <p><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);font-size: 15px;">业务进度很紧,人力不够怎么办?</span></p> <p><span style="font-size: 15px;"><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">收集需要重构的</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(4, 50, 255);">证据</span><span style="font-family: AlibabaPuHuiTiR;color: rgb(0, 0, 0);">,技术汇报的时候有理有据。</span></span></p> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>

SpringBoot:一个注解就能帮你下载任意对象

作者:微信小助手

<section data-mpa-template="t" mpa-paragraph-type="ignored" style="margin-bottom: 0px;text-wrap: wrap;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);" data-mpa-powered-by="yiban.io"> <p style="text-align: left;"><span style="font-size: 16px;"><strong>目录</strong></span></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 介绍 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 思路 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 结束 </section></li> </ul> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-category="模板" style="width: 100%;padding: 0 15px;" data-mid="" mpa-from-tpl="t"> <section style="width: 100%;padding: 15px 17px 20px;background: #ebf4ff;font-size: 14px;font-weight: 400;color: #6273aa;line-height: 20px;" data-mid="" mpa-from-tpl="t"> <p data-mid="" mpa-is-content="t" style="text-align: left;">文章来源:https://blog.csdn.net/m0_64360721/article/details/122960311</p> </section> <section style="width: 100%;display: flex;justify-content: flex-end;align-items: flex-start;padding-right: 5px;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t" style="width: 23px;height: 27px;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/dLHvdVqeWINyJQzMVmQzxIcFqDsaiaK6ATCCANPe11FbZKCApfz0TbDtfc5gfSQNgJpic86YejM6qcNU5gubeetQ/640&quot;) no-repeat;background-size: contain;background-position: center center;margin-top: -27px;z-index: 10;"> <br> </section> </section> <section style="width: 100%;display: flex;justify-content: flex-start;align-items: flex-start;" data-mid="" mpa-from-tpl="t"> <section style="width: 52.3%;height: 8px;background: #6273AA;margin-top: -6px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 10px;height: 8px;background: #6273AA;transform: skew(35deg);margin-left: -5px;margin-top: -6px;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> <section style="width: 100%;display: flex;justify-content: flex-end;align-items: flex-start;" data-mid="" mpa-from-tpl="t"> <section style="width: 10px;height: 3px;background: #6273AA;transform: skew(35deg);margin-right: -5px;margin-top: -3px;" data-mid="" mpa-from-tpl="t"> <br> </section> <section style="width: 42.2%;height: 3px;background: #6273AA;margin-top: -3px;" data-mid="" mpa-from-tpl="t"> <br> </section> </section> </section> </section> <h2 data-tool="mdnice编辑器"><span style="display: none;"></span><br mpa-from-tpl="t"></h2> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <blockquote style="margin: 5px auto;padding: 0px;max-width: 100%;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;color: rgb(68, 153, 231);" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <blockquote style="margin: 5px auto;padding: 0px;max-width: 100%;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;text-align: center;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto -38px;padding: 0px 15px;max-width: 100%;display: inline-block;background-color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <p style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;clear: both;min-height: 1em;color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><span style="font-family: Arial, Helvetica, sans-serif;"><strong mpa-from-tpl="t"><span style="border-color: rgb(68, 153, 231);color: rgb(255, 255, 255);font-size: 16px;" mpa-is-content="t">介绍</span></strong></span></p> </section> <section style="margin: -40px 25px 50px;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 3px 0px 0px;padding: 10px 0px;max-width: 100%;box-sizing: border-box;display: inline-block;width: 495px;color: rgb(68, 153, 231);float: left;border-color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 1em 0px 0px;padding: 0px;max-width: 100%;box-sizing: border-box;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);clear: both;color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px 0px -3px;padding: 0px;max-width: 100%;float: right;border-color: rgb(68, 153, 231);width: 6px;border-radius: 50%;background-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;height: 6px !important;" mpa-from-tpl="t"> <br> </section> <section style="margin: 0px 0px -2px;padding: 0px;max-width: 100%;text-align: left;border-color: rgb(68, 153, 231);width: 6px;border-radius: 50%;background-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;height: 6px !important;" mpa-from-tpl="t"> <br> </section> <section style="margin: -20px 0px 0px;padding: 0px;max-width: 100%;box-sizing: border-box;text-decoration: inherit;color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box;border-top: 1px solid rgb(68, 153, 231);width: 495px;float: left;border-right-color: rgb(68, 153, 231);border-bottom-color: rgb(68, 153, 231);border-left-color: rgb(68, 153, 231);color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <br> </section> </section> </section> </section> </section> </section> </blockquote> </section> </section> </blockquote> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">下载功能应该是比较常见的功能了,虽然一个项目里面可能出现的不多,但是基本上每个项目都会有,而且有些下载功能其实还是比较繁杂的,倒不是难,而是麻烦。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">所以结合之前的下载需求,我写了一个库来简化下载功能的实现</p> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;line-height: 1.8;border-radius: 0px 0px 10px 10px;color: rgb(14, 136, 235);background: rgb(255, 255, 255);box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> <p style="padding-top: 8px;padding-bottom: 8px;letter-spacing: 0.2em;word-spacing: 0.1em;line-height: 26px;font-size: 15px;">❝</p> <p style="padding-top: 8px;padding-bottom: 8px;letter-spacing: 0.2em;word-spacing: 0.1em;line-height: 26px;font-size: 15px;">传送门:https://github.com/Linyuzai/concept/wiki/Concept-Download</p> <p style="padding-top: 8px;padding-bottom: 8px;letter-spacing: 0.2em;word-spacing: 0.1em;line-height: 26px;font-size: 15px;">❞</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">如果我说现在只需要一个注解就能帮你下载任意的对象,是不是觉得非常的方便</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/hzVGicX27IG1xSmLWhia6IibKjtW00qp2PJNo0qoyFEJa2wicj5SKvYw9vv9ic2BpNvSkccicwsH7ICu0Xz0m69eynXiaPq3bUOEKpt/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #1E1E1E;border-radius: 5px;"><span style="color: #9B9B9B;line-height: 26px;">@Download</span>(source&nbsp;=&nbsp;<span style="color: #D69D85;line-height: 26px;">"classpath:/download/README.txt"</span>)<br><span style="color: #9B9B9B;line-height: 26px;">@GetMapping</span>(<span style="color: #D69D85;line-height: 26px;">"/classpath"</span>)<br><span style="line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">public</span>&nbsp;<span style="color: #569CD6;line-height: 26px;">void</span>&nbsp;<span style="line-height: 26px;">classpath</span><span style="line-height: 26px;">()</span>&nbsp;</span>{<br><br>}<br><br><span style="color: #9B9B9B;line-height: 26px;">@Download</span><br><span style="color: #9B9B9B;line-height: 26px;">@GetMapping</span>(<span style="color: #D69D85;line-height: 26px;">"/file"</span>)<br><span style="line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">public</span>&nbsp;File&nbsp;<span style="line-height: 26px;">file</span><span style="line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #569CD6;line-height: 26px;">return</span>&nbsp;<span style="color: #569CD6;line-height: 26px;">new</span>&nbsp;File(<span style="color: #D69D85;line-height: 26px;">"/Users/Shared/README.txt"</span>);<br>}<br><br><span style="color: #9B9B9B;line-height: 26px;">@Download</span><br><span style="color: #9B9B9B;line-height: 26px;">@GetMapping</span>(<span style="color: #D69D85;line-height: 26px;">"/http"</span>)<br><span style="line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="line-height: 26px;">http</span><span style="line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #569CD6;line-height: 26px;">return</span>&nbsp;<span style="color: #D69D85;line-height: 26px;">"http://127.0.0.1:8080/concept-download/image.jpg"</span>;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">感觉差别不大?那就听听我遇到的一个下载需求</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">我们有一个平台是管理设备的,然后每个设备都会有一个二维码图片,用一个字段存储的 http 地址</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">现在需要导出所有设备二维码图片的压缩包,图片名称需要用设备名称加 .png 后缀,需求上来说并不难,但是着实有点麻烦</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 首先我需要将设备列表查出来 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 然后使用二维码地址下载图片并写到本地缓存文件 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 在下载之前需要先判断是否已经存在缓存 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 下载时需要并发下载提升性能 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 等所有图片下载结束后 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 再生成一个压缩文件 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 然后再操作输入输出流写到响应中 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">看着我实现了将近 200 行的代码,真是又臭又长,一个下载功能咋能那么麻烦呢,于是我就想有没有更简单的方式</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">我当时的需求很简单,我想着我只要提供需要下载的数据,比如一个文件路径,一个文件对象,一段字符串文本,一个http地址,或者混搭了前面所有类型的一个集合,甚至是我们自定义的某个类的实例,后面的事情我就不用管了</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">文件路径是一个文件还是一个目录?字符串文本需要先写入一个文本文件中?http资源如何下载到本地?多个文件怎么压缩?最后怎么写到响应中?我才不想花时间管这些</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">比如就像我现在这个需求,我只要返回设备列表就行了,其他的事情我都不用管</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/hzVGicX27IG1xSmLWhia6IibKjtW00qp2PJNo0qoyFEJa2wicj5SKvYw9vv9ic2BpNvSkccicwsH7ICu0Xz0m69eynXiaPq3bUOEKpt/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #1E1E1E;border-radius: 5px;"><span style="color: #9B9B9B;line-height: 26px;">@Download</span>(filename&nbsp;=&nbsp;<span style="color: #D69D85;line-height: 26px;">"二维码.zip"</span>)<br><span style="color: #9B9B9B;line-height: 26px;">@GetMapping</span>(<span style="color: #D69D85;line-height: 26px;">"/download"</span>)<br><span style="line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">public</span>&nbsp;List&lt;Device&gt;&nbsp;<span style="line-height: 26px;">download</span><span style="line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #569CD6;line-height: 26px;">return</span>&nbsp;deviceService.all();<br>}<br><br><span style="color: #569CD6;line-height: 26px;">public</span>&nbsp;<span style="color: #B8D7A3;line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">class</span>&nbsp;<span style="color: #DCDCDC;line-height: 26px;">Device</span>&nbsp;</span>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">//设备名称</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #569CD6;line-height: 26px;">private</span>&nbsp;String&nbsp;name;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">//设备二维码</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">//注解表示该http地址是需要下载的数据</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">@SourceObject</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #569CD6;line-height: 26px;">private</span>&nbsp;String&nbsp;qrCodeUrl;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">//注解表示文件名称</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">@SourceName</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="line-height: 26px;">getQrCodeName</span><span style="line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #569CD6;line-height: 26px;">return</span>&nbsp;name&nbsp;+&nbsp;<span style="color: #D69D85;line-height: 26px;">".png"</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">//省略其他属性方法</span><br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">通过在 Device 的字段上标注某些注解(或是实现某个接口)来指定文件名称和文件地址</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">如果能这样实现,省时省心省力,又多了写 199 行代码的摸鱼时间难道不香么</p> <h2 data-tool="mdnice编辑器"><br></h2> <h2 data-tool="mdnice编辑器"><span style="display: none;"></span><br mpa-from-tpl="t"></h2> <section data-mpa-template="t" mpa-from-tpl="t"> <blockquote style="margin: 5px auto;padding: 0px;max-width: 100%;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 25.6px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;color: rgb(68, 153, 231);" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <blockquote style="margin: 5px auto;padding: 0px;max-width: 100%;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto;padding: 0px;max-width: 100%;text-align: center;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px auto -38px;padding: 0px 15px;max-width: 100%;display: inline-block;background-color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <p style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;clear: both;min-height: 1em;color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><span style="font-family: Arial, Helvetica, sans-serif;"><strong mpa-from-tpl="t"><span style="border-color: rgb(68, 153, 231);color: rgb(255, 255, 255);font-size: 16px;" mpa-is-content="t">思路</span></strong></span></p> </section> <section style="margin: -40px 25px 50px;padding: 0px;max-width: 100%;border-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 3px 0px 0px;padding: 10px 0px;max-width: 100%;box-sizing: border-box;display: inline-block;width: 495px;color: rgb(68, 153, 231);float: left;border-color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 1em 0px 0px;padding: 0px;max-width: 100%;box-sizing: border-box;border-width: 0px;border-style: none;border-color: rgb(68, 153, 231);clear: both;color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px 0px -3px;padding: 0px;max-width: 100%;float: right;border-color: rgb(68, 153, 231);width: 6px;border-radius: 50%;background-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;height: 6px !important;" mpa-from-tpl="t"> <br> </section> <section style="margin: 0px 0px -2px;padding: 0px;max-width: 100%;text-align: left;border-color: rgb(68, 153, 231);width: 6px;border-radius: 50%;background-color: rgb(68, 153, 231);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;height: 6px !important;" mpa-from-tpl="t"> <br> </section> <section style="margin: -20px 0px 0px;padding: 0px;max-width: 100%;box-sizing: border-box;text-decoration: inherit;color: rgb(68, 153, 231);border-color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <section style="margin: 0px;padding: 0px;max-width: 100%;box-sizing: border-box;border-top: 1px solid rgb(68, 153, 231);width: 495px;float: left;border-right-color: rgb(68, 153, 231);border-bottom-color: rgb(68, 153, 231);border-left-color: rgb(68, 153, 231);color: rgb(68, 153, 231);word-wrap: break-word !important;overflow-wrap: break-word !important;" mpa-from-tpl="t"> <br> </section> </section> </section> </section> </section> </section> </blockquote> </section> </section> </blockquote> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">下面来讲讲这个库的主要设计思路,以及中间遇到的坑,大家有兴趣可以继续往下看</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">其实基于一开始的设想,我觉得功能并没有多复杂,于是就决定开肝</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">只是万万没想到实现起来比我想象的更复杂(这是后话了)</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>基础<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">首先整个库基于响应式编程,但却并不是完全意义上的响应式,只能说是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">Mono&lt;InputStream</code>&gt;这样的。。。奇怪组合?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">为什么会这样呢,很大的一个原因是由于需要兼容webmvc和webflux,导致我仅仅是将之前实现的InputStream方式重构成了响应式,所以就出现了这样的组合</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">这也是我遇到的最大的一个坑,我先前已经基本调通了基于Servlet的整个下载流程,然后就想着支持一下webflux</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">大家都知道webmvc中,我们可以通过RequestContextHolder来获得请求和响应对象,但是在webflux中就不行了,当然我们可以在方法参数中注入</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/hzVGicX27IG1xSmLWhia6IibKjtW00qp2PJNo0qoyFEJa2wicj5SKvYw9vv9ic2BpNvSkccicwsH7ICu0Xz0m69eynXiaPq3bUOEKpt/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #1E1E1E;border-radius: 5px;"><span style="color: #9B9B9B;line-height: 26px;">@Download</span>(source&nbsp;=&nbsp;<span style="color: #D69D85;line-height: 26px;">"classpath:/download/README.txt"</span>)<br><span style="color: #9B9B9B;line-height: 26px;">@GetMapping</span>(<span style="color: #D69D85;line-height: 26px;">"/classpath"</span>)<br><span style="line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">public</span>&nbsp;<span style="color: #569CD6;line-height: 26px;">void</span>&nbsp;<span style="line-height: 26px;">classpath</span><span style="line-height: 26px;">(ServerHttpResponse&nbsp;response)</span>&nbsp;</span>{<br><br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">结合Spring自带的注入功能,我们就可以通过AOP拿到响应的入参了,但是总觉得这样写有点多余,强迫症表示不能忍</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">有什么办法既能把用不到的入参干掉,又能拿到响应对象呢,在网上找到了一种实现方式</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/hzVGicX27IG1xSmLWhia6IibKjtW00qp2PJNo0qoyFEJa2wicj5SKvYw9vv9ic2BpNvSkccicwsH7ICu0Xz0m69eynXiaPq3bUOEKpt/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(30, 30, 30);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #DCDCDC;display: -webkit-box;fo

1.入门-K8s 集群架构介绍

作者:微信小助手

<section data-role="outer" label="edit by 135editor"> <p style="text-align:center;"><img class="rich_pages wxw-img" data-ratio="1" src="/upload/08df4a90871b04c5e2d71e0fbf281f40.png" data-w="400" data-width="141px" style="vertical-align: inherit;width: 141px;" width="141"></p> <section data-role="paragraph"> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="36" data-source-title=""> <section class="js_blockquote_digest"> <p>加微信 “AmsNeil” 领取所有系列Markdown/PDF文档和源码<span style="font-size: 18px;font-weight: bold;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;letter-spacing: 2px;text-align: left;"></span></p> </section> </blockquote> </section> <section data-tools="135编辑器" data-id="125616" data-color="#0070c0"> <section> <section data-width="80%"> <section> <section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;word-break: break-word;text-align: left;line-height: 1.25;letter-spacing: 2px;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">Kubernetes(通常简称为K8s)是一个用于自动部署、扩展和管理容器化应用程序的开源容器编排平台。它提供了一种便捷的方式来管理容器,使得在一个集群中运行、调度和扩展应用程序变得更加简单。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(145, 109, 213);">为什么使用k8s而不是直接使用Docker?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">尽管Docker提供了优秀的容器化解决方案,但它主要专注于构建、打包和运行容器。Kubernetes在这个基础上提供了更高级的编排和管理功能,特别适用于复杂的微服务架构和大规模的容器化应用程序。</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;font-size: 15px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「自动化和编排:」</strong> Kubernetes提供了自动化和编排容器的能力,使得在生产环境中运行大规模、多组件的应用程序变得容易。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「高可用性:」</strong> Kubernetes的设计目标之一是确保应用程序的高可用性,即使在节点故障或其他问题时,也能保持服务的可用性。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「水平扩展:」</strong> Kubernetes支持水平扩展,能够根据负载自动调整应用程序的规模,以应对流量的变化。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「服务发现和负载均衡:」</strong> Kubernetes提供了内置的服务发现机制和负载均衡,使得在应用程序组件之间进行通信更加容易。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「滚动更新和回滚:」</strong> Kubernetes支持滚动更新,使得应用程序的升级变得更加平滑,同时也支持回滚到之前的版本。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「资源管理:」</strong> Kubernetes允许对资源进行灵活的管理和调度,确保Pods获得适当的资源分配。</p> </section></li> </ol> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(145, 109, 213);">K8s基本概念</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">以下是Kubernetes的一些基本概念和入门介绍:</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;text-align: center;"><span style="display: none;"></span><span style="border-bottom: 2px solid #d89cf6;">1. <strong style="color: rgb(145, 109, 213);">「容器化技术基础」</strong></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">Kubernetes主要用于管理和编排容器化应用程序。容器是一种轻量级、可移植的软件打包方式,其中包含应用程序及其所有依赖关系。Docker是一个流行的容器化工具,但K8s也支持其他容器运行时。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;text-align: center;"><span style="display: none;"></span><span style="border-bottom: 2px solid #d89cf6;">2. <strong style="color: rgb(145, 109, 213);">「Kubernetes的核心概念」</strong></span><span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-imgfileid="100011228" data-ratio="0.48518518518518516" src="/upload/6d91dfa10730aa4a79358f0f5b0ece41.png" data-type="png" data-w="1080" style="border-radius: 6px;display: block;margin: 20px auto;object-fit: contain;box-shadow: rgb(153, 153, 153) 2px 4px 7px;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>2.1 <strong style="color: rgb(145, 109, 213);">「Pods(Pod)」</strong><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">Pod是Kubernetes中最小的可部署单元,它包含一个或多个相关的容器。这些容器共享网络命名空间和存储卷,它们通常协同工作来构成一个应用程序。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>2.2 <strong style="color: rgb(145, 109, 213);">「Service(服务)」</strong><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">Service定义了一组Pod的逻辑集合,并提供了一个访问这些Pod的稳定入口点。Service可以通过集群内部或外部的网络访问这些Pod。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>2.3 <strong style="color: rgb(145, 109, 213);">「Deployment(部署)」</strong><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">Deployment用于定义应用程序的期望状态,并确保实际运行的Pod副本数量与期望状态一致。Deployment还支持滚动更新和回滚操作,以便更新应用程序。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>2.4 <strong style="color: rgb(145, 109, 213);">「ConfigMap和Secret」</strong><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">ConfigMap用于将配置数据从应用程序中分离出来,而Secret则用于安全地存储敏感信息,如密码、API密钥等。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>2.4 <strong style="color: rgb(145, 109, 213);">「Ingress」</strong><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">Kubernetes Ingress(K8s Ingress)是一种用于管理和公开Kubernetes集群中服务的API对象。它允许外部流量进入集群,并提供路由规则来决定如何将该流量路由到不同的服务.</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;text-align: center;"><span style="display: none;"></span><span style="border-bottom: 2px solid #d89cf6;">3. <strong style="color: rgb(145, 109, 213);">「Kubernetes的工作原理」</strong></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">Kubernetes集群由一组物理或虚拟机器组成,这些机器被称为节点。集群有一个主节点(Master)和多个工作节点(Node)。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>3.1 <strong style="color: rgb(145, 109, 213);">「主节点(Master)」</strong><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">主节点负责管理集群的整体状态和控制工作节点的操作。它包括以下组件:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;font-size: 15px;list-style-type: circle;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <strong style="color: rgb(145, 109, 213);">「API Server:」</strong> 提供了K8s API的入口,用于与Kubernetes进行交互。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <strong style="color: rgb(145, 109, 213);">「Controller Manager:」</strong> 负责监控系统状态,确保实际状态符合期望状态。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <strong style="color: rgb(145, 109, 213);">「Scheduler:」</strong> 负责将Pod调度到工作节点上运行。 </section></li> </ul> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>3.2 <strong style="color: rgb(145, 109, 213);">「工作节点(Node)」</strong><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">工作节点是集群中的计算资源,用于运行容器。每个工作节点包括以下组件:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;font-size: 15px;list-style-type: circle;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <strong style="color: rgb(145, 109, 213);">「Kubelet:」</strong> 负责与主节点通信,确保在节点上运行所需的Pod。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <strong style="color: rgb(145, 109, 213);">「Container Runtime:」</strong> 用于启动和管理容器的软件,如Docker。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <strong style="color: rgb(145, 109, 213);">「Kube Proxy:」</strong> 负责在节点上实现Service的网络代理。 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;text-align: center;"><span style="display: none;"></span><span style="border-bottom: 2px solid #d89cf6;">4. <strong style="color: rgb(145, 109, 213);">「Kubernetes的使用流程」</strong></span><span style="display: none;"></span></h3> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;font-size: 15px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「定义应用程序:」</strong> 使用K8s的YAML文件定义应用程序的组件,包括Pods、Services、Deployments等。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「部署应用程序:」</strong> 使用kubectl工具或Kubernetes API将定义的应用程序组件部署到集群中。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「Kubernetes控制器处理:」</strong> 控制器(如Deployment)会接收定义并确保集群状态与定义状态一致。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「应用程序运行:」</strong> K8s会在工作节点上创建和调度Pods,确保应用程序正常运行。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 14px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin-top: 10px;margin-bottom: 10px;word-spacing: 2px;"><strong style="color: rgb(145, 109, 213);">「监控和维护:」</strong> 使用K8s的监控工具来监测集群状态,进行日志管理和故障排除。</p> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">Kubernetes为应用程序提供了弹性、可伸缩性和高可用性的运行环境,使得应用程序在多个环境中更容易部署和管理。学习和掌握Kubernetes需要逐步深入,通过实践和使用各种资源来加深理解。</p> </section> <section class="mp_profile_iframe_wrp"> <span style="display: none;line-height: 0px;">‍</span> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-weui-theme="light" data-id="MzU2MzYwMDI0Ng==" data-headimg="http://mmbiz.qpic.cn/sz_mmbiz_png/L3TFosuayYqHqhI3kVX5yJNicB3gQYEUr07zpQuiajmfCYwlhM8lnDYeC9qqtBLiab2WmtQP0cbFqlKM6sZXp06ew/0?wx_fmt=png" data-nickname="乐哥聊编程" data-alias="lglbc2022" data-signature="专注编程分享,聊程序人生" data-from="0" data-is_biz_ban="0"></mp-common-profile> <span style="display: none;line-height: 0px;">‍</span> </section> </section> </section> </section> </section> </section> </section> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>

DevOps搭建(十四)-基于Jenkins流水线方式部署详细步骤

作者:微信小助手

<section> <section style="display: inline-block;"> <img data-ratio="0.4876847290640394" src="/upload/ab14bbc01b375895aa11b42936822b54.jpg" data-type="jpeg" data-w="1015"> </section>​ </section> <p> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22xh4zZ%22%2C%22name%22%3A%22h1%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u97929273%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%221%E3%80%81%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%B5%81%E6%B0%B4%E7%BA%BF%E9%A1%B9%E7%9B%AE%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22udadbc489%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22u608f5f59%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688569713172-f2d0f4a5-7d6f-4dd9-8501-df82b7629496.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1320%2C%22height%22%3A756%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A109076%2C%22width%22%3A1056%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22ua2a8d858-f5c6-4f9c-b895-12430dc4083%22%2C%22clientId%22%3A%22udb903c88-cbf3-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A38%2C%22y%22%3A37%2C%22width%22%3A195%2C%22height%22%3A27%2C%22text%22%3A%22%E8%BE%93%E5%85%A5%E4%B8%80%E4%B8%AA%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0%22%7D%2C%7B%22x%22%3A50%2C%22y%22%3A127%2C%22width%22%3A177%2C%22height%22%3A19%2C%22text%22%3A%22DEVOPS-PIPELINE-TEST%22%7D%2C%7B%22x%22%3A40%2C%22y%22%3A168%2C%22width%22%3A69%2C%22height%22%3A17%2C%22text%22%3A%22%3E%E5%BF%85%E5%A1%AB%E9%A1%B9%22%7D%2C%7B%22x%22%3A110%2C%22y%22%3A246%2C%22width%22%3A263%2C%22height%22%3A25%2C%22text%22%3A%22%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%87%AA%E7%94%B1%E9%A3%8E%E6%A0%BC%E7%9A%84%E8%BD%AF%E4%BB%B6%E9%A1%B9%E7%9B%AE%22%7D%2C%7B%22x%22%3A109%2C%22y%22%3A280%2C%22width%22%3A882%2C%22height%22%3A24%2C%22text%22%3A%22%E8%BF%99%E6%98%AFJENKINS%E7%9A%84%E4%B8%BB%E8%A6%81%E5%8A%9F%E8%83%BD%2CJENKINS%E5%B0%86%E4%BC%9A%E7%BB%93%E5%90%88%E4%BB%BB%E4%BD%95%E6%9E%84%E5%BB%BA%E7%B3%BB%E7%BB%9F%E6%9D%A5%E6%9E%84%E5%BB%BA%E7%B3%BB%E7%BB%9F%E6%9D%A5%E6%9E%84%E5%BB%BA%E4%BD%A0%E7%9A%84%E9%A1%B9%E7%9B%AE%2C%E7%94%9A%E8%87%B3%E5%8F%AF%E4%BB%A5%E6%9E%84%E5%BB%BA%E8%BD%AF%E4%BB%B6%E4%BB%A5%E5%A4%96%E7%9A%84%E7%B3%BB%E7%BB%9F.%22%7D%2C%7B%22x%22%3A112%2C%22y%22%3A339%2C%22width%22%3A62%2C%22height%22%3A22%2C%22text%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%22%7D%2C%7B%22x%22%3A110%2C%22y%22%3A374%2C%22width%22%3A1053%2C%22height%22%3A22%2C%22text%22%3A%22%E7%B2%BE%E5%BF%83%E5%9C%B0%E7%BB%84%E7%BB%87%E4%B8%80%E4%B8%AA%E5%8F%AF%E4%BB%A5%E9%95%BF%E6%9C%9F%E8%BF%90%E8%A1%8C%E5%9C%A8%E5%A4%9A%E4%B8%AA%E8%8A%82%E7%82%B9%E4%B8%8A%E7%9A%84%E4%BB%BB%E5%8A%A1.%E9%80%82%E7%94%A8%E4%BA%8E%E6%9E%84%E5%BB%BA%E6%B5%81%E6%B0%B4%E9%95%9C(%E9%87%8D%E5%8A%A0%E6%AD%A3%E5%BC%8F%E5%9C%B0%E5%BA%94%E5%BD%93%E7%A7%B0%E4%B8%BA%E5%B7%A5%E4%BD%9C%E6%B5%81)%2C%E5%A2%9E%E5%8A%A0%E6%88%96%E8%80%85%E7%BB%84%E7%BB%87%E5%BB%BA%E4%BB%A5%E9%87%87%E7%94%A8%E8%87%AA%E7%94%B1%E9%A3%8E%E6%A0%BC%22%7D%2C%7B%22x%22%3A111%2C%22y%22%3A402%2C%22width%22%3A93%2C%22height%22%3A19%2C%22text%22%3A%22%E7%9A%84%E4%BB%BB%E5%8A%A1%E7%B1%BB%E5%9E%8B.%22%7D%2C%7B%22x%22%3A112%2C%22y%22%3A458%2C%22width%22%3A181%2C%22height%22%3A22%2C%22text%22%3A%22%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%A4%9A%E9%85%8D%E7%BD%AE%E9%A1%B9%E7%9B%AE%22%7D%2C%7B%22x%22%3A111%2C%22y%22%3A492%2C%22width%22%3A421%2C%22height%22%3A21%2C%22text%22%3A%22%E9%80%82%E7%94%A8%E4%BA%8E%E5%A4%9A%E9%85%8D%E7%BD%AE%E9%A1%B9%E7%9B%AE%2C%E4%BE%8B%E5%A6%82%E5%A4%9A%E7%8E%AF%E5%A2%83%E6%B5%8B%E8%AF%95%2C%E5%B9%B3%E5%8F%B0%E6%8C%87%E5%AE%9A%E6%9E%84%E5%BB%BA%2C%E7%AD%89%E7%AD%89.%22%7D%2C%7B%22x%22%3A114%2C%22y%22%3A550%2C%22width%22%3A93%2C%22height%22%3A22%2C%22text%22%3A%22%7B0%5D%E6%96%87%E4%BB%B6%E5%A4%B9%22%7D%2C%7B%22x%22%3A111%2C%22y%22%3A579%2C%22width%22%3A639%2C%22height%22%3A28%2C%22text%22%3A%22CREATES%20A%20SET%20OF%20MULTIBRANCH%20PROJECT%20SUBFOLDERS%20BY%20SCANNING%20FOR%20REPOSITORIES.%22%7D%2C%7B%22x%22%3A112%2C%22y%22%3A641%2C%22width%22%3A122%2C%22height%22%3A22%2C%22text%22%3A%22%E5%A4%9A%E5%88%86%E6%94%AF%E6%B5%81%E6%B0%B4%E7%BA%BF%22%7D%2C%7B%22x%22%3A199%2C%22y%22%3A677%2C%22width%22%3A326%2C%22height%22%3A20%2C%22text%22%3A%22CM%E4%BB%93%E5%BA%93%E4%B8%AD%E6%A3%80%E6%B5%8B%E5%88%B0%E7%9A%84%E5%88%86%E6%94%AF%E5%88%9B%E5%BB%BA%E4%B8%80%E7%B3%BB%E5%88%97%E6%B5%81%E6%B0%B4%E7%BA%BF.%22%7D%2C%7B%22x%22%3A91%2C%22y%22%3A716%2C%22width%22%3A35%2C%22height%22%3A20%2C%22text%22%3A%22%E7%A1%AE%E5%AE%9A%22%7D%5D%2C%22search%22%3A%22%E8%BE%93%E5%85%A5%E4%B8%80%E4%B8%AA%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0%20DEVOPS-PIPELINE-TEST%20%3E%E5%BF%85%E5%A1%AB%E9%A1%B9%20%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%87%AA%E7%94%B1%E9%A3%8E%E6%A0%BC%E7%9A%84%E8%BD%AF%E4%BB%B6%E9%A1%B9%E7%9B%AE%20%E8%BF%99%E6%98%AFJENKINS%E7%9A%84%E4%B8%BB%E8%A6%81%E5%8A%9F%E8%83%BD%2CJENKINS%E5%B0%86%E4%BC%9A%E7%BB%93%E5%90%88%E4%BB%BB%E4%BD%95%E6%9E%84%E5%BB%BA%E7%B3%BB%E7%BB%9F%E6%9D%A5%E6%9E%84%E5%BB%BA%E7%B3%BB%E7%BB%9F%E6%9D%A5%E6%9E%84%E5%BB%BA%E4%BD%A0%E7%9A%84%E9%A1%B9%E7%9B%AE%2C%E7%94%9A%E8%87%B3%E5%8F%AF%E4%BB%A5%E6%9E%84%E5%BB%BA%E8%BD%AF%E4%BB%B6%E4%BB%A5%E5%A4%96%E7%9A%84%E7%B3%BB%E7%BB%9F.%20%E6%B5%81%E6%B0%B4%E7%BA%BF%20%E7%B2%BE%E5%BF%83%E5%9C%B0%E7%BB%84%E7%BB%87%E4%B8%80%E4%B8%AA%E5%8F%AF%E4%BB%A5%E9%95%BF%E6%9C%9F%E8%BF%90%E8%A1%8C%E5%9C%A8%E5%A4%9A%E4%B8%AA%E8%8A%82%E7%82%B9%E4%B8%8A%E7%9A%84%E4%BB%BB%E5%8A%A1.%E9%80%82%E7%94%A8%E4%BA%8E%E6%9E%84%E5%BB%BA%E6%B5%81%E6%B0%B4%E9%95%9C(%E9%87%8D%E5%8A%A0%E6%AD%A3%E5%BC%8F%E5%9C%B0%E5%BA%94%E5%BD%93%E7%A7%B0%E4%B8%BA%E5%B7%A5%E4%BD%9C%E6%B5%81)%2C%E5%A2%9E%E5%8A%A0%E6%88%96%E8%80%85%E7%BB%84%E7%BB%87%E5%BB%BA%E4%BB%A5%E9%87%87%E7%94%A8%E8%87%AA%E7%94%B1%E9%A3%8E%E6%A0%BC%20%E7%9A%84%E4%BB%BB%E5%8A%A1%E7%B1%BB%E5%9E%8B.%20%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%A4%9A%E9%85%8D%E7%BD%AE%E9%A1%B9%E7%9B%AE%20%E9%80%82%E7%94%A8%E4%BA%8E%E5%A4%9A%E9%85%8D%E7%BD%AE%E9%A1%B9%E7%9B%AE%2C%E4%BE%8B%E5%A6%82%E5%A4%9A%E7%8E%AF%E5%A2%83%E6%B5%8B%E8%AF%95%2C%E5%B9%B3%E5%8F%B0%E6%8C%87%E5%AE%9A%E6%9E%84%E5%BB%BA%2C%E7%AD%89%E7%AD%89.%20%7B0%5D%E6%96%87%E4%BB%B6%E5%A4%B9%20CREATES%20A%20SET%20OF%20MULTIBRANCH%20PROJECT%20SUBFOLDERS%20BY%20SCANNING%20FOR%20REPOSITORIES.%20%E5%A4%9A%E5%88%86%E6%94%AF%E6%B5%81%E6%B0%B4%E7%BA%BF%20CM%E4%BB%93%E5%BA%93%E4%B8%AD%E6%A3%80%E6%B5%8B%E5%88%B0%E7%9A%84%E5%88%86%E6%94%AF%E5%88%9B%E5%BB%BA%E4%B8%80%E7%B3%BB%E5%88%97%E6%B5%81%E6%B0%B4%E7%BA%BF.%20%E7%A1%AE%E5%AE%9A%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23f59762%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uc6294b48%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u8fd989cc%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E8%BF%9B%E5%85%A5%E9%85%8D%E7%BD%AE%E6%9C%80%E4%B8%8B%E6%96%B9%E7%9A%84%E6%B5%81%E6%B0%B4%E7%BA%BF%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%89%E6%8B%A9Hello%20World%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84demo%E4%BD%93%E9%AA%8C%E3%80%82%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u2a723587%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22u71ba7323%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688569850526-647a1920-a7f8-4d66-941d-b53933c6ad9f.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1540%2C%22height%22%3A781%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A56940%2C%22width%22%3A1232%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22u02cc3e8a-0289-494c-8fbf-e699744fa6a%22%2C%22clientId%22%3A%22udb903c88-cbf3-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A90%2C%22y%22%3A12%2C%22width%22%3A70%2C%22height%22%3A24%2C%22text%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%22%7D%2C%7B%22x%22%3A89%2C%22y%22%3A81%2C%22width%22%3A40%2C%22height%22%3A20%2C%22text%22%3A%22%E5%AE%9A%E4%B9%89%22%7D%2C%7B%22x%22%3A104%2C%22y%22%3A132%2C%22width%22%3A122%2C%22height%22%3A23%2C%22text%22%3A%22PIPELINE%20SCRIPT%22%7D%2C%7B%22x%22%3A129%2C%22y%22%3A205%2C%22width%22%3A44%2C%22height%22%3A21%2C%22text%22%3A%22%E8%84%9A%E6%9C%AC%22%7D%2C%7B%22x%22%3A185%2C%22y%22%3A247%2C%22width%22%3A92%2C%22height%22%3A16%2C%22text%22%3A%22PIPELINE%22%7D%2C%7B%22x%22%3A1141%2C%22y%22%3A249%2C%22width%22%3A107%2C%22height%22%3A19%2C%22text%22%3A%22HELLOWORLD%22%7D%2C%7B%22x%22%3A230%2C%22y%22%3A267%2C%22width%22%3A74%2C%22height%22%3A13%2C%22text%22%3A%22AGENT%20ANY%22%7D%2C%7B%22x%22%3A1141%2C%22y%22%3A274%2C%22width%22%3A169%2C%22height%22%3A16%2C%22text%22%3A%22TRY%20SAMPLE%20PINELINE%22%7D%2C%7B%22x%22%3A158%2C%22y%22%3A292%2C%22width%22%3A26%2C%22height%22%3A170%2C%22text%22%3A%2234567890ML%22%7D%2C%7B%22x%22%3A1141%2C%22y%22%3A298%2C%22width%22%3A107%2C%22height%22%3A17%2C%22text%22%3A%22HELLO%20WORLD%22%7D%2C%7B%22x%22%3A230%2C%22y%22%3A302%2C%22width%22%3A64%2C%22height%22%3A14%2C%22text%22%3A%22STAGES%22%7D%2C%7B%22x%22%3A262%2C%22y%22%3A319%2C%22width%22%3A134%2C%22height%22%3A17%2C%22text%22%3A%22STAGE('HELLO)%7B%22%7D%2C%7B%22x%22%3A1143%2C%22y%22%3A324%2C%22width%22%3A146%2C%22height%22%3A17%2C%22text%22%3A%22GITHUB%2BMAVEN%22%7D%2C%7B%22x%22%3A292%2C%22y%22%3A338%2C%22width%22%3A64%2C%22height%22%3A14%2C%22text%22%3A%22STEPS%22%7D%2C%7B%22x%22%3A1144%2C%22y%22%3A346%2C%22width%22%3A145%2C%22height%22%3A19%2C%22text%22%3A%22SCRIPTEDPIPELINE%22%7D%2C%7B%22x%22%3A324%2C%22y%22%3A354%2C%22width%22%3A152%2C%22height%22%3A16%2C%22text%22%3A%22ECHO%20HELLO%20WORLD'%22%7D%2C%7B%22x%22%3A171%2C%22y%22%3A594%2C%22width%22%3A174%2C%22height%22%3A25%2C%22text%22%3A%22%E4%BD%BF%E7%94%A8GROOVY%E6%B2%99%E7%9B%92%3F%22%7D%2C%7B%22x%22%3A131%2C%22y%22%3A667%2C%22width%22%3A92%2C%22height%22%3A22%2C%22text%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%AF%AD%E6%B3%95%22%7D%2C%7B%22x%22%3A263%2C%22y%22%3A745%2C%22width%22%3A36%2C%22height%22%3A18%2C%22text%22%3A%22%E5%BA%94%E7%94%A8%22%7D%2C%7B%22x%22%3A132%2C%22y%22%3A745%2C%22width%22%3A33%2C%22height%22%3A17%2C%22text%22%3A%22%E4%BF%9D%E5%AD%98%22%7D%5D%2C%22search%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%20%E5%AE%9A%E4%B9%89%20PIPELINE%20SCRIPT%20%E8%84%9A%E6%9C%AC%20PIPELINE%20HELLOWORLD%20AGENT%20ANY%20TRY%20SAMPLE%20PINELINE%2034567890ML%20HELLO%20WORLD%20STAGES%20STAGE('HELLO)%7B%20GITHUB%2BMAVEN%20STEPS%20SCRIPTEDPIPELINE%20ECHO%20HELLO%20WORLD'%20%E4%BD%BF%E7%94%A8GROOVY%E6%B2%99%E7%9B%92%3F%20%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%AF%AD%E6%B3%95%20%E5%BA%94%E7%94%A8%20%E4%BF%9D%E5%AD%98%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23fdfcfb%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22Er7xJ%22%2C%22name%22%3A%22h1%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u992eb432%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222%E3%80%81%E7%BC%96%E5%86%99%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22Gnocw%22%2C%22name%22%3A%22h2%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uf46f5cd2%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222.1%E3%80%81%E7%BC%96%E5%86%99%E6%95%B4%E4%BD%93%E7%9A%84%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ue83efdb5%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22udfb96c9d%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E6%95%B4%E4%BD%93%E4%BB%96%E8%84%9A%E6%9C%AC%E6%A0%BC%E5%BC%8F%E5%A6%82%E4%B8%8B%EF%BC%8C%E6%88%91%E4%BB%AC%E5%8F%AA%E8%A6%81%E5%9C%A8%E5%AF%B9%E5%BA%94%E7%9A%84%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u704b1a37%22%2C%22name%22%3A%22hole%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22SNenO%22%2C%22name%22%3A%22codeblock%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22mode%22%3A%22plain%22%2C%22code%22%3A%22%2F%2F%E6%89%80%E6%9C%89%E7%9A%84%E8%84%9A%E6%9C%AC%E5%91%BD%E4%BB%A4%E9%83%BD%E6%94%BE%E5%9C%A8pipeline%E4%B8%AD%5Cnpipeline%20%7B%5Cn%20%20%20%20%2F%2F%E6%8C%87%E5%AE%9A%E4%BB%BB%E5%8A%A1%E5%9C%A8%E5%93%AA%E4%B8%AA%E9%9B%86%E7%BE%A4%E8%8A%82%E7%82%B9%E4%B8%AD%E6%89%A7%E8%A1%8C%5Cn%20%20%20%20agent%20any%5Cn%5Ct%5Cn%20%20%20%20%2F%2F%E5%A3%B0%E6%98%8E%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%EF%BC%8C%E6%96%B9%E4%BE%BF%E5%90%8E%E9%9D%A2%E4%BD%BF%E7%94%A8%5Cn%20%20%20%20environment%20%7B%5Cn%20%20%20%20%20%20%20%20key%20%3D%20'value'%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20stages%20%7B%5Cn%20%20%20%20%20%20%20%20stage('%E6%8B%89%E5%8F%96git%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81')%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20steps%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20echo%20'%E6%8B%89%E5%8F%96git%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81%20ok'%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20stage('%E9%80%9A%E8%BF%87maven%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE')%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20steps%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20echo%20'%E9%80%9A%E8%BF%87maven%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE%20ok'%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20stage('%E9%80%9A%E8%BF%87SonarQube%E5%81%9A%E4%BB%A3%E7%A0%81%E8%B4%A8%E9%87%8F%E6%A3%80%E6%B5%8B')%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20steps%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20echo%20'%E9%80%9A%E8%BF%87SonarQube%E5%81%9A%E4%BB%A3%E7%A0%81%E8%B4%A8%E9%87%8F%E6%A3%80%E6%B5%8B%20ok'%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20stage('%E9%80%9A%E8%BF%87Docker%E5%88%B6%E4%BD%9C%E8%87%AA%E5%AE%9A%E4%B9%89%E9%95%9C%E5%83%8F')%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20steps%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20echo%20'%E9%80%9A%E8%BF%87Docker%E5%88%B6%E4%BD%9C%E8%87%AA%E5%AE%9A%E4%B9%89%E9%95%9C%E5%83%8F%20ok'%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20stage('%E5%B0%86%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E6%8E%A8%E9%80%81%E5%88%B0Harbor%E4%BB%93%E5%BA%93')%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20steps%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20echo%20'%E5%B0%86%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E6%8E%A8%E9%80%81%E5%88%B0Harbor%E4%BB%93%E5%BA%93%20ok'%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20stage('%E9%80%9A%E8%BF%87Publish%20Over%20SSH%E9%80%9A%E7%9F%A5%E7%9B%AE%E6%A0%87%E6%9C%8D%E5%8A%A1%E5%99%A8')%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20steps%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20echo%20'%E9%80%9A%E8%BF%87Publish%20Over%20SSH%E9%80%9A%E7%9F%A5%E7%9B%AE%E6%A0%87%E6%9C%8D%E5%8A%A1%E5%99%A8%20ok'%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%7D%5Cn%7D%22%2C%22autoWrap%22%3Afalse%2C%22lineNumbers%22%3Atrue%2C%22heightLimit%22%3Atrue%2C%22collapsed%22%3Afalse%2C%22hideToolbar%22%3Afalse%2C%22name%22%3A%22%22%2C%22tabSize%22%3Anull%2C%22indentWithTab%22%3Afalse%2C%22lightLines%22%3A%5B%5D%2C%22foldLines%22%3A%5B%5D%2C%22theme%22%3A%22Github%20Light%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22block%22%7D%2C%22cardType%22%3A%22block%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22HSPdM%22%2C%22name%22%3A%22h2%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ub32ad2ad%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222.2%E3%80%81%E7%94%9F%E6%88%90%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%AF%AD%E6%B3%95%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u4c94863f%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u19d54239%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E7%82%B9%E5%87%BB%E2%80%9C%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%AF%AD%E6%B3%95%E2%80%9D%E9%93%BE%E6%8E%A5%E8%BF%9B%E5%8E%BB%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u9daaa182%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22u7f3e8238%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688571700383-eb472700-c70c-492a-bc5d-f0547a7af020.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1371%2C%22height%22%3A712%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A44887%2C%22width%22%3A1096.8%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22u61e1a648-a7d4-476e-9cb3-9f0cebb9cca%22%2C%22clientId%22%3A%22u98bb8987-139a-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A43%2C%22y%22%3A5%2C%22width%22%3A71%2C%22height%22%3A26%2C%22text%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%22%7D%2C%7B%22x%22%3A45%2C%22y%22%3A74%2C%22width%22%3A40%2C%22height%22%3A21%2C%22text%22%3A%22%E5%AE%9A%E4%B9%89%22%7D%2C%7B%22x%22%3A58%2C%22y%22%3A126%2C%22width%22%3A121%2C%22height%22%3A22%2C%22text%22%3A%22PIPELINE%20SCRIPT%22%7D%2C%7B%22x%22%3A85%2C%22y%22%3A200%2C%22width%22%3A41%2C%22height%22%3A20%2C%22text%22%3A%22%E8%84%9A%E6%9C%AC%22%7D%2C%7B%22x%22%3A150%2C%22y%22%3A239%2C%22width%22%3A265%2C%22height%22%3A19%2C%22text%22%3A%22%2F%2F%E6%89%80%E6%9C%89%E7%9A%84%E8%84%9A%E6%9C%AC%E5%91%BD%E4%BB%A4%E9%83%BD%E6%94%BE%E5%9C%A8PIPELINE%E4%B8%AD%22%7D%2C%7B%22x%22%3A120%2C%22y%22%3A259%2C%22width%22%3A145%2C%22height%22%3A18%2C%22text%22%3A%222*PIPELINE%7B%22%7D%2C%7B%22x%22%3A114%2C%22y%22%3A265%2C%22width%22%3A18%2C%22height%22%3A260%2C%22text%22%3A%22123456780MNHUNNR%22%7D%2C%7B%22x%22%3A184%2C%22y%22%3A275%2C%22width%22%3A247%2C%22height%22%3A21%2C%22text%22%3A%221%2F%E6%8C%87%E5%AE%9A%E4%BB%BB%E5%8A%A1%E5%9C%A8%E5%93%AA%E4%B8%AA%E9%9B%86%E7%BE%A4%E8%8A%82%E7%82%B9%E4%B8%AD%E6%89%A7%E8%A1%8C%22%7D%2C%7B%22x%22%3A186%2C%22y%22%3A298%2C%22width%22%3A69%2C%22height%22%3A14%2C%22text%22%3A%22AGENT%20ANY%22%7D%2C%7B%22x%22%3A184%2C%22y%22%3A331%2C%22width%22%3A231%2C%22height%22%3A16%2C%22text%22%3A%22%2F%2F%E5%A3%B0%E6%98%8E%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%2C%E6%96%B9%E4%BE%BF%E5%90%8E%E9%9D%A2%E4%BD%BF%E7%94%A8%22%7D%2C%7B%22x%22%3A182%2C%22y%22%3A351%2C%22width%22%3A116%2C%22height%22%3A13%2C%22text%22%3A%22ENVIRONMENT%EF%BF%A5%22%7D%2C%7B%22x%22%3A213%2C%22y%22%3A368%2C%22width%22%3A111%2C%22height%22%3A14%2C%22text%22%3A%22KEY%20'VALUE'%22%7D%2C%7B%22x%22%3A183%2C%22y%22%3A422%2C%22width%22%3A62%2C%22height%22%3A14%2C%22text%22%3A%22STAGES%22%7D%2C%7B%22x%22%3A216%2C%22y%22%3A438%2C%22width%22%3A198%2C%22height%22%3A16%2C%22text%22%3A%22STAGE(%60%E6%8B%89%E5%8F%96GIT%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81)%22%7D%2C%7B%22x%22%3A248%2C%22y%22%3A459%2C%22width%22%3A57%2C%22height%22%3A14%2C%22text%22%3A%22STEPS%22%7D%2C%7B%22x%22%3A281%2C%22y%22%3A472%2C%22width%22%3A208%2C%22height%22%3A20%2C%22text%22%3A%22ECHO'%E6%8B%89%E5%8F%96GIT%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81%20OK'%22%7D%2C%7B%22x%22%3A217%2C%22y%22%3A529%2C%22width%22%3A236%2C%22height%22%3A19%2C%22text%22%3A%22STAGE(%E9%80%9A%E8%BF%87MAVEN%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE)%22%7D%2C%7B%22x%22%3A128%2C%22y%22%3A591%2C%22width%22%3A152%2C%22height%22%3A21%2C%22text%22%3A%22%E4%BD%BF%E7%94%A8GROOVY%E6%B2%99%E7%9B%92%22%7D%2C%7B%22x%22%3A86%2C%22y%22%3A662%2C%22width%22%3A90%2C%22height%22%3A19%2C%22text%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%AF%AD%E6%B3%95%22%7D%5D%2C%22search%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%20%E5%AE%9A%E4%B9%89%20PIPELINE%20SCRIPT%20%E8%84%9A%E6%9C%AC%20%2F%2F%E6%89%80%E6%9C%89%E7%9A%84%E8%84%9A%E6%9C%AC%E5%91%BD%E4%BB%A4%E9%83%BD%E6%94%BE%E5%9C%A8PIPELINE%E4%B8%AD%202*PIPELINE%7B%20123456780MNHUNNR%201%2F%E6%8C%87%E5%AE%9A%E4%BB%BB%E5%8A%A1%E5%9C%A8%E5%93%AA%E4%B8%AA%E9%9B%86%E7%BE%A4%E8%8A%82%E7%82%B9%E4%B8%AD%E6%89%A7%E8%A1%8C%20AGENT%20ANY%20%2F%2F%E5%A3%B0%E6%98%8E%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%2C%E6%96%B9%E4%BE%BF%E5%90%8E%E9%9D%A2%E4%BD%BF%E7%94%A8%20ENVIRONMENT%EF%BF%A5%20KEY%20'VALUE'%20STAGES%20STAGE(%60%E6%8B%89%E5%8F%96GIT%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81)%20STEPS%20ECHO'%E6%8B%89%E5%8F%96GIT%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81%20OK'%20STAGE(%E9%80%9A%E8%BF%87MAVEN%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE)%20%E4%BD%BF%E7%94%A8GROOVY%E6%B2%99%E7%9B%92%20%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%AF%AD%E6%B3%95%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23fefdfd%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uab0843f4%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ued9f6ba7%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E9%87%8C%E8%BE%B9%E6%9C%89%E5%BE%88%E5%A4%9A%E5%AE%9E%E4%BE%8B%E6%AD%A5%E9%AA%A4%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%A0%B9%E6%8D%AE%E5%85%B7%E4%BD%93%E7%9A%84%E9%9C%80%E6%B1%82%E9%80%89%E9%A1%B9%E7%94%9F%E6%88%90%EF%BC%8C%E6%AF%94%E5%A6%82%E6%88%91%E4%BB%AC%E8%A6%81%E7%94%9F%E6%88%90%E4%B8%80%E6%AE%B5git%E6%8B%89%E5%8F%96%E4%BB%A3%E7%A0%81%E7%9A%84%E8%84%9A%E6%9C%AC%EF%BC%8C%E9%80%89%E6%8B%A9%E5%A6%82%E4%B8%8B%E5%9B%BE%EF%BC%9A%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ud0060316%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22ufa099e04%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688571778878-68ed5d03-c29f-4247-b769-acedef3c1610.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1501%2C%22height%22%3A711%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A72601%2C%22width%22%3A1200.8%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22ub1897d96-e2e4-45ae-91ee-1e5f4c1e4f5%22%2C%22clientId%22%3A%22u98bb8987-139a-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A55%2C%22y%22%3A24%2C%22width%22%3A49%2C%22height%22%3A23%2C%22text%22%3A%22%E6%AD%A5%E9%AA%A4%22%7D%2C%7B%22x%22%3A56%2C%22y%22%3A92%2C%22width%22%3A73%2C%22height%22%3A21%2C%22text%22%3A%22%E7%A4%BA%E4%BE%8B%E6%AD%A5%E9%AA%A4%22%7D%2C%7B%22x%22%3A67%2C%22y%22%3A145%2C%22width%22%3A212%2C%22height%22%3A19%2C%22text%22%3A%22ARCHIVEARTIFACTS%3A%E5%BD%92%E6%A1%A3%E6%88%90%E5%93%81%22%7D%2C%7B%22x%22%3A67%2C%22y%22%3A181%2C%22width%22%3A218%2C%22height%22%3A19%2C%22text%22%3A%22ARCHIVEARTIFACTS%3A%E5%BD%92%E6%A1%A3%E6%88%90%E5%93%81%22%7D%2C%7B%22x%22%3A69%2C%22y%22%3A205%2C%22width%22%3A226%2C%22height%22%3A18%2C%22text%22%3A%22BAT%3AWINDOWS%20BATCH%20SCRIPT%22%7D%2C%7B%22x%22%3A67%2C%22y%22%3A227%2C%22width%22%3A151%2C%22height%22%3A21%2C%22text%22%3A%22BUILD%3ABUILD%20AJOB%22%7D%2C%7B%22x%22%3A66%2C%22y%22%3A254%2C%22width%22%3A451%2C%22height%22%3A18%2C%22text%22%3A%22CATCHERROR%3ACATCH%20ERROR%20AND%20SET%20BUILD%20RESULT%20TO%20FAILURE%22%7D%2C%7B%22x%22%3A70%2C%22y%22%3A279%2C%22width%22%3A359%2C%22height%22%3A17%2C%22text%22%3A%22CHECKOUT%3ACHECK%20OUT%20FROM%20VERSION%20CONTROL%22%7D%2C%7B%22x%22%3A69%2C%22y%22%3A302%2C%22width%22%3A405%2C%22height%22%3A19%2C%22text%22%3A%22CLEANWS%3ADELETE%20WORKSPACE%20WHEN%20BUILD%20IS%20DONE%22%7D%2C%7B%22x%22%3A69%2C%22y%22%3A325%2C%22width%22%3A604%2C%22height%22%3A20%2C%22text%22%3A%22DELETEDIR%3A%20RECURSIVELY%20DELETE%20THE%20CURRENT%20DIRECTORY%20FROM%20THE%20WORKSPACE%22%7D%2C%7B%22x%22%3A67%2C%22y%22%3A349%2C%22width%22%3A252%2C%22height%22%3A20%2C%22text%22%3A%22DIR%3ACHANGE%20CURRENT%20DIRECTORY%22%7D%2C%7B%22x%22%3A68%2C%22y%22%3A374%2C%22width%22%3A174%2C%22height%22%3A17%2C%22text%22%3A%22ECHO%3APRINT%20MESSAGE%22%7D%2C%7B%22x%22%3A66%2C%22y%22%3A398%2C%22width%22%3A220%2C%22height%22%3A18%2C%22text%22%3A%22EMAILEXT%3AEXTENDED%20EMAIL%22%7D%2C%7B%22x%22%3A66%2C%22y%22%3A421%2C%22width%22%3A397%2C%22height%22%3A21%2C%22text%22%3A%22EMAILEXTRECIPIENTS%3AEXTENDED%20EMAIL%20RECIPIENTS%22%7D%2C%7B%22x%22%3A68%2C%22y%22%3A447%2C%22width%22%3A156%2C%22height%22%3A18%2C%22text%22%3A%22ERROR%3AERROR%20SIGNAL%22%7D%2C%7B%22x%22%3A68%2C%22y%22%3A468%2C%22width%22%3A354%2C%22height%22%3A21%2C%22text%22%3A%22FILEEXISTS%3AVERIFY%20IF%20FILE%20EXISTS%20IN%20WORKSPACE%22%7D%2C%7B%22x%22%3A67%2C%22y%22%3A494%2C%22width%22%3A367%2C%22height%22%3A19%2C%22text%22%3A%22FINDBUILDSCANS%3AFIND%20PUBLISHED%20BUILD%20SCANS%22%7D%2C%7B%22x%22%3A66%2C%22y%22%3A516%2C%22width%22%3A304%2C%22height%22%3A20%2C%22text%22%3A%22FINGERPRINT%3A%E8%AE%B0%E5%BD%95%E6%96%87%E4%BB%B6%E7%9A%84%E6%8C%87%E7%BA%B9%E7%94%A8%E4%BA%8E%E8%BF%BD%E8%B8%AA%22%7D%2C%7B%22x%22%3A67%2C%22y%22%3A540%2C%22width%22%3A74%2C%22height%22%3A21%2C%22text%22%3A%22GIT%3AGIT%22%7D%2C%7B%22x%22%3A67%2C%22y%22%3A562%2C%22width%22%3A185%2C%22height%22%3A25%2C%22text%22%3A%22INPUT%3A%E7%AD%89%E5%BE%85%E4%BA%A4%E4%BA%92%E5%BC%8F%E8%BE%93%E5%85%A5%22%7D%2C%7B%22x%22%3A66%2C%22y%22%3A586%2C%22width%22%3A389%2C%22height%22%3A23%2C%22text%22%3A%22ISUNIX%3ACHECKS%20IF%20RUNNING%20ON%20A%20UNIX-LIKE%20NODE%22%7D%2C%7B%22x%22%3A65%2C%22y%22%3A613%2C%22width%22%3A358%2C%22height%22%3A20%2C%22text%22%3A%22JUNIT%3AARCHIVE%20JUNIT-FORMATTED%20TEST%20RESULTS%22%7D%2C%7B%22x%22%3A67%2C%22y%22%3A637%2C%22width%22%3A273%2C%22height%22%3A21%2C%22text%22%3A%22LIBRARY%3ALOAD%20A%20LIBRARY%20ON%20THE%20FLY%22%7D%5D%2C%22search%22%3A%22%E6%AD%A5%E9%AA%A4%20%E7%A4%BA%E4%BE%8B%E6%AD%A5%E9%AA%A4%20ARCHIVEARTIFACTS%3A%E5%BD%92%E6%A1%A3%E6%88%90%E5%93%81%20ARCHIVEARTIFACTS%3A%E5%BD%92%E6%A1%A3%E6%88%90%E5%93%81%20BAT%3AWINDOWS%20BATCH%20SCRIPT%20BUILD%3ABUILD%20AJOB%20CATCHERROR%3ACATCH%20ERROR%20AND%20SET%20BUILD%20RESULT%20TO%20FAILURE%20CHECKOUT%3ACHECK%20OUT%20FROM%20VERSION%20CONTROL%20CLEANWS%3ADELETE%20WORKSPACE%20WHEN%20BUILD%20IS%20DONE%20DELETEDIR%3A%20RECURSIVELY%20DELETE%20THE%20CURRENT%20DIRECTORY%20FROM%20THE%20WORKSPACE%20DIR%3ACHANGE%20CURRENT%20DIRECTORY%20ECHO%3APRINT%20MESSAGE%20EMAILEXT%3AEXTENDED%20EMAIL%20EMAILEXTRECIPIENTS%3AEXTENDED%20EMAIL%20RECIPIENTS%20ERROR%3AERROR%20SIGNAL%20FILEEXISTS%3AVERIFY%20IF%20FILE%20EXISTS%20IN%20WORKSPACE%20FINDBUILDSCANS%3AFIND%20PUBLISHED%20BUILD%20SCANS%20FINGERPRINT%3A%E8%AE%B0%E5%BD%95%E6%96%87%E4%BB%B6%E7%9A%84%E6%8C%87%E7%BA%B9%E7%94%A8%E4%BA%8E%E8%BF%BD%E8%B8%AA%20GIT%3AGIT%20INPUT%3A%E7%AD%89%E5%BE%85%E4%BA%A4%E4%BA%92%E5%BC%8F%E8%BE%93%E5%85%A5%20ISUNIX%3ACHECKS%20IF%20RUNNING%20ON%20A%20UNIX-LIKE%20NODE%20JUNIT%3AARCHIVE%20JUNIT-FORMATTED%20TEST%20RESULTS%20LIBRARY%3ALOAD%20A%20LIBRARY%20ON%20THE%20FLY%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23fbfaf9%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u2e9b19df%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ucdd61ede%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E7%BA%BF%E4%B8%8B%E7%9B%B8%E5%85%B3%E7%9A%84git%E4%BF%A1%E6%81%AF%E5%90%8E%EF%BC%8C%E7%9B%B4%E6%8E%A5%E7%82%B9%E5%87%BB%E7%94%9F%E6%88%90%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%E5%8D%B3%E5%8F%AF%E3%80%82%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u72bcd70b%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22u5a1a6c9e%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688572031010-16234c09-5b58-47dc-8c0d-44a176681b05.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1489%2C%22height%22%3A396%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A22055%2C%22width%22%3A1191.2%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22ud176abbd-e3b3-4e3d-a486-ecfc0adc71f%22%2C%22clientId%22%3A%22u98bb8987-139a-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A131%2C%22y%22%3A23%2C%22width%22%3A190%2C%22height%22%3A22%2C%22text%22%3A%22INCLUDE%20IN%20POLLING%3F%22%7D%2C%7B%22x%22%3A132%2C%22y%22%3A93%2C%22width%22%3A199%2C%22height%22%3A21%2C%22text%22%3A%22INCLUDE%20IN%20CHANGELOG%3F%22%7D%2C%7B%22x%22%3A78%2C%22y%22%3A171%2C%22width%22%3A110%2C%22height%22%3A17%2C%22text%22%3A%22%E7%94%9F%E6%88%90%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%22%7D%5D%2C%22search%22%3A%22INCLUDE%20IN%20POLLING%3F%20INCLUDE%20IN%20CHANGELOG%3F%20%E7%94%9F%E6%88%90%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23fefcfa%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22cMTkF%22%2C%22name%22%3A%22h2%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ue2f8e029%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222.3%E3%80%81%E5%B0%86%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%E6%94%BE%E5%88%B0git%E4%B8%8A%E7%AE%A1%E7%90%86%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ub4dcf1be%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ub22eb066%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E4%B8%BA%E4%BA%86%E6%96%B9%E4%BE%BF%E7%BB%B4%E6%8A%A4%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%EF%BC%8C%E6%88%91%E4%BB%AC%E8%BF%98%E5%8F%AF%E4%BB%A5%E5%B0%86%E8%84%9A%E6%9C%AC%E6%94%BE%E5%88%B0git%E4%B8%8A%EF%BC%8C%E9%9C%80%E8%A6%81%E5%9C%A8%E9%A1%B9%E7%9B%AE%E6%A0%B9%E7%9B%AE%E5%BD%95%E5%A2%9E%E5%8A%A0Jenkinsfile%E6%96%87%E4%BB%B6%EF%BC%8C%E5%B0%86%E5%AF%B9%E5%BA%94%E7%9A%84%E8%84%9A%E6%9C%AC%E6%94%BE%E5%88%B0%E8%BF%99%E4%B8%AA%E6%96%87%E4%BB%B6%E5%8D%B3%E5%8F%AF%E3%80%82%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ue1b4d4ed%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22ub26e3067%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688601950322-ac1da030-d3dc-4c1f-a36b-25855bfd4f87.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1346%2C%22height%22%3A748%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A41742%2C%22width%22%3A1076.8%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22uf7724fbc-eb1d-4965-bb83-71c4cf74be2%22%2C%22clientId%22%3A%22u35064983-9549-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A27%2C%22y%22%3A13%2C%22width%22%3A71%2C%22height%22%3A25%2C%22text%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%22%7D%2C%7B%22x%22%3A27%2C%22y%22%3A81%2C%22width%22%3A40%2C%22height%22%3A19%2C%22text%22%3A%22%E5%AE%9A%E4%B9%89%22%7D%2C%7B%22x%22%3A38%2C%22y%22%3A131%2C%22width%22%3A215%2C%22height%22%3A21%2C%22text%22%3A%22PIPELINE%20SCRIPT%20FROM%20SCM%22%7D%2C%7B%22x%22%3A70%2C%22y%22%3A206%2C%22width%22%3A43%2C%22height%22%3A19%2C%22text%22%3A%22SCM%22%7D%2C%7B%22x%22%3A81%2C%22y%22%3A259%2C%22width%22%3A27%2C%22height%22%3A17%2C%22text%22%3A%22GIT%22%7D%2C%7B%22x%22%3A109%2C%22y%22%3A331%2C%22width%22%3A107%2C%22height%22%3A21%2C%22text%22%3A%22REPOSITORIES%22%7D%2C%7B%22x%22%3A131%2C%22y%22%3A399%2C%22width%22%3A132%2C%22height%22%3A21%2C%22text%22%3A%22REPOSITORY%20URL%22%7D%2C%7B%22x%22%3A142%2C%22y%22%3A448%2C%22width%22%3A406%2C%22height%22%3A25%2C%22text%22%3A%22HTTP%3A%2F%2F192.168.88.125%3A8929%2FROOT%2FDEVOPS-TEST.GIT%22%7D%2C%7B%22x%22%3A241%2C%22y%22%3A524%2C%22width%22%3A17%2C%22height%22%3A20%2C%22text%22%3A%22%3F%22%7D%2C%7B%22x%22%3A133%2C%22y%22%3A526%2C%22width%22%3A95%2C%22height%22%3A19%2C%22text%22%3A%22CREDENTIALS%22%7D%2C%7B%22x%22%3A151%2C%22y%22%3A577%2C%22width%22%3A38%2C%22height%22%3A20%2C%22text%22%3A%22%E6%97%A0%22%7D%2C%7B%22x%22%3A68%2C%22y%22%3A709%2C%22width%22%3A35%2C%22height%22%3A20%2C%22text%22%3A%22%E4%BF%9D%E5%AD%98%22%7D%2C%7B%22x%22%3A201%2C%22y%22%3A711%2C%22width%22%3A35%2C%22height%22%3A17%2C%22text%22%3A%22%E5%BA%94%E7%94%A8%22%7D%5D%2C%22search%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%20%E5%AE%9A%E4%B9%89%20PIPELINE%20SCRIPT%20FROM%20SCM%20SCM%20GIT%20REPOSITORIES%20REPOSITORY%20URL%20HTTP%3A%2F%2F192.168.88.125%3A8929%2FROOT%2FDEVOPS-TEST.GIT%20%3F%20CREDENTIALS%20%E6%97%A0%20%E4%BF%9D%E5%AD%98%20%E5%BA%94%E7%94%A8%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23fefaf8%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22XKpzV%22%2C%22name%22%3A%22h2%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u561b1d77%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222.4%E3%80%81%E5%88%B6%E4%BD%9C%E5%AE%8C%E6%95%B4%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22jrXru%22%2C%22name%22%3A%22h3%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u79b5dada%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222.4.1%E3%80%81%E6%8B%89%E5%8F%96git%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u379a7f2e%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ua336d8cd%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E9%80%9A%E8%BF%87%22%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u4f084c6b%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22bold%22%3Atrue%7D%2C%22data%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%AF%AD%E6%B3%95-%3E%E7%A4%BA%E4%BE%8B%E6%AD%A5%E9%AA%A4-%3E%22%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u6bfeeb8a%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22bold%22%3Atrue%2C%22color%22%3A%22rgb(32%2C%2033%2C%2036)%22%7D%2C%22data%22%3A%22checkout%3A%20Check%20out%20from%20version%20control%3E%E7%94%9F%E6%88%90%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22udfed2b69%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u90c9431e%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(32%2C%2033%2C%2036)%22%7D%2C%22data%22%3A%22%E7%94%9F%E6%88%90%E7%9A%84%E8%84%9A%E6%9C%AC%E5%A6%82%E4%B8%8B%EF%BC%8C%E5%85%B6%E4%B8%AD%24tag%E4%B8%BA%E4%B8%8A%E6%96%87%E5%AE%9A%E4%B9%89%E7%9A%84%E6%A0%87%E7%AD%BE%E5%90%8D%E7%A7%B0%3A%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u6ed2a440%22%2C%22name%22%3A%22hole%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22JIGdC%22%2C%22name%22%3A%22codeblock%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22mode%22%3A%22plain%22%2C%22code%22%3A%22checkout%20scmGit(branches%3A%20%5B%5Bname%3A%20'%24tag'%5D%5D%2C%20extensions%3A%20%5B%5D%2C%20userRemoteConfigs%3A%20%5B%5Burl%3A%20'http%3A%2F%2F192.168.88.125%3A8929%2Froot%2Fdevops-test.git'%5D%5D)%22%2C%22autoWrap%22%3Afalse%2C%22lineNumbers%22%3Atrue%2C%22heightLimit%22%3Atrue%2C%22collapsed%22%3Afalse%2C%22hideToolbar%22%3Afalse%2C%22name%22%3A%22%22%2C%22tabSize%22%3Anull%2C%22indentWithTab%22%3Afalse%2C%22lightLines%22%3A%5B%5D%2C%22foldLines%22%3A%5B%5D%2C%22theme%22%3A%22Github%20Light%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22block%22%7D%2C%22cardType%22%3A%22block%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uf52e3e59%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ufb6e9064%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E5%B0%86%E5%85%B6%E7%B2%98%E8%B4%B4%E5%88%B0Jenkinsfile%E6%96%87%E4%BB%B6%E4%B8%AD%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uedc82dbf%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22ufecec94a%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688604999699-d30bba0d-413f-4e9e-9671-5a3a5b150f05.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1373%2C%22height%22%3A221%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A24032%2C%22width%22%3A1098.4%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22ube6462f8-bc06-4dbb-85ea-8527148fde6%22%2C%22clientId%22%3A%22u35064983-9549-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A4%2C%22y%22%3A4%2C%22width%22%3A237%2C%22height%22%3A25%2C%22text%22%3A%22STAGE('%E6%8B%89%E5%8F%96%E4%BB%A3%E7%A0%81')%22%7D%2C%7B%22x%22%3A62%2C%22y%22%3A38%2C%22width%22%3A71%2C%22height%22%3A18%2C%22text%22%3A%22STEPS%22%7D%2C%7B%22x%22%3A177%2C%22y%22%3A57%2C%22width%22%3A327%2C%22height%22%3A28%2C%22text%22%3A%22%E5%BC%80%E5%A7%8B%E6%8B%89%E5%8F%96GIT%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81%22%7D%2C%7B%22x%22%3A118%2C%22y%22%3A62%2C%22width%22%3A87%2C%22height%22%3A22%2C%22text%22%3A%22ECHO%20LI%22%7D%2C%7B%22x%22%3A157%2C%22y%22%3A86%2C%22width%22%3A1150%2C%22height%22%3A24%2C%22text%22%3A%22ECKOUT%20SCNGIT(BRANCHES%3A%20%5B%5BNAME%3A%20ISTAG'LL%2C%20EXTENSIONS%3A%20%5BL%2C%20USERREMOTECONFIGS%3A%20%5B%5B%5B%5B%5BURL%3B%22%7D%2C%7B%22x%22%3A118%2C%22y%22%3A92%2C%22width%22%3A48%2C%22height%22%3A17%2C%22text%22%3A%22CHEQ%22%7D%2C%7B%22x%22%3A130%2C%22y%22%3A116%2C%22width%22%3A702%2C%22height%22%3A24%2C%22text%22%3A%22(HTTP%3A%2F%2F192.168.88.125%3A8929%2FROOT%2FDEVOPS-TEST.GIT'11)%22%7D%2C%7B%22x%22%3A192%2C%22y%22%3A140%2C%22width%22%3A358%2C%22height%22%3A23%2C%22text%22%3A%22%E5%BC%80%E5%A7%8B%E6%8B%89%E5%8F%96GIT%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81%E5%AE%8C%E6%AF%95.%22%7D%2C%7B%22x%22%3A119%2C%22y%22%3A145%2C%22width%22%3A53%2C%22height%22%3A17%2C%22text%22%3A%22ECHO%22%7D%2C%7B%22x%22%3A61%2C%22y%22%3A170%2C%22width%22%3A15%2C%22height%22%3A23%2C%22text%22%3A%22%E4%BA%86%22%7D%5D%2C%22search%22%3A%22STAGE('%E6%8B%89%E5%8F%96%E4%BB%A3%E7%A0%81')%20STEPS%20%E5%BC%80%E5%A7%8B%E6%8B%89%E5%8F%96GIT%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81%20ECHO%20LI%20ECKOUT%20SCNGIT(BRANCHES%3A%20%5B%5BNAME%3A%20ISTAG'LL%2C%20EXTENSIONS%3A%20%5BL%2C%20USERREMOTECONFIGS%3A%20%5B%5B%5B%5B%5BURL%3B%20CHEQ%20(HTTP%3A%2F%2F192.168.88.125%3A8929%2FROOT%2FDEVOPS-TEST.GIT'11)%20%E5%BC%80%E5%A7%8B%E6%8B%89%E5%8F%96GIT%E4%BB%93%E5%BA%93%E4%BB%A3%E7%A0%81%E5%AE%8C%E6%AF%95.%20ECHO%20%E4%BA%86%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23fbf9f8%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22JBDdv%22%2C%22name%22%3A%22h3%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u5f9e7721%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222.4.2%E3%80%81%E9%80%9A%E8%BF%87maven%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u5e110e05%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u48369135%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E9%80%9A%E8%BF%87%22%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u487c647b%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22bold%22%3Atrue%7D%2C%22data%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%AF%AD%E6%B3%95-%3E%E7%A4%BA%E4%BE%8B%E6%AD%A5%E9%AA%A4-%3E%22%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u619ef007%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22bold%22%3Atrue%2C%22color%22%3A%22rgb(32%2C%2033%2C%2036)%22%7D%2C%22data%22%3A%22sh%3A%20Shell%20Script%3E%E7%94%9F%E6%88%90%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u9b795289%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u2cf16092%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(32%2C%2033%2C%2036)%22%7D%2C%22data%22%3A%22%E5%85%B6%E4%B8%ADSell%20Script%E8%BE%93%E5%85%A5%E4%BB%A5%E4%B8%8B%E6%89%93%E5%8C%85%E5%8E%9F%E5%A7%8B%E8%84%9A%E6%9C%AC%EF%BC%9A%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u68fe14b8%22%2C%22name%22%3A%22hole%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22JrJ14%22%2C%22name%22%3A%22codeblock%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22mode%22%3A%22shell%22%2C%22code%22%3A%22%2Fvar%2Fjenkins_home%2Fmaven%2Fbin%2Fmvn%20clean%20package%20-DskipTests%22%2C%22autoWrap%22%3Afalse%2C%22lineNumbers%22%3Atrue%2C%22heightLimit%22%3Atrue%2C%22collapsed%22%3Afalse%2C%22hideToolbar%22%3Afalse%2C%22name%22%3A%22%22%2C%22tabSize%22%3Anull%2C%22indentWithTab%22%3Afalse%2C%22lightLines%22%3A%5B%5D%2C%22foldLines%22%3A%5B%5D%2C%22theme%22%3A%22Github%20Light%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22block%22%7D%2C%22cardType%22%3A%22block%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uc6874513%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ua379c823%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(32%2C%2033%2C%2036)%22%7D%2C%22data%22%3A%22%E7%94%9F%E6%88%90%E7%9A%84%E8%84%9A%E6%9C%AC%E5%A6%82%E4%B8%8B%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uddd0247b%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22u3b188091%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688605871951-bc038a53-f387-470c-9c4a-b5861220ad0f.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1426%2C%22height%22%3A762%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A30076%2C%22width%22%3A1140.8%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22uc8afe2d7-70a2-4d70-8e9e-38064e927ea%22%2C%22clientId%22%3A%22u35064983-9549-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A25%2C%22y%22%3A4%2C%22width%22%3A48%2C%22height%22%3A24%2C%22text%22%3A%22%E6%AD%A5%E9%AA%A4%22%7D%2C%7B%22x%22%3A25%2C%22y%22%3A74%2C%22width%22%3A73%2C%22height%22%3A20%2C%22text%22%3A%22%E7%A4%BA%E4%BE%8B%E6%AD%A5%E9%AA%A4%22%7D%2C%7B%22x%22%3A36%2C%22y%22%3A125%2C%22width%22%3A126%2C%22height%22%3A21%2C%22text%22%3A%22SH%3ASHELL%20SCRIPT%22%7D%2C%7B%22x%22%3A66%2C%22y%22%3A202%2C%22width%22%3A23%2C%22height%22%3A17%2C%22text%22%3A%22SH%22%7D%2C%7B%22x%22%3A67%2C%22y%22%3A277%2C%22width%22%3A119%2C%22height%22%3A22%2C%22text%22%3A%22SHELL%20SCRIPT%3F%22%7D%2C%7B%22x%22%3A78%2C%22y%22%3A324%2C%22width%22%3A527%2C%22height%22%3A27%2C%22text%22%3A%22%2FVAR%2FJENKINS_HOME%2FMAVEN%2FBIN%2FMVN%20CLEAN%20PACKAGE-DSKIPTESTS%22%7D%2C%7B%22x%22%3A82%2C%22y%22%3A499%2C%22width%22%3A37%2C%22height%22%3A19%2C%22text%22%3A%22%E9%AB%98%E7%BA%A7%22%7D%2C%7B%22x%22%3A52%2C%22y%22%3A580%2C%22width%22%3A108%2C%22height%22%3A18%2C%22text%22%3A%22%E7%94%9F%E6%88%90%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%22%7D%2C%7B%22x%22%3A38%2C%22y%22%3A631%2C%22width%22%3A555%2C%22height%22%3A25%2C%22text%22%3A%22SH'%2FVAR%2FJENKINS%20HOME%2FMAVEN%2FBIN%2FBIN%2FMVN%20CLEAN%20PACKAGE%20-DSKIPTESTS%5C%22%22%7D%5D%2C%22search%22%3A%22%E6%AD%A5%E9%AA%A4%20%E7%A4%BA%E4%BE%8B%E6%AD%A5%E9%AA%A4%20SH%3ASHELL%20SCRIPT%20SH%20SHELL%20SCRIPT%3F%20%2FVAR%2FJENKINS_HOME%2FMAVEN%2FBIN%2FMVN%20CLEAN%20PACKAGE-DSKIPTESTS%20%E9%AB%98%E7%BA%A7%20%E7%94%9F%E6%88%90%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%20SH'%2FVAR%2FJENKINS%20HOME%2FMAVEN%2FBIN%2FBIN%2FMVN%20CLEAN%20PACKAGE%20-DSKIPTESTS%5C%22%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23fefcfb%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uaace90eb%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u8a67f4b5%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E7%94%9F%E6%88%90%E7%9A%84%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%E5%A6%82%E4%B8%8B%EF%BC%9A%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ufab18b59%22%2C%22name%22%3A%22hole%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22yx2nz%22%2C%22name%22%3A%22codeblock%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22mode%22%3A%22shell%22%2C%22code%22%3A%22sh%20'%2Fvar%2Fjenkins_home%2Fmaven%2Fbin%2Fmvn%20clean%20package%20-DskipTests'%22%2C%22autoWrap%22%3Afalse%2C%22lineNumbers%22%3Atrue%2C%22heightLimit%22%3Atrue%2C%22collapsed%22%3Afalse%2C%22hideToolbar%22%3Afalse%2C%22name%22%3A%22%22%2C%22tabSize%22%3Anull%2C%22indentWithTab%22%3Afalse%2C%22lightLines%22%3A%5B%5D%2C%22foldLines%22%3A%5B%5D%2C%22theme%22%3A%22Github%20Light%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22block%22%7D%2C%22cardType%22%3A%22block%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uaec13e9d%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ufe2ae6e6%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E5%B0%86%E5%85%B6%E7%B2%98%E8%B4%B4%E5%88%B0Jenkinsfile%E6%96%87%E4%BB%B6%E4%B8%AD%E5%AF%B9%E5%BA%94%E7%9A%84%E6%AD%A5%E9%AA%A4%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u74c98407%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22u171b4871%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688606098514-77c7299b-2dd3-48ce-bd9d-e6041455152d.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1210%2C%22height%22%3A202%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A18950%2C%22width%22%3A968%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22uf0ae1aa3-538c-4f60-be14-d80e16ed78b%22%2C%22clientId%22%3A%22u35064983-9549-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A34%2C%22y%22%3A11%2C%22width%22%3A267%2C%22height%22%3A25%2C%22text%22%3A%22STAGE((%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE)%22%7D%2C%7B%22x%22%3A91%2C%22y%22%3A43%2C%22width%22%3A98%2C%22height%22%3A19%2C%22text%22%3A%22STEPS%20I%22%7D%2C%7B%22x%22%3A151%2C%22y%22%3A65%2C%22width%22%3A406%2C%22height%22%3A28%2C%22text%22%3A%22ECHO%20%E5%BC%80%E5%A7%8B%E9%80%9A%E8%BF%87MAVEN%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE...........................................%22%7D%2C%7B%22x%22%3A848%2C%22y%22%3A95%2C%22width%22%3A160%2C%22height%22%3A19%2C%22text%22%3A%22-DSKIPTESTS%22%7D%2C%7B%22x%22%3A145%2C%22y%22%3A97%2C%22width%22%3A691%2C%22height%22%3A20%2C%22text%22%3A%22SH%20'%2FVAR%2FJENKINS%20HOME%2FMAVEN%2FBIN%2FMVN%20CLEAN%20PACKAGE%22%7D%2C%7B%22x%22%3A145%2C%22y%22%3A120%2C%22width%22%3A387%2C%22height%22%3A23%2C%22text%22%3A%22ECHO%20%E9%80%9A%E8%BF%87MAVEN%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE%E5%AE%8C%E6%AF%95%22%7D%5D%2C%22search%22%3A%22STAGE((%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE)%20STEPS%20I%20ECHO%20%E5%BC%80%E5%A7%8B%E9%80%9A%E8%BF%87MAVEN%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE...........................................%20-DSKIPTESTS%20SH%20'%2FVAR%2FJENKINS%20HOME%2FMAVEN%2FBIN%2FMVN%20CLEAN%20PACKAGE%20ECHO%20%E9%80%9A%E8%BF%87MAVEN%E6%9E%84%E5%BB%BA%E9%A1%B9%E7%9B%AE%E5%AE%8C%E6%AF%95%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23fbfaf9%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22afi9J%22%2C%22name%22%3A%22h3%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u9b20c4b2%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222.4.3%E3%80%81%E9%80%9A%E8%BF%87Docker%E5%88%B6%E4%BD%9C%E8%87%AA%E5%AE%9A%E4%B9%89%E9%95%9C%E5%83%8F%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u10319690%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u6d7a494d%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E5%90%8C%E7%90%86%EF%BC%8C%E5%8E%9F%E5%A7%8B%E8%84%9A%E6%9C%AC%EF%BC%9A%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u8dc309b6%22%2C%22name%22%3A%22hole%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22fA2Kx%22%2C%22name%22%3A%22codeblock%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22mode%22%3A%22shell%22%2C%22code%22%3A%22mv%20.%2Ftarget%2F*.jar%20.%2Fdocker%2F%5Cndocker%20build%20-t%20%24%7BJOB_NAME%7D%3A%24%7Btag%7D%20.%2Fdocker%2F%22%2C%22autoWrap%22%3Afalse%2C%22lineNumbers%22%3Atrue%2C%22heightLimit%22%3Atrue%2C%22collapsed%22%3Afalse%2C%22hideToolbar%22%3Afalse%2C%22name%22%3A%22%22%2C%22tabSize%22%3Anull%2C%22indentWithTab%22%3Afalse%2C%22lightLines%22%3A%5B%5D%2C%22foldLines%22%3A%5B%5D%2C%22theme%22%3A%22Github%20Light%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22block%22%7D%2C%22cardType%22%3A%22block%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uc379e72b%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u4fb40df8%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E7%94%9F%E6%88%90%E7%9A%84%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%E5%A6%82%E4%B8%8B%EF%BC%9A%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u56792f12%22%2C%22name%22%3A%22hole%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22oo3G0%22%2C%22name%22%3A%22codeblock%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22mode%22%3A%22shell%22%2C%22code%22%3A%22sh%20'''mv%20.%2Ftarget%2F*.jar%20.%2Fdocker%2F%5Cndocker%20build%20-t%20%24%7BJOB_NAME%7D%3A%24%7Btag%7D%20.%2Fdocker%2F'''%22%2C%22autoWrap%22%3Afalse%2C%22lineNumbers%22%3Atrue%2C%22heightLimit%22%3Atrue%2C%22collapsed%22%3Afalse%2C%22hideToolbar%22%3Afalse%2C%22name%22%3A%22%22%2C%22tabSize%22%3Anull%2C%22indentWithTab%22%3Afalse%2C%22lightLines%22%3A%5B%5D%2C%22foldLines%22%3A%5B%5D%2C%22theme%22%3A%22Github%20Light%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22block%22%7D%2C%22cardType%22%3A%22block%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ud9f22ce9%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22uc1cfd1c2%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688606790762-291ea514-d2de-4521-9db3-435899332db1.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1044%2C%22height%22%3A229%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A22534%2C%22width%22%3A835.2%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22u9fab5676-e0e1-4362-a546-e777cd2ce5d%22%2C%22clientId%22%3A%22u35064983-9549-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A6%2C%22y%22%3A8%2C%22width%22%3A241%2C%22height%22%3A27%2C%22text%22%3A%22STAGE('%E5%88%B6%E4%BD%9C%E9%95%9C%E5%83%8F)%22%7D%2C%7B%22x%22%3A64%2C%22y%22%3A41%2C%22width%22%3A95%2C%22height%22%3A18%2C%22text%22%3A%22STEPS%20F%22%7D%2C%7B%22x%22%3A193%2C%22y%22%3A62%2C%22width%22%3A389%2C%22height%22%3A24%2C%22text%22%3A%22%E9%80%9A%E8%BF%87DOCKER%E5%88%B6%E4%BD%9C%E8%87%AA%E5%AE%9A%E4%B9%89%E9%95%9C%E5%83%8F%22%7D%2C%7B%22x%22%3A120%2C%22y%22%3A67%2C%22width%22%3A55%2C%22height%22%3A17%2C%22text%22%3A%22ECHO%22%7D%2C%7B%22x%22%3A174%2C%22y%22%3A89%2C%22width%22%3A410%2C%22height%22%3A25%2C%22text%22%3A%22LI'MV%20.%2FTARGET%2F*.JAR%20.%2FDOCKER%2F%22%7D%2C%7B%22x%22%3A121%2C%22y%22%3A94%2C%22width%22%3A27%2C%22height%22%3A16%2C%22text%22%3A%22SH%22%7D%2C%7B%22x%22%3A121%2C%22y%22%3A112%2C%22width%22%3A655%2C%22height%22%3A35%2C%22text%22%3A%22DOCKER%20BUILD%20-T%20%24%5BJOB%20NAME%5D%3A%24%5BTAG)%20.%2FDOCKER%2F'IT%22%7D%2C%7B%22x%22%3A121%2C%22y%22%3A141%2C%22width%22%3A482%2C%22height%22%3A25%2C%22text%22%3A%22ECHO'%E9%80%9A%E8%BF%87DOCKER%E5%88%B6%E4%BD%9C%E8%87%AA%E5%AE%9A%E4%B9%89%E9%95%9C%E5%83%8F%E5%AE%8C%E6%AF%95%22%7D%5D%2C%22search%22%3A%22STAGE('%E5%88%B6%E4%BD%9C%E9%95%9C%E5%83%8F)%20STEPS%20F%20%E9%80%9A%E8%BF%87DOCKER%E5%88%B6%E4%BD%9C%E8%87%AA%E5%AE%9A%E4%B9%89%E9%95%9C%E5%83%8F%20ECHO%20LI'MV%20.%2FTARGET%2F*.JAR%20.%2FDOCKER%2F%20SH%20DOCKER%20BUILD%20-T%20%24%5BJOB%20NAME%5D%3A%24%5BTAG)%20.%2FDOCKER%2F'IT%20ECHO'%E9%80%9A%E8%BF%87DOCKER%E5%88%B6%E4%BD%9C%E8%87%AA%E5%AE%9A%E4%B9%89%E9%95%9C%E5%83%8F%E5%AE%8C%E6%AF%95%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23fbfaf8%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22h38ki%22%2C%22name%22%3A%22h3%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u9ae39e9d%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222.4.4%E3%80%81%E6%8E%A8%E9%80%81%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E5%88%B0Harbor%E4%BB%93%E5%BA%93%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ucc7b7fed%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u0e6fc78b%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E5%90%8C%E7%90%86%EF%BC%8C%E5%8E%9F%E5%A7%8B%E8%84%9A%E6%9C%AC%EF%BC%9A%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ub2859f63%22%2C%22name%22%3A%22hole%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22ciJMQ%22%2C%22name%22%3A%22codeblock%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22mode%22%3A%22shell%22%2C%22code%22%3A%22docker%20login%20-u%20%24%7BharborUser%7D%20-p%20%24%7BharborPassword%7D%20%24%7BharborAddress%7D%5Cndocker%20tag%20%24%7BJOB_NAME%7D%3A%24%7Btag%7D%20%24%7BharborAddress%7D%2F%24%7BharborRepo%7D%2F%24%7BJOB_NAME%7D%3A%24%7Btag%7D%5Cndocker%20push%20%24%7BharborAddress%7D%2F%24%7BharborRepo%7D%2F%24%7BJOB_NAME%7D%3A%24%7Btag%7D%5Cndocker%20image%20prune%20-f%22%2C%22autoWrap%22%3Afalse%2C%22lineNumbers%22%3Atrue%2C%22heightLimit%22%3Atrue%2C%22collapsed%22%3Afalse%2C%22hideToolbar%22%3Afalse%2C%22name%22%3A%22%22%2C%22tabSize%22%3Anull%2C%22indentWithTab%22%3Afalse%2C%22lightLines%22%3A%5B%5D%2C%22foldLines%22%3A%5B%5D%2C%22theme%22%3A%22Github%20Light%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22block%22%7D%2C%22cardType%22%3A%22block%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ub4191cbf%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u3e7de775%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E5%85%B6%E4%B8%AD%EF%BC%8C%24%7BharborUser%7D%20%E3%80%81%24%7BharborPassword%7D%E3%80%81%24%7BharborAddress%7D%E3%80%81%24%7BharborRepo%7D%E4%B8%BAJenkinsfile%E5%A4%B4%E9%83%A8%E5%A3%B0%E6%98%8E%E7%9A%84%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%EF%BC%8C%E5%8D%B3Harbor%E7%9A%84%E4%BF%A1%E6%81%AF%E3%80%82%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u9e60df4a%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uded8529e%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E7%94%9F%E6%88%90%E7%9A%84%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%E5%A6%82%E4%B8%8B%EF%BC%9A%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uff3bc6e8%22%2C%22name%22%3A%22hole%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22iP74r%22%2C%22name%22%3A%22codeblock%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22mode%22%3A%22shell%22%2C%22code%22%3A%22sh%20'''docker%20login%20-u%20%24%7BharborUser%7D%20-p%20%24%7BharborPassword%7D%20%24%7BharborAddress%7D%5Cndocker%20tag%20%24%7BJOB_NAME%7D%3A%24%7Btag%7D%20%24%7BharborAddress%7D%2F%24%7BharborRepo%7D%2F%24%7BJOB_NAME%7D%3A%24%7Btag%7D%5Cndocker%20push%20%24%7BharborAddress%7D%2F%24%7BharborRepo%7D%2F%24%7BJOB_NAME%7D%3A%24%7Btag%7D%5Cndocker%20image%20prune%20-f'''%22%2C%22autoWrap%22%3Afalse%2C%22lineNumbers%22%3Atrue%2C%22heightLimit%22%3Atrue%2C%22collapsed%22%3Afalse%2C%22hideToolbar%22%3Afalse%2C%22name%22%3A%22%22%2C%22tabSize%22%3Anull%2C%22indentWithTab%22%3Afalse%2C%22lightLines%22%3A%5B%5D%2C%22foldLines%22%3A%5B%5D%2C%22theme%22%3A%22Github%20Light%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22block%22%7D%2C%22cardType%22%3A%22block%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u2c284509%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22udc1dfd32%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688627568103-206cda98-6d7e-4a3b-bdda-148f29821aa2.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1271%2C%22height%22%3A248%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A31121%2C%22width%22%3A1016.8%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22u22edce07-280f-42c8-9f92-9bbde84a766%22%2C%22clientId%22%3A%22uab39175f-99c6-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A3%2C%22y%22%3A3%2C%22width%22%3A247%2C%22height%22%3A25%2C%22text%22%3A%22STAGE(%20%E6%8E%A8%E9%80%81%E9%95%9C%E5%83%8F)%22%7D%2C%7B%22x%22%3A62%2C%22y%22%3A35%2C%22width%22%3A87%2C%22height%22%3A20%2C%22text%22%3A%22STEPS%22%7D%2C%7B%22x%22%3A195%2C%22y%22%3A54%2C%22width%22%3A440%2C%22height%22%3A26%2C%22text%22%3A%22'%E5%B0%86%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E6%8E%A8%E9%80%81%E5%88%B0HARBOR%E4%BB%93%E5%BA%93%22%7D%2C%7B%22x%22%3A117%2C%22y%22%3A61%2C%22width%22%3A56%2C%22height%22%3A18%2C%22text%22%3A%22ECHO%22%7D%2C%7B%22x%22%3A198%2C%22y%22%3A85%2C%22width%22%3A939%2C%22height%22%3A23%2C%22text%22%3A%22'DOCKER%20LOGIN%20-U%20S(HARBORUSER!%20-P%20%24%5BHARBORPASSWORD%5D%20S%5BHARBORADDRESS!%22%7D%2C%7B%22x%22%3A116%2C%22y%22%3A84%2C%22width%22%3A71%2C%22height%22%3A23%2C%22text%22%3A%22SH%20U%22%7D%2C%7B%22x%22%3A116%2C%22y%22%3A113%2C%22width%22%3A957%2C%22height%22%3A23%2C%22text%22%3A%22DOCKER%20TAG%20%24(JOB%20NAME)%3AS(TAG)%20S(HARBORADDRESS!%2FSTHARBORREPO%7D%2FSIJOB%20NA%22%7D%2C%7B%22x%22%3A1038%2C%22y%22%3A113%2C%22width%22%3A182%2C%22height%22%3A25%2C%22text%22%3A%22B%20NAME%20J%3A%24%7BTAG%20)%22%7D%2C%7B%22x%22%3A116%2C%22y%22%3A140%2C%22width%22%3A881%2C%22height%22%3A22%2C%22text%22%3A%22DOCKER%20PUSH%20%24(HARBORADDRESS%7D%2FS%5BHARBORREPO)%2FS(JOB%20NAME%5D%3AS%5BTAG%5D'I''%22%7D%2C%7B%22x%22%3A192%2C%22y%22%3A164%2C%22width%22%3A463%2C%22height%22%3A26%2C%22text%22%3A%22%E5%B0%86%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E6%8E%A8%E9%80%81%E5%88%B0HARBOR%E4%BB%93%E5%BA%93%E5%AE%8C%E6%88%90%22%7D%2C%7B%22x%22%3A116%2C%22y%22%3A170%2C%22width%22%3A55%2C%22height%22%3A17%2C%22text%22%3A%22ECHO%22%7D%5D%2C%22search%22%3A%22STAGE(%20%E6%8E%A8%E9%80%81%E9%95%9C%E5%83%8F)%20STEPS%20'%E5%B0%86%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E6%8E%A8%E9%80%81%E5%88%B0HARBOR%E4%BB%93%E5%BA%93%20ECHO%20'DOCKER%20LOGIN%20-U%20S(HARBORUSER!%20-P%20%24%5BHARBORPASSWORD%5D%20S%5BHARBORADDRESS!%20SH%20U%20DOCKER%20TAG%20%24(JOB%20NAME)%3AS(TAG)%20S(HARBORADDRESS!%2FSTHARBORREPO%7D%2FSIJOB%20NA%20B%20NAME%20J%3A%24%7BTAG%20)%20DOCKER%20PUSH%20%24(HARBORADDRESS%7D%2FS%5BHARBORREPO)%2FS(JOB%20NAME%5D%3AS%5BTAG%5D'I''%20%E5%B0%86%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E6%8E%A8%E9%80%81%E5%88%B0HARBOR%E4%BB%93%E5%BA%93%E5%AE%8C%E6%88%90%20ECHO%22%2C%22crop%22%3A%5B0%2C0%2C1%2C1%5D%2C%22showTitle%22%3Afalse%2C%22title%22%3A%22%22%2C%22rotation%22%3A0%2C%22averageHue%22%3A%22%23faf9f8%22%2C%22__spacing%22%3A%22both%22%7D%2C%22cardType%22%3A%22inline%22%7D%2C%22cardType%22%3A%22inline%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22eaJWS%22%2C%22name%22%3A%22h3%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u647bb9e2%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%222.4.5%E3%80%81%E9%80%9A%E7%9F%A5%E7%9B%AE%E6%A0%87%E6%9C%8D%E5%8A%A1%E5%99%A8%20%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ue8871a41%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u68f6f85a%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E8%BF%99%E9%87%8C%E4%BD%BF%E7%94%A8Publish%20Over%20SSH%E9%80%9A%E7%9F%A5%E7%9B%AE%E6%A0%87%E6%9C%8D%E5%8A%A1%E5%99%A8%E3%80%82%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22udc7f9869%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ub33eb499%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22%E9%80%9A%E8%BF%87Jenkins%20%22%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u4a157adc%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22bold%22%3Atrue%7D%2C%22data%22%3A%22%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%AF%AD%E6%B3%95-%3E%E7%A4%BA%E4%BE%8B%E6%AD%A5%E9%AA%A4-%3E%22%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ufc7dabc1%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22bold%22%3Atrue%2C%22color%22%3A%22rgb(0%2C%200%2C%200)%22%7D%2C%22data%22%3A%22sshPublisher%3A%20Send%20build%20artifacts%20over%20SSH%22%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uc5f79b84%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22bold%22%3Atrue%2C%22color%22%3A%22rgb(32%2C%2033%2C%2036)%22%7D%2C%22data%22%3A%22%3E%E7%94%9F%E6%88%90%E6%B5%81%E6%B0%B4%E7%BA%BF%E8%84%9A%E6%9C%AC%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ua47e4fc4%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22card%22%2C%22id%22%3A%22uc264ef91%22%2C%22name%22%3A%22image%22%2C%22attrs%22%3A%7B%22value%22%3A%7B%22src%22%3A%22https%3A%2F%2Fcdn.nlark.com%2Fyuque%2F0%2F2023%2Fpng%2F619135%2F1688624364922-13aa3d69-e3a8-42d8-905f-efc60a406b08.png%22%2C%22original%22%3A%7B%22type%22%3A%22binary%22%2C%22from%22%3A%22paste%22%2C%22ratio%22%3A1.25%2C%22width%22%3A1227%2C%22height%22%3A528%7D%2C%22name%22%3A%22image.png%22%2C%22size%22%3A54547%2C%22width%22%3A981.6%2C%22status%22%3A%22done%22%2C%22style%22%3A%22none%22%2C%22taskId%22%3A%22ubee2639f-4d0c-4df4-9dbc-f4d48df81b7%22%2C%22clientId%22%3A%22u35064983-9549-4%22%2C%22linkExternal%22%3Atrue%2C%22ocr%22%3A%5B%7B%22x%22%3A8%2C%22y%22%3A7%2C%22width%22%3A178%2C%22height%22%3A22%2C%22text%22%3A%22NODE%3A%20ALLOCATE%20NODE%22%7D%2C%7B%22x%22%3A8%2C%22y%22%3A32%2C%22width%22%3A232%2C%22height%22%3A21%2C%22text%22%3A%22PARALLEL%3AEXECUTE%20IN%20PARALLEL%22%7D%2C%7B%22x%22%3A8%2C%22y%22%3A57%2C%22width%22%3A341%2C%22height%22%3A20%2C%22text%22%3A%22POWERSHELL%3A%20WINDOWS%20POWERSHELL%20SCRIPT%22%7D%2C%7B%22x%22%3A9%2C%22y%22%3A81%2C%