作者:微信小助手
<p style="margin-right: 8px;margin-left: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;background-color: rgb(255, 255, 255);text-align: center;font-family: -apple-system-font, BlinkMacSystemFont, Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击▲关注 “<span style="max-width: 100%;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">爪哇笔记</span>” 给公众号标星置顶</span></p> <p style="margin-right: 8px;margin-left: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;background-color: rgb(255, 255, 255);text-align: center;font-family: -apple-system-font, BlinkMacSystemFont, Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">更多精彩 第一时间直达</span></p> <p style="text-align: left;"><img class="rich_pages" data-ratio="0.5625" data-s="300,640" src="/upload/49b4615a67796b80ac00f08016283c2f.jpg" data-type="jpeg" data-w="720" style=""><strong style="color: rgb(21, 153, 87);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: start;">前言</strong></p> <p style="box-sizing: border-box;font-size: 14px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;color: rgb(62, 62, 62);margin-bottom: 15px;margin-top: 15px;line-height: 2em;text-align: start;white-space: normal;">通过 Python 爬取十万博文之后,最重要的是要让互联网用户访问到,那么如何做呢?</p> <h2 style="box-sizing: border-box;margin-top: 2rem;margin-bottom: 1rem;color: rgb(21, 153, 87);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;text-align: start;white-space: normal;"><strong>选型</strong></h2> <p style="box-sizing: border-box;font-size: 14px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;color: rgb(62, 62, 62);margin-bottom: 15px;margin-top: 15px;line-height: 2em;text-align: start;white-space: normal;">从后台框架、前端模板、数据库连接池、缓存、代理服务、限流等组件多个维度选型。</p> <ul style="" class=" list-paddingleft-2"> <li><p><span style="font-size: 14px;">后台框架 SpringBoot2+、JPA</span></p></li> <li><p><span style="font-size: 14px;">前端框架 Vue</span></p></li> <li><p><span style="font-size: 14px;">模块框架 Thymeleaf</span></p></li> <li><p><span style="font-size: 14px;">数据库连接池 HikariCP</span></p></li> <li><p><span style="font-size: 14px;">缓存 Redis</span></p></li> <li><p><span style="font-size: 14px;">限流 Guava</span></p></li> <li><p><span style="font-size: 14px;">代理服务 Nginx</span></p></li> <li><p><span style="font-size: 14px;">文章编辑 Markdown</span></p></li> </ul> <h2 style="box-sizing: border-box;margin-top: 2rem;margin-bottom: 1rem;color: rgb(21, 153, 87);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;text-align: start;white-space: normal;"><strong>架构</strong></h2> <p style="box-sizing: border-box;font-size: 14px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;color: rgb(62, 62, 62);margin-bottom: 15px;margin-top: 15px;line-height: 2em;text-align: start;white-space: normal;"><img class="" data-ratio="0.44830783495595733" src="/upload/d1a5fcee1a6a278063d6003717ec6c18.png" data-type="png" data-w="2157"></p> <h2 style="box-sizing: border-box;margin-top: 2rem;margin-bottom: 1rem;color: rgb(21, 153, 87);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;text-align: start;white-space: normal;"><strong>博文</strong></h2> <p style="box-sizing: border-box;font-size: 14px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;color: rgb(62, 62, 62);margin-bottom: 15px;margin-top: 15px;line-height: 2em;text-align: start;white-space: normal;">我们可以通过以下方式访问:</p> <pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box;overflow: auto;font-family: Consolas, Menlo, Courier, monospace;font-size: 10px;background: rgb(29, 31, 33);border-width: 1px;border-style: solid;border-color: rgb(136, 136, 136);padding: 2px;color: rgb(80, 97, 109);text-align: start;line-height: 12px;"> <ol class="linenums list-paddingleft-2" style=""> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">https</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">:</span><span class="com" style="box-sizing: border-box;">//blog.52itstyle.top/49.html</span></code></p></li> </ol></pre> <p style="box-sizing: border-box;font-size: 14px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;color: rgb(62, 62, 62);margin-bottom: 15px;margin-top: 15px;line-height: 2em;text-align: start;white-space: normal;">亦或是:</p> <pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box;overflow: auto;font-family: Consolas, Menlo, Courier, monospace;font-size: 10px;background: rgb(29, 31, 33);border-width: 1px;border-style: solid;border-color: rgb(136, 136, 136);padding: 2px;color: rgb(80, 97, 109);text-align: start;line-height: 12px;"> <ol class="linenums list-paddingleft-2" style=""> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">https</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">:</span><span class="com" style="box-sizing: border-box;">//blog.52itstyle.top/49.shtml</span></code></p></li> </ol></pre> <p style="box-sizing: border-box;font-size: 14px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;color: rgb(62, 62, 62);margin-bottom: 15px;margin-top: 15px;line-height: 2em;text-align: start;white-space: normal;">当然,如果你愿意你也可以显示为:</p> <pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box;overflow: auto;font-family: Consolas, Menlo, Courier, monospace;font-size: 10px;background: rgb(29, 31, 33);border-width: 1px;border-style: solid;border-color: rgb(136, 136, 136);padding: 2px;color: rgb(80, 97, 109);text-align: start;line-height: 12px;"> <ol class="linenums list-paddingleft-2" style=""> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">https</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">:</span><span class="com" style="box-sizing: border-box;">//blog.52itstyle.top/49.php</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">https</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">:</span><span class="com" style="box-sizing: border-box;">//blog.52itstyle.top/49.asp</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">https</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">:</span><span class="com" style="box-sizing: border-box;">//blog.52itstyle.top/49.jsp</span></code></p></li> </ol></pre> <p style="box-sizing: border-box;font-size: 14px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;color: rgb(62, 62, 62);margin-bottom: 15px;margin-top: 15px;line-height: 2em;text-align: start;white-space: normal;">只需要在后台配置对应的映射关系即可:</p> <pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box;overflow: auto;font-family: Consolas, Menlo, Courier, monospace;font-size: 10px;background: rgb(29, 31, 33);border-width: 1px;border-style: solid;border-color: rgb(136, 136, 136);padding: 2px;color: rgb(80, 97, 109);text-align: start;line-height: 12px;"> <ol class="linenums list-paddingleft-2" style=""> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="com" style="box-sizing: border-box;">/**</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="com" style="box-sizing: border-box;">* 博文</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="com" style="box-sizing: border-box;">*/</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="lit" style="box-sizing: border-box;color: rgb(222, 147, 95);">@RequestMapping</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">(</span><span class="str" style="box-sizing: border-box;color: rgb(181, 189, 104);">"{id}.html"</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">)</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="kwd" style="box-sizing: border-box;color: rgb(178, 148, 187);">public</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="typ" style="box-sizing: border-box;color: rgb(129, 162, 190);">String</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> blog</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">(</span><span class="lit" style="box-sizing: border-box;color: rgb(222, 147, 95);">@PathVariable</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">(</span><span class="str" style="box-sizing: border-box;color: rgb(181, 189, 104);">"id"</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">)</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="typ" style="box-sizing: border-box;color: rgb(129, 162, 190);">Long</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> id</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">,</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="typ" style="box-sizing: border-box;color: rgb(129, 162, 190);">ModelMap</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> model</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">)</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">{</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="typ" style="box-sizing: border-box;color: rgb(129, 162, 190);">Blog</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> blog </span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">=</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> blogService</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">.</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">getById</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">(</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">id</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">);</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> model</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">.</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">addAttribute</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">(</span><span class="str" style="box-sizing: border-box;color: rgb(181, 189, 104);">"blog"</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">,</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">blog</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">);</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="kwd" style="box-sizing: border-box;color: rgb(178, 148, 187);">return</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="str" style="box-sizing: border-box;color: rgb(181, 189, 104);">"article"</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">;</span></code></p></li> <li><p><code style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">}</span></code></p></li> </ol></pre> <p style="box-sizing: border-box;font-size: 14px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;color: rgb(62, 62, 62);margin-bottom: 15px;margin-top: 15px;line-height: 2em;text-align: start;white-space: normal;">由于数据库存储的是 markedown 格式的数据,前台我们通过 editormd 转为 html 代码显示,这里只展示部分代码:</p> <pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box;overflow: auto;font-family: Consolas, Menlo, Courier, monospace;font-size: 10px;background: rgb(29, 31, 33);border-width: 1px;border-style: solid;border-color: rgb(136, 136, 136);padding: 2px;color: rgb(80, 97, 109);text-align: start;line-height: 12px;"> <ol class="linenums list-paddingleft-2" style=""> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);"><script</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="atn" style="box-sizing: border-box;color: rgb(222, 147, 95);">type</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">=</span><span class="atv" style="box-sizing: border-box;color: rgb(138, 190, 183);">'text/javascript'</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="atn" style="box-sizing: border-box;color: rgb(222, 147, 95);">src</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">=</span><span class="atv" style="box-sizing: border-box;color: rgb(138, 190, 183);">'js/jquery.min.js'</span><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);">></script></span></code></p></li> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="com" style="box-sizing: border-box;"><!--省略部分代码--></span></code></p></li> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);"><script</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="atn" style="box-sizing: border-box;color: rgb(222, 147, 95);">type</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">=</span><span class="atv" style="box-sizing: border-box;color: rgb(138, 190, 183);">'text/javascript'</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="atn" style="box-sizing: border-box;color: rgb(222, 147, 95);">src</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">=</span><span class="atv" style="box-sizing: border-box;color: rgb(138, 190, 183);">"editor/editormd.min.js"</span><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);">></script></span></code></p></li> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="com" style="box-sizing: border-box;"><!--省略部分代码--></span></code></p></li> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);"><div</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="atn" style="box-sizing: border-box;color: rgb(222, 147, 95);">id</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">=</span><span class="atv" style="box-sizing: border-box;color: rgb(138, 190, 183);">"article"</span><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);">></span></code></p></li> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);"><textarea</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="atn" style="box-sizing: border-box;color: rgb(222, 147, 95);">th:text</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">=</span><span class="atv" style="box-sizing: border-box;color: rgb(138, 190, 183);">"${blog.content}"</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="atn" style="box-sizing: border-box;color: rgb(222, 147, 95);">style</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">=</span><span class="atv" style="box-sizing: border-box;color: rgb(138, 190, 183);">"</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">display</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">:</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);">none</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">;</span><span class="atv" style="box-sizing: border-box;color: rgb(138, 190, 183);">"</span><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="atn" style="box-sizing: border-box;color: rgb(222, 147, 95);">placeholder</span><span class="pun" style="box-sizing: border-box;color: rgb(197, 200, 198);">=</span><span class="atv" style="box-sizing: border-box;color: rgb(138, 190, 183);">"markdown语言"</span><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);">></span></code></p></li> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="pln" style="box-sizing: border-box;color: rgb(197, 200, 198);"> </span><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);"></textarea></span></code></p></li> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="tag" style="box-sizing: border-box;color: rgb(204, 102, 102);"></div></span></code></p></li> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="com" style="box-sizing: border-box;"><!--省略部分代码--></span></code></p></li> <li><p><code class="html language-html" style="box-sizing: border-box;font-family: monospace, monospace;display: inline;max-width: initial;overflow: initial;line-height: 12px;overflow-wrap: normal;background-color: transparent;border-width: 0px;border-style: initial;border-color: initial;"><span class="tag" style="
作者:微信小助手
<h2><strong><span style="font-size: 24px;">1.说下Struts的设计模式</span></strong></h2> <section class="output_wrapper" style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><code class="hljs sql" style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">MVC模式: <br>web应用程序启动时<br>就会加载并初始化ActionServler。<br>用户提交表单时,<br>一个配置好的ActionForm对象被创建,<br>并被填入表单相应的数据,<br>ActionServler根据Struts-config.xml文件<br>配置好的设置决定是否需要表单验证,<br>如果需要就调用ActionForm的Validate()<br>验证后选择将请求发送到哪个Action,<br>如果Action不存在,<br>ActionServlet会先创建这个对象,<br>然后调用Action的<span class="hljs-keyword" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">execute</span>()方法。<br><span class="hljs-keyword" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">Execute</span>()从ActionForm对象中获取数据,<br>完成业务逻辑,<br>返回一个ActionForward对象,<br>ActionServlet再把客户请求 <br>转发给ActionForward对象指定的jsp组件,<br>ActionForward对象指定的jsp生<br>成动态的网页,返回给客户。<br></code></pre> </section> <h2><strong><span style="font-size: 24px;">2.拦截器和过滤器的区别?</span></strong></h2> <section class="output_wrapper" style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><code class="hljs" style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">1、拦截器是基于java反射机制的,<br>而过滤器是基于函数回调的。<br><br>2、过滤器依赖于servlet容器,<br>而拦截器不依赖于servlet容器。<br><br>3、拦截器只能对Action请求起作用,<br>而过滤器则可以对几乎所有请求起作用。<br><br>4、拦截器可以访问Action上下文、<br>值栈里的对象,而过滤器不能。<br><br>5、在Action的生命周期中,<br>拦截器可以多次调用,<br>而过滤器只能在容器初始化时被调用一次。<br></code></pre> </section> <p><br></p> <h2><span style="font-size: 24px;"><strong>3.struts2框架的核心控制器是什么?它有什么作用?</strong></span></h2> <section class="output_wrapper" style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><code class="hljs xml" style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">1)Struts2框架的核心控制器是<br>StrutsPrepareAndExecuteFilter。 <br><br>2)作用: <br><br> 负责拦截由<span class="hljs-tag" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><<span class="hljs-name" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">url-pattern</span>></span>/*<span class="hljs-tag" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"></<span class="hljs-name" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">url-pattern</span>></span><br>指定的所有用户请求,<br>当用户请求到达时,<br>该Filter会过滤用户的请求。<br>默认情况下,<br>如果用户请求的路径 <br><br>不带后缀或者后缀以.action结尾,<br>这时请求将被转入struts2框架处理,<br>否则struts2框架将略过该请求的处理。 <br><br>可以通过常量"struts.action.extension"修改action的后缀,<br>如: <br><span class="hljs-tag" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><<span class="hljs-name" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">constant</span> <span class="hljs-attr" style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);word-wrap: inherit !important;word-break: inherit !important;">name</span>=<span class="hljs-string" style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"struts.action.extension"</span> <span class="hljs-attr" style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);word-wrap: inherit !important;word-break: inherit !important;">value</span>=<span class="hljs-string" style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"do"</span>/></span> <br>如果用户需要指定多个请求后缀,<br>则多个后缀之间以英文逗号(,)隔开。<br><span class="hljs-tag" style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;"><<span class="hljs-name" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">constant</span> <span class="hljs-attr" style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);word-wrap: inherit !important;word-break: inherit !important;">name</span>=<span class="hljs-string" style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"struts.action.extension"</span> <span class="hljs-attr" style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);word-wrap: inherit !important;word-break: inherit !important;">value</span>=<span class="hljs-string" style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"do,go"</span>/></span><br></code></pre> </section> <h2><strong><span style="font-size: 24px;">4.struts2如何访问HttpServletRequest、HttpSession、ServletContext三个域对象?</span></strong></h2> <section class="output_wrapper" style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><code class="hljs vbscript" style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">方案一: <br><br>HttpServletRequest <span class="hljs-built_in" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">request</span> =<br>ServletActionContext.getRequest(); <br><br>HttpServletResponse <span class="hljs-built_in" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">response</span> =<br>ServletActionContext.getResponse(); <br><br>HttpSession session= <br><span class="hljs-built_in" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">request</span>.getSession(); <br><br>ServletContext servletContext=<br>ServletActionContext.getServletContext(); <br><br><br><br>方案二: <br><br>类 implements ServletRequestAware,ServletResponseAware,SessionAware,ServletContextAware <br><br>注意:框架自动传入对应的域对象<br></code></pre> </section> <h2><span style="font-size: 24px;"><strong>5.ActionContext、ServletContext、pageContext的区别?</strong></span></h2> <section class="output_wrapper" style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><code class="hljs vbscript" style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;"><span class="hljs-number" style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">1</span>)ActionContext是当前的Action的上下文环境,<br>通过ActionContext可以<br>获取到<span class="hljs-built_in" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">request</span>、session、ServletContext等<br>与Action有关的对象的引用; <br><br><span class="hljs-number" style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">2</span>)ServletContext是域对象,<br>一个web应用中只有一个ServletContext,<br>生命周期伴随整个web应用; <br><br><span class="hljs-number" style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">3</span>)pageContext是JSP中的最重要的一个内置对象,<br>可以通过pageContext获取其他域对象的应用,<br>同时它是一个域对象,<br>作用范围只针对当前页面,<br>当前页面结束时,<br>pageContext销毁, <br><br>生命周期是JSP四个域对象中最小的。<br></code></pre> </section> <p><br></p> <h2 style="box-sizing: border-box;font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;font-weight: 700;line-height: 1.7;color: rgb(47, 47, 47);margin-bottom: 15px;font-size: 24px;text-rendering: optimizeLegibility;white-space: normal;background-color: rgb(255, 255, 255);">6.描述Struts2的工作原理</h2> <section class="output_wrapper" style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><code class="hljs css" style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">客户端发送请求<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">--</span>》<br>请求经过一系列过滤器<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">-</span>><br><span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">FilterDispatcher</span>通过<br><span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">ActionMapper</span>来决定这个<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">Reques</span><br><span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">t</span>需要调用哪个<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">Action</span> <span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">-</span>><br><span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">FilterDispatcher</span>把请求的处理交给<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">ActionProxy-</span>> <br>通过<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">ConfigurationManager</span>询问<br><span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">Struts</span>配置文件(<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">Struts</span><span class="hljs-selector-class" style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);word-wrap: inherit !important;word-break: inherit !important;">.xml</span>)<br>找到需要调用的<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">Action</span>类<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">-</span>><br><span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">ActionProxy</span>创建一个<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">ActionInvocation</span>的实例 <span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">-</span>><br>调用<span class="hljs-selector-tag" style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">Action-</span>>执行完毕,<br>返回结果<br></code></pre> </section> <h2 style="box-sizing: border-box;font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;font-weight: 700;line-height: 1.7;color: rgb(47, 47, 47);margin-bottom: 15px;font-size: 24px;text-rendering: optimizeLegibility;white-space: normal;background-color: rgb(255, 255, 255);">7.result的type属性中有哪几种结果类型?</h2> <section class="output_wrapper" style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><code class="hljs" style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">一共10种: <br><br>dispatcher <br><br>struts默认的结果类型,<br>把控制权转发给应用程序里的<br>某个资源不能把控制权<br>转发给一个外部资源,<br>若需要把控制权重定向到<br>一个外部资源, 应该使用 <br><br>redirect结果类型 <br>redirect <br>把响应重定向到另一个资源(包括一个外部资源) <br><br>redirectAction <br>把响应重定向到另一个 Action <br><br>freemarker、<br>velocity、<br>chain、<br>httpheader、<br>xslt、<br>plainText、<br>stream<br></code></pre> </section> <h2 style="box-sizing: border-box;font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;font-weight: 700;line-height: 1.7;color: rgb(47, 47, 47);margin-bottom: 15px;font-size: 24px;text-rendering: optimizeLegibility;white-space: normal;background-color: rgb(255, 255, 255);">8.拦截器的生命周期与工作过程?</h2> <section class="output_wrapper" style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 0px;margin-bottom: 0px;padding: 0px;"><code class="hljs makefile" style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;display: block !important;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;">1)每个拦截器都是实现了I<br>nterceptor接口的 Java 类; <br><br><span class="hljs-section" style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);word-wrap: inherit !important;word-break: inherit !important;">2)init(): 该方法将在拦截器被创建后立即被调用, </span><br>它在拦截器的生命周期内只被调用一次. <br>可以在该方法中对相关资源<br>进行必要的初始化; <br><br>3)intercept(ActionInvocation invocation): <br>每拦截一个动作请求,<br> 该方法就会被调用一次; <br><br><span class="hljs-section" style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);word-wrap: inherit !important;word-break: inherit !important;">4)destroy: </span><br>该方法将在拦截器被销毁之前被调用,&n
作者:微信小助手
<h2 mpa-is-content="t" style="margin: 5px 8px;padding-right: 10px;padding-left: 10px;font-weight: bold;white-space: normal;border-left: 5px solid rgb(255, 125, 65);border-top-color: rgb(255, 125, 65);border-bottom-color: rgb(255, 125, 65);border-right-color: rgb(255, 125, 65);line-height: 1.5em;"><span style="font-size: 12px;font-family: Optima-Regular, PingFangTC-light;color: rgb(136, 136, 136);">导读:随着计算机技术和工程架构的发展,微服务变得越来越热。如今,绝大多数服务都处于分布式环境中,其中,数据一致性是我们一直关注的重点。分布式锁到底是什么?经过了哪些发展演进?工程上有哪些实现方案?各种方案的利弊权衡又有哪些?希望这篇文章能够对你有一些帮助。</span><br></h2> <p><br></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 19px;color: rgb(64, 64, 64);">▍<strong>阅读</strong><strong>索引</strong></span></p> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: circle;margin-left: 8px;margin-right: 8px;"> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">0. 名词定义</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">1. 问题引入</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">2. 分布式环境的特点 </span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">3. 锁</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">4. 分布式锁</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">5. 分布式锁实现方案</span></p></li> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">5.1. 朴素Redis实现方案、朴素Redis方案小结</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">5.2. ZooKeeper实现方案、ZooKeeper方案小结</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">5.3. Redisson实现方案、</span><span style="color: rgb(102, 102, 102);font-size: 14px;text-indent: 0em;">Redisson方案小结</span></p></li> </ul> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">6. 总结</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">7. 结束语</span></p></li> <li><p style="margin-left: 8px;margin-right: 8px;text-align: left;text-indent: 0em;"><span style="color: rgb(102, 102, 102);font-size: 14px;">8. Reference</span></p></li> </ul> <p style="margin-top: 10px;white-space: normal;text-align: center;margin-left: 8px;margin-right: 8px;"><br></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><img class="" data-copyright="0" data-ratio="0.02847130968024529" data-s="300,640" data-type="png" data-w="2283" style="text-align: center;width: 677px !important;visibility: visible !important;" src="/upload/8912fc230b8db334779b59d2e661c1e6.png"></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="color: rgb(255, 125, 65);font-size: 19px;">▍</span><strong><span style="font-size: 19px;">0. 名词定义</span></strong></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;color: rgb(64, 64, 64);">分布式锁:顾名思义,是指在分布式环境下的锁,重点在锁。所以我们先从锁开始讲起。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <h1 class="" style="white-space: normal;"><p style="margin-left: 8px;margin-right: 8px;"><span style="color: rgb(255, 125, 65);font-size: 19px;">▍</span><span style="color: rgb(64, 64, 64);"><strong><span style="font-size: 19px;">1. 问题引入</span></strong></span></p></h1> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">举个例子:</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">某服务记录数据X,当前值为100。A请求需要将X增加200;同时,B请求需要将X减100。在理想的情况下,A先读取到X=100,然后X增加200,最后写入X=300。B请求接着读取到X=300,减少100,最后写入X=200。然而在真实情况下,如果不做任何处理,则可能会出现:A和B同时读取到X=100;A写入之前B读取到X;B比A先写入等等情况。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">上面这个例子相信大家都非常熟悉。出现不符合预期的结果本质上是对临界资源没有做好互斥操作。互斥性问题通俗来讲,就是对共享资源的抢占问题。对于共享资源争抢的正确性,锁是最常用的方式,其他的如CAS(compare and swap)等,这里不展开。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <h1 class="" style="white-space: normal;"><p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 19px;"><strong style="font-size: 14px;color: rgb(64, 64, 64);font-family: -apple-system, system-ui, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span style="color: rgb(255, 125, 65);font-size: 19px;">▍</span></strong></span><strong><span style="font-size: 19px;">2. 分布式环境的特点</span></strong></p></h1> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">我们的绝大部分服务都处于分布式环境中。那么,分布式系统有哪些特点呢?大致如下:</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">* 可扩展性:可通过横向水平扩展提高系统的性能和吞吐量。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">* 高可靠性:高容错,即使系统中一台或几台故障,系统仍可提供服务。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">* 高并发性:各机器并行独立处理和计算。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">* 廉价高效:多台小型机而非单台高性能机。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="color: rgb(255, 125, 65);font-size: 19px;">▍</span><strong><span style="font-size: 19px;">3.锁</span></strong></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">我们先来看下非分布式情况下的锁方案(多线程和多进程的情况),然后再演进到分布式锁。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="margin-bottom: 15px;white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 16px;"><span style="color: rgb(64, 64, 64);"><strong style="font-size: 14px;font-family: -apple-system, system-ui, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span style="font-family: PingFangSC-Regular;"><strong><span style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"><strong style="font-size: 16px;letter-spacing: 0.544px;"><span style="font-family: Optima-Regular, PingFangTC-light;"><strong><strong>▍</strong></strong></span></strong></span></strong></span></strong></span><strong>多线程下的锁机制:</strong></span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">各种语言有不同的实现方式,比较成熟。比如,go语言中的sync.RWMutex(读写锁)、sync.Mutex(互斥锁);JAVA中的ReentrantLock、synchronized;在php中没有找到原生的支持锁的方式,只能通过外部来间接实现,比如文件锁,借助外部存储的锁等。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="margin-bottom: 15px;white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 16px;"><strong style="color: rgb(64, 64, 64);font-size: 14px;font-family: -apple-system, system-ui, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span style="font-family: PingFangSC-Regular;"><strong><span style="font-family: Optima-Regular, PingFangTC-light;">▍</span></strong></span></strong><strong>多进程下的锁机制:</strong></span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">对于临界资源的访问已经超出了单个进程的控制范围。在多进程的情况下,主要是利用操作系统层面的进程间通信原理来解决临界资源的抢占问题。比较常见的一种方法便是使用信号量(Semaphores)。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 16px;"><strong>▍对信号量的操作,主要是P操作(wait)和V操作(signal):</strong></span></p> <p style="margin-right: 8px;margin-left: 8px;white-space: normal;"><br></p> <p style="margin-bottom: 15px;white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong>* P操作 ( wait ) :</strong></span></p> <p style="margin-bottom: 5px;white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">先检查信号量的大小,若值大于零,则将信号量减1,同时进程获得共享资源的访问权限,继续执行;若小于或者等于零,则该进程被阻塞后,进入等待队列。</span></p> <p style="white-space: normal;"><br></p> <p style="margin-bottom: 15px;white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong>* V操作 ( signal ) :</strong></span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">该操作将信号量的值加1,如果有进程阻塞着等待该信号量,那么其中一个进程将被唤醒。</span></p> <p line="CTO3" class="" style="white-space: normal;"><br></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">可看出,多进程锁方案跟多线程的锁方案实现思路大同小异。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">我们将互斥的级别拉高,分布式环境下不同节点不同进程或线程之间的互斥,就是分布式锁的挑战之一。后面再细讲。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">另外,在传统的基于数据库的架构中,对于数据的抢占问题也可以通过数据库事务(ACID)来保证。在分布式环境中,出于对性能以及一致性敏感度的要求,使得分布式锁成为了一种比较常见而高效的解决方案。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 16px;"><strong><strong style="font-size: 14px;color: rgb(64, 64, 64);font-family: -apple-system, system-ui, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span style="font-family: PingFangSC-Regular;"><strong><span style="font-family: Optima-Regular, PingFangTC-light;">▍</span></strong></span></strong></strong><strong>从上面对于多线程和多进程锁的概括,可以总结出锁的抽象条件:</strong></span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="margin-bottom: 10px;white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong>1)“需要有存储锁的空间,并且锁的空间是可以访问到的”:</strong></span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">对于多线程就是内存(进程中不同的线程都可以读写),多进程中通过共享内存的方式,也是提供一块地方,供不同进程读写。主要目的是保证不同的进线程改动对于其他进线程可见,进而满足互斥性需求。</span></p> <p line="UkB5" class="" style="white-space: normal;"><br></p> <p style="margin-bottom: 10px;white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong>2)“锁需要被唯一标识”:</strong></span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">不同的共享资源,必然需要用不同的锁进行保护,因此相应的锁必须有唯一的标识。在多线程环境中,锁可以是一个对象,那么对这个对象的引用便是这个唯一标识。多进程下,比如有名信号量,便是用硬盘中的文件名作为唯一标识。</span></p> <p line="ognS" class="" style="white-space: normal;"><br></p> <p style="margin-bottom: 10px;white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong>3)“锁要有至少两种状态”:</strong></span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">有锁,没锁。存在,不存在等等。很好理解。</span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"> </span></p> <p style="white-space: normal;margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">满足上述三个条件就可以实现基础的分布式锁了。但是随着技术的演进,</span></p> <p style="mar
作者:微信小助手
<p style="white-space: normal;text-align: left;" data-mpa-powered-by="yiban.io"><img class="" data-ratio="0.6666666666666666" data-type="png" data-w="127" src="/upload/4c8b91599182ea5ba1ead110e9271956.png" style="height: 41px;vertical-align: bottom;width: 76px;"></p> <p style="white-space: normal;color: rgb(153, 80, 51);line-height: normal;"><span style="font-size: 15px;letter-spacing: 1px;">还没关注?伸出中指点这里!</span><br></p> <p style="white-space: normal;color: rgb(153, 80, 51);line-height: normal;"><br></p> <section class="KolEditor" data-tools-id="85858" style="white-space: normal;"> <section class="Powered-by-KolEditor V5" powered-by="KolEditor.us"> <section class=""> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-bottom: 5px;height: 5px;background-color: rgb(154, 157, 170);"></section> <section class="" style="margin-top: -40px;margin-right: 1.5em;margin-left: 1.5em;padding: 10px;background-color: rgb(226, 230, 0);"> <section class="Powered-by-KolEditor V5" powered-by="KolEditor.us"> <section class=""> <section class="" style="text-align: center;color: rgb(255, 255, 255);"> <section> <span style="color: rgb(0, 0, 0);font-size: 15px;">聊技术、论职场!</span> </section> <section> <span style="color: rgb(0, 0, 0);"><span style="font-size: 15px;">为IT人打造一个“有温度”的</span><strong style="font-size: 15px;"><span style="color: rgb(201, 56, 28);">狸猫技术窝</span></strong></span> </section> </section> </section> </section> </section> </section> </section> </section> <p style="white-space: normal;text-align: right;line-height: normal;"><span style="color: rgb(204, 204, 204);font-size: 10px;">来源:http://u6.gg/svBd4</span><br></p> <p style="white-space: normal;"><br></p> <h2 data-id="heading-0"><span style="color: rgb(57, 137, 31);"><strong><br></strong></span></h2> <h2 data-id="heading-0"><span style="color: rgb(57, 137, 31);"><strong>Tomcat是什么</strong></span></h2> <p><br></p> <blockquote> <p style="line-height: 2em;"><span style="font-size: 15px;">Tomcat是开源的 Java Web 应用服务器,实现了 Java EE 的部分技术规范,比如 Java Servlet、Java Server Page、JSTL、Java WebSocket。</span></p> <p style="line-height: 2em;"><span style="font-size: 15px;"><br></span></p> <p style="line-height: 2em;"><span style="font-size: 15px;">Java EE 是 Sun 公 司为企业级应用推出的标准平台,定义了一系列用于企业级开发的技术规范。</span></p> <p style="line-height: 2em;"><span style="font-size: 15px;"><br></span></p> <p style="line-height: 2em;"><span style="font-size: 15px;">除了上述的之外,还有 EJB、Java Mail、JPA、JTA、JMS 等,而这些都依赖具体容器的实现。</span></p> </blockquote> <p><br></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="1280" data-width="800" src="/upload/cc61e178e60febc2b341a36e7d3e6f9d.other"> </figure> <p><br></p> <p style="line-height: 2em;">上图对比了 Java EE 容器的实现情况,Tomcat 和 Jetty 都只提供了 Java Web 容器必需的 Servlet 和 JSP 规范,开发者要想实现其他的功能,需要自己依赖其他开源实现。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">Glassfish 是由 sun 公司推出,Java EE 最新规范出来之后,首先会在 Glassfish 上进行实现,所以是研究 Java EE 最新技术的首选。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">最常见的情况是使用 Tomcat 作为 Java Web 服务器,使用 Spring 提供的开箱即用的强大功能,并依赖其他开源库来完成负责的业务功能实现。</p> <p><strong><br></strong></p> <p><strong><br></strong></p> <p><span style="color: rgb(57, 137, 31);"><strong>Servlet容器<br></strong></span></p> <p><strong><br></strong></p> <p style="line-height: 2em;"><strong><span style="font-size: 15px;color: rgb(51, 51, 51);">Tomcat 组成</span></strong></p> <p style="line-height: 2em;">如下图所示,主要有 Container 和 Connector 以及相关组件构成。<span style="color: rgb(57, 137, 31);"><br></span></p> <figure> <img class="" data-ratio="0.6666666666666666" data-type="jpeg" data-w="2008" src="/upload/4daf727a48a55fb0f4bea34cdbd95346.jpg"> </figure> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="line-height: 2em;"><strong>Server</strong>:指的就是整个 Tomcat 服 务器,包含多组服务,负责管理和 启动各个 Service,同时监听 8005 端口发过来的 shutdown 命令,用 于关闭整个容器 ;</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Service</strong>:Tomcat 封装的、对外提 供完整的、基于组件的 web 服务, 包含 Connectors、Container 两个 核心组件,以及多个功能组件,各 个 Service 之间是独立的,但是共享 同一 JVM 的资源 ;</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Connector</strong>:Tomcat 与外部世界的连接器,监听固定端口接收外部请求,传递给 Container,并 将 Container 处理的结果返回给外部</p><p><br></p></li> <li><p style="line-height: 2em;"><strong>Container</strong>:Catalina,Servlet 容器,内部有多层容器组成,用于管理 Servlet 生命周期,调用 servlet 相关方法</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Loader</strong>:封装了 Java ClassLoader,用于 Container 加载类文件;Realm:Tomcat 中为 web 应用程序提供访问认证和角色管理的机制;</p><p><br></p></li> <li><p style="line-height: 2em;"><strong>JMX</strong>:Java SE 中定义技术规范,是一个为应用程序、设备、系统等植入管理功能的框架,通过 JMX 可以远程监控 Tomcat 的运行状态</p><p><br></p></li> <li><p style="line-height: 2em;"><strong>Jasper</strong>:Tomcat 的 Jsp 解析引擎,用于将 Jsp 转换成 Java 文件,并编译成 class 文件。Session:负责管理和创建 session,以及 Session 的持久化(可自定义),支持 session 的集群。</p><p><br></p></li> <li><p style="line-height: 2em;"><strong>Pipeline</strong>:在容器中充当管道的作用,管道中可以设置各种 valve(阀门),请求和响应在经由管 道中各个阀门处理,提供了一种灵活可配置的处理请求和响应的机制。</p><p><br></p></li> <li><p style="line-height: 2em;"><strong>Naming</strong>:命名服务,JNDI, Java 命名和目录接口,是一组在 Java 应用中访问命名和目录服务的 API。命名服务将名称和对象联系起来,使得我们可以用名称访问对象,目录服务也是一种命名 服务,对象不但有名称,还有属性。Tomcat 中可以使用 JNDI 定义数据源、配置信息,用于开发 与部署的分离。</p></li> </ul> <p><strong><br></strong></p> <p><strong><br></strong></p> <p><strong>Container组成</strong></p> <p><strong><br></strong></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="1205" data-width="800" src="/upload/279d9795302cf9bdadbe3c2322cba241.other"> </figure> <p><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="line-height: 2em;"><strong>Engine</strong>:Servlet 的顶层容器,包含一 个或多个 Host 子容器;</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Host</strong>:虚拟主机,负责 web 应用的部 署和 Context 的创建;</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Context</strong>:Web 应用上下文,包含多个 Wrapper,负责 web 配置的解析、管 理所有的 Web 资源;</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Wrapper</strong>:最底层的容器,是对 Servlet 的封装,负责 Servlet 实例的创 建、执行和销毁。</p></li> </ul> <p><br></p> <p><br></p> <p style="line-height: 2em;"><strong>生命周期管理</strong><br>Tomcat 为了方便管理组件和容器的生命周期,定义了从创建、启动、到停止、销毁共 12 种状态</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">tomcat 生命周期管理了内部状态变化的规则控制,组件和容器只需实现相应的生命周期方法,即可完成各生命周期内的操作(initInternal、startInternal、stopInternal、 destroyInternal);</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">比如执行初始化操作时,会判断当前状态是否 New,如果不是则抛出生命周期异常;是的话则设置当前状态为 Initializing,并执行 initInternal 方法,由子类实现,方法执行成功则设置当前状态为 Initialized,执行失败则设置为 Failed 状态;</p> <p><br></p> <figure> <img class="" data-ratio="0.6666666666666666" data-type="jpeg" data-w="3068" src="/upload/c1498737179d4123236e920dd4b6c483.jpg"> </figure> <p><br></p> <p style="line-height: 2em;">Tomcat 的生命周期管理引入了<strong>事件机制</strong>,在组件或容器的生命周期状态发生变化时会通知事件监听器,监听器通过判断事件的类型来进行相应的操作。事件监听器的添加可以在 server.xml 文件中进行配置;<br></p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">Tomcat 各类容器的配置过程是通过添加 listener 的方式来进行的,从而达到配置逻辑与容器的解耦。如 EngineConfig、HostConfig、ContextConfig。<br><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="line-height: 2em;">EngineConfig:主要打印启动和停止日志</p><p><br></p></li> <li><p style="line-height: 2em;">HostConfig:主要处理部署应用,解析应用 META-INF/context.xml 并创建应用</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">Context ContextConfig:主要解析并合并 web.xml,扫描应用的各类 web 资源 (filter、servlet、listener)</p></li> </ul> <p><br></p> <figure> <img class="" data-ratio="0.6666666666666666" data-type="jpeg" data-w="2560" src="/upload/7cd6874eccf2c1446d6916dd21ea0742.jpg"> </figure> <p><br></p> <p><br></p> <p><strong>Tomcat 的启动过程</strong></p> <p><br></p> <figure> <img class="" data-ratio="0.6666666666666666" data-type="jpeg" data-w="2296" src="/upload/15c10cdf26f0307e9f790b1cfe6ff019.jpg"> </figure> <p><br></p> <p style="line-height: 2em;">启动从 Tomcat 提供的 start.sh 脚本开始,shell 脚本会调用 Bootstrap 的 main 方法,实际调用了 Catalina 相应的 load、start 方法。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">load 方法会通过 Digester 进行 config/server.xml 的解析,在解析的过程中会根据 xml 中的关系 和配置信息来创建容器,并设置相关的属性。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">接着 Catalina 会调用 StandardServer 的 init 和 start 方法进行容器的初始化和启动。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">按照 xml 的配置关系,server 的子元素是 service,service 的子元素是顶层容器 Engine,每层容器都持有自己的子容器,而这些元素都实现了生命周期管理的各个方法,因此就很容易的完成整个容器的启动、关闭等生命周期的管理。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">StandardServer 完成 init 和 start 方法调用后,会一直监听来自 8005 端口(可配置)</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">如果接收 到 shutdown 命令,则会退出循环监听,执行后续的 stop 和 destroy 方法,完成 Tomcat 容器的关闭。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">同时也会调用 JVM 的 Runtime.getRuntime()﴿.addShutdownHook 方法,在虚拟机意外退出的时候来关闭容器。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">所有容器都是继承自 ContainerBase,基类中封装了容器中的重复工作,负责启动容器相关的组件 Loader、Logger、Manager、Cluster、Pipeline,启动子容器(线程池并发启动子容器,通过线程池 submit 多个线程,调用后返回 Future 对象,线程内部启动子容器,接着调用 Future 对象 的 get 方法来等待执行结果)。</p> <p><br></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t" mpa-from-tpl="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 6px;overflow-x: auto;white-space: nowrap;" class="hljs-default">List<future <void> > results = <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none;font-weight: 400;font-style: normal;">new</span> ArrayList<future <void> >(); <br mpa-from-tpl="t"> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none;font-weight: 400;font-style: normal;">for</span> ( <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none;font-weight: 400;font-style: normal;">int</span> i = <span class="hljs-default-number" style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 6px;text-decoration: none;font-weight: 400;font-style: normal;">0</span>; i < children.length; i++) { <br mpa-from-tpl="t"> results. <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none;font-weight: 400;font-style: normal;">add</span>(startStopExecutor.submit( <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none;font-weight: 400;font-style: normal;">new</span> StartChild(children[i]))); <br mpa-from-tpl="t">} <br mpa-from-tpl="t">boolean fail = <span class="hljs-default-literal" style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none;font-weight: 400;font-style: normal;">false</span>; <br mpa-from-tpl="t"> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none;font-weight: 400;font-style: normal;">for</span> (Future <void> result :results) { <br mpa-from-tpl="t"> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none;font-weight: 400;font-style: normal;">try</span> { <br mpa-from-tpl="t"> result. <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none;font-weight: 400;font-style: normal;">get</span>(); <br mpa-from-tpl="t"> } <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none;font-weight: 400;font-style: normal;">catch</span> (Exception e) { <br mpa-from-tpl="t"> log.error(sm.getString( <span class="hljs-default-string" style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 231px;text-decoration: none;font-weight: 400;font-style: normal;">"containerBase.threadedStartFailed"</span>), e); <br mpa-from-tpl="t"> fail = <span class="hljs-default-literal" style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none;font-weight: 400;font-style: normal;">true</span>; <br mpa-from-tpl="t"> } <br mpa-from-tpl="t">} </void> </void> </void></code></pre> </section> <pre><code class="hljs java copyable"><span class="copy-code-btn"></span></code><br></pre> <p style="line-height: 2em;"><strong>Web 应用的部署方式</strong><br>注:catalina.home:安装目录;catalina.base:工作目录;默认值 user.dir</p> <ul class=" list-paddingleft-2"> <li><p style="line-height: 2em;">Server.xml 配置 Host 元素,指定 appBase 属性,默认\$catalina.base/webapps/</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">Server.xml 配置 Context 元素,指定 docBase,元素,指定 web 应用的路径</p><p style="line-height: 2em;"><br></p></li> <li><p style="text-align: left;line-height: 2em;">自定义配置:在\$catalina.base/EngineName/HostName/XXX.xml 配置 Context 元素</p><p style="text-align: left;"><br></p><p style="text-align: left;"><br></p></li> </ul> <p style="line-height: 2em;">HostConfig 监听了 StandardHost 容器的事件,在 start 方法中解析上述配置文件:</p> <ul class=" list-paddingleft-2"> <li><p style="line-height: 2em;">扫描 appbase 路径下的所有文件夹和 war 包,解析各个应用的 META-INF/context.xml,并 创建 StandardContext,并将 Context 加入到 Host 的子容器中。</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">解析$catalina.base/EngineName/HostName/下的所有 Context 配置,找到相应 web 应 用的位置,解析各个应用的 META-INF/context.xml,并创建 StandardContext,并将 Context 加入到 Host 的子容器中。</p></li> </ul> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">注:</p> <ul class=" list-paddingleft-2"> <li><p style="line-height: 2em;">HostConfig 并没有实际解析 Context.xml,而是在 ContextConfig 中进行的。</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">HostConfig 中会定期检查 watched 资源文件(context.xml 配置文件)</p><p style="line-height: 2em;"><br></p></li> </ul> <p style="line-height: 2em;">ContextConfig 解析 context.xml 顺序:</p> <ul class=" list-paddingleft-2"> <li><p style="line-height: 2em;">先解析全局的配置 config/context.xml</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">然后解析 Host 的默认配置 EngineName/HostName/context.xml.default</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">最后解析应用的 META-INF/context.xml</p><p style="line-height: 2em;"><br></p><p style="line-height: 2em;"><br></p></li> </ul> <p style="line-height: 2em;">ContextConfig 解析 web.xml 顺序:</p> <ul class=" list-paddingleft-2"> <li><p style="line-height: 2em;">先解析全局的配置 config/web.xml</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">然后解析 Host 的默认配置 EngineName/HostName/web.xml.default 接着解析应用的 MEB-INF/web.xml</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">扫描应用 WEB-INF/lib/下的 jar 文件,解析其中的 META-INF/web-fragment.xml 最后合并 xml 封装成 WebXml,并设置 Context</p><p style="line-height: 2em;"><br></p></li> </ul> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">注:</p> <ul class=" list-paddingleft-2"> <li><p style="line-height: 2em;">扫描 web 应用和 jar 中的注解(Filter、Listener、Servlet)就是上述步骤中进行的。</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">容器的定期执行:backgroundProcess,由 ContainerBase 来实现的,并且只有在顶层容器 中才会开启线程。(backgroundProcessorDelay=10 标志位来控制)</p></li> </ul> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;"><strong>Servlet 生命周期</strong></p> <p><br></p> <figure> <img class="" data-ratio="0.6666666666666666" data-type="jpeg" data-w="1760" src="/upload/47f97227c0c4960bfbee540fc59af187.jpg"> </figure> <p><br></p> <p style="line-height: 2em;">Servlet 是用 Java 编写的服务器端程序,其主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。</p> <ol class=" list-paddingleft-2"> <li><p style="line-height: 2em;">请求到达 server 端,server 根据 url 映射到相应的 Servlet</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">判断 Servlet 实例是否存在,不存在则加载和实例化 Servlet 并调用 init 方法</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">Server 分别创建 Request 和 Response 对象,调用 Servlet 实例的 service 方法(service 方法 内部会根据 http 请求方法类型调用相应的 doXXX 方法)</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">doXXX 方法内为业务逻辑实现,从 Request 对象获取请求参数,处理完毕之后将结果通过 response 对象返回给调用方</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">当 Server 不再需要 Servlet 时(一般当 Server 关闭时),Server 调用 Servlet 的 destroy() 方 法。</p></li> </ol> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">load on startup</p> <p style="line-height: 2em;">当值为 0 或者大于 0 时,表示容器在应用启动时就加载这个 servlet; 当是一个负数时或者没有指定时,则指示容器在该 servlet 被选择时才加载; 正数的值越小,启动该 servlet 的优先级越高;</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">single thread model</p> <p style="line-height: 2em;">每次访问 servlet,新建 servlet 实体对象,但并不能保证线程安全,同时 tomcat 会限制 servlet 的实例数目</p> <p style="line-height: 2em;"><br>最佳实践:不要使用该模型,servlet 中不要有全局变量</p> <p style="line-height: 2em;"><strong><br></strong></p> <p style="line-height: 2em;"><strong><br></strong></p> <p style="line-height: 2em;"><strong>请求处理过程</strong></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="617" data-width="800" src="/upload/baff1acdc534bf4c0b07e48e5fe31d17.other"> </figure> <p><br></p> <ol class=" list-paddingleft-2"> <li><p style="line-height: 2em;">根据 server.xml 配置的指定的 connector 以及端口监听 http、或者 ajp 请求</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">请求到来时建立连接,解析请求参数,创建 Request 和 Response 对象,调用顶层容器 pipeline 的 invoke 方法</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">容器之间层层调用,最终调用业务 servlet 的 service 方法</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">Connector 将 response 流中的数据写到 socket 中</p></li> </ol> <p style="line-height: 2em;"><strong><br></strong></p> <p style="line-height: 2em;"><strong>Pipeline 与 Valve</strong></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="1043" data-width="800" src="/upload/e1bcd824bf080789c7a77929ed50d6.other"> </figure> <p><br></p> <p style="line-height: 2em;">Pipeline 可以理解为现实中的管道,Valve 为管道中的阀门,Request 和 Response 对象在管道中 经过各个阀门的处理和控制。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">每个容器的管道中都有一个必不可少的 basic valve,其他的都是可选的,basic valve 在管道中最 后调用,同时负责调用子容器的第一个 valve。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">Valve 中主要的三个方法:setNext、getNext、invoke;valve 之间的关系是单向链式结构,本身 invoke 方法中会调用下一个 valve 的 invoke 方法。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">各层容器对应的 basic valve 分别是 StandardEngineValve、StandardHostValve、 StandardContextValve、StandardWrapperValve。</p> <h2 data-id="heading-2" style="line-height: 2em;"><br></h2> <h2 data-id="heading-2" style="line-height: 2em;"><br></h2> <h2 data-id="heading-2" style="line-height: 2em;"><strong><span style="color: rgb(57, 137, 31);">JSP引擎</span></strong></h2> <figure> <img class="" data-ratio="0.6666666666666666" data-type="png" data-w="505" src="/upload/b5f1b8fe192a87304cced80c4ee4d2c8.png"> </figure> <p><br></p> <p style="line-height: 2em;"><strong>JSP 生命周期</strong></p> <ul class=" list-paddingleft-2"> <li><p style="line-height: 2em;">编译阶段:servlet 容器编译 servlet 源文<br>件,生成 servlet 类</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">初始化阶段:加载与 JSP 对应的 servlet 类, 创建其实例,并调用它的初始化方法</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">执行阶段:调用与 JSP 对应的 servlet 实例的 服务方法</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">销毁阶段:调用与 JSP 对应的 servlet 实例的 销毁方法,然后销毁 servlet 实例</p></li> </ul> <p style="line-height: 2em;"><strong><br></strong></p> <p style="line-height: 2em;"><strong>JSP元素</strong><br>代码片段:<%><br>JSP声明:<%! ...=""><br>JSP表达式:<%=><br>JSP注释:<%--><br>JSP指令:<%@ directive="" attribute="“value”"><br>JSP行为: <jsp:action_name attribute="“value”"> <br>HTML元素:html/head/body/div/p/… <br>JSP隐式对象:request、response、out、session、application、config、pageContext、page、Exception </jsp:action_name></p> <p style="line-height: 2em;"> <jsp:action_name attribute="“value”"> <br> </jsp:action_name></p> <p style="line-height: 2em;"> <jsp:action_name attribute="“value”"> <br> </jsp:action_name></p> <p style="line-height: 2em;"><strong>JSP 元素说明</strong><br><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="line-height: 2em;">代码片段:包含任意量的 Java 语句、变量、方法或表达式;</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 声明:一个声明语句可以声明一个或多个变量、方法,供后面的 Java 代码使用;</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 表达式:输出 Java 表达式的值,String 形式;</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 注释:为代码作注释以及将某段代码注释掉</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 指令:用来设置与整个 JSP 页面相关的属性</p></li> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p style="line-height: 2em;"><%@ page="" ...="">定义页面的依赖属性,比如 language、contentType、errorPage、 isErrorPage、import、isThreadSafe、session 等等</p></li> <li><p style="line-height: 2em;"><%@ include="" ...="">包含其他的 JSP 文件、HTML 文件或文本文件,是该 JSP 文件的一部分,会被同时编译执行</p></li> <li><p style="line-height: 2em;"><%@ taglib="" ...="">引入标签库的定义,可以是自定义标签</p><p style="line-height: 2em;"><br></p></li> </ul> <li><p style="line-height: 2em;">JSP 行为:jsp:include、jsp:useBean、jsp:setProperty、jsp:getProperty、jsp:forward</p></li> </ul> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;"><strong>Jsp 解析过程</strong></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="666" data-width="800" src="/upload/c59cb6785ded80bd8ea9ec8bbce4d8a4.other"> </figure> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">代码片段:在_jspService()方法内直接输出</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 声明: 在 servlet 类中进行输出</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 表达式:在_jspService()方法内直接输出</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 注释:直接忽略,不输出</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 指令:根据不同指令进行区分,include:对引入的文件进行解析;page 相关的属性会做为 JSP 的属性,影响的是解析和请求处理时的行为</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 行为:不同的行为有不同的处理方式,jsp:useBean 为例,会从 pageContext 根据 scope 的 类别获取 bean 对象,如果没有会创建 bean,同时存到相应 scope 的 pageContext 中</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">HTML:在_jspService()方法内直接输出</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">JSP 隐式对象:在_jspService()方法会进行声明,只能在方法中使用;</p></li> </ul> <h2 data-id="heading-3" style="line-height: 2em;"><br></h2> <h2 data-id="heading-3" style="line-height: 2em;"><br></h2> <h2 data-id="heading-3" style="line-height: 2em;"><strong><span style="color: rgb(57, 137, 31);">Connector</span></strong></h2> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="729" data-width="800" src="/upload/393ddb4a379c12ab5270fa9518a410e7.other"> </figure> <p style="line-height: 2em;"><strong>Http:</strong>HTTP 是超文本传输协议,是客户端浏览器或其他程序与 Web 服务器之间的应用层通信协 议</p> <p style="line-height: 2em;"><br><strong>AJP</strong>:Apache JServ 协议(AJP)是一种二进制协议,专门代理从 Web 服务器到位于后端的应用 程序服务器的入站请求<br><strong><br></strong></p> <p style="line-height: 2em;"><strong><br></strong></p> <p style="line-height: 2em;"><strong>阻塞 IO</strong></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="674" data-width="800" src="/upload/ae83bebdbc70f7cec052107c26e7a1c2.other"> </figure> <p><br></p> <p><br></p> <p><strong>非阻塞 IO</strong></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="674" data-width="800" src="/upload/f86c2e7b83da6a5de21e11aca556e36a.other"> </figure> <p><br></p> <p><br></p> <p><strong> IO多路复用</strong></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="683" data-width="800" src="/upload/40c1bf504af07c6b3a4d2cfaeff1cc9a.other"> </figure> <p><br></p> <p style="line-height: 2em;">阻塞与非阻塞的区别在于进行读操作和写操作的系统调用时,如果此时内核态没有数据可读或者没有缓冲空间可写时,是否阻塞。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">IO多路复用的好处在于可同时监听多个socket的可读和可写事件,这样就能使得应用可以同时监听多个socket,释放了应用线程资源。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;"><strong>Tomcat各类Connector对比</strong></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="1280" data-width="800" src="/upload/831c01601ca8612e8a345bd23b1c60e4.other"> </figure> <p><br></p> <p style="line-height: 2em;">Connector的实现模式有三种,分别是BIO、NIO、APR,可以在server.xml中指定。</p> <p><br></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;"><strong>JIO</strong>:用java.io编写的TCP模块,阻塞IO</p></li> <li><p style="line-height: 2em;"><strong>NIO</strong>:用java.nio编写的TCP模块,非阻塞IO,(IO多路复用)</p></li> <li><p style="line-height: 2em;"><strong>APR</strong>:全称Apache Portable Runtime,使用JNI的方式来进行读取文件以及进行网络传输</p></li> </ul> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">Apache Portable Runtime是一个高度可移植的库,它是Apache HTTP Server 2.x的核心。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">APR具有许多用途,包括访问高级IO功能(如sendfile,epoll和OpenSSL),操作系统级功能(随机数生成,系统状态等)和本地进程处理(共享内存,NT管道和Unix套接字)</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">表格中字段含义说明:</p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;"><strong>Support Polling</strong>:是否支持基于IO多路复用的socket事件轮询</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Polling Size</strong>:轮询的最大连接数</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Wait for next Request</strong>:在等待下一个请求时,处理线程是否释放,BIO是没有释放的,所以在keep-alive=true的情况下处理的并发连接数有限</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Read Request Headers</strong>:由于request header数据较少,可以由容器提前解析完毕,不需要阻塞</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Read Request Body</strong>:读取request body的数据是应用业务逻辑的事情,同时Servlet的限制,是需要阻塞读取的</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Write Response</strong>:跟读取request body的逻辑类似,同样需要阻塞写</p></li> </ul> <p style="line-height: 2em;"><strong><br></strong></p> <p style="line-height: 2em;"><strong><br></strong></p> <p style="line-height: 2em;"><strong>NIO处理相关类</strong></p> <p><br></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="1182" data-width="800" src="/upload/8e9ebd445997da86c7e502a2885b3591.other"> </figure> <p><br></p> <p style="line-height: 2em;">Acceptor线程负责接收连接,调用accept方法阻塞接收建立的连接,并对socket进行封装成PollerEvent,指定注册的事件为op_read,并放入到EventQueue队列中,PollerEvent的run方法逻辑的是将Selector注册到socket的指定事件;</p> <p><br></p> <p style="line-height: 2em;">Poller线程从EventQueue获取PollerEvent,并执行PollerEvent的run方法,调用Selector的select方法,如果有可读的Socket则创建Http11NioProcessor,放入到线程池中执行</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">CoyoteAdapter是Connector到Container的适配器,Http11NioProcessor调用其提供的service方法,内部创建Request和Response对象,并调用最顶层容器的Pipeline中的第一个Valve的invoke方法</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">Mapper主要处理http url 到servlet的映射规则的解析,对外提供map方法</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;"><strong>NIO Connector主要参数</strong></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="1280" data-width="800" src="/upload/4ff8b37cea414979107a61ef16be82c3.other"> </figure> <p><br></p> <p><br></p> <h2 data-id="heading-4" style="line-height: 2em;"><strong><span style="color: rgb(57, 137, 31);">Comet</span></strong></h2> <p style="line-height: 2em;">Comet是一种用于web的推送技术,能使服务器实时地将更新的信息传送到客户端,而无须客户端发出请求</p> <p style="line-height: 2em;"><br>在WebSocket出来之前,如果不适用comet,只能通过浏览器端轮询Server来模拟实现服务器端推送。</p> <p style="line-height: 2em;"><br>Comet支持servlet异步处理IO,当连接上数据可读时触发事件,并异步写数据(阻塞)</p> <figure> <img class="" data-ratio="0.6666666666666666" data-type="jpeg" data-w="2360" src="/upload/d2352f9c7f57e316e164790eabeed863.jpg"> </figure> <p><br></p> <p style="line-height: 2em;">Tomcat要实现Comet,只需继承HttpServlet同时,实现CometProcessor接口</p> <p style="line-height: 2em;"><br></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;"><strong>Begin</strong>:新的请求连接接入调用,可进行与Request和Response相关的对象初始化操作,并保存response对象,用于后续写入数据</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Read</strong>:请求连接有数据可读时调用</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>End</strong>:当数据可用时,如果读取到文件结束或者response被关闭时则被调用</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Error</strong>:在连接上发生异常时调用,数据读取异常、连接断开、处理异常、socket超时</p><p style="line-height: 2em;"><br></p></li> </ul> <p style="line-height: 2em;"><strong><span style="color: rgb(201, 56, 28);">Note:</span></strong></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;"><strong>Read</strong>:在post请求有数据,但在begin事件中没有处理,则会调用read,如果read没有读取数据,在会触发Error回调,关闭socket</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>End</strong>:当socket超时,并且response被关闭时也会调用;server被关闭时调用</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;"><strong>Error</strong>:除了socket超时不会关闭socket,其他都会关闭socket</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">End和Error时间触发时应关闭当前comet会话,即调用CometEvent的close方法</p><p style="line-height: 2em;"><br></p><p style="line-height: 2em;">Note:在事件触发时要做好线程安全的操作</p></li> </ul> <h2 data-id="heading-5"><br></h2> <p><br></p> <h2 data-id="heading-5" style="line-height: 2em;"><strong><span style="color: rgb(57, 137, 31);">异步Servlet</span></strong></h2> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="600" data-width="800" src="/upload/eecf6031ee0542fe9c3a8eb7c623fa58.other"> </figure> <p style="line-height: 2em;">传统流程:</p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">首先,Servlet 接收到请求之后,request数据解析;</p></li> <li><p style="line-height: 2em;">接着,调用业务接口的某些方法,以完成业务处理;</p></li> <li><p style="line-height: 2em;">最后,根据处理的结果提交响应,Servlet 线程结束</p></li> </ul> <p><br></p> <figure> <img class="lazyload inited loaded" data-height="600" data-ratio="0.6666666666666666" data-type="other" data-w="668" data-width="800" src="/upload/e07949cea8afccda22a182b6cd04eebb.other"> </figure> <p style="line-height: 2em;">异步处理流程:<br></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">客户端发送一个请求</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">Servlet容器分配一个线程来处理容器中的一个servlet</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">servlet调用request.startAsync(),保存AsyncContext, 然后返回</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">任何方式存在的容器线程都将退出,但是response仍然保持开放</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">业务线程使用保存的AsyncContext来完成响应(线程池)</p><p style="line-height: 2em;"><br></p></li> <li><p style="line-height: 2em;">客户端收到响应</p></li> </ul> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">Servlet 线程将请求转交给一个异步线程来执行业务处理,线程本身返回至容器,此时 Servlet 还没有生成响应数据,异步线程处理完业务以后,可以直接生成响应数据(异步线程拥有 ServletRequest 和 ServletResponse 对象的引用)</p> <p style="line-height: 2em;"><strong><br></strong></p> <p style="line-height: 2em;"><strong>为什么web应用中支持异步?</strong></p> <p style="line-height: 2em;">推出异步,主要是针对那些比较耗时的请求:比如一次缓慢的数据库查询,一次外部REST API调用, 或者是其他一些I/O密集型操作。这种耗时的请求会很快的耗光Servlet容器的线程池,继而影响可扩展性。</p> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">Note:从客户端的角度来看,request仍然像任何其他的HTTP的request-response交互一样,只是耗费了更长的时间而已</p> <p style="line-height: 2em;"><strong><br></strong></p> <p style="line-height: 2em;"><strong>异步事件监听</strong></p> <ul class=" list-paddingleft-2" style=""> <li><p style="line-height: 2em;">onStartAsync:Request调用startAsync方法时触发</p></li> <li><p style="line-height: 2em;">onComplete:syncContext调用complete方法时触发</p></li> <li><p style="line-height: 2em;">onError:处理请求的过程出现异常时触发</p></li> <li><p style="line-height: 2em;">onTimeout:socket超时触发</p></li> </ul> <p style="line-height: 2em;"><br></p> <p style="line-height: 2em;">Note :<br>onError/ onTimeout触发后,会紧接着回调onComplete<br>onComplete 执行后,就不可再操作request和response</p> <p><br></p> <p style="white-space: normal;text-align: center;"><span style="color: rgb(57, 137, 31);font-size: 24px;"><strong>END</strong></span></p> <p style="white-space: normal;letter-spacing: 0.544px;line-height: 2em;text-align: center;"><span style="font-size: 14px;">长按下图二维码,即刻关注【<span style="color: rgb(241, 136, 35);"><strong>狸猫技术窝</strong></span>】</span></p> <p style="white-space: normal;letter-spacing: 0.544px;line-height: 2em;text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 14px;letter-spacing: 0.544px;">阿里、京东、美团、字节跳动</span><br></p> <p style="white-space: normal;letter-spacing: 0.544px;line-height: 2em;text-align: center;"><span style="font-size: 14px;"><strong><span style="font-size: 13px;color: rgb(0, 0, 0);">顶尖技术专家</span></strong><span style="font-size: 13px;color: rgb(0, 0, 0);">坐镇</span></span></p> <p style="white-space: normal;letter-spacing: 0.544px;line-height: 2em;text-align: center;"><span style="color: rgb(0, 0, 0);font-size: 14px;">为IT人打造一个 “有温度” 的技术窝!</span></p> <section class="KolEditor" data-tools-id="69164" style="white-space: normal;"> <section style="margin-top: 20px;"> <section style="margin-right: auto;margin-left: auto;background-image: url(https://mmbiz.qpic.cn/mmbiz_gif/vnOqylzBGCSwjFsfNvrwxsRkgjr6jVfOHXUSyNIpYXY62BsG3zqZ8S3VEgqu9Ulib1Tdvqibcic8kag4XoVoygzew/640?wx_fmt=gif);background-repeat: no-repeat;width: 240px;background-size: 100%;text-align: center;"> <section class="" style="margin-right: auto;margin-left: auto;padding-top: 8px;padding-bottom: 20px;padding-left: 90px;width: 210px;"> <img class="" data-copyright="0" data-cropselx1="0" data-cropselx2="120" data-cropsely1="0" data-cropsely2="120" data-ratio="0.6666666666666666" data-type="jpeg" data-w="258" src="/upload/578288c965b89f74b583291d3fc98c86.jpg" style="height: 120px;width: 120px;"> </section> </section> </section> </section> <p><br></p>
作者:微信小助手
<section class="xmteditor" style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn"></section> <section class="xmteditor" style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn"></section> <section class="" data-tools="135编辑器" data-id="91525"> <section style="margin: 8px;padding: 10px;max-width: 100%;box-sizing: border-box;word-wrap: break-word !important;line-height: 25.6px;border-radius: 10px;height: auto;box-shadow: rgb(221, 221, 221) 2px 2px 8px;display: -webkit-flex;"> <section style="max-width: 100%;flex: 0 0 2cm;height: 78px;width: 75px;box-sizing: border-box !important;word-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="" data-copyright="0" data-cropselx1="0" data-cropselx2="76" data-cropsely1="0" data-cropsely2="76" data-ratio="1" src="/upload/9816e4ca9d7f3628b8e2432c5f8a0fb7.jpg" data-type="jpeg" data-w="400" style="letter-spacing: 0.544px;line-height: 25.6px;text-align: justify;color: rgb(62, 62, 62);border-radius: 3em;height: 76px;box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: 76px;"></p> </section> <section style="padding-right: 10px;padding-left: 10px;max-width: 100%;box-sizing: border-box;flex: 1 1 auto;height: 55px;word-wrap: break-word !important;"> <section style="max-width: 100%;line-height: 35px;white-space: nowrap;box-sizing: border-box !important;word-wrap: break-word !important;"> <span style="max-width: 100%;font-family: 宋体, SimSun;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(31, 73, 125);box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="">程序员大咖</strong></span></strong></span> <span style="max-width: 100%;font-family: 黑体, SimHei;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(31, 73, 125);box-sizing: border-box !important;word-wrap: break-word !important;"></span></strong><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(31, 73, 125);box-sizing: border-box !important;word-wrap: break-word !important;"></span></strong><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(31, 73, 125);box-sizing: border-box !important;word-wrap: break-word !important;"></span></strong></span> </section> <section style="max-width: 100%;font-size: 13px;line-height: 20px;color: rgb(127, 127, 127);box-sizing: border-box !important;word-wrap: break-word !important;"> <span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(165, 165, 165);font-family: 黑体, SimHei;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="">点击右侧关注,免费进阶高级!</span></span> </section> </section> <section style="max-width: 100%;flex: 0 0 1.5cm;font-size: 15px;color: rgb(86, 187, 55);letter-spacing: 0px;text-align: center;line-height: 6;box-sizing: border-box !important;word-wrap: break-word !important;"> <section style="margin-top: 25px;max-width: 100px;vertical-align: middle;overflow: hidden;box-sizing: border-box !important;word-wrap: break-word !important;"> <section style="max-width: 100%;width: 55px;height: 30px;box-sizing: border-box !important;word-wrap: break-word !important;background-image: url(https://mmbiz.qpic.cn/mmbiz_gif/S7SAuLQzeTVj0YaoibbZqxicYkQrLnR3WtTQlHpHouqUmibjUCY9F5wpG0DmyMetZy9pjDdiabWo4XXdtCib3VcnI7w/640?wx_fmt=gif);background-size: 100% 100%;background-repeat: no-repeat;"> <section style="max-width: 100%;opacity: 0;box-sizing: border-box !important;word-wrap: break-word !important;"> <a href="https://mp.weixin.qq.com/s?__biz=MzAxMzQ3NzQ3Nw==&mid=2654251628&idx=6&sn=3f3e44c1d450a8953420db746c350403&scene=21#wechat_redirect" target="_blank"><span class="js_jump_icon h5_image_link" data-positionback="static" style="top: auto;left: auto;margin: 0px;right: auto;bottom: auto;"><img class="" data-copyright="0" data-cropselx1="0" data-cropselx2="55" data-cropsely1="0" data-cropsely2="63" data-ratio="1" src="/upload/1f180962c0d23c5df8c05ea79b5fb8f0.jpg" data-type="jpeg" data-w="258" style="margin: 0px;top: auto;left: auto;right: auto;bottom: auto;width: 63px;height: 63px;box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;" title="1081255447.jpg"></span></a> </section> </section> </section> </section> </section> </section> <p><br></p> <blockquote style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: justify;background-color: rgb(255, 255, 255);box-sizing: border-box !important;word-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 10px;color: rgb(136, 136, 136);">转自:李学凯</span></p> <p style="font-size: 17px;max-width: 100%;min-height: 1em;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 10px;color: rgb(136, 136, 136);box-sizing: border-box !important;word-wrap: break-word !important;">blog.csdn.net/qq_27093465/article/details/52918873</span></p> </blockquote> <p style="white-space: normal;"><br></p> <section data-role="outer" label="Powered by 135editor.com" style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section class="" data-tools="135编辑器" data-id="91525" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word;line-height: 27.2px;letter-spacing: 0.544px;min-height: 0px;font-size: 15px;background-image: none;background-clip: border-box;background-size: auto;border-width: 0px;border-style: none;border-color: rgb(51, 51, 51);bottom: auto;height: auto;left: auto;max-height: none;min-width: 0px;top: auto;z-index: auto;visibility: visible;background-position: 0% 0%;background-repeat: repeat;">刚刚使用IntelliJ IDEA 编辑器的时候,会有很多设置,会方便以后的开发,磨刀不误砍柴工。</span> </section> </section> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;color: rgb(171, 25, 66);box-sizing: border-box !important;overflow-wrap: break-word !important;">比如:设置文件字体大小,代码自动完成提示,版本管理,本地代码历史,自动导入包,修改注释,修改tab的显示的数量和行数,打开项目方式,等等一大堆东西。</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">总结一下,免得下次换了系统,还得再找一遍配置。</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(249, 3, 21);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">设置外观和字体大小</strong></span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <section data-mpa-template="t" class="" mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img class="" data-ratio="0.43989547038327526" data-type="png" data-w="1148" width="100%" src="/upload/bc359cab50e5cc4de63a10e11cc2f471.null" style="box-shadow: none;border-width: 0px;border-style: solid;border-color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"> </section> </section> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">这个呢是设置一下外观。和字体大小。放在第一个没问题。</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(249, 3, 21);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">设置编辑器的快捷键,也就是keymap</strong></span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <section data-mpa-template="t" class="" mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img class="" data-ratio="0.5687568756875687" data-type="png" data-w="909" width="100%" src="/upload/79cb7348f67c5e48f0ac589716c3768a.null" style="box-shadow: none;border-width: 0px;border-style: solid;border-color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"> </section> </section> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">这个是修改咱习惯的快捷键映射表,因为我是从eclipse转来的,估计大部分都和我差不多啦,那就可以在这配置成eclipse的快捷键映射表,那么就没有必要再去记一套快捷键映射了,比如我们常用的删除一行 Ctrl d,复制一行Ctrl + alt + 下方向。注释一行,Ctrl + / 这都是我们常用的。也是我们习惯的,这个也是极好的设置啊。点击</span><a href="http://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247484370&idx=1&sn=8a091d43b1af8cae35256be22ff44193&chksm=eb5386e4dc240ff2834261929d96402822a29919a8a2098063ccb74513296d13f05e768ea496&scene=21#wechat_redirect" target="_blank" style="color: rgb(0, 0, 0);text-decoration: underline;max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">这里</a><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">查看Intellij IDEA非常6的十个姿势!<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">我图上就是把eclipse的键盘映射复制一下,然后重命名一下,因为还是有些快捷键修改下,用着比较好。</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(249, 3, 21);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">关于整个项目的文件目录的说明</strong></span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">快捷键简单搞定 之后,再熟悉一下,下面这个图。</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <section data-mpa-template="t" class="" mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img class="" data-ratio="0.621550591327201" data-type="png" data-w="761" width="100%" src="/upload/dcdec3334bb88971bd8a8897b5fcb1bb.null" style="box-shadow: none;border-width: 0px;border-style: solid;border-color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"> </section> </section> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;letter-spacing: 0px;box-sizing: border-box !important;overflow-wrap: break-word !important;">这个也是通用结构,我箭头所指的地方有三个按钮,<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">第一个,点击之后,就会在左侧的文件一栏里,定位到你当前打开的文件的位置,找文件,定位文件位置用的非常多。</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">第二个,合并所有目录,这个在你打开太多目录的时候,一点击之后,就会把目录全部折叠起来。</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">第三个,点了之后,就看到上面的那个弹出框。这个有点特殊,建议,红框里面的设置的跟我的一样,比较好,这样的话你在左侧,查看项目目录结构的时候,就不会觉得奇怪。至于为什么会觉得奇怪,你可以先把这2个都点上之后,看看你的目录是什么情况,就知道我说的是啥啦,</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">这样子配置,可以很清楚的看到目录的层级结构。但是你要是点了,他就会把空的包直接连在一起,就是com.lxk.aop。。。。等等吧,试一下就知道啦。</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: justify;line-height: 27.2px;widows: 1;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">这个也是很有必要说明一下的。</span></p> <p mpa-paragraph-type="body" style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans
作者:じ☆ve宝贝
## 使用Java 反射机制 1.获取指定类对应的Class对象: getClass()方法、forName()静态方法、类名.class获取对象class对象 2.获取类的全限定名: getName()例子结果:cn.studyjava.reflect.User,如果为user内的类结果为 cn.studyjava.reflect.User$A getSimpleName()例子结果:User getCanonicalName()例子结果:cn.studyjava.reflect.User 3.获取类的包名 getPackage() 4.获取类的修饰符 Modifier.toString(method.getModifiers());//获取修饰符 5.获取类的父类 getSuperclass() 6.获取类实现的接口 getInterfaces() 7.获取类的成员变量 Field[] getFields()//获得成员变量名 Field[] getDeclaredFields()//得到子类和父类中公开的成员变量 Field getField("age")//得到自己的声明的所有成员变量 Field getDeclaredField("age") 8.获取类的构造方法 getConstructors()//返回子类父类所有公共构造方法 getDeclaredConstructors()//返回当前声明类的公公构造方法 getDeclaredConstructor(Class... parameterTypes) //返回对象表示类的构造方法 9.获取类的成员方法 Method[] getMethods()//获得父类和子类中的所有共开方法 Method[] getDeclaredMethods()//获得该类所有的方法 Method getMethod("getAge")//获得指定的方法 Method getDeclaredMethod("getAge")
作者:微信小助手
<p style="white-space: normal;background-color: rgb(255, 255, 255);text-align: center;letter-spacing: 1px;line-height: 1.5em;overflow-wrap: break-word !important;" data-mpa-powered-by="yiban.io"><span style="font-size: 15px;"><span style="color: rgb(136, 136, 136);border-width: 0px;border-style: initial;border-color: initial;font-style: inherit;font-variant: inherit;font-weight: inherit;font-stretch: inherit;line-height: inherit;font-family: PingFangSC-Regular;vertical-align: baseline;overflow-wrap: break-word !important;">点击上方</span><span style="border-width: 0px;border-style: initial;border-color: initial;font-style: inherit;font-variant: inherit;font-weight: inherit;font-stretch: inherit;line-height: inherit;font-family: PingFangSC-Regular;vertical-align: baseline;color: rgb(61, 170, 214);overflow-wrap: break-word !important;"><strong>"</strong><strong>蓝字", </strong></span><span style="border-width: 0px;border-style: initial;border-color: initial;font-style: inherit;font-variant: inherit;font-weight: inherit;font-stretch: inherit;line-height: inherit;font-family: PingFangSC-Regular;vertical-align: baseline;color: rgb(136, 136, 136);overflow-wrap: break-word !important;">右上角</span><span style="color: rgb(136, 136, 136);border-width: 0px;border-style: initial;border-color: initial;font-style: inherit;font-variant: inherit;font-weight: inherit;font-stretch: inherit;line-height: inherit;font-family: PingFangSC-Regular;vertical-align: baseline;overflow-wrap: break-word !important;">选择“设为星标”</span></span></p> <p style="white-space: normal;background-color: rgb(255, 255, 255);text-align: center;letter-spacing: 1px;line-height: 1.5em;overflow-wrap: break-word !important;"><span style="border-width: 0px;border-style: initial;border-color: initial;font-style: inherit;color: rgb(136, 136, 136);font-variant: inherit;font-weight: inherit;font-stretch: inherit;line-height: inherit;font-family: PingFangSC-Regular;vertical-align: baseline;font-size: 15px;overflow-wrap: break-word !important;"> 周一至周五早8点半!精品技术文章准时送上!</span></p> <section class="KolEditor" data-tools-id="47339" style="white-space: normal;"> <section data-width="100%" style="width: 556px;text-align: center;"> <section style="margin-right: auto;margin-left: auto;display: inline-block;height: 30px;word-break: normal !important;"> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.6666666666666666" data-s="300,640" data-type="jpeg" data-w="1280" src="/upload/6657ba148b18be651d581593076c298e.jpg" style=""></p> <section class="KolEditor"> <section class="领库brush layout" style="padding: 1.5em;margin: 10px auto;background: #fff;-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 60px rgba(0, 0, 0, 0.1) inset;-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 40px rgba(0, 0, 0, 0.1) inset;box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 40px rgba(0, 0, 0, 0.1) inset;"> <p style="white-space: normal;text-align: center;line-height: 3em;"><strong>目录:</strong></p> <ol class=" list-paddingleft-2" style=""> <li><p style="text-align: left;line-height: 2em;"><span style="font-size: 14px;">面试官为啥要出这样一个开放式问题</span></p></li> <li><p style="text-align: left;line-height: 2em;"><span style="font-size: 14px;">生产消费模型及核心数据结构</span></p></li> <li><p style="line-height: 2em;text-align: left;"><span style="font-size: 14px;">支撑TB级数据写入的分布式架构</span></p></li> <li><p style="line-height: 2em;text-align: left;"><span style="font-size: 14px;">数据宕机场景下的高可用架构</span></p></li> <li><p style="line-height: 2em;text-align: left;"><span style="font-size: 14px;">支持数据不丢失的ack机制</span></p></li> <li><p style="line-height: 2em;text-align: left;"><span style="font-size: 14px;">最后的总结</span></p></li> </ol> </section> </section> <p style="border-width: 0px;border-style: initial;border-color: initial;background-image: -webkit-linear-gradient(left, rgb(17, 67, 87), rgb(242, 148, 146), rgb(17, 67, 87));background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;-webkit-background-clip: text;-webkit-text-fill-color: transparent;word-break: normal !important;"><span style="font-size: 18px;word-break: normal !important;"><strong><span style="color: rgb(110, 191, 248);font-size: 14px;"> </span></strong></span></p> </section> </section> </section> <p style="white-space: normal;"><br></p> <section class="KolEditor"> <section style="margin-top: 10px;margin-bottom: 10px;"> <span style="font-size: 18px;color: rgb(255, 255, 255);"><strong style="color:inherit;"><span style="border-radius: 0px 50px 50px 0px;padding: 5px 15px 5px 10px;background-color: rgb(89, 155, 171);font-size: 15px;font-weight: 700;">1、面试官为啥要出这样一个开放式问题</span></strong></span> </section> </section> <p><br></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">这篇文章简单给大家来聊一个互联网大厂的Java面试题:<span style="font-size: 15px;color: rgb(64, 179, 230);">如果让你设计一个消息中间件,你会怎么做?</span></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">其实这个问题之前大致给大家聊过,本质就是面试官在考察一个高级以上的Java工程师的系统设计能力。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">给你一个平时大家都常用的一个消息中间件作为命题,让你现场开放式发挥,立马开动脑筋说说如果让你来设计这么一个消息中间件。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">让你从整体架构,核心流程,数据结构,等各个层面来考虑,你会如何完成这个设计?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">其实任何一个面试官都应该知道,如果一个人没有真的做过消息中间件开发的话,是不太可能在短时间内,瞬间给出一套特别靠谱的架构设计方案的。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">但是用这个题目作为一个开放式命题,他最大的好处,就是可以尽可能的挖掘出一个候选人的较为真实的系统设计的能力和功底。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">为什么这么说呢?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">因为如果面试的时候很多东西都是一些常见的技术问题,比如说:</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">消息中间件如何保证数据不丢失?</span></p></li> <li><p style="line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">聊聊Elasticsearch的架构原理以及性能优化?</span></p></li> <li><p style="line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">你们公司的微服务架构整体如何设计的?</span></p></li> </ul> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">这些问题相对来说都是比较固定的一些问题。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">所谓固定的问题,就是只要你花费一些时间去学习了相关的技术,或者是在自己所在的公司确实有过一些落地的经验,通常来说回答出这些问题就不是太大的问题了。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">但是这些问题都不够开放,如果两个候选人都同样具备常规问题的回答能力,那么此时通过一道有深度的开放式问题,就可以把几个人里迅速拉开差距,找出来到底谁的技术功底更加深厚,谁的架构设计能力更加强。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">那么本文就从各个角度来引导大家去思考一下,假如让你回答这个问题,你可以从哪些方面入手来现场做一些考虑和回答?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="line-height: 2em;margin-left: 8px;margin-right: 8px;"><span style="font-size: 15px;"><br></span></p> <p style="line-height: 2em;"><br></p> <section class="KolEditor"> <section style="margin-top: 10px;margin-bottom: 10px;"> <span style="font-size: 18px;color: rgb(255, 255, 255);"><strong style="color:inherit;"><span style="border-radius: 0px 50px 50px 0px;padding: 5px 15px 5px 10px;background-color: rgb(89, 155, 171);font-size: 15px;font-weight: 700;">2、生产消费模型以及核心数据结构</span></strong></span> </section> </section> <p><br></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">首先第一个点,消息中间件本身要做的就是可以允许有人来生产消息,还可以允许有人来消费这个消息。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">那么这里要考虑的第一个点,就是消息中间件自己本身的核心数据结构。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">也就是说,<span style="letter-spacing: 2px;font-size: 15px;color: rgb(64, 179, 230);">如果有人生产了消息,你作为一个消息中间件,应该如何存储这个数据?</span></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">你会存储在内存里呢?还是存储在磁盘文件里呢?或者两者都同时共存?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">可以先允许数据写入内存作为一个缓冲,然后每隔几秒再把数据刷入磁盘文件中?数据刷入磁盘文件之后,这个磁盘文件有多少个?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">你总不能一直搞一个磁盘文件来存放所有的数据吧?那么按照什么样的规则对磁盘文件做一个拆分?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">数据写入磁盘文件之后,是不是要有相应的一些metadata来标识这个数据的具体信息?比如这个数据的offset偏移量,或者是一个内置的唯一id?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">接着现在数据是被存储在磁盘文件里了,那么此时你如何把数据投递到下游的消费者里去呢?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">你的消费模型是什么样的?比如说一个queue里的数据,是会均匀分配给消费者的各个实例呢?还是会怎么做呢?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">在这里给大家做一个提示,建议大家可以去研究研究比如kafka底层的文件存储原理,那是非常经典的高性能高并发消息中间件存储架构的实现。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">另外就是可以参考一下rabbitmq和kafka的官网,研究一下不同中间件的消费模型是怎么做的。</span></p> <p style="line-height: 2em;"><span style="font-size: 15px;"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="528" src="/upload/80117bb5e46201d72dc06403b2e2dfd7.png"></span></p> <p style="line-height: 2em;"><span style="font-size: 15px;"><br></span></p> <p style="line-height: 2em;"><span style="font-size: 15px;"><br></span></p> <p style="line-height: 2em;"><br></p> <section class="KolEditor"> <section style="margin-top: 10px;margin-bottom: 10px;"> <span style="font-size: 18px;color: rgb(255, 255, 255);"><strong style="color:inherit;"><span style="border-radius: 0px 50px 50px 0px;padding: 5px 15px 5px 10px;background-color: rgb(89, 155, 171);font-size: 15px;font-weight: 700;">3、支撑TB级数据写入的分布式架构</span></strong></span> </section> </section> <p><br></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">接着你应该考虑第二个大的问题,就是你的消息中间件肯定会遇到每天TB级海量数据高并发高吞吐写入的场景。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;color: rgb(64, 179, 230);letter-spacing: 2px;">此时,你的消息中间件的架构如何支撑呢?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">所以这里你就要考虑一下,<strong>你的数据是不是要分布式的存储</strong>?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">比如说假如你一天写入几百TB的数据,那不可能都放在一台机器上吧?所以数据的分布式存储是不是你要考虑的另外一个很重要的问题?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">你是不是要考虑把一个大的数据集合做分片存储,比如说分成N片数据,每个数据分片放在一台机器上,这样就可以充分利用多台机器的资源来承载TB级的大量数据了。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">此外你还需要考虑,你的数据分片是不是要可以支撑扩容?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">比如你一开始设置的分片数量是10个,存在10台机器上。结果现在发现10台机器都扛不住了,需要扩容到20个分片,放在20台机器上才可以。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">那你是不是要支持数据分片的扩容以及自动数据负载均衡迁移?也就是10个分片的数据自动均匀分配给扩容后的20个分片。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">所以这种分布式以及可伸缩的架构,是另外一个非常核心的点。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">我个人同样比较建议大家研究一下kafka在这块的架构设计,非常的优秀,</span><span style="letter-spacing: 2px;font-size: 15px;">采用了partition的概念实现数据分片,支持分布式的数据存储,而且还支持动态扩容。</span></p> <p style="line-height: 2em;"><span style="font-size: 15px;"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="546" src="/upload/f4fd47ca54a39c3ba60b59ab75a4bec3.png"></span></p> <p style="line-height: 2em;"><span style="font-weight: bold;font-size: 15px;"><br></span></p> <p style="line-height: 2em;"><br></p> <section class="KolEditor"> <section style="margin-top: 10px;margin-bottom: 10px;"> <span style="font-size: 18px;color: rgb(255, 255, 255);"><strong style="color:inherit;"><span style="border-radius: 0px 50px 50px 0px;padding: 5px 15px 5px 10px;background-color: rgb(89, 155, 171);font-size: 15px;font-weight: 700;">4、数据宕机场景下的高可用架构</span></strong></span> </section> </section> <p><br></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">大家此时就要考虑另外一个问题了,就是一旦数据分布式存储之后,那么每台机器上都有一部分数据。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;color: rgb(64, 179, 230);letter-spacing: 2px;">万一这台机器宕机了呢?那么数据是不是就丢失了?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">是的!所以高可用的架构在这里就必须考虑到了。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">一般分布式系统实现高可用架构,都是采用<span style="letter-spacing: 2px;font-size: 15px;color: rgb(201, 56, 28);"><strong>多副本冗余机制</strong></span></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">也就是说一份数据在多台机器上都搞一个副本,这样任何一台机器宕机了,数据肯定不会丢失,你还可以继续使用其他机器上的副本数据来支持生产和消费。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">同样建议大家,研究一下kafka的多副本冗余机制,他的每个partition数据分片都是有多个副本的,任何一台机器宕机,丢失一个数据分片,还有其他机器上的副本分片在,可以支持数据不丢失。</span></p> <p style="line-height: 2em;"><span style="font-size: 15px;"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="649" src="/upload/d80df5a597cf933a17390aa60a80c4e3.png"></span></p> <p style="line-height: 2em;"><span style="font-weight: bold;font-size: 15px;"><br></span></p> <p style="line-height: 2em;"><br></p> <section class="KolEditor"> <section style="margin-top: 10px;margin-bottom: 10px;"> <span style="font-size: 18px;color: rgb(255, 255, 255);"><strong style="color:inherit;"><span style="border-radius: 0px 50px 50px 0px;padding: 5px 15px 5px 10px;background-color: rgb(89, 155, 171);font-size: 15px;font-weight: 700;">5、支持数据不丢失的ack机制</span></strong></span> </section> </section> <p><br></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">最后再考虑一个问题,你的消息中间件肯定是要支持数据绝对不丢失的吧?</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">那么你必须要支持生产端和消费端的ack机制,这块内容我们之前都用多篇文章讲解过里面的具体的原理,大家可以参考一下:</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484350&idx=1&sn=a0c52e23bea19f8b973d5deec604a693&chksm=fba6ebbdccd162ab3e8c88e34803e31c85ccc1d1218ae87345155ceff0999815a9870033d78b&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2"><span style="color: rgb(0, 112, 192);font-size: 15px;text-decoration: underline;letter-spacing: normal;">互联网面试必杀:如何保证消息中间件全链路数据100%不丢失(上)</span></a></p></li> <li><p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484362&idx=1&sn=a34f070b9020d4803615fa6d7da15d93&chksm=fba6ebc9ccd162df440ad1f463ded513967beec08a92d85666a585e3810ea178e18fe0c15435&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2"><span style="color: rgb(0, 112, 192);font-size: 15px;text-decoration: underline;letter-spacing: normal;">互联网面试必杀:如何保证消息中间件全链路数据100%不丢失(下)</span></a></p></li> </ul> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">在这里你必须考虑两块ack机制,一个是生产端,一旦投递了消息,必须要求他将数据比如写入多个副本之后,才返回一个ack回调响应。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">否则要是一直没收到ack的话,就需要重发一条消息过去,保证生产投递成功。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">另外一个是消费端,一旦消费处理成功一条消息了,必须返回一个ack给消息中间件,然后消息中间件才能删除这条消息。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">否则一旦消费者宕机,就必须重发这条消息给其他的消费者实例,保证消息一定会被处理成功。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">这块如果大家不清楚,建议一定重看之前的系列文章,我们基于rabbitmq来阐述的这个数据不丢失的全链路ack机制。</span></p> <p style="line-height: 2em;"><span style="font-size: 15px;"><img class="inline-img" data-ratio="0.6666666666666666" data-type="png" data-w="640" src="/upload/4fe1a5d17ada2aba35f3a51240cc2c32.png"></span></p> <p style="line-height: 2em;"><strong><span style="font-size: 15px;"><br></span></strong></p> <p style="line-height: 2em;"><br></p> <section class="KolEditor"> <section style="margin-top: 10px;margin-bottom: 10px;"> <span style="font-size: 18px;color: rgb(255, 255, 255);"><strong style="color:inherit;"><span style="font-size: 18px;border-radius: 0px 50px 50px 0px;padding: 5px 15px 5px 10px;background-color: rgb(89, 155, 171);"><strong style="white-space: normal;"><span style="font-size: 15px;">6、最后的总结</span></strong></span></strong></span> </section> </section> <p><br></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">这种开放式面试题,牵扯了大量的底层细节和架构思想,非常区分不同人的技术水平。如果你往简单了回答,就本文涉及到的一些东西简单说一说,基本也能过关。</span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;line-height: 2em;"><span style="font-size: 15px;letter-spacing: 2px;">但是如果你想技压群雄,就必须要根据本文每个部分提示的东西,真的去对各种MQ中间件的底层源码进行深入的研究,然后才能在回答这个问题的时候,展现出“碾压其他人”的技术功底和架构实力。</span></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;text-align: center;line-height: 2em;"><span style="font-size: 15px;">扫描下方二维码,回复:“<span style="font-size: 15px;color: rgb(201, 56, 28);"><strong>资料</strong></span>”, “<span style="font-size: 15px;color: rgb(110, 191, 248);">秘制</span>” 精品学习资料即可送达</span></p> <section class="KolEditor" style="white-space: normal;"> <section style="margin: 10px auto;padding-top: 40px;width: 200px;background-image: url(https://mmbiz.qpic.cn/mmbiz_png/1J6IbIcPCLYjibVZs24bM4o7e33V5Lt4qgShsQmIiciaIxuXvsq0L6RUNt60celLPEMAOI7PzGPkRNAzOicuINgOyw/640?wx_fmt=png);background-repeat: no-repeat;background-size: 100%;height: 206px;"> <p style="margin-right: auto;margin-left: auto;width: 120px;line-height: 2em;"><img class="KolImg" data-ratio="0.6666666666666666" data-type="jpeg" data-w="596" src="/upload/7e2499d89041ce1a2c66f3c5147d3ffa.jpg" style="vertical-align: bottom;width:auto !important;max-width:100% !important;height:auto !important;"></p> </section> </section> <p style="white-space: normal;"><br></p> <section class="KolEditor" style="white-space: normal;"> <section class="KolEditor"> <p style="margin: 10px auto;width: 84px;line-height: 2em;"><img class="" data-ratio="0.6666666666666666" data-type="gif" data-w="84" src="/upload/6a286db350525e28360841d498522434.gif"></p> </section> </section> <p style="white-space: normal;text-align: center;line-height: 2em;"><span style="color: rgb(241, 136, 35);font-size: 20px;"><strong>End</strong></span></p> <p style="white-space: normal;line-height: 2em;text-align: center;"><br></p> <section class="KolEditor checkSelected" data-tools-id="56033" style="white-space: normal;"> <section class="KolEditor"> <section style="margin-top: 20px;"> <section style="margin-top: 5px;height: 4px;background: rgb(248, 212, 151);"></section> <section style="margin-top: -24px;text-align: center;"> <section style="padding: 5px 10px;background: rgb(248, 212, 151);display: inline-block;"> <p class="white title" style="min-width: 1px;font-size: 18px;color: rgb(255, 255, 255);"><span style="color: rgb(255, 76, 65);"><strong>推荐阅读</strong></span></p> </section> </section> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484255&idx=1&sn=60425e65474a4f2d895e05447e48d59c&chksm=fba6eb5cccd1624a8988e90fc38a86c61b99e3eeb1e0f677d4c375547736109183828d8f0e9e&scene=21#wechat_redirect" target="_blank" data-linktype="2"><span style="font-size: 15px;text-decoration: underline;color: rgb(110, 191, 248);">精品专栏之微服务系列</span></a></p></li> <li><p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484255&idx=1&sn=60425e65474a4f2d895e05447e48d59c&chksm=fba6eb5cccd1624a8988e90fc38a86c61b99e3eeb1e0f677d4c375547736109183828d8f0e9e&scene=21#wechat_redirect" target="_blank" data-linktype="2"><span style="font-size: 15px;text-decoration: underline;color: rgb(110, 191, 248);">精品专栏之分布式系列</span></a></p></li> <li><p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484255&idx=1&sn=60425e65474a4f2d895e05447e48d59c&chksm=fba6eb5cccd1624a8988e90fc38a86c61b99e3eeb1e0f677d4c375547736109183828d8f0e9e&scene=21#wechat_redirect" target="_blank" data-linktype="2"><span style="font-size: 15px;text-decoration: underline;color: rgb(110, 191, 248);">精品专栏之亿级流量架构演进系列</span></a></p></li> <li><p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484255&idx=1&sn=60425e65474a4f2d895e05447e48d59c&chksm=fba6eb5cccd1624a8988e90fc38a86c61b99e3eeb1e0f677d4c375547736109183828d8f0e9e&scene=21#wechat_redirect" target="_blank" data-linktype="2"><span style="font-size: 15px;text-decoration: underline;color: rgb(110, 191, 248);">精品专栏之并发系列</span></a></p></li> <li><p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484255&idx=1&sn=60425e65474a4f2d895e05447e48d59c&chksm=fba6eb5cccd1624a8988e90fc38a86c61b99e3eeb1e0f677d4c375547736109183828d8f0e9e&scene=21#wechat_redirect" target="_blank" data-linktype="2"><span style="font-size: 15px;text-decoration: underline;color: rgb(110, 191, 248);">精品专栏之大数据系列</span></a></p></li> <li><p style="line-height: 2em;"><a href="http://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484419&idx=2&sn=09c9e0b6adcfde3bb6edfa30678005ae&chksm=fba6ec00ccd1651614cfb9912868e02381f43359439a4b0f1a5178e29173d15871df567bcdca&scene=21#wechat_redirect" target="_blank" data-linktype="2"><span style="font-size: 15px;text-decoration: underline;color: rgb(110, 191, 248);">精品专栏之Java进阶面试系列</span></a></p></li> </ul> <section style="margin-top: 10px;height: 4px;background: rgb(57, 207, 202);"></section> <section style="margin-top: 5px;height: 2px;background: rgb(248, 212, 151);"></section> </section> </section> <p style="vertical-align: baseline;letter-spacing: 1px;line-height: 1.5em;text-align: center;"><br></p> <p style="vertical-align: baseline;letter-spacing: 1px;line-height: 1.5em;text-align: center;"><strong><span style="font-size: 16px;"><span style="font-family: 宋体;">一大波</span><strong><span style="font-family: 宋体;">微服务、分布式、高并发、高可用</span></strong><span style="font-family: 宋体;">的</span><em><span style="font-family: 宋体;">原创系列</span></em><span style="font-family: 宋体;">文章正在路上。</span></span></strong></p> <p style="vertical-align: baseline;letter-spacing: 1px;line-height: 1.5em;"><br></p> <p style="vertical-align: baseline;letter-spacing: 1px;line-height: 1.5em;text-align: center;"><strong><span style="font-size: 16px;font-family: 宋体;"><span style="color: rgb(201, 56, 28);"><strong>欢迎扫描下方二维码</strong></span>,持续关注:</span></strong></p> <section class="KolEditor" data-tools-id="66348"> <section style="margin: 10px;display: flex;flex-direction: column;align-items: center;"> <section style="margin-bottom: -20px;padding: 8px;background: rgb(255, 255, 255);z-index: 4;"> <section class="KolEditor"> <section style="margin-top: 20px;"> <section style="margin-right: auto;margin-left: auto;background-image: url(https://mmbiz.qpic.cn/mmbiz_gif/1J6IbIcPCLYzapicOfUCIWp88Nib7dlgHDtCCKAEVAKI0cxmYTxOicyZJ6TsIPw1N4gJ4zU2szB8WjkUa3HfBbN6w/640?wx_fmt=gif);background-repeat: no-repeat;width: 240px;background-size: 100%;text-align: center;"> <section class="" style="margin-right: auto;margin-left: auto;padding-top: 32px;padding-bottom: 30px;width: 70px;"> <img class="" data-ratio="0.6666666666666666" data-type="jpeg" data-w="344" src="/upload/364e64b5ea4be7b9382dd0f8d4c10f86.jpg" style="width: 70px;"> </section> </section> </section> </section> <p><br></p> <p style="font-size: 15px;letter-spacing: 5px;color: rgb(59, 88, 49);text-align: center;"><strong style="letter-spacing: 1px;"><span style="font-style: inherit;font-variant-ligatures: inherit;font-variant-caps: inherit;-webkit-font-smoothing: antialiased;border-width: 0px;border-style: initial;border-color: initial;font-weight: bolder;font-stretch: inherit;vertical-align: baseline;user-select: text;color: rgba(13, 0, 19, 0.72);font-family: PingFangSC-Regular;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 23.324px;text-align: justify;widows: 1;font-size: 16px;">石杉的架构笔记(id:shishan100)</span></strong></p> <p style="font-size: 15px;letter-spacing: 5px;color: rgb(59, 88, 49);text-align: center;"><strong><span style="color: rgba(13, 0, 19, 0.72);font-family: PingFangSC-Regular;font-size: 14px;text-align: justify;widows: 1;-webkit-font-smoothing: antialiased;border-width: 0px;border-style: initial;border-color: initial;font-variant-numeric: normal;font-stretch: inherit;line-height: 23.324px;vertical-align: baseline;user-select: text;">十余年<span style="-webkit-font-smoothing: antialiased;font-variant: inherit;font-weight: inherit;font-stretch: inherit;line-height: inherit;vertical-align: baseline;user-select: text;color: rgb(247, 150, 70);">BAT架构经验</span>倾囊相授</span></strong></p> </section> </section> </section> <p><br></p> <p><br></p> <br> </section> <section class="KolEditor" style="white-space: normal;"> <section style="font-size: 16px;border-width: 0px;border-style: none;border-color: initial;"> <section style="margin-top: 0.5em;margin-bottom: 0.5em;"> <img class="" data-ratio="0.6666666666666666" data-type="png" data-w="640" src="/upload/2a91c95850337a2b69e8d27fe83c5285.null" style="width:auto !important;max-width:100% !important;height:auto !important;"> </section> </section> </section> <p><br></p>
作者:微信小助手
<p><br></p> <p style="text-align: center;"><img class="rich_pages" data-copyright="0" data-ratio="0.4255555555555556" data-s="300,640" src="/upload/b8ecd67cb4ab316dddd5d1dcaf98a95e.jpg" data-type="jpeg" data-w="900" style=""></p> <p style="margin-right: 8px;margin-bottom: 15px;margin-left: 8px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;white-space: normal;max-width: 100%;min-height: 1em;caret-color: rgb(51, 51, 51);text-size-adjust: auto;letter-spacing: 1px;text-align: right;line-height: normal;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">作者 | <span style="color: rgb(154, 154, 154);font-size: 14px;">安卓大叔</span></span><br></p> <p style="margin-right: 8px;margin-bottom: 15px;margin-left: 8px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;white-space: normal;max-width: 100%;min-height: 1em;caret-color: rgb(51, 51, 51);text-size-adjust: auto;letter-spacing: 1px;text-align: right;line-height: normal;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">来源 | <span style="color: rgb(154, 154, 154);font-size: 14px;">www.jianshu.com/u/1d933ff900e7</span></span></p> <p style="white-space: normal;font-variant-ligatures: normal;orphans: 2;widows: 2;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">小吴正在写红黑树的相关系列文章,不过内容太多,动画做起来比较慢,大家可以先看一下这篇红黑树的介绍,内容很不错。</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">本文将通过图文的方式讲解红黑树的知识点,并且不会涉及到任何代码,相信我,在懂得红黑树实现原理前,看代码会一头雾水的,当原理懂了,代码也就按部就班写而已,没任何难度。</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">阅读本文你需具备知识点:</span></p> <blockquote style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">二叉查找树</span></p> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">完美平衡二叉树</span></p> </blockquote> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">事不宜迟,让我们进入正题吧。</span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">红黑树也是二叉查找树,我们知道,二叉查找树这一数据结构并不难,而红黑树之所以难是难在它是自平衡的二叉查找树,在进行插入和删除等可能会破坏树的平衡的操作时,需要重新自处理达到平衡状态。现在在脑海想下怎么实现?是不是太多情景需要考虑了?啧啧,先别急,通过本文的学习后,你会觉得,其实也不过如此而已。好吧,我们先来看下红黑树的定义和一些基本性质。</span></p> <h3 style="margin-top: 1.5em;margin-right: 5px;margin-bottom: 2em;padding: 8px 15px;font-weight: bold;font-size: 1em;max-width: 100%;box-sizing: border-box;white-space: normal;color: rgb(255, 255, 255);line-height: inherit;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;text-align: start;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: inherit;line-height: inherit;font-size: 15px;overflow-wrap: break-word !important;">红黑树定义和性质</span></h3> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">红黑树是一种含有红黑结点并能自平衡的二叉查找树。它必须满足下面性质:<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <ul class=" list-paddingleft-2" style=""> <li><p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">性质1:每个节点要么是黑色,要么是红色。</span></p></li> <li><p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">性质2:根节点是黑色。</span></p></li> <li><p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">性质3:每个叶子节点(NIL)是黑色。</span></p></li> <li><p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">性质4:每个红色结点的两个子结点一定都是黑色。</span></p></li> <li><p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。</span></strong></span></p></li> </ul> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">从性质5又可以推出:</span></p> <ul class=" list-paddingleft-2" style=""> <li><p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">性质5.1:如果一个结点存在黑子结点,那么该结点肯定有两个子结点</span></p></li> </ul> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">图1就是一颗简单的红黑树。其中Nil为叶子结点,并且它是黑色的。(值得提醒注意的是,在Java中,叶子结点是为null的结点。)</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="" data-ratio="0.6615969581749049" src="/upload/8543d65260d458fc412dcfa4ddfede97.other" data-type="other" data-w="526" style="box-sizing: border-box !important;overflow-wrap: break-word !important;width: 526px !important;visibility: visible !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;line-height: normal;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">图1 一颗简单的红黑树<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">红黑树并不是一个完美平衡二叉查找树,从图1可以看到,根结点P的左子树显然比右子树高,但左子树和右子树的黑结点的层数是相等的,也即任意一个结点到到每个叶子结点的路径都包含数量相同的黑结点(性质5)。所以我们叫红黑树这种平衡为<strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">黑色完美平衡</strong>。</span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">介绍到此,为了后面讲解不至于混淆,我们还需要来约定下红黑树一些结点的叫法,如图2所示。</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="" data-ratio="0.6994818652849741" src="/upload/d09c40807bda6659aee200538c949f69.other" data-type="other" data-w="772" style="box-sizing: border-box !important;overflow-wrap: break-word !important;width: 677px !important;visibility: visible !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;line-height: normal;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">图2 结点叫法约定</span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">我们把正在处理(遍历)的结点叫做当前结点,如图2中的D,它的父亲叫做父结点,它的父亲的另外一个子结点叫做兄弟结点,父亲的父亲叫做祖父结点。</span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">前面讲到红黑树能自平衡,它靠的是什么?三种操作:左旋、右旋和变色。</span></p> <ul class=" list-paddingleft-2" style=""> <li><p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">左旋:</span></strong><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。如图3。</span></span></p></li> <li><p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">右旋:</span></strong><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。如图4。</span></span></p></li> <li><p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">变色:</span></strong><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">结点的颜色由红变黑或由黑变红。</span></span></p></li> </ul> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="" data-ratio="0.333" src="/upload/5222a1a299df8da67ad235a2d43ee75f.other" data-type="other" data-w="1000" style="box-sizing: border-box !important;overflow-wrap: break-word !important;width: 677px !important;visibility: visible !important;"></p> <p style="margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;line-height: normal;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">图3 左旋</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="" data-ratio="0.314" src="/upload/cc6d1bd6b635f21a44b6c84edb61d4e2.other" data-type="other" data-w="1000" style="box-sizing: border-box !important;overflow-wrap: break-word !important;width: 677px !important;visibility: visible !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;line-height: normal;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">图4 右旋</span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">上面所说的旋转结点也即旋转的支点,图4和图5中的P结点。</span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">我们先忽略颜色,可以看到旋转操作不会影响旋转结点的父结点,父结点以上的结构还是保持不变的。</span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">左旋</span></strong><span style="font-size: 15px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">只影响旋转结点和其<strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">右子树</strong>的结构,把右子树的结点往左子树挪了。</span></span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">右旋</strong>只影响旋转结点和其<strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">左子树</strong>的结构,把左子树的结点往右子树挪了。</span></p> <p style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">所以旋转�
作者:微信小助手
<section class="xmteditor" style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn"></section> <p style="text-align: center;"><strong style="max-width: 100%;letter-spacing: 0.544px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-size: 16px;white-space: pre-line;background-color: rgb(255, 255, 255);text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></strong></p> <p style="white-space: normal;text-align: center;"><span style="font-size: 14px;color: rgb(136, 136, 136);">点击蓝色“</span><span style="color: rgb(0, 128, 255);"><span style="font-size: 14px;">程序猿DD</span></span><span style="font-size: 14px;color: rgb(136, 136, 136);">”关注我哟</span></p> <p style="white-space: normal;text-align: center;"><span style="font-size: 14px;color: rgb(136, 136, 136);">加个“</span><span style="color: rgb(0, 128, 255);"><span style="font-size: 14px;">星标</span></span><span style="font-size: 14px;color: rgb(136, 136, 136);">”,不忘签到哦</span></p> <p><br></p> <p style="text-align: left;"><img class="" data-ratio="0.5983333333333334" src="/upload/a190ed5fc20937669b567a5894eeb82a.jpg" data-type="jpeg" data-w="600"></p> <p style="text-align: right;"><span style="color: rgb(136, 136, 136);font-family: -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", SimSun, sans-serif;font-size: 12px;letter-spacing: 0.16px;text-align: right;white-space: pre-line;background-color: rgb(255, 255, 255);">来源:SpringForAll社区</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 style="text-align: right;"><span style="color: rgb(136, 136, 136);font-family: -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", SimSun, sans-serif;font-size: 12px;letter-spacing: 0.16px;text-align: right;white-space: pre-line;background-color: rgb(255, 255, 255);"></span><br></p> <h2 style="margin-bottom: 1rem;font-size: 24px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;color: rgb(21, 153, 87);line-height: 1.35;text-align: start;overflow-wrap: break-word !important;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(0, 0, 0);overflow-wrap: break-word !important;">1.概述</strong></h2> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;text-size-adjust: auto;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;overflow-wrap: break-word !important;">当我们构建微服务解决方案时,SpringCloud和Kubernetes都是最佳解决方案,因为它们为解决最常见的挑战提供组件。但是,如果我们决定选择Kubernetes作为我们的解决方案的主要容器管理器和部署平台,我们仍然可以主要通过SpringCloudKubernetes项目使用SpringCloud的有趣特性。这个相对较新的项目无疑可以与Kubernetes轻松集成Spring Boot应用程序。在开始之前,了解如何在Minikube(本地Kubernetes环境)上部署Spring Boot应用程序可能会有所帮助。</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;text-size-adjust: auto;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;overflow-wrap: break-word !important;">在本教程中,我们将:</p> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;overflow-wrap: break-word !important;font-size: 14px !important;"><span style="max-width: 100%;box-sizing: border-box;line-height: 22px;overflow-wrap: break-word !important;">在我们的本地计算机上安装Minikube。</span></span></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;overflow-wrap: break-word !important;font-size: 14px !important;"><span style="max-width: 100%;box-sizing: border-box;line-height: 22px;overflow-wrap: break-word !important;">开发一个微服务架构示例,其中两个独立的Spring Boot应用程序通过REST进行通信。</span></span></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;overflow-wrap: break-word !important;font-size: 14px !important;"><span style="max-width: 100%;box-sizing: border-box;line-height: 22px;overflow-wrap: break-word !important;">使用Minikube在单节点集群上设置应用程序。</span></span></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;overflow-wrap: break-word !important;font-size: 14px !important;"><span style="max-width: 100%;box-sizing: border-box;line-height: 22px;overflow-wrap: break-word !important;">使用YAML配置文件部署应用程序。</span></span></p></li> </ul> <h2 style="margin-top: 1.5rem;margin-bottom: 1rem;font-size: 24px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;color: rgb(21, 153, 87);line-height: 1.35;text-align: start;overflow-wrap: break-word !important;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(0, 0, 0);overflow-wrap: break-word !important;">2.情景</strong></h2> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;text-size-adjust: auto;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;overflow-wrap: break-word !important;">在我们的示例中,我们使用的场景是旅行社向客户提供各种交易,客户将不时查询旅行社服务。我们将用它来演示:</p> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;overflow-wrap: break-word !important;font-size: 14px !important;"><span style="max-width: 100%;box-sizing: border-box;line-height: 22px;overflow-wrap: break-word !important;">通过Spring Cloud Kubernetes进行<strong style="max-width: 100%;box-sizing: border-box;color: rgb(0, 0, 0);overflow-wrap: break-word !important;">服务发现</strong>。</span></span></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;overflow-wrap: break-word !important;font-size: 14px !important;"><span style="max-width: 100%;box-sizing: border-box;line-height: 22px;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(0, 0, 0);overflow-wrap: break-word !important;">配置管理</strong>和使用SpringCloudKubernetes配置向应用程序包注入Kubernetes配置和机密。</span></span></p></li> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(74, 74, 74);line-height: 22px;overflow-wrap: break-word !important;font-size: 14px !important;"><span style="max-width: 100%;box-sizing: border-box;line-height: 22px;overflow-wrap: break-word !important;">使用Spring Cloud Kubernetes功能区进行<strong style="max-width: 100%;box-sizing: border-box;color: rgb(0, 0, 0);overflow-wrap: break-word !important;">负载均衡</strong>。</span></span></p></li> </ul> <h2 style="margin-top: 1.5rem;margin-bottom: 1rem;font-size: 24px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;color: rgb(21, 153, 87);line-height: 1.35;text-align: start;overflow-wrap: break-word !important;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;"><strong style="max-width: 100%;box-sizing: border-box;color: rgb(0, 0, 0);overflow-wrap: break-word !important;">3.环境设置</strong></h2> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;box-sizing: border-box;min-height: 1em;letter-spacing: 0.544px;text-size-adjust: auto;font-size: 16px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;overflow-wrap: break-word !important;">首先,我们需要在本地机器上安装minikube,最好是虚拟机驱动程序,如virtualbox。在执行此环境设置之前,还建议先查看kubernetes及其主要功能。让我们启动本地单节点Kubernetes集群:</p> <pre class="" style="padding-top: 8px;padding-bottom: 6px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;text-size-adjust: auto;background-color: rgb(241, 239, 238);border-radius: 0px;overflow-y: auto;color: rgb(80, 97, 109);text-align: start;font-size: 10px;line-height: 12px;overflow-wrap: break-word !important;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei"!important;border-width: 1px !important;border-style: solid !important;border-color: rgb(226, 226, 226) !important;"> <ol class=" list-paddingleft-2" style="list-style-type: none;"> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(74, 74, 74);display: block;line-height: 22px;overflow-wrap: break-word !important;font-size: 14px !important;word-break: inherit !important;"><span style="max-width: 100%;box-sizing: border-box;line-height: 22px;display: block;overflow-wrap: break-word !important;word-break: inherit !important;"><code class="" style="margin-left: -20px;max-width: 100%;box-sizing: border-box;display: flex;line-height: 12px;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;overflow-wrap: break-word !important;font-family: inherit !important;"><span class="" style="max-width: 100%;box-sizing: border-box;color: rgb(27, 25, 24);line-height: 20px;overflow-wrap: break-word !important;font-size: 13px !important;white-space: inherit !important;">minikube start </span><span class="" style="max-width: 100%;box-sizing: border-box;color: rgb(27, 25, 24);line-height: 20px;overflow-wrap: break-word !important;font-size: 13px !important;white-space: inherit !important;">--</span><span class="" style="max-width: 100%;box-sizing: border-box;color: rgb(27, 25, 24);line-height: 20px;overflow-wrap: break-word !important;font-size: 13px !important;white-space: inherit !important;">vm</span><span class="" style="max-width: 100%;box-sizing: border-box;color: rgb(27, 25, 24);line-height: 20px;overflow-wrap: break-word !important;font-size: 13px !important;white-space: inherit !important;">-</span><span class="" style="max-width: 100%;box-sizing: border-box;color: rgb(27, 25, 24);line-height: 20px;overflow-wrap: break-word !important;font-size: 13px !important;white-space: inherit !important;">driver</span><span class="" style="max-width: 100%;box-sizing: border-box;color: rgb(27, 25, 24);line-height: 20px;overflow-wrap: break-word !important;font-size: 13px !important;white-space: inherit !important;">=</span><span class="" style="max-width: 100%;box-sizing: border-box;color: rgb(27, 25, 24);line-heigh
作者:じ☆ve宝贝
## 1、can not run elasticsearch as root 切换到非root用户 ## 2、main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTrustPermission" "register") 改变elasticsearch文件夹所有者到当前用户 sudo chown -R noroot:noroot elasticsearch ## 3、max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] sudo vi /etc/sysctl.conf 添加下面配置: vm.max_map_count=655360 并执行命令: sudo sysctl -p ## 4、max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536] sudo vi /etc/security/limits.conf 添加如下内容: * soft nofile 65536 * hard nofile 131072 **注意:如果不生效,请重新链接Linux端即可** ## 安装后允许外网访问 vi /{es_home}/config/elasticsearch.yml #增加(允许外网访问) network.host: 0.0.0.0 #解决跨域 http.cors.enabled: true http.cors.allow-origin: "*"