文章列表

阿里面试:Seata 如何实现 RC ?保证事务的隔离性?

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;background: rgba(0, 0, 0, 0.05);padding: 10px 1em;border-left-color: rgb(221, 221, 221);margin-top: 1.2em;margin-bottom: 1.2em;border-left-width: 4px;color: rgb(119, 119, 119);quotes: none;"> <p style="padding-top: 8px;padding-bottom: 8px;text-wrap: wrap;text-size-adjust: auto;font-size: 15px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;line-height: 1.75em;">Seata 如何实现 RC ?保证事务的隔离性?</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin-bottom: 16px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Segoe UI&quot;, Arial, freesans, sans-serif;font-size: 15px;text-wrap: wrap;text-size-adjust: auto;line-height: 1.75em;">最近有小伙伴在面试阿里,又遇到了相关的面试题。小伙伴懵了,因为没有遇到过,所以支支吾吾的说了几句,面试官不满意,面试挂了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin-bottom: 16px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Segoe UI&quot;, Arial, freesans, sans-serif;font-size: 15px;text-wrap: wrap;text-size-adjust: auto;line-height: 1.75em;">所以,尼�

联邦查询神器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>