作者:微信小助手
<section data-mpa-template="t" mpa-paragraph-type="ignored" style="white-space: normal;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);" data-mpa-powered-by="yiban.io"> <h3 style="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;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);"> <section powered-by="xiumi.us"> <section> <section powered-by="xiumi.us"> <section> <p style="margin-left: 0px;margin-right: 0px;"><span style="font-size: 15px;">往期热门文章:</span></p> </section> </section> </section> </section></h3> <h4 style="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;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);"><p style="margin: 10px 0px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: left;word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="font-size: 14px;">1、</span><a href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247489898&idx=1&sn=5c5e41a0f695649046de3db1b1810df5&chksm=e9c5e0dbdeb269cd52f798c675f58295ad0f632283c0fb07db4140949c72796deed7dfe7d434&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="color: rgb(62, 62, 62);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;letter-spacing: 0.544px;font-size: 14px;">《</a><a href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247489402&idx=2&sn=af5c3bb38717e828d92ed48874f03fe8&chksm=e9c5eecbdeb267dd3d05c159bdb9c611f24c4ca7fb7dafa12daf459becb0ef4fab7bcc2d1a67&scene=21#wechat_redirect" target="_blank" data-linktype="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;"><span style="font-size: 14px;">往期</span><span style="cursor: pointer;letter-spacing: 0.544px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);font-size: 14px;">精选优秀博文都在这里了!</span><span style="cursor: pointer;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);color: rgb(62, 62, 62);letter-spacing: 0.544px;">》</span></a></p><p style="margin: 10px 0px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: left;word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="font-size: 14px;">2、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247491046&idx=1&sn=11c2b2af810246322f3b8e6154d40828&chksm=e9c5e457deb26d41ca0115b87a400ae93e70d528d444ee0fdb8eb13e09f74dabf86c9b001f6c&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">关于MySQL索引面试题的6连炮!招架的住吗?</a></span></p><p style="margin: 10px 0px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: left;word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="font-size: 14px;">3、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247491013&idx=1&sn=228cf3e44ffe0015b6bf3e9d052ff328&chksm=e9c5e474deb26d620c836fb493fa64c06c71aeb4b2fbeaafeb09a6185bc30bbe1068aa1aafc4&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">真香!IDEA 最新版本,支持免打扰和轻量模式!</a></span></p><p style="margin: 10px 0px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: left;word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="font-size: 14px;">4、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490984&idx=1&sn=769a10817e936f6b59e86b3051b0892f&chksm=e9c5e419deb26d0f5a62eb1dbdb507101f337426494c498aa9905bf90f50ac818c4328453011&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">微服务如何防止雪崩?阿里开源之Sentinel限流、熔断来帮你!</a></span></p><p style="margin: 10px 0px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;text-align: left;word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="font-size: 14px;">5<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490974&idx=1&sn=90704164199aa8b1d1deec7810f5129b&chksm=e9c5e42fdeb26d39e38e34d45110055a983fdc9f63007be280b319669bf850d7fb4d7ee6e0fb&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">、为什么很多SpringBoot开发者放弃了Tomcat,选择了Undertow?</a></span><span style="font-size: 14px;letter-spacing: 0.544px;"></span></p></h4> <p style="margin-top: 15px;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;white-space: normal;background-color: rgb(255, 255, 255);margin-left: 0px;margin-right: 0px;"><span style="color: rgb(136, 136, 136);font-size: 14px;letter-spacing: 0.544px;text-align: center;">本文来源:<span style="letter-spacing: 0.544px;background-color: rgb(255, 255, 255);">jianshu.com/p/e4192d7c6844</span></span></p> </section> <p style="white-space: normal;letter-spacing: 0.544px;text-align: right;background-color: rgb(255, 255, 255);margin-left: 0px;margin-right: 0px;"><br></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-size: 16px;margin-top: -1em;font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;"> <section style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> Easycode是idea的一个插件,可以直接对数据的表生成entity,controller,service,dao,mapper,无需任何编码,简单而强大。 </section> <h1 data-tool="mdnice编辑器" style="font-weight: bold;margin: 1em 0px;font-size: 1.4em;padding-bottom: 0.3em;border-bottom: 1px solid rgb(223, 226, 229);line-height: 1.6 !important;"><span style="color: rgb(61, 167, 66);line-height: 1.6 !important;">1、安装(EasyCode)</span></h1> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"><img data-ratio="0.6757281553398058" src="/upload/9a112e3ca2a2606ec79dcb5c6bda1168.png" data-type="png" data-w="2060" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;">我这里的话是已经那装好了。</p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 建议大家在安装一个插件,叫做Lombok。Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。 </section></li> </ul> <h1 data-tool="mdnice编辑器" style="font-weight: bold;margin: 1em 0px;font-size: 1.4em;padding-bottom: 0.3em;border-bottom: 1px solid rgb(223, 226, 229);line-height: 1.6 !important;"><span style="color: rgb(61, 167, 66);line-height: 1.6 !important;">2、建立数据库</span></h1> <pre data-tool="mdnice编辑器" style="margin-top: 1em;margin-bottom: 1em;border-radius: 4px;line-height: 1.6 !important;"><p style="overflow-x: auto;padding: 16px;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 0.875em;margin-left: 0px;margin-right: 0px;line-height: 1.6 !important;">-- ----------------------------<br>-- Table structure <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">for</span> user<br>-- ----------------------------<br>DROP TABLE <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">IF</span> EXISTS `user`;<br>CREATE TABLE `user` (<br> `id` int(<span style="line-height: 1.6 !important;">11</span>) NOT <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">NULL</span>,<br> `username` varchar(<span style="line-height: 1.6 !important;">20</span>) <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">DEFAULT</span> <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">NULL</span>,<br> `sex` varchar(<span style="line-height: 1.6 !important;">6</span>) <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">DEFAULT</span> <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">NULL</span>,<br> `birthday` date <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">DEFAULT</span> <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">NULL</span>,<br> `address` varchar(<span style="line-height: 1.6 !important;">20</span>) <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">DEFAULT</span> <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">NULL</span>,<br> `password` varchar(<span style="line-height: 1.6 !important;">20</span>) <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">DEFAULT</span> <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">NULL</span>,<br> PRIMARY KEY (`id`)<br>) ENGINE=InnoDB <span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">DEFAULT</span> CHARSET=utf8;<br>SET FOREIGN_KEY_CHECKS = <span style="line-height: 1.6 !important;">1</span>;<br></p></pre> <h1 data-tool="mdnice编辑器" style="font-weight: bold;margin: 1em 0px;font-size: 1.4em;padding-bottom: 0.3em;border-bottom: 1px solid rgb(223, 226, 229);line-height: 1.6 !important;"><span style="color: rgb(61, 167, 66);line-height: 1.6 !important;">3、在IDEA配置连接数据库</span></h1> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> <p style="margin-top: 1em;margin-bottom: 1em;font-size: inherit;color: rgb(51, 51, 51);line-height: 1.6 !important;">在这个之前,新建一个Springboot项目,这个应该是比较简单的。</p> </section></li> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> <p style="margin-top: 1em;margin-bottom: 1em;font-size: inherit;color: rgb(51, 51, 51);line-height: 1.6 !important;">建好SpringBoot项目之后,如下图所示,找到这个Database</p> </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="0.9745916515426497" src="/upload/e2d4f25bdc8bc9f721c0c43d15116d88.png" data-type="png" data-w="1102" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 按照如下图所示进行操作: </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="1.4188376753507015" src="/upload/96956f5bd8318387966bec86025a7113.png" data-type="png" data-w="998" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 然后填写数据库名字,用户名,密码。点击OK即可。这样的话,IDEA连接数据库就完事了。 </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="0.6984126984126984" src="/upload/a6e18ff21dade7b3e3e758717b145ea4.png" data-type="png" data-w="2142" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <h1 data-tool="mdnice编辑器" style="font-weight: bold;margin: 1em 0px;font-size: 1.4em;padding-bottom: 0.3em;border-bottom: 1px solid rgb(223, 226, 229);line-height: 1.6 !important;"><span style="color: rgb(61, 167, 66);line-height: 1.6 !important;">4、开始生成代码</span></h1> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 在这个里面找到你想生成的表,然后右键,就会出现如下所示的截面。 </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="1.5065666041275798" src="/upload/d5fa788913b047aee6f070aba3c1349f.png" data-type="png" data-w="1066" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 点击1所示的位置,选择你要将生成的代码放入哪个文件夹中,选择完以后点击OK即可。 </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="0.5401459854014599" src="/upload/72da68127874b048ab9a1a4cdb69b574.png" data-type="png" data-w="2466" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 勾选你需要生成的代码,点击OK。 </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="0.7692307692307693" src="/upload/bef8041221c9dd04a24bebd1aa91a489.png" data-type="png" data-w="832" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 这样的话就完成了代码的生成了,生成的代码如下图所示: </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="1.4437869822485208" src="/upload/61e9d2de413bc7d5e8cf3b88f210a1a7.png" data-type="png" data-w="1014" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <h1 data-tool="mdnice编辑器" style="font-weight: bold;margin: 1em 0px;font-size: 1.4em;padding-bottom: 0.3em;border-bottom: 1px solid rgb(223, 226, 229);line-height: 1.6 !important;"><span style="color: rgb(61, 167, 66);line-height: 1.6 !important;">5、pom.xml</span></h1> <pre data-tool="mdnice编辑器" style="margin-top: 1em;margin-bottom: 1em;border-radius: 4px;line-height: 1.6 !important;"> <p style="overflow-x: auto;padding: 16px;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 0.875em;margin-left: 0px;margin-right: 0px;line-height: 1.6 !important;"><span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">dependency</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">groupId</span>></span>org.springframework.boot<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">groupId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">artifactId</span>></span>spring-boot-starter<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">artifactId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">dependency</span>></span><br><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">dependency</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">groupId</span>></span>org.springframework.boot<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">groupId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">artifactId</span>></span>spring-boot-starter-web<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">artifactId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">dependency</span>></span><br><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">dependency</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">groupId</span>></span>org.projectlombok<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">groupId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">artifactId</span>></span>lombok<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">artifactId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">optional</span>></span>true<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">optional</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">dependency</span>></span><br><br> <span style="color: #75715e;line-height: 1.6 !important;"><!--热部署--></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">dependency</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">groupId</span>></span>org.springframework.boot<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">groupId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">artifactId</span>></span>spring-boot-devtools<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">artifactId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">optional</span>></span>true<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">optional</span>></span> <span style="color: #75715e;line-height: 1.6 !important;"><!-- 这个需要为 true 热部署才有效 --></span><br> <span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">dependency</span>></span><br><br> <span style="color: #75715e;line-height: 1.6 !important;"><!--mybatis--></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">dependency</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">groupId</span>></span>org.mybatis.spring.boot<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">groupId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">artifactId</span>></span>mybatis-spring-boot-starter<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">artifactId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">version</span>></span>1.3.2<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">version</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">dependency</span>></span><br><br> <span style="color: #75715e;line-height: 1.6 !important;"><!-- mysql --></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">dependency</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">groupId</span>></span>mysql<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">groupId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">artifactId</span>></span>mysql-connector-java<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">artifactId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">version</span>></span>5.1.47<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">version</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">dependency</span>></span><br><br> <span style="color: #75715e;line-height: 1.6 !important;"><!--阿里巴巴连接池--></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">dependency</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">groupId</span>></span>com.alibaba<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">groupId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">artifactId</span>></span>druid<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">artifactId</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"><<span style="line-height: 1.6 !important;">version</span>></span>1.0.9<span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">version</span>></span><br> <span style="color: #f92672;line-height: 1.6 !important;"></<span style="line-height: 1.6 !important;">dependency</span>></span><br></p></pre> <h1 data-tool="mdnice编辑器" style="font-weight: bold;margin: 1em 0px;font-size: 1.4em;padding-bottom: 0.3em;border-bottom: 1px solid rgb(223, 226, 229);line-height: 1.6 !important;"><span style="color: rgb(61, 167, 66);line-height: 1.6 !important;">6、Application.yml</span></h1> <pre data-tool="mdnice编辑器" style="margin-top: 1em;margin-bottom: 1em;border-radius: 4px;line-height: 1.6 !important;"><p style="overflow-x: auto;padding: 16px;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 0.875em;margin-left: 0px;margin-right: 0px;line-height: 1.6 !important;">server:<br> port: <span style="line-height: 1.6 !important;">8089</span><br>spring:<br> datasource:<br> url: jdbc:mysql:<span style="color: #75715e;line-height: 1.6 !important;">//127.0.0.1:3306/database?useUnicode=true&characterEncoding=UTF-8</span><br> username: root<br> password: <span style="line-height: 1.6 !important;">123456</span><br> type: com.alibaba.druid.pool.DruidDataSource<br> driver-<span style="line-height: 1.6 !important;"><span style="color: #f92672;font-weight: bold;line-height: 1.6 !important;">class</span>-<span style="font-weight: bold;color: white;line-height: 1.6 !important;">name</span>: <span style="color: #a6e22e;font-weight: bold;line-height: 1.6 !important;">com.mysql.jdbc.Driver</span></span><br><br>mybatis:<br> mapper-locations: classpath:/mapper<span style="color: #75715e;line-height: 1.6 !important;">/*Dao.xml<br> typeAliasesPackage: com.vue.demo.entity<br></span></p></pre> <h1 data-tool="mdnice编辑器" style="font-weight: bold;margin: 1em 0px;font-size: 1.4em;padding-bottom: 0.3em;border-bottom: 1px solid rgb(223, 226, 229);line-height: 1.6 !important;"><span style="color: rgb(61, 167, 66);line-height: 1.6 !important;">7、启动项目</span></h1> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;">在启动项目之前,我们需要先修改两个地方。</p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 在dao层加上@mapper注解 </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="0.6406685236768802" src="/upload/2a23cf05ebbafd08bf86adbcce1bc724.png" data-type="png" data-w="2154" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 在启动类里面加上@MapperScan("com.vue.demo.dao")注解。 </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="0.4528301886792453" src="/upload/45400b581338ac45228161d6bf579da5.png" data-type="png" data-w="2014" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 启动项目 </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="0.1888162672476398" src="/upload/68b050bbf39fe0179c5fe42665763ef4.png" data-type="png" data-w="2754" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <ul data-tool="mdnice编辑器" style="margin-left: 0px;margin-right: 0px;" class="list-paddingleft-2"> <li> <section style="color: rgb(1, 1, 1);margin-top: 0.3em;margin-bottom: 0.3em;line-height: 1.6 !important;"> 测试一下 </section></li> </ul> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"> <img data-ratio="0.11758474576271187" src="/upload/ee94ec39d56a324a4d15fdcbcf7aab39.png" data-type="png" data-w="1888" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> <p style="margin: 1em 0px;font-size: inherit;line-height: 1.6 !important;"><img data-ratio="0.08131241084165478" src="/upload/50579646a0b9181dd74d8261927ae5fd.png" data-type="png" data-w="2804" style="display: block;margin: 0px;width: 100%;line-height: 1.6 !important;top: auto;left: auto;right: auto;bottom: auto;"></p> </section> <section data-mpa-template="t" mpa-paragraph-type="ignored" style="white-space: normal;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);"> <section style="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;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;text-align: left;"> <p style="margin: 15px 0px;"><span style="font-size: 15px;"><strong style="letter-spacing: 0.544px;"><span style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;color: rgb(255, 76, 65);">往期热门文章:</span></strong></span><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;text-align: justify;"></span></p> </section> <pre style="color: inherit;background-color: rgb(255, 255, 255);text-align: left;letter-spacing: 0.5px;line-height: inherit;"><h4 style="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;white-space: normal;"><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="font-size: 15px;">1、</span><a href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247489898&idx=1&sn=5c5e41a0f695649046de3db1b1810df5&chksm=e9c5e0dbdeb269cd52f798c675f58295ad0f632283c0fb07db4140949c72796deed7dfe7d434&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="color: rgb(62, 62, 62);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;letter-spacing: 0.544px;font-size: 15px;">《</a><a href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247489402&idx=2&sn=af5c3bb38717e828d92ed48874f03fe8&chksm=e9c5eecbdeb267dd3d05c159bdb9c611f24c4ca7fb7dafa12daf459becb0ef4fab7bcc2d1a67&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;letter-spacing: 0.544px;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;letter-spacing: 0.544px;font-size: 15px;">历史文章分类导读列表!精选优秀博文都在这里了!</span><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;letter-spacing: 0.544px;color: rgb(62, 62, 62);font-size: 15px;">》</span></a></p><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 15px;">2、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247491046&idx=1&sn=11c2b2af810246322f3b8e6154d40828&chksm=e9c5e457deb26d41ca0115b87a400ae93e70d528d444ee0fdb8eb13e09f74dabf86c9b001f6c&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">关于MySQL索引面试题的6连炮!招架的住吗?</a></span></p><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 15px;">3、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490850&idx=1&sn=e715d5a8761ec22cca3ee06e38ab4b02&chksm=e9c5e493deb26d85d4575117b2ef821d484eac94da90eec2de9c9aa9714fd032b2f3a7b018c5&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">MyBatis她不香吗?为啥老外却喜欢Hibernate/Jpa?</a></span></p><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 15px;">4<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490318&idx=1&sn=f7f7ecbcec999dd7b0126cfd4430040e&chksm=e9c5e2bfdeb26ba9506c5780d4f9b59e6d1769bfdec2a7c0c141fc5fb2e9223d34b0b543b721&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">、</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490844&idx=1&sn=1f92c6f6ae9e9dc48e219c30d86d9a54&chksm=e9c5e4addeb26dbbda0c26678a9140bd250fc2fc02d3c23115e117711731219d85cb345671fc&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">代码对比工具,我就用这7个!</a></span></p><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 15px;">5<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490318&idx=1&sn=f7f7ecbcec999dd7b0126cfd4430040e&chksm=e9c5e2bfdeb26ba9506c5780d4f9b59e6d1769bfdec2a7c0c141fc5fb2e9223d34b0b543b721&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">、</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490812&idx=1&sn=77724eaa49f7a4f4efc4c0045e1db80f&chksm=e9c5e54ddeb26c5bdad60eac3e35daa0391def6a1c1be7de10383958b606ce8940e77d47c916&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">Mybatis 中经典的 9 种设计模式!面试可以吹牛了!</a></span></p><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 15px;">6<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490318&idx=1&sn=f7f7ecbcec999dd7b0126cfd4430040e&chksm=e9c5e2bfdeb26ba9506c5780d4f9b59e6d1769bfdec2a7c0c141fc5fb2e9223d34b0b543b721&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">、</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490761&idx=1&sn=7a2483e9a0f9870b4fc3c8364d769718&chksm=e9c5e578deb26c6e51a0b9039f5263b736f73b2a4c3bca3921b6f5e78ea5f963625b24f88b96&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">海量交易订单查询没做“重试”,一哥们“喜提”P3故障!</a></span></p><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 15px;">7<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490318&idx=1&sn=f7f7ecbcec999dd7b0126cfd4430040e&chksm=e9c5e2bfdeb26ba9506c5780d4f9b59e6d1769bfdec2a7c0c141fc5fb2e9223d34b0b543b721&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">、</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490744&idx=1&sn=0f57a20f486b99503c9d16122ed7a5f3&chksm=e9c5e509deb26c1f53c3841a8b2a092cc487a5e6d8502c9a753eaa6fabcdb102e0d6789e207e&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">2020年Java框架排行榜,谁居榜首?</a></span></p><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 15px;">8<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490318&idx=1&sn=f7f7ecbcec999dd7b0126cfd4430040e&chksm=e9c5e2bfdeb26ba9506c5780d4f9b59e6d1769bfdec2a7c0c141fc5fb2e9223d34b0b543b721&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">、</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490732&idx=1&sn=c3cc842faeffca602cb89258f9c56a97&chksm=e9c5e51ddeb26c0b8047223784f2057fa2f0bd597d495787f81535990addbaa25c59ed581c7a&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">格式化时间用了YYYY-MM-dd,元旦当天老板喊我回去改Bug!</a></span></p><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: 15px;">9<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490318&idx=1&sn=f7f7ecbcec999dd7b0126cfd4430040e&chksm=e9c5e2bfdeb26ba9506c5780d4f9b59e6d1769bfdec2a7c0c141fc5fb2e9223d34b0b543b721&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">、</a><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490691&idx=1&sn=51ee2df8d2f46efdbdf628fd2f26b7c7&chksm=e9c5e532deb26c241c036e2b032d4d4eb4974f40e6f1394120bc1faf867220fbcb28a3e4c3cb&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">除了 P 站,程序员在摸鱼时还喜欢上这些网站...</a></span></p><p style="margin: 15px 0px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><span style="letter-spacing: 0.544px;"><span style="font-size: 15px;">10</span>、</span><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247490672&idx=1&sn=2fcd199987d644a5a3560fb87b4a3552&chksm=e9c5e5c1deb26cd7a3748c8e8b7a1b193dbbd2a65fa3f232a69c2e0b18b8c5ee1e538dd3be3d&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-size: inherit;letter-spacing: 0.544px;">39 个奇葩代码注释,看完笑哭了。。。</a><span style="font-size: 15px;letter-spacing: 0.544px;"></span></p><p style="margin: 15px 0px;font-size: inherit;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);word-spacing: 1px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;"><img data-copyright="0" data-ratio="0.5" data-s="300,640" data-type="png" data-w="800" width="auto" data-backw="574" data-backh="287" data-before-oversubscription-url="/upload/e46fc654dfcccf189c5d81430fa2708f.null" src="/upload/e46fc654dfcccf189c5d81430fa2708f.null" style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;color: rgb(51, 51, 51);font-size: 14px;text-align: center;word-spacing: 2px;visibility: visible !important;width: 677px !important;"></p></h4></pre> </section>
作者:微信小助手
<p style="text-align: center;" data-mpa-powered-by="yiban.io"><br></p> <blockquote cid="n24" mdtype="blockquote" style="box-sizing: border-box;margin-top: 0.8em;margin-bottom: 0.8em;border-left-width: 4px;border-left-color: rgb(66, 185, 131);padding: 10px 15px;color: rgb(119, 119, 119);background-color: rgba(66, 185, 131, 0.098);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;text-size-adjust: auto;"> <p cid="n25" mdtype="paragraph" style="box-sizing: border-box;line-height: 1.6rem;orphans: 4;white-space: pre-wrap;word-spacing: 0.05rem;"><span style="font-size: 16px;"><strong>“</strong>本文15391字,阅读大约需要39分钟<strong>。”</strong></span></p> </blockquote> <hr style="border-style: solid;border-width: 1px 0px 0px;border-color: rgba(0, 0, 0, 0.1);transform-origin: 0px 0px;transform: scale(1, 0.5);"> <blockquote cid="n16" mdtype="blockquote" style="margin-top: 0.8em;margin-bottom: 0.8em;border-left-width: 4px;border-left-color: rgb(66, 185, 131);padding: 10px 15px;color: rgb(119, 119, 119);background-color: rgba(66, 185, 131, 0.098);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;text-size-adjust: auto;"> <p cid="n17" mdtype="paragraph" style="line-height: 1.6rem;orphans: 4;white-space: pre-wrap;word-spacing: 0.05rem;"><strong><span md-inline="plain">缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。</span></strong><span md-inline="plain"></span></p> </blockquote> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain">说实话,我起始真的不知道怎么去介绍缓存,所以引用了上面相对官方的定义。我想几乎每个开发者都碰到过缓存的问题吧,甚至有很多情况下我们会说<span md-inline="code" spellcheck="false" style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">这个问题已经修复了,你清理下缓存就好了</code></span><span md-inline="plain" style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;">。这篇文章我们就细细的来挖掘下缓存的种种轶事。</span></span> </section> <h3 cid="n19" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;font-size: 1.4rem;margin-top: 20px;margin-bottom: 7px;font-weight: bold;line-height: 1.43;cursor: text;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">🦋缓存的种类</span></h3> <section style="text-indent: 2em;"> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">很多开发者习惯把cookie、webStorage以及IndexedDB存储的数据也称之为缓存,理由是都是保存在客户端的数据,没有什么区别。其实这是不严谨的,cookie的存在更多的是为了让服务端区别用户,webStorage和IndexedDB则更多用在保存具体的数据和在客户端存储大量结构化数据(文件/blobs)上面。</span> </section> <section style="text-indent: 2em;"> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"><span md-inline="plain" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);">实际上所谓的缓存只有一种——它是</span><span md-inline="strong" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">请求资源的副本</span></strong><span md-inline="plain">。试想一下,如果每一个资源我们客户端都会保存一份副本,这会怎么样?客户端会炸掉,开发者会疯掉!所以我们需要一份协议来处理缓存,可以让开发者控制缓存的建立和删除。谁呢?还能有谁,</span><span md-inline="code" spellcheck="false"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">HTTP</code><span md-inline="plain">呗。HTTP协议里定义了很多关于缓存的请求和响应字段,这也是接下来我们重点要逼逼叨的对象,研究下究竟是哪些字段怎么影响缓存的。</span></span></span><span style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"></span></span> </section> <p cid="n22" mdtype="paragraph" style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">纳尼?你问我为什么要缓存?😱</span></p> <p cid="n23" mdtype="paragraph" style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">那就太容易说道了🤣,缓存好处有很多:</span></p> <section style="text-indent: 2em;"> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;text-indent: 7px;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">1. 缓解服务器压力(不用每次去请求资源);</span> </section> <section style="text-indent: 2em;"> <span style="color:#34495e;font-family:Source Sans Pro, Helvetica Neue, Arial, sans-serif;"><span style="font-size: 14px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);">2. <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;text-indent: 7px;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">提升性能(打开本地资源速度当然比请求回来再打开要快得多)</span>;</span></span> </section> <section style="text-indent: 2em;"> <span style="color:#34495e;font-family:Source Sans Pro, Helvetica Neue, Arial, sans-serif;"><span style="font-size: 14px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);">3. <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;text-indent: 7px;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">减少带宽消耗(我相信你可以理解)</span>;</span></span> </section> <p style="text-indent: 2em;"><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;text-indent: 7px;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"></span><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">🤦♀️那么问题又来了,既然缓存这么好,如果我请求的服务器中间有代理也缓存了怎么办?代理服务器缓存了我的资源导致我没法从源服务器拿到最新的资源怎么办?HTTP当然也想到了这块的诉求。接下来我们也会逐层剖析。</span></p> <p style="text-indent: 2em;"><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"><span md-inline="plain" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);">🍉缓存在宏观上可以分成两类:</span><span md-inline="strong" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">私有缓存</span></strong><span md-inline="plain">和</span><span md-inline="strong"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">共享缓存</span></strong><span md-inline="plain">。共享缓存就是那些能被各级代理缓存的缓存(咋觉得有点绕)。私有缓存就是用户专享的,各级代理不能缓存的缓存。</span></span></span><span style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"></span></span></p> <p style="text-indent: 2em;"><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">🐜微观上可以分下面三类:</span></span></p> <h4 cid="n34" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;font-size: 1.2rem;margin-top: 1rem;margin-bottom: 1rem;font-weight: bold;line-height: 1.4;cursor: text;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">1. 浏览器缓存</span></h4> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain">我相信只要你经常使用某个浏览器🌎(Chrome,Firefox,IE等),肯定知道这些浏览器在设置里面都是有个清除缓存功能,这个功能存在的作用就是删除存储在你本地磁盘上资源副本,也就是清除缓存。</span> </section> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain">缓存存在的意义就是当用户点击back按钮或是再次去访问某个页面的时候能够更快的响应。尤其是在多页应用的网站中,如果你在多个页面使用了一张相同的图片,那么缓存这张图片就变得特别的有用。😏</span> </section> <h4 cid="n37" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;font-size: 1.2rem;margin-top: 1rem;margin-bottom: 1rem;font-weight: bold;line-height: 1.4;cursor: text;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">2. 代理服务器缓存</span></h4> <p style="text-indent: 2em;"><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"></span><span md-inline="plain" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);">代理服务器缓存原理和浏览器端类似,但规模要大得多,因为是为成千上万的用户提供缓存机制,大公司和大型的ISP提供商通常会将它们设立在防火墙上或是作为一个独立的设备来运营。(</span><span md-inline="strong" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">下文如果没有特殊说明,所有提到的缓存服务器都是指代理服务器。</span></strong><span md-inline="plain">)</span></span><span style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"></span></p> <p style="text-indent: 2em;"><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">由于缓存服务器不是客户端或是源服务器的一部分,它们存在于网络中,请求路由必须经过它们才会生效,所以实际上你可以去手动设置浏览器的代理,或是通过一个中间服务器来进行转发,这样用户自然就察觉不到代理服务器的存在了。🤥</span></p> <p style="text-indent: 2em;"><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">代理服务器缓存就是一个共享缓存,不只为一个用户服务,经常为大量用户使用,因此在减少相应时间和带宽使用方面很有效:因为同一个缓存可能会被重用多次。</span></p> <h4 cid="n41" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;font-size: 1.2rem;margin-top: 1rem;margin-bottom: 1rem;font-weight: bold;line-height: 1.4;cursor: text;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">3. 网关缓存</span></h4> <section style="text-indent: 2em;"> <span md-inline="plain" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 34px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);">也被称为</span> <span md-inline="strong" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 34px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">代理缓存或反向代理缓存</span></strong><span md-inline="plain">,网关也是一个中间服务器,网关缓存一般是网站管理员自己部署,从让网站拥有更好的性能。🙂</span></span> </section> <section style="text-indent: 2em;"> <span style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 34px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"></span> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">CDNS(网络内容分发商)分布网关缓存到整个(或部分)互联网上,并出售缓存服务给需要的网站,比如国内的七牛云、又拍云都有这种服务。</span> </section> <h4 cid="n44" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;font-size: 1.2rem;margin-top: 1rem;margin-bottom: 1rem;font-weight: bold;line-height: 1.4;cursor: text;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">4. 数据库缓存</span></h4> <section style="text-indent: 2em;"> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">数据库缓存是指当我们的应用极其复杂,表自然也很繁杂,我们必须进行频繁的进行数据库查询,这样可能导致数据库不堪重负,一个好的办法就是将查询后的数据放到内存中,下一次查询直接从内存中取就好了。关于数据库缓存本篇不会展开。🙃</span> </section> <h3 cid="n46" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;font-size: 1.4rem;margin-top: 20px;margin-bottom: 7px;font-weight: bold;line-height: 1.43;cursor: text;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">🦄浏览器的缓存策略</span></h3> <p><strong style="padding-right: 1px;padding-left: 1px;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;"><span md-inline="plain">缓存的目标:</span></strong></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">一个检索请求的成功响应: 对于 GET请求,响应状态码为:200,则表示为成功。一个包含例如HTML文档,图片,或者文件的响应<span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">;</span></span></p></li> <li><p><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">不变的重定向: 响应状态码:301<span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">;</span></span></p></li> <li><p><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">可用缓存响应:响应状态码:304,这个存在疑问,Chrome会缓存304中的缓存设置,Firefox<span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">;</span></span></p></li> <li><p><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">错误响应: 响应状态码:404 的一个页面</span>;</span><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;"></span></p></li> <li><p><span style="background-color: rgb(255, 255, 255);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);text-size-adjust: auto;">不完全的响应: 响应状态码 206,只返回局部的信息</span><span style="background-color: rgb(255, 255, 255);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);">;</span></p></li> </ul> <section style="orphans: 4;text-align: left;text-indent: 2em;"> <br> </section> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="background-color: rgb(255, 255, 255);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);text-size-adjust: auto;">除了 GET 请求外,如果匹配到作为一个已被定义的cache键名的响应</span><span style="background-color: rgb(255, 255, 255);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);">;</span></p></li> </ul> <section style="orphans: 4;text-align: left;text-indent: 2em;"> <br> </section> <p><span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">以上,对于我们可以和应该缓存的目标有个了解。🤗</span></p> <p><strong style="padding-right: 1px;padding-left: 1px;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;"><span md-inline="plain">浏览器对于缓存的处理是根据第一次请求资源时返回的响应头来确定的。</span></strong></p> <p cid="n63" mdtype="paragraph" style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">那么浏览器怎么确定一个资源该不该缓存,如何去缓存呢❓响应头!响应头!响应头!重要的事情说三遍。✌️</span></p> <p cid="n64" mdtype="paragraph" style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">我们看🌰:</span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer">Age:23146</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">Cache</span>-Control:<span class="code-snippet__keyword">max</span>-age=<span class="code-snippet__number">2592000</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__built_in">Date</span>:Tue, <span class="code-snippet__number">28</span> Nov <span class="code-snippet__number">2017</span> <span class="code-snippet__number">12</span>:<span class="code-snippet__number">26</span>:<span class="code-snippet__number">41</span> GMT</span></code><code><span class="code-snippet_outer">ETag:W/<span class="code-snippet__string">"5a1cf09a-63c6"</span></span></code><code><span class="code-snippet_outer">Expires:Thu, <span class="code-snippet__number">28</span> <span class="code-snippet__built_in">Dec</span> <span class="code-snippet__number">2017</span> <span class="code-snippet__number">05</span>:<span class="code-snippet__number">27</span>:<span class="code-snippet__number">45</span> GMT</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">Last</span>-Modified:Tue, <span class="code-snippet__number">28</span> Nov <span class="code-snippet__number">2017</span> <span class="code-snippet__number">05</span>:<span class="code-snippet__number">14</span>:<span class="code-snippet__number">02</span> GMT</span></code><code><span class="code-snippet_outer">Vary:<span class="code-snippet__keyword">Accept</span>-<span class="code-snippet__keyword">Encoding</span></span></code></pre> </section> <h4 cid="n66" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;font-size: 1.2rem;margin-top: 1rem;margin-bottom: 1rem;font-weight: bold;line-height: 1.4;cursor: text;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">1. 强缓存阶段</span></h4> <section style="text-indent: 2em;"> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"><span md-inline="plain" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);">以上请求头来自百度首页某个CSS文件的响应头。我去除了一些和缓存无关的字段,只保留了以上部分。我们来分析下,</span><span md-inline="code" spellcheck="false" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">Expires</code><span md-inline="plain">是HTTP/1.0中的定义缓存的字段,它规定了缓存过期的一个绝对时间。</span><span md-inline="code" spellcheck="false"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">Cache-Control:max-age=2592000</code><span md-inline="plain">是HTTP/1.1定义的关于缓存的字段,它规定了缓存过期的一个相对时间。优先级上当然是版本高的优先了,</span><span md-inline="code" spellcheck="false"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">max-age > Expires</code><span md-inline="plain">。</span></span></span></span></span> </section> <section style="text-indent: 2em;"> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"><span md-inline="code" spellcheck="false" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"><span md-inline="code" spellcheck="false"><span md-inline="code" spellcheck="false"><span md-inline="plain"></span></span></span></span><span style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"></span><span md-inline="plain">这就是</span><span md-inline="strong"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">强缓存阶段</span></strong><span md-inline="plain">,当浏览器再次试图访问这个CSS文件,发现有这个文件的缓存,那么就判断根据上一次的响应判断是否过期,如果没过期,使用缓存。加载文件,OVER!✌️</span></span></span> </section> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain">Firefox浏览器表现为一个灰色的200状态码。</span> </section> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain">Chrome浏览器状态码表现为:</span> </section> <blockquote cid="n71" mdtype="blockquote" style="margin-top: 0.8em;margin-bottom: 0.8em;border-left-width: 4px;border-left-color: rgb(66, 185, 131);padding: 10px 15px;color: rgb(119, 119, 119);background-color: rgba(66, 185, 131, 0.098);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;text-size-adjust: auto;"> <p cid="n72" mdtype="paragraph" style="line-height: 1.6rem;orphans: 4;white-space: pre-wrap;word-spacing: 0.05rem;"><span md-inline="plain">200 (from disk cache)或是200 OK (from memory cache)</span></p> </blockquote> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain"><span md-inline="strong" style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">多说一点:</span></strong></span><span md-inline="plain" style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;">关于缓存是从磁盘中获取还是从内存中获取,查找了很多资料,得出了一个较为可信的结论:Chrome会根据本地内存的使用率来决定缓存存放在哪,如果内存使用率很高,放在磁盘里面,内存的使用率很高会暂时放在内存里面。这就可以比较合理的解释了为什么同一个资源有时是from memory cache有时是from disk cache的问题了。</span></span> </section> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain"><span md-inline="plain" style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;"><span md-inline="plain">那么当这个CSS文件过期了怎么办?</span><span md-inline="code" spellcheck="false"><code style="text-align: left;margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">ETag</code><span md-inline="plain">和</span><span md-inline="code" spellcheck="false"><code style="text-align: left;margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">Last-Modified</code><span md-inline="plain">就该闪亮登场了。</span></span></span></span></span> </section> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain"><span md-inline="plain" style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;"><span md-inline="code" spellcheck="false"><span md-inline="code" spellcheck="false"><span md-inline="plain"></span></span></span><span md-inline="plain">先说</span><span md-inline="code" spellcheck="false"><code style="text-align: left;margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">Last-Modified</code><span md-inline="plain">,这个字段是文件最后一次修改的时间;</span></span></span></span> </section> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain" style="word-spacing: 0.05rem;"><span md-inline="plain" style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;"><code style="text-align: left;margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">ETag</code><span md-inline="plain" style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;">呢?ETag是对文件的一个标记,嗯,可以这么说,具体生成方式HTTP并没有给出一个明确的方式,所以理论上只要不会重复生成方式无所谓,比如对资源内容使用抗碰撞散列函数,使用最近修改的时间戳的哈希值,甚至只是一个版本号。</span></span></span> </section> <h4 cid="n77" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;font-size: 1.2rem;margin-top: 1rem;margin-bottom: 1rem;font-weight: bold;line-height: 1.4;cursor: text;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">2. 协商缓存阶段</span></h4> <section style="text-indent: 2em;"> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"><span md-inline="strong"><span md-inline="plain"></span></span></span> <span md-inline="plain" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);">利用这两个字段浏览器可以进入</span> <span md-inline="strong" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">协商缓存阶段</span></strong><span md-inline="plain">,当浏览器再次试图访问这个CSS文件,发现缓存过期,于是会在本次请求的请求头里携带</span><span md-inline="code" spellcheck="false"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">If-Moified-Since</code><span md-inline="plain">和</span><span md-inline="code" spellcheck="false"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">If-None-Match</code><span md-inline="plain">这两个字段,服务器通过这两个字段来判断资源是否有修改,如果有修改则返回状态码</span><span md-inline="strong"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">200和新的内容</span></strong><span md-inline="plain">,如果没有修改返回状态码</span><span md-inline="strong"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">304</span></strong><span md-inline="plain">,浏览器收到200状态码,该咋处理就咋处理(相当于首次访问这个文件了),发现返回</span><span md-inline="strong"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">304</span></strong><span md-inline="plain">,于是知道了本地缓存虽然过期但仍然可以用,于是加载本地缓存。然后根据新的返回的响应头来设置缓存。(这一步有所差异,发现不同浏览器的处理是不同的,chrome会为304设置缓存,firefox则不会)😑</span></span></span></span></span></span></span> </section> <section style="text-indent: 2em;"> <span md-inline="strong" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"><span md-inline="code" spellcheck="false"><span md-inline="code" spellcheck="false"><span md-inline="strong"><span md-inline="strong"><span md-inline="strong"><span md-inline="plain"><span md-inline="plain">具体两个字段携带的内容如下(分别和上面的</span><span md-inline="code" spellcheck="false"><code style="text-align: left;margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">Last-Modified</code><span md-inline="plain">、</span><span md-inline="code" spellcheck="false"><code style="text-align: left;margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">ETag</code><span md-inline="plain">携带的值对应):</span></span></span></span></span></span></span></span></span></span> </section> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="php"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">If</span>-Moified-Since: Tue, <span class="code-snippet__number">28</span> Nov <span class="code-snippet__number">2017</span> <span class="code-snippet__number">05</span>:<span class="code-snippet__number">14</span>:<span class="code-snippet__number">02</span> GMT</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">If</span>-None-Match: W/<span class="code-snippet__string">"5a1cf09a-63c6"</span></span></code></pre> </section> <section style="text-indent: 2em;"> <span style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.7px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"></span> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">到这协商缓存结束。</span> </section> <h4 cid="n82" mdtype="heading" style="break-after: avoid-page;break-inside: avoid;font-size: 1.2rem;margin-top: 1rem;margin-bottom: 1rem;font-weight: bold;line-height: 1.4;cursor: text;white-space: pre-wrap;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><span md-inline="plain">3. 启发式缓存阶段</span></h4> <section style="line-height: 1.6rem;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;word-spacing: 0.05rem;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;text-align: start;background-color: rgb(255, 255, 255);text-indent: 2em;"> <span md-inline="plain">我们把上面的响应头改下:</span> </section> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="css"><code><span class="code-snippet_outer"><span class="code-snippet__selector-tag">Age</span><span class="code-snippet__selector-pseudo">:23146</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__selector-tag">Cache-Control</span>: <span class="code-snippet__selector-tag">public</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__selector-tag">Date</span><span class="code-snippet__selector-pseudo">:Tue</span>, 28 <span class="code-snippet__selector-tag">Nov</span> 2017 12<span class="code-snippet__selector-pseudo">:26</span><span class="code-snippet__selector-pseudo">:41</span> <span class="code-snippet__selector-tag">GMT</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__selector-tag">Last-Modified</span><span class="code-snippet__selector-pseudo">:Tue</span>, 28 <span class="code-snippet__selector-tag">Nov</span> 2017 05<span class="code-snippet__selector-pseudo">:14</span><span class="code-snippet__selector-pseudo">:02</span> <span class="code-snippet__selector-tag">GMT</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__selector-tag">Vary</span><span class="code-snippet__selector-pseudo">:Accept-Encoding</span></span></code></pre> </section> <section style="text-indent: 2em;"> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: left;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);"></span> <span md-inline="plain" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);">发现没?浏览器用来确定缓存过期时间的字段一个都没有!那该怎么办?有人可能会说下次请求直接进入协商缓存阶段,携带</span> <span md-inline="code" spellcheck="false" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">If-Moified-Since</code><span md-inline="plain">呗,不是的,浏览器还有个</span><span md-inline="strong"><strong style="padding-right: 1px;padding-left: 1px;"><span md-inline="plain">启发式缓存阶段</span></strong><span md-inline="plain">😎</span></span></span> <span style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"></span> </section> <section style="text-indent: 2em;"> <strong style="padding-right: 1px;padding-left: 1px;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;"><span md-inline="plain">根据响应头中2个时间字段 Date 和 Last-Modified 之间的时间差值,取其值的10%作为缓存时间周期。</span></strong> </section> <section style="text-indent: 2em;"> <span md-inline="plain" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);">这就是启发式缓存阶段。这个阶段很容让人忽视,但实际上每时每刻都在发挥着作用。所以在今后的开发过程中如果遇到那种</span> <span md-inline="code" spellcheck="false" style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-radius: 2px;font-size: 0.92rem;color: rgb(233, 105, 0);background-color: rgb(248, 248, 248);font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important;">默认缓存</code><span md-inline="plain">的坑,不要叫嚣,不要生气,浏览器只是在遵循启发式缓存协议而已。</span></span> <span style="color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;text-indent: 28px;white-space: pre-wrap;word-spacing: 0.8px;caret-color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);"></span> </section> <p><img data-ratio="1.0166240409207161" src="/upload/999a40af27e1a383fa49e55401fd26cf.svg" data-type="svg" data-w="782" style="border-width: 0px 4px 0px 2px;border-right-style: solid;border-left-style: solid;border-right-color: transparent;border-left-color: transparent;vertical-align: middle;cursor: default;transform: translateZ(0px);display: block;margin: auto;caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: monospace;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;"></p> <section style="text-indent: 2em;"> <span style="caret-color: rgb(52, 73, 94);color: rgb(52, 73, 94);font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;font-size: 14px;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.7px;text-size-adjust: auto;background-color: rgb(255, 255, 255);">👌对于缓存策略介绍到这,�
作者:微信小助手
<p style="text-align: center;" data-mpa-powered-by="yiban.io"><img class="rich_pages" data-ratio="1" data-s="300,640" src="/upload/276dbce71ce6b5f0004e66899ef242da.jpg" data-type="jpeg" data-w="1080" style=""></p> <h1 style="margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 28px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">前言</h1> <p style="margin-top: 15px;margin-bottom: 15px;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;">不知大家现在有没有去公司复工,我已经在家办公将近 3 周了,同时也在家呆了一个多月;还好工作并没有受到任何影响,我个人一直觉得远程工作和 IT 行业是非常契合的,这段时间的工作效率甚至比在办公室还高,同时由于我们公司的业务在海外,所以疫情几乎没有造成太多影响。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">扯远了,这次主要是想和大家分享一下 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Java</span></code> 的 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">SPI</span></code> 机制。周末没啥事,我翻了翻我之前的写的博客 <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIyMzgyODkxMQ==&mid=2247484004&idx=1&sn=68c792ee8fb37567ab9fa31ee0e0fe55&chksm=e8190ca4df6e85b2278ebc822c47828bfb1392116c27a514b78cd72b00b0254008166fee9e44&scene=21#wechat_redirect" textvalue="《设计一个可拔插的 IOC 容器》" data-itemshowtype="0" tab="innerlink" data-linktype="2">《设计一个可拔插的 IOC 容器》</a>,发现当时的实现并不那么优雅。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">还没看过的朋友的我先做个前景提要,当时的需求:</p> <blockquote style="margin-bottom: 1.2em;padding: 15px 15px 15px 1rem;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);font-size: 14px;line-height: 22px;background: rgb(242, 247, 251);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;text-align: start;white-space: normal;"> <p style="margin-bottom: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">我实现了一个类似于的 SpringMVC 但却很轻量的 http 框架 cicada,其中当然也需要一个 IOC 容器,可以存放所有的单例 bean。</p> <p style="margin-top: 15px;white-space: pre-line;line-height: 30px;color: rgb(74, 74, 74);">这个 IOC 容器的实现我希望可以有多种方式,甚至可以提供一个接口供其他人实现;当然切换这个 IOC 容器的过程肯定是不能存在硬编码的,也就是这里所提到的<strong style="color: rgb(0, 0, 0);">可拔插</strong>。当我想使用 A 的实现方式时,我就引入 A 的 jar 包,使用 B 时就引入 B 的包。</p> </blockquote> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.8421875" data-s="300,640" src="/upload/12ddb948bd27136f8905b2a881a51ee0.jpg" data-type="jpeg" data-w="1280" style=""></p> <p><br></p> <p style="margin-top: 15px;margin-bottom: 15px;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;">先给大家看看两次实现的区别,先从代码简洁程度来说就是 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">SPI</span></code> 更胜一筹。</p> <h1 style="margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 28px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">什么是 SPI</h1> <p style="margin-top: 15px;margin-bottom: 15px;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;">在具体分析之前还是先了解下 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">SPI</span></code> 是什么?</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">首先它其实是 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Service</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">provider</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">interface</span></code> 的简写,翻译成中文就是服务提供发现接口。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">不过这里不要被这个名词搞混了,这里的 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">服务发现</span></code>和我们常听到的微服务中的服务发现并不能划等号。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">就如同上文提到的对 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">IOC</span></code> 容器的多种实现方式 A、B、C(可以把它们理解为服务),我需要在运行时知道应该使用哪一种具体的实现。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">其实本质上来说这就是一种典型的面向接口编程,这一点在我们刚开始学习编程的时候就被反复强调了。</p> <h1 style="margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 28px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">SPI 实践</h1> <p style="margin-top: 15px;margin-bottom: 15px;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;">接下来我们来如何来利用 SPI 实现刚才提到的可拔插 IOC 容器。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">既然刚才都提到了 SPI 的本质就是面向接口编程,所以自然我们首先需要定义一个接口:</p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.7453125" data-s="300,640" src="/upload/b38d25901acec7ebb52c365587b715eb.jpg" data-type="jpeg" data-w="1280" style=""></p> <p><br></p> <p style="margin-top: 15px;margin-bottom: 15px;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;">其中包含了一些 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Bean</span></code> 容器所必须的操作:注册、获取、释放 bean。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">为了让其他人也能实现自己的 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">IOC</span></code> 容器,所以我们将这个接口单独放到一个 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Module</span></code> 中,可供他人引入实现。</p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.4944649446494465" data-s="300,640" src="/upload/b15a188031c03902336f30fa837c182e.jpg" data-type="jpeg" data-w="1084" style=""></p> <p><br></p> <p style="margin-top: 15px;margin-bottom: 15px;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;">所以当我要实现一个单例的 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">IOC</span></code> 容器时,我只需要新建一个 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Module</span></code> 然后引入刚才的模块并实现 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">CicadaBeanFactory</span></code> 接口即可。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">当然其中最重要的则是需要在 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">resources</span></code> 目录下新建一个 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">META</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">-</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">INF</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">/</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">services</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">/</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">top</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">.</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">crossoverjie</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">.</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">cicada</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">.</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">base</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">.</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">bean</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">.</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">CicadaBeanFactory</span></code> 文件,文件名必须得是我们之前定义接口的全限定名(SPI 规范)。</p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.3472727272727273" data-s="300,640" src="/upload/19d465901c89814aa5e0e24f823e23.jpg" data-type="jpeg" data-w="1100" style=""></p> <p><br></p> <p style="margin-top: 15px;margin-bottom: 15px;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;">其中的内容便是我们自己实现类的全限定名:</p> <pre style="padding-top: 8px;padding-bottom: 6px;background: rgb(255, 255, 255);border-radius: 0px;overflow-y: auto;color: rgb(80, 97, 109);text-align: start;font-size: 10px;line-height: 12px;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><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">top</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">crossoverjie</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">cicada</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">bean</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">ioc</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(0, 134, 179);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">CicadaIoc</span></code></span></span></p></li> </ol></pre> <p style="margin-top: 15px;margin-bottom: 15px;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;">可以想象最终会通过这里的全限定名来反射创建对象。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">只不过这个过程 Java 已经提供 API 屏蔽掉了:</p> <pre style="padding-top: 8px;padding-bottom: 6px;background: rgb(255, 255, 255);border-radius: 0px;overflow-y: auto;color: rgb(80, 97, 109);text-align: start;font-size: 10px;line-height: 12px;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><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(167, 29, 93);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">public</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(167, 29, 93);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">static</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(0, 134, 179);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">CicadaBeanFactory</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> getCicadaBeanFactory</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">()</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">{</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(0, 134, 179);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">ServiceLoader</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><</span><span style="color: rgb(0, 134, 179);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">CicadaBeanFactory</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">></span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> cicadaBeanFactories </span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(0, 134, 179);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">ServiceLoader</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">load</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">(</span><span style="color: rgb(0, 134, 179);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">CicadaBeanFactory</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(167, 29, 93);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">class</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">);</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(167, 29, 93);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">if</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">(</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">cicadaBeanFactories</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">iterator</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">().</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">hasNext</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">()){</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(167, 29, 93);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">return</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> cicadaBeanFactories</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">iterator</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">().</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">next</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">()</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">;</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">}</span></code></span></span></p></li> <li><p><br></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(167, 29, 93);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">return</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(167, 29, 93);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">new</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(0, 134, 179);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">CicadaDefaultBean</span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">();</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">}</span></code></span></span></p></li> </ol></pre> <p style="margin-top: 15px;margin-bottom: 15px;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;">当 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">classpath</span></code> 中存在我们刚才的实现类(引入实现类的 jar 包),便可以通过 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">java</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">.</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">util</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">.</span><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">ServiceLoader</span></code> 工具类来找到所有的实现类(可以有多个实现类同时存在,只不过通常我们只需要一个)。</p> <hr style="margin-top: 1.5rem;margin-bottom: 1.5rem;border-style: dashed none none;border-top-color: rgb(165, 165, 165);border-right-width: initial;border-right-color: initial;border-left-width: initial;border-left-color: initial;border-bottom-width: initial;border-bottom-color: initial;height: 1px;color: rgb(80, 97, 109);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-size: 16px;text-align: start;white-space: normal;"> <p style="margin-top: 15px;margin-bottom: 15px;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;">一些都准备好之后,使用自然就非常简单了。</p> <pre style="padding-top: 8px;padding-bottom: 6px;background: rgb(255, 255, 255);border-radius: 0px;overflow-y: auto;color: rgb(80, 97, 109);text-align: start;font-size: 10px;line-height: 12px;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><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(0, 0, 128);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><dependency></span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(0, 0, 128);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><groupId></span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">top.crossoverjie.opensource</span><span style="color: rgb(0, 0, 128);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></groupId></span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(0, 0, 128);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><artifactId></span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">cicada-ioc</span><span style="color: rgb(0, 0, 128);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></artifactId></span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(0, 0, 128);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"><version></span><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">2.0.4</span><span style="color: rgb(0, 0, 128);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></version></span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(51, 51, 51);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(0, 0, 128);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"></dependency></span></code></span></span></p></li> </ol></pre> <p style="margin-top: 15px;margin-bottom: 15px;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;">我们只需要引入这个依赖便能使用它的实现,当我们想换一种实现方式时只需要更换一个依赖即可。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">这样就做到了不修改一行代码灵活的 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">可拔插</span></code>选择 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">IOC</span></code> 容器了。</p> <h1 style="margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 28px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">SPI 的一些其他应用</h1> <p style="margin-top: 15px;margin-bottom: 15px;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;">虽然平时并不会直接使用到 SPI 来实现业务,但其实我们使用过的绝大多数框架都会提供 SPI 接口方便使用者扩展自己的功能。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">比如 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Dubbo</span></code> 中提供一系列的扩展:</p> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.5514950166112957" data-s="300,640" src="/upload/5dff8fbc36e6bcd7878dd3fba98f6d86.jpg" data-type="jpeg" data-w="602" style=""></p> <p><br></p> <p style="margin-top: 15px;margin-bottom: 15px;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;">同类型的 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">RPC</span></code> 框架 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">motan</span></code> 中也提供了响应的扩展:</p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.8894601542416453" data-s="300,640" src="/upload/dc47afce9b217be002dd969f35e6285e.jpg" data-type="jpeg" data-w="778" style=""></p> <p><br></p> <p style="margin-top: 15px;margin-bottom: 15px;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;">他们的使用方式都和 Java SPI 非常类似,只不过原理略有不同,同时也新增了一些功能。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">比如 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">motan</span></code> 的 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">spi</span></code> 允许是否为单例等等。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">再比如 MySQL 的驱动包也是利用 SPI 来实现自己的连接逻辑。</p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.6276276276276276" data-s="300,640" src="/upload/607b9cf76e2ea05b664a4dafb7f482cf.jpg" data-type="jpeg" data-w="666" style=""></p> <p><br></p> <h1 style="margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 28px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">总结</h1> <p style="margin-top: 15px;margin-bottom: 15px;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;"><code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Java</span></code> 自身的 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">SPI</span></code> 其实也有点小毛病,比如:</p> <ul style="list-style-type: square;" class="list-paddingleft-2"> <li><p><span style="color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="line-height: 22px;">遍历加载所有实现类效率较低。</span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);line-height: 22px;font-size: 14px !important;"><span style="line-height: 22px;">当多个 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);font-size: 16px;line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;line-height: 22px;font-size: 14px !important;">ServiceLoader</span></code> 同时 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);font-size: 16px;line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;line-height: 22px;font-size: 14px !important;">load</span></code> 时会有并发问题(虽然没人这么干)。</span></span></p></li> </ul> <p style="margin-top: 15px;margin-bottom: 15px;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;">最后总结一下, <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">SPI</span></code> 并不是某项高深的技术,本质就是面向接口编程,而面向接口本身在我们日常开发中也是必备技能,所以了解使用 <code style="background: rgb(243, 241, 241);color: rgb(88, 88, 88);line-height: 18px;font-family: consolas, menlo, courier, monospace, "Microsoft Yahei" !important;border-width: 0px !important;border-style: initial !important;border-color: initial !important;"><span style="background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">SPI</span></code> 也是很用处的。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">本文所有源码:</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">https://github.com/TogetherOS/cicada</p> <p style="margin-top: 15px;margin-bottom: 15px;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;"><strong style="color: rgb(0, 0, 0);">你的点赞与分享是对我最大的支持</strong></p> <p><br></p>
作者:微信小助手
<section style="font-size: 14px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-size-adjust: auto;font-size: 15px;word-spacing: 2px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击蓝色“</span><span style="max-width: 100%;letter-spacing: 0.544px;font-size: 14px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">架构文摘</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">”关注我哟</span></p> <p style="margin-bottom: 10px;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-size-adjust: auto;font-size: 15px;word-spacing: 2px;text-align: center;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><span style="max-width: 100%;color: rgb(0, 128, 255);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">星标</span><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”,每天上午 09:25,干货推送!</span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);font-size: 14px;white-space: normal;letter-spacing: 0.544px;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-backh="36" data-backw="578" data-ratio="0.0625" data-s="300,640" data-type="jpeg" data-w="640" width="100%" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.null" style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"></p> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"></h3> <p><span style="color: rgb(136, 136, 136);font-size: 12px;">作者:</span><span style="color: rgb(136, 136, 136);font-size: 12px;">10pcm </span></p> <p><span style="color: rgb(136, 136, 136);font-size: 12px;">链接:</span><span style="color: rgb(136, 136, 136);font-size: 12px;">https://blog.51cto.com/superpcm/2095395</span></p> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">1. Keepalived高可用软件</span><br></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能。因此,keepalived除了能够管理LVS软件外,还可以作为其他服务的高可用解决方案软件。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">keepalived软件主要是通过VRRP协议实现高可用功能的。VRRP是Virtual Router Redundancy Protocol(虚拟路由冗余协议)的缩写,VRRP出现的目的就是为了解决静态路由的单点故障问题的,它能保证当个别节点宕机时,整个网络可以不间断地运行。所以,keepalived一方面具有配置管理LVS的功能,同时还具有对LVS下面节点进行健康检查的功能,另一方面也可以实现系统网络服务的高可用功能。</p> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">2. Keepalived高可用故障切换转移原理</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Keepalived高可用服务对之间的故障切换转移,是通过VRRP来实现的。在keepalived服务工作时,主Master节点会不断地向备节点发送(多播的方式)心跳消息,用来告诉备Backup节点自己还活着。当主节点发生故障时,就无法发送心跳的消息了,备节点也因此无法继续检测到来自主节点的心跳了。于是就会调用自身的接管程序,接管主节点的IP资源和服务。当主节点恢复时,备节点又会释放主节点故障时自身接管的IP资源和服务,恢复到原来的备用角色。</p> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">3. Keepalived高可用实验环境说明</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">如下图所示,前端有两台的Nginx负载均衡器,用来分发接收到客户端的请求。在前文已经配置好了Nginx01,Nginx02也是一样的配置。现在要在两个Nginx负载均衡器上做高可用配置,Nginx01作为主节点,Nginx02作为备节点。</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.31381957773512476" src="/upload/2b559c7f1d8b11a5938205968d189cd9.png" data-type="png" data-w="1042" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">4.安装并启用keepalived</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">keepalived的安装非常简单,直接使用yum来安装即可。</p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;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;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"> <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">yum</span> install keepalived -y<br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">安装之后,启动keepalived服务,顺便把keepalived写入开机启动的脚本里面去。。</p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;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;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">/etc/init.d/keepalived star<br>echo <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"/etc/init.d/keepalived start"</span> <span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">>></span>/etc/rc.local<br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">启动之后会有三个进程,没问题之后可以关闭keepalived软件,接下来要修改keepalived的配置文件。</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.10693400167084377" src="/upload/ae7a07934192230478a11e2ee0c059f.png" data-type="png" data-w="1197" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">5.修改keepalived配置文件并且重启keepalived服务</span></h3> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;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;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">/etc/init.d/keepalived <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">stop</span> <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#关闭keepalived服务 </span><br>vim /etc/keepalived/keepalived.conf <span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#用vim打开编辑</span><br></code></pre> <h4 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">主节点的配置文件</span></h4> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;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;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">! Configuration File <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">for</span> keepalived<br><br><br><br>global_defs {<br><br> notification_email {<br><br> acassen<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@firewall</span>.loc<br><br> failover<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@firewall</span>.loc<br><br> sysadmin<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@firewall</span>.loc<br><br> }<br><br> notification_email_from Alexandre.Cassen<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@firewall</span>.loc<br><br> smtp_server <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">192.168</span>.200.1<br><br> smtp_connect_timeout <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">30</span><br><br> router_id lb01<br><br>}<br><br><br><br>vrrp_instance VI_1 {<br><br> state MASTER<br><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">interface</span> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">eth1</span><br><br> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">virtual_router_id</span> 55<br><br> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">priority</span> 150<br><br> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">advert_int</span> 1<br><br> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">authentication</span> </span>{<br><br> auth_type PASS<br><br> auth_pass <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">123456</span><br><br> }<br><br> virtual_ipaddress {<br><br> <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">192.168</span>.31.5/<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">24</span> dev eth1 label eth1:<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">1</span><br><br> }<br><br>}<br><br>......<br></code></pre> <h4 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.2em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">备节点的配置文件</span></h4> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;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;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">! Configuration File <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">for</span> keepalived<br><br><br><br>global_defs {<br><br> notification_email {<br><br> acassen<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@firewall</span>.loc<br><br> failover<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@firewall</span>.loc<br><br> sysadmin<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@firewall</span>.loc<br><br> }<br><br> notification_email_from Alexandre.Cassen<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">@firewall</span>.loc<br><br> smtp_server <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">192.168</span>.200.1<br><br> smtp_connect_timeout <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">30</span><br><br> router_id lb02<br><br>}<br><br><br><br>vrrp_instance VI_1 {<br><br> state BACKUP<br><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">interface</span> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">eth1</span><br><br> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">virtual_router_id</span> 55<br><br> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">priority</span> 100<br><br> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">advert_int</span> 1<br><br> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">authentication</span> </span>{<br><br> auth_type PASS<br><br> auth_pass <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">123456</span><br><br> }<br><br> virtual_ipaddress {<br><br> <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">192.168</span>.31.5 dev eth1 label eth1:<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">1</span><br><br> }<br><br>}<br><br>......<br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">注解:修改配置文件主要就是上面加粗的几个地方,下面说明一下那几个参数的意思:</p> <ul style="" class="list-paddingleft-2"> <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">router_id 是路由标识,在一个局域网里面应该是唯一的;</span></p></li> <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">vrrp_instance VI_1{…}这是一个VRRP实例,里面定义了keepalived的主备状态、接口、优先级、认证和IP信息;</span></p></li> <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">state 定义了VRRP的角色,interface定义使用的接口,这里我的服务器用的网卡都是eth1,根据实际来填写,virtual_router_id是虚拟路由ID标识,一组的keepalived配置中主备都是设置一致,priority是优先级,数字越大,优先级越大,auth_type是认证方式,auth_pass是认证的密码</span></p></li> <li><p><span style="font-size: inherit;color: inherit;line-height: inherit;">virtual_ipaddress {…}定义虚拟IP地址,可以配置多个IP地址,这里我定义为192.168.31.5,绑定了eth1的网络接口,虚拟接口eth1:1</span></p></li> </ul> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">修改好主节点之后,保存退出,然后启动keepalived,几分钟内会生成一个虚拟IP:192.168.31.5</strong></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.32570905763952424" src="/upload/e0d0ec286ba2cb2a67cc2f341758f4ff.png" data-type="png" data-w="1093" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">然后修改备节点的配置文件,保存退出后启动keepalived,不会生成虚拟IP,如果生成那就是配置文件出现了错误。备节点和主节点争用IP资源,这个现象叫做“裂脑”。</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.30655586334256696" src="/upload/cbdf11466e7f222c4c243dbc4f88dc2b.png" data-type="png" data-w="1083" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">6.进行高可用的主备服务器切换实验</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">停掉主节点的keepalived服务,查看备节点会不会生成VIP:192.168.31.5</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.10462287104622871" src="/upload/4d589ac01a88113dbe12d77473ee27c8.png" data-type="png" data-w="822" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.30431034482758623" src="/upload/a469fc1e11a75448aa347792f53d8319.png" data-type="png" data-w="1160" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">启动主节点的keepalived服务,然后查看主节点和备节点的VIP,主节点应该会抢夺回来VIP:</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.3583556747095621" src="/upload/697434e2057303da9355e55085d9c727.png" data-type="png" data-w="1119" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.2891674127126231" src="/upload/cefb0526e534a5b99feebc4b38879334.png" data-type="png" data-w="1117" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">7.搭配Nginx负载均衡来测试</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">修改windows的hosts文件,把域名指向到VIP上</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.1325178389398573" src="/upload/1ca888e4a6c7d11bea619a133c8ae283.png" data-type="png" data-w="981" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">然后用浏览器打开www.pcm.com的页面,在web01上查看access.log日志记录到的客户端IP地址</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.12512716174974567" src="/upload/9f6e4fc4e48b3705094fa925ccdec821.png" data-type="png" data-w="983" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.08391070053887606" src="/upload/18951f75d8e0225498f675d1d6798cc8.png" data-type="png" data-w="1299" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">可以看到日志记录到的客户端的IP地址是192.168.31.1,反向代理服务器是主服务器192.168.31.3.下面我们停止keepalived服务,看备节点会不会接替主节点的VIP和服务。</p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.06370875995449374" src="/upload/17d6c42804cf15ba225cd8525de3d432.png" data-type="png" data-w="879" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.13719512195121952" src="/upload/f6a745720b545a9b855290a5ec7995da.png" data-type="png" data-w="984" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.08120649651972157" src="/upload/e520a3107baaa94dcb3e1124225bb34e.png" data-type="png" data-w="1293" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title=""> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">可以看到,备节点确实接替了主节点的工作。重新启用主节点,实验的结果就不验证了。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><br></p> <h3 style="margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;font-size: 1.3em;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;white-space: normal;line-height: inherit;color: rgb(0, 172, 193);"><span style="font-size: inherit;color: inherit;line-height: inherit;">8.编写Nginx Web服务的守护脚本</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">上面的实验测试有一个问题就是,我们是用Nginx做负载均衡分发请求的数据包的。如果主节点的Keepalived服务正常运行,而Nginx运行异常,那么将会出现Nginx负载均衡服务失灵,无法切换到Nginx负载均衡器02上,后端的Web服务器无法收到请求。所以,我们应该要检测Nginx的服务是否正常运行,如果不是正常运行,应该停掉Keepalived的服务,这样才能自动切换到备节点上。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">我们可以通过检测80端口是否开启来判定Nginx的运行情况,2秒钟检测一次,脚本如下</p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;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;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;">#!/bin/bash</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">while</span> <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">true</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">do</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> [ $(netstat -tlnp|grep nginx|wc -l) -ne 1 ]<br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">then</span><br> /etc/init.d/keepalived stop<br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">fi</span><br>sleep 2<br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">done</span><br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">实验的结果可以后台执行命令之后然后停止Nginx服务检验</p> </section> <p><br></p> <section mpa-from-tpl="t" style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);font-size: 15px;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;font-size: medium;display: inline-block;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;border-left: 1px solid rgb(51, 51, 51);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="padding-left: 5px;max-width: 100%;border-left: 5px solid rgb(51, 51, 51);line-height: 1.5em;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;font-size: 18px;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: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;">推荐阅读:</span></p> </section> </section> </section> </section> <ul class="list-paddingleft-2" mpa-from-tpl="t" style=""> <li><p style="margin-top: 5px;max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247489007&idx=1&sn=bb323c9fddc307d148d8b16da2e3741b&chksm=9f477927a830f03189245ad19cfa109968018719f8d887865287a12359af50fd4f0d83631a29&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;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;">使用 Spring Cloud 和 Docker 轻松构建微服务架构!</span></a></p></li> <li><p style="margin-top: 5px;max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247489000&idx=1&sn=ee9815b8c2f337a7f5a17a017b610bf2&chksm=9f477920a830f03633822b11812090c91bfb6b4cbd0521dab93393d4365868a10b7fde7eef8c&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;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;">分布式、服务化的企业级 ERP 系统架构设计方案</span></a></p></li> <li><p style="margin-top: 5px;max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247488991&idx=1&sn=4af65f79ae0f4df58c798f5ea4b1687c&chksm=9f477917a830f001e4650aace87baa5e0a190142e0388c65b011afb68e99253f02c877e4efde&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;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;">不懂 Zookeeper?没关系,看这篇就够了</span></a></p></li> <li><p style="margin-top: 5px;max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247488981&idx=1&sn=89de18352f8687f6940335f7d6770e28&chksm=9f47791da830f00b540c924d6c03dd0f94ebd4a5af82c49a72ec344987f38110d30a9399f6a3&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;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></a></p></li> <li><p style="margin-top: 5px;max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247488977&idx=1&sn=6d31d4da4d65ae11475c60599ebd1519&chksm=9f477919a830f00ffd13ca7ac1febc7966ddc8071d8579d76fe65c65759484453f8705ab15e9&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">Google 出品的 Java 编码规范,强烈推荐,权威又科学!</a></span></p></li> </ul> </section> </section> </section> </section> <p><br></p> <p style="margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);line-height: 2em;"><img class="rich_pages" data-ratio="0.5555555555555556" data-s="300,640" src="/upload/9d786e52e671b1ce4beb338d1e0d1815.jpg" data-type="jpeg" data-w="900" style="text-align: center;color: rgb(51, 51, 51);font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;"><br></p> <pre ng-bind-html="message.MMActualContent" style="font-size: 16px;letter-spacing: 0.544px;white-space: pre-wrap;word-break: normal;"><p style="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;white-space: normal;text-align: right;line-height: 2em;"><span style="font-size: 14px;">如有收获,点个在看,诚挚感谢</span><img data-ratio="1" data-type="png" data-w="19" width="19px" src="/upload/5f7454d24a334e968c32b8ce9ae53c5.png" style="display: inline-block;vertical-align: text-bottom;visibility: visible !important;width: 19px !important;"></p></pre>
作者:微信小助手
<section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;"><section style="font-size: 16px;margin: 30px 0% 20px;box-sizing: border-box;" powered-by="xiumi.us"><section style="display: inline-block;width: 100%;vertical-align: top;box-sizing: border-box;"><section style="box-sizing: border-box;" powered-by="xiumi.us"><section style="display: inline-block;width: 100%;vertical-align: top;border-width: 3px;border-radius: 20px;border-style: solid;border-color: rgb(226, 241, 246);overflow: hidden;padding: 5px 10px;background-color: rgb(226, 241, 246);box-sizing: border-box;"><section style="transform: translate3d(1px, 0px, 0px);-webkit-transform: translate3d(1px, 0px, 0px);-moz-transform: translate3d(1px, 0px, 0px);-o-transform: translate3d(1px, 0px, 0px);box-sizing: border-box;" powered-by="xiumi.us"><section style="text-align: center;font-size: 14px;color: rgb(149, 187, 202);box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;">文章出自 原创</p></section></section></section></section><section style="box-sizing: border-box;" powered-by="xiumi.us"><p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><br style="box-sizing: border-box;"></p></section></section></section><section style="font-size: 16px;text-align: left;margin: 0px 0% -15px;transform: translate3d(20px, 0px, 0px);box-sizing: border-box;" powered-by="xiumi.us"><section style="display: inline-block;width: 55px;height: 40px;vertical-align: top;overflow: hidden;box-sizing: border-box;"><section style="text-align: center;margin: 0px 0%;box-sizing: border-box;" powered-by="xiumi.us"><section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;"><img data-ratio="0.696" data-w="500" data-src="https://mmbiz.qpic.cn/mmbiz_gif/45NMxDklFiapMK1icfKjSaPE7NIDHxs0ApBDDkLyfHXjialp1woeXyt0iadGChEMMknDUaJvmdVh7nnUjGlBoMIoZQ/640?wx_fmt=gif" style="vertical-align: middle; max-width: 100%; box-sizing: border-box; width: 500px !important; height: auto !important; visibility: visible !important;" data-type="gif" _width="500px" class=" __bg_gif" src="https://mmbiz.qpic.cn/mmbiz_gif/45NMxDklFiapMK1icfKjSaPE7NIDHxs0ApBDDkLyfHXjialp1woeXyt0iadGChEMMknDUaJvmdVh7nnUjGlBoMIoZQ/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1" data-order="0" data-fail="0"></section></section></section></section><section style="font-size: 16px;box-sizing: border-box;" powered-by="xiumi.us"><p style="text-align: center;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="text-shadow: rgb(195, 134, 234) 2px 0px 7px;box-sizing: border-box;"><strong style="box-sizing: border-box;">点击蓝字波哥的IT人生,关注我们<br style="box-sizing: border-box;"></strong></span></p></section><section style="font-size: 16px;text-align: right;margin: 0px 0% 10px;box-sizing: border-box;" powered-by="xiumi.us"><section style="display: inline-block;vertical-align: middle;width: 40%;box-sizing: border-box;"><section style="text-align: center;margin: 0px 0%;box-sizing: border-box;" powered-by="xiumi.us"><section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;width: 100%;box-sizing: border-box;"><img data-ratio="0.2106667" data-w="750" data-src="https://mmbiz.qpic.cn/mmbiz_gif/aTmLxN8SLsP7UzbWF1nzhC69JQFrdhVwvOJQAf25GvLSXaeLvAYvOW1picxzTc3HdhVnFibx86L56Ab0HyzFibHqQ/640?wx_fmt=gif" style="vertical-align: middle; max-width: 100%; box-sizing: border-box; width: 100% !important; height: auto !important; visibility: visible !important;" width="100%" data-type="gif" _width="100%" class=" __bg_gif" src="https://mmbiz.qpic.cn/mmbiz_gif/aTmLxN8SLsP7UzbWF1nzhC69JQFrdhVwvOJQAf25GvLSXaeLvAYvOW1picxzTc3HdhVnFibx86L56Ab0HyzFibHqQ/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1" data-order="1" data-fail="0"></section></section></section><section style="display: inline-block;vertical-align: middle;width: 25%;padding: 0px;box-sizing: border-box;"><section style="margin: 0.5em 0px;box-sizing: border-box;" powered-by="xiumi.us"><section style="background-color: rgb(29, 29, 29);height: 1px;box-sizing: border-box;"><br></section></section></section></section><section powered-by="xiumi.us"><p style="text-align: left;"><br></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">波哥私人珍藏都是常用的命令:<br></p><section class="code-snippet__fix code-snippet__js"><pre class="code-snippet__js hljs cpp" data-lang="apache"><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment">#查看所有<span class="hljs-keyword"><span class="hljs-keyword">namespace</span></span>的pods运行情况</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get pods --<span class="code-snippet__literal">all</span>-namespaces </span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment">#查看具体pods,记得后边跟<span class="hljs-keyword"><span class="hljs-keyword">namespace</span></span>名字哦</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get pods kubernetes-dashboard<span class="hljs-number"><span class="hljs-number">-76479</span></span>d66bb-nj8wr --<span class="hljs-keyword"><span class="hljs-keyword">namespace</span></span>=kube-system</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 查看pods具体信息</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get pods -o wide kubernetes-dashboard<span class="hljs-number"><span class="hljs-number">-76479</span></span>d66bb-nj8wr --<span class="hljs-keyword"><span class="hljs-keyword">namespace</span></span>=kube-system</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 查看集群健康状态</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get cs</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 获取所有deployment</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get deployment --<span class="code-snippet__literal">all</span>-namespaces</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 查看kube-system <span class="hljs-keyword"><span class="hljs-keyword">namespace</span></span>下面的pod/svc/deployment 等等(-o wide 选项可以查看存在哪个对应的节点)</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get pod /svc/deployment -n kube-system</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 列出该 <span class="hljs-keyword"><span class="hljs-keyword">namespace</span></span> 中的所有 pod 包括未初始化的</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get pods --include-uninitialized</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 查看deployment()</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get deployment nginx-app</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 查看rc和servers</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get rc,services</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 查看pods结构信息(重点,通过这个看日志分析错误)</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 对控制器和服务,node同样有效</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> describe pods xxxxpodsname --<span class="hljs-keyword"><span class="hljs-keyword">namespace</span></span>=xxxnamespace</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 其他控制器类似吧,就是kubectl get 控制器 控制器具体名称</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 查看pod日志</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> logs $POD_NAME</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 查看pod变量</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> exec my-nginx<span class="hljs-number"><span class="hljs-number">-5</span></span>j8ok -- printenv | grep SERVICE</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"># 集群</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get cs # 集群健康情况</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> cluster-info # 集群核心组件运行情况</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get namespaces # 表空间名</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> version # 版本</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> api-versions # API</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get events # 查看事件</span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute">kubectl</span> get nodes <span class="hljs-comment"><span class="hljs-comment">//获取全部节点</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> node k8s2 <span class="hljs-comment">//删除节点</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> rollout status deploy nginx-test</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> get deployment --</span><span class="code-snippet__literal"><span class="hljs-comment">all</span></span><span class="hljs-comment">-namespaces</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> get svc --</span><span class="code-snippet__literal"><span class="hljs-comment">all</span></span><span class="hljs-comment">-namespaces</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 创建</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> create -f ./nginx.yaml # 创建资源</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> apply -f xxx.yaml (创建+更新,可以重复使用)</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> create -f . # 创建当前目录下的所有yaml资源</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> create -f ./nginx1.yaml -f ./mysql2.yaml # 使用多个文件创建资源</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> create -f ./dir # 使用目录下的所有清单文件来创建资源</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> create -f https:<span class="hljs-comment">//git.io/vPieo # 使用 url 来创建资源</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> run -i --tty busybox --image=busybox ----创建带有终端的pod</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> run nginx --image=nginx # 启动一个 nginx 实例</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> run mybusybox --image=busybox --replicas=<span class="hljs-number">5</span> ----启动多个pod</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> explain pods,svc # 获取 pod 和 svc 的文档</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 更新</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> rolling-update python-v1 -f python-v2.json # 滚动更新 pod frontend-v1</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> rolling-update python-v1 python-v2 --image=image:v2 # 更新资源名称并更新镜像</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> rolling-update python --image=image:v2 # 更新 frontend pod 中的镜像</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> rolling-update python-v1 python-v2 --rollback # 退出已存在的进行中的滚动更新</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">cat</span></span><span class="hljs-comment"> pod.json | kubectl replace -f - # 基于 <span class="hljs-built_in">stdin</span> 输入的 JSON 替换 pod</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 为 nginx RC 创建服务,启用本地 <span class="hljs-number">80</span> 端口连接到容器上的 <span class="hljs-number">8000</span> 端口</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> expose rc nginx --port=<span class="hljs-number">80</span> --target-port=<span class="hljs-number">8000</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 更新单容器 pod 的镜像版本(tag)到 v4</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> get pod nginx-pod -o yaml | sed <span class="hljs-string">'s/\(image: myimage\):.*$/\1:v4/'</span> | kubectl replace -f -</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> label pods nginx-pod <span class="hljs-keyword">new</span>-label=awesome # 添加标签</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> annotate pods nginx-pod icon-url=http:<span class="hljs-comment">//goo.gl/XXBTWq # 添加注解</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> autoscale deployment foo --min=<span class="hljs-number">2</span> --max=<span class="hljs-number">10</span> # 自动扩展 deployment “foo”</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 编辑资源</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> edit svc/docker-registry # 编辑名为 docker-registry 的 service</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">KUBE_EDITOR</span></span><span class="hljs-comment">=</span><span class="code-snippet__string"><span class="hljs-comment"><span class="hljs-string">"nano"</span></span></span><span class="hljs-comment"> kubectl edit svc/docker-registry # 使用其它编辑器</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">vim</span></span><span class="hljs-comment"> /etc/systemd/system/kubelet.service.d/<span class="hljs-number">10</span>-kubeadm.conf #修改启动参数</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 动态伸缩pod</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> scale --replicas=<span class="hljs-number">3</span> rs/foo # 将foo副本集变成<span class="hljs-number">3</span>个</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> scale --replicas=<span class="hljs-number">3</span> -f foo.yaml # 缩放“foo”中指定的资源。</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> scale --current-replicas=<span class="hljs-number">2</span> --replicas=<span class="hljs-number">3</span> deployment/mysql # 将deployment/mysql从<span class="hljs-number">2</span>个变成<span class="hljs-number">3</span>个</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> scale --replicas=<span class="hljs-number">5</span> rc/foo rc/bar rc/baz # 变更多个控制器的数量</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> rollout status deploy deployment/mysql # 查看变更进度</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"><span class="hljs-meta">#label 操作</span></span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> label:添加label值 kubectl label nodes node1 zone=north #增加节点lable值 spec.nodeSelector: zone: north #指定pod在哪个节点</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> label pod redis-master<span class="hljs-number">-1033017107</span>-q47hh role=master #增加lable值</span><span class="code-snippet__meta"><span class="hljs-comment"> [key]=[value]</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> label pod redis-master<span class="hljs-number">-1033017107</span>-q47hh role- #删除lable值</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> label pod redis-master<span class="hljs-number">-1033017107</span>-q47hh role=backend --overwrite #修改lable值</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 滚动升级</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> rolling-update:滚动升级 kubectl rolling-update redis-master -f redis-master-controller-v2.yaml #配置文件滚动升级</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> rolling-update redis-master --image=redis-master:<span class="hljs-number">2.0</span> #命令升级</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> rolling-update redis-master --image=redis-master:<span class="hljs-number">1.0</span> --rollback #pod版本回滚</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"><span class="hljs-meta"># etcdctl 常用操作</span></span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">etcdctl</span></span><span class="hljs-comment"> cluster-health #检查网络集群健康状态</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">etcdctl</span></span><span class="hljs-comment"> --endpoints=https:<span class="hljs-comment">//192.168.71.221:2379 cluster-health #带有安全认证检查网络集群健康状态</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">etcdctl</span></span><span class="hljs-comment"> member <span class="hljs-built_in">list</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">etcdctl</span></span><span class="hljs-comment"> <span class="hljs-built_in">set</span> /k8s/network/config ‘{ “Network”: “<span class="hljs-number">10.1</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span>/<span class="hljs-number">16</span>” }’</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">etcdctl</span></span><span class="hljs-comment"> get /k8s/network/config</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 删除</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> pod -l app=flannel -n kube-system # 根据label删除:</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> -f ./pod.json # 删除 pod.json 文件中定义的类型和名称的 pod</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> pod,service baz foo # 删除名为“baz”的 pod 和名为“foo”的 service</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> pods,services -l name=myLabel # 删除具有 name=myLabel 标签的 pod 和 serivce</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> pods,services -l name=myLabel --include-uninitialized # 删除具有 name=myLabel 标签的 pod 和 service,包括尚未初始化的</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> -n my-ns <span class="hljs-keyword">delete</span> po,svc --</span><span class="code-snippet__literal"><span class="hljs-comment">all</span></span><span class="hljs-comment"> # 删除 my-ns <span class="hljs-keyword">namespace</span>下的所有 pod 和 serivce,包括尚未初始化的</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> pods prometheus<span class="hljs-number">-7f</span>cfcb9f89-qkkf7 --grace-period=<span class="hljs-number">0</span> --force 强制删除</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> deployment kubernetes-dashboard --<span class="hljs-keyword">namespace</span>=kube-system</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> svc kubernetes-dashboard --<span class="hljs-keyword">namespace</span>=kube-system</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> <span class="hljs-keyword">delete</span> -f kubernetes-dashboard.yaml</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> replace --force -f ./pod.json # 强制替换,删除后重新创建资源。会导致服务中断。</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 交互</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> logs nginx-pod <span class="hljs-meta"># dump 输出 pod 的日志(stdout)</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> logs nginx-pod -c my-container <span class="hljs-meta"># dump 输出 pod 中容器的日志(stdout,pod 中有多个容器的情况下使用)</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> logs -f nginx-pod # 流式输出 pod 的日志(<span class="hljs-built_in">stdout</span>)</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> logs -f nginx-pod -c my-container # 流式输出 pod 中容器的日志(<span class="hljs-built_in">stdout</span>,pod 中有多个容器的情况下使用)</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> run -i --tty busybox --image=busybox -- sh # 交互式 shell 的方式运行 pod</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> attach nginx-pod -i # 连接到运行中的容器</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> port-forward nginx-pod <span class="hljs-number">5000</span>:<span class="hljs-number">6000</span> # 转发 pod 中的 <span class="hljs-number">6000</span> 端口到本地的 <span class="hljs-number">5000</span> 端口</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> exec nginx-pod -- ls / # 在已存在的容器中执行命令(只有一个容器的情况下)</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> exec nginx-pod -c my-container -- ls / # 在已存在的容器中执行命令(pod 中有多个容器的情况下)</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> top pod POD_NAME --containers # 显示指定 pod和容器的指标度量</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> exec -ti podName /bin/bash # 进入pod</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 调度配置</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> cordon k8s-node # 标记 my-node 不可调度</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> drain k8s-node # 清空 my-node 以待维护</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> uncordon k8s-node # 标记 my-node 可调度</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> top node k8s-node # 显示 my-node 的指标度量</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> cluster-info dump # 将当前集群状态输出到 <span class="hljs-built_in">stdout</span> </span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> cluster-info dump --output-directory=/path/to/cluster-state # 将当前集群状态输出到 /path/to/cluster-state</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment">#如果该键和影响的污点(taint)已存在,则使用指定的值替换</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> taint nodes foo dedicated=special-user:NoSchedule</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment">#查看kubelet进程启动参数</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">ps</span></span><span class="hljs-comment"> -ef | grep kubelet</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__comment"><span class="hljs-comment"># 查看日志:</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">journalctl</span></span><span class="hljs-comment"> -u kubelet -f</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment">导出配置文件:</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment"> 导出</span><span class="code-snippet__attribute"><span class="hljs-comment">proxy</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment"> </span><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> get ds -n kube-system -l k8s-app=kube-proxy -o yaml>kube-proxy-ds.yaml</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment"> 导出</span><span class="code-snippet__attribute"><span class="hljs-comment">kube</span></span><span class="hljs-comment">-dns</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment"> </span><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> get deployment -n kube-system -l k8s-app=kube-dns -o yaml >kube-dns-dp.yaml</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment"> </span><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> get services -n kube-system -l k8s-app=kube-dns -o yaml >kube-dns-services.yaml</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment"> 导出所有 </span><span class="code-snippet__attribute"><span class="hljs-comment">configmap</span></span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment"> </span><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> get configmap -n kube-system -o wide -o yaml > configmap.yaml</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><br></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment">复杂操作命令:</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment"> 删除</span><span class="code-snippet__attribute"><span class="hljs-comment">kube</span></span><span class="hljs-comment">-system 下Evicted状态的所有pod:</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">kubectl</span></span><span class="hljs-comment"> get pods -n kube-system |grep Evicted| awk ‘{print </span><span class="code-snippet__number"><span class="hljs-comment">$<span class="hljs-number">1</span></span></span><span class="hljs-comment">}’|xargs kubectl <span class="hljs-keyword">delete</span> pod -n kube-system</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment">以下为维护环境相关命令:</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="hljs-comment">重启</span><span class="code-snippet__attribute"><span class="hljs-comment">kubelet</span></span><span class="hljs-comment">服务</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">systemctl</span></span><span class="hljs-comment"> daemon-reload</span></span></code><code class="hljs" style="display:block;"><span class="code-snippet_outer"><span class="code-snippet__attribute"><span class="hljs-comment">systemctl</span></span><span class="hljs-comment"> restart kubelet</span></span></code></pre></section><section>整理不易,江湖规矩:点赞、转发选一个!<br></section><p><br></p></section><section powered-by="xiumi.us" style="font-size: 16px;margin-top: 10px;margin-bottom: 10px;white-space: normal;text-align: right;box-sizing: border-box;"><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484740&idx=1&sn=0683fbf63643218045c1b8cd522137ec&chksm=fe7b0a78c90c836e85c254cce4b8c6897579fd4f6a1386b59084b6fe4cfdd3a72bbcbfbce96f&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" style="background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;text-align: justify;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" hasload="1"></a><br></section></section>
作者:微信小助手
<section> <section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.2777777777777778" src="/upload/93ad3e05febf8f9d4acbdee687babb8.gif" data-type="gif" data-w="1080" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <blockquote data-tool="mdnice编辑器" style="font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <ul style="" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="font-size: 16px;line-height: 26px;color: rgb(89, 89, 89);">你有一个思想,我有一个思想,我们交换后,一个人就有两个思想</p></section> </li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="font-size: 16px;line-height: 26px;color: rgb(89, 89, 89);">If you can NOT explain it simply, you do NOT understand it well enough</p></section> </li> </ul> </blockquote> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">现陆续将Demo代码和技术文章整理在一起 Github实践精选 (https://github.com/FraserYu/learnings),方便大家阅读查看,觉得不错,还请Star🌟</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.18518518518518517" src="/upload/f5db925f5edacf442d54e3825debb0be.gif" data-type="gif" data-w="1080" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">抗击疫情,在家办公。工作照常干,领导需要几个新功能接口开发。以前在公司办公,通常开发完的功能没什么问题,暴露出 Swagger 接口文档,直接找旁边的前端大人联调测试了</p> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">当下,君在长江头,我在长江尾,夜夜思君不敢出门见君啊,一切测试全交给自己吧,</p> <img data-ratio="1" src="/upload/cb3fa1f4e55babba9f183bcbfd71a4c2.png" data-type="png" data-w="720" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;zoom: 50%;"> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">虽然想念前端,但是在家办公也绝对是和在公司办公一样一样的,高效不(qu)摸鱼</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 24px;line-height: 1.5em;margin-top: 2.2em;margin-bottom: 35px;"> <span style="display: inline-block;background-image: linear-gradient(rgb(255, 255, 255) 60%, rgb(255, 177, 27) 40%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;color: rgb(81, 81, 81);padding: 2px 13px;margin-right: 3px;height: 50%;">插播背景</span></h2> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">在多个产品线上来回穿切换着开发功能,以前用Postman的场景是这样的:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.42777777777777776" src="/upload/a9ddf98ba1ee0659ee6208cc71f3c1b1.png" data-type="png" data-w="1800" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">实际远远不止这几个文件夹来归类多个产品线的接口,Postman的功能非常强大,但是面对以下这些状况时,我觉得调试一个接口太麻烦了 (这里不讨论工具的好坏,工具是帮助我们提高效率的,每个人的需求也不一样,我只说明我个人遇到的一些情况,不喜请勿喷)</p> <ul data-tool="mdnice编辑器" style="" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">查找配置多数要通过鼠标点来点去, 与习惯文本和快捷键操作的便捷方式违背</section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">调试别人接口要导入他们的一些数据,比较麻烦</section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">多个产品线环境变量查看不直观</section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">写完接口要来回切换应用进行测试,比如(IDEA <——> Postman)</section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">快速定位接口比较麻烦</section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">......</section></li> </ul> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">无意间发现 IntelliJ IDEA 的 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">HTTP Client</code>工具刚好能解决我上面提到的一些问题,简单的说就是能直接在 IDEA 的代码编辑器中 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">创建,编辑,执行</code>HTTP请求,就像这样(如果你心动了,请继续向下看吧):</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.21246458923512748" src="/upload/af491d99c00ebeeb978dd816836d9151.gif" data-type="gif" data-w="1412" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">于是,去官网查看一番作出如下整理:</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 24px;line-height: 1.5em;margin-top: 2.2em;margin-bottom: 35px;"> <span style="display: inline-block;background-image: linear-gradient(rgb(255, 255, 255) 60%, rgb(255, 177, 27) 40%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;color: rgb(81, 81, 81);padding: 2px 13px;margin-right: 3px;height: 50%;">走进 Http Client</span></h2> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">HTTP Client 是 IDEA 默认绑定好并启用的插件,如果你那里没有启用,按照下图启用就好</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.3865461847389558" src="/upload/a51147a026730a28c66bc98cfcd29e8b.png" data-type="png" data-w="1992" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">点击菜单: <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">Tools</code>— <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">HTTP Client</code>— <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">Test RESTful Web Service</code></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5827645051194539" src="/upload/4fd6c041c432747e38ac44f1cf29572.png" data-type="png" data-w="2344" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">接下来进入下面的界面:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5955259975816203" src="/upload/718d3ddc32d2420ad9451e780f4cca28.png" data-type="png" data-w="3308" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">上图已给出提示,REST Client 是被弃用的,点击右侧的 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">Convert request to new format</code>, 进到下面界面:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5947083583884546" src="/upload/f4d6c9509773377cd78c35f95f88ef54.png" data-type="png" data-w="3326" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">默认会创建一个名为 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">rest-api.http</code>的文件,该文件被存储在 Scratches 文件夹下,为了突出主角光环,关于 Scratch Files 请官网自行查看 ( <strong style="color: black;">继续向下看不影响理解的</strong>),黄色框线的功能也非常有用,继续向下看</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 24px;line-height: 1.5em;margin-top: 2.2em;margin-bottom: 35px;"> <span style="display: inline-block;background-image: linear-gradient(rgb(255, 255, 255) 60%, rgb(255, 177, 27) 40%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;color: rgb(81, 81, 81);padding: 2px 13px;margin-right: 3px;height: 50%;">创建 HTTP request 文件</span></h2> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">刚刚提到的 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">rest-api.http</code>就是 HTTP request 文件,可以通过两种方式创建:</p> <ol data-tool="mdnice编辑器" style="" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">通过快捷键 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">⇧⌘N</code> 然后选择 <strong style="color: black;">HTTP Request</strong>. (文件存放在Scratches 文件夹)</section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">通过菜单操作 File—New—HTTP Request (文件存放在我们指定的目录下,就和我们平时创建class/package是一样一样滴)</section></li> </ol> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">如果在项目中使用,这里推荐使用第二种方式,因为它可以作为项目文件,通过 Git 提交到仓库,大家共享文件,共同维护接口请求数据,自然就不会出现调试别人接口还要导入他人数据的情况啦</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 24px;line-height: 1.5em;margin-top: 2.2em;margin-bottom: 35px;"> <span style="display: inline-block;background-image: linear-gradient(rgb(255, 255, 255) 60%, rgb(255, 177, 27) 40%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;color: rgb(81, 81, 81);padding: 2px 13px;margin-right: 3px;height: 50%;">编辑 HTTP request 文件</span></h2> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">我们模拟实际项目中场景来编辑文件</p> <ol data-tool="mdnice编辑器" style="" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">用户登录,成功后获取 Token,通常是 POST 请求</section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">用户后续访问行为都要在请求头中携带登录成功返回的 Token</section></li> </ol> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">通过点击 Add Request,选择相应的方法就可以编写啦</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.4125105663567202" src="/upload/24c1d8f534c50ad9f3bf957dbda5c9b5.png" data-type="png" data-w="2366" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">都知道,通常写一个完整的请求需要写好多内容,贴心的 IDEA 给我们提供了模版,我们只需要在 Examples 中找模版就可以啦,比如找 POST 请求的模版,选取合适的拷贝过去就可以,so easy~~~</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.7606112054329371" src="/upload/cb17b7e566f57bdc3004e105d5f0bd62.png" data-type="png" data-w="2356" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">到这里,就可以发送基本的请求了,但是,一个项目中接口众多,如何快速生成参数?如何快速切换端口?如何让登录之后的每个请求自动携带成功返回的 Token?我们需要更高级的玩法</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 24px;line-height: 1.5em;margin-top: 2.2em;margin-bottom: 35px;"> <span style="display: inline-block;background-image: linear-gradient(rgb(255, 255, 255) 60%, rgb(255, 177, 27) 40%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;color: rgb(81, 81, 81);padding: 2px 13px;margin-right: 3px;height: 50%;">HTTP Client 进阶玩法</span></h2> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;line-height: 1.4;padding-top: 10px;margin-top: 10px;margin-bottom: 5px;"> <span style="color: rgb(81, 81, 81);font-size: 1em;padding-left: 20px;border-left: 3px solid rgb(249, 191, 69);">使用环境变量</span></h3> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">在编写HTTP请求时,可以使用变量对其元素进行参数化。变量可以保存请求的host、port和path、查询参数或值、请求头值或请求体值等.</p> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">使用变量的方式非常简单,就用两个大括号包围定义好的变量就可以了,就像这样:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5132450331125827" src="/upload/a3efda68b5e913d19f523d4f42bce7c4.png" data-type="png" data-w="1208" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">当然我们也要有地方定义变量</p> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;line-height: 1.4;padding-top: 10px;margin-top: 10px;margin-bottom: 5px;"> <span style="color: rgb(81, 81, 81);font-size: 1em;padding-left: 20px;border-left: 3px solid rgb(249, 191, 69);">定义环境变量</span></h3> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">环境变量需要定义在环境文件中,环境文件有两种:</p> <ol data-tool="mdnice编辑器" style="" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">创建名为 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">rest-client.env.json</code>或者 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">http-client.env.json</code>的环境文件(其实里面就是保存 JSON 数据),该文件里可以定义用在整个项目上的所有常规变量</section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">创建名为 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">rest-client.private.env.json</code>或者 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">http-client.private.env.json</code>, 看文件名你应该也猜到这是保存敏感数据的,比如密码,token等,该文件默认是被加入到 VCS 的 ignore文件中的,同时优先级高于其他环境文件, 也就是说,该文件的变量会覆盖其他环境文件中的变量值</section></li> </ol> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">里面的文件内容就像这样</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">{ <br> <span style="color: #d19a66;line-height: 26px;">"dev"</span>: { <br> <span style="color: #d19a66;line-height: 26px;">"host"</span>: <span style="color: #98c379;line-height: 26px;">"localhost"</span>, <br> <span style="color: #d19a66;line-height: 26px;">"port"</span>: <span style="color: #d19a66;line-height: 26px;">8081</span>, <br> <span style="color: #d19a66;line-height: 26px;">"identifier"</span>: <span style="color: #98c379;line-height: 26px;">"tanrgyb"</span>, <br> <span style="color: #d19a66;line-height: 26px;">"password"</span>: <span style="color: #98c379;line-height: 26px;">"iloveu"</span> <br>}, <br> <span style="color: #d19a66;line-height: 26px;">"prod"</span>: { <br> <span style="color: #d19a66;line-height: 26px;">"host"</span>: <span style="color: #98c379;line-height: 26px;">"dayarch.top"</span>, <br> <span style="color: #d19a66;line-height: 26px;">"port"</span>: <span style="color: #d19a66;line-height: 26px;">8080</span>, <br> <span style="color: #d19a66;line-height: 26px;">"identifier"</span>: <span style="color: #98c379;line-height: 26px;">"admin"</span>, <br> <span style="color: #d19a66;line-height: 26px;">"password"</span>: <span style="color: #98c379;line-height: 26px;">"admin"</span> <br>} <br>} <br></code></pre> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">运行一下我们编写的请求吧:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.546583850931677" src="/upload/79c3d97616467419466dc469b0f0a92.png" data-type="png" data-w="966" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">IDEA自动识别多个环境,这样就可以轻而易举的切换环境,使用不同的变量值了(这皮鞋,你说亮不亮,还有更亮的)</p> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;line-height: 1.4;padding-top: 10px;margin-top: 10px;margin-bottom: 5px;"> <span style="color: rgb(81, 81, 81);font-size: 1em;padding-left: 20px;border-left: 3px solid rgb(249, 191, 69);">巧用 response handler 脚本</span></h3> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">上面提到,我们要让登录成功后的所有请求都自动携带成功返回的 Token,这样不用我们每次都手动将其添加到header中,同样有两种方式将脚本插入到请求中</p> <ul data-tool="mdnice编辑器" style="" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">内嵌方式</section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">GET host/api/test <br> <br>> {% <br>response 脚本 <br>%} <br></code></pre> <ul data-tool="mdnice编辑器" style="" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">外部文件方式(就是将内嵌的脚本抽离出到文件中)</section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">GET host/api/test <br> <br>> scripts/my-script.js <br></code></pre> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">以登录返回获取的token设置到变量中为例,看代码:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">POST http://{{host}}:{{port}}/login <br>Content-Type: application/json <br>Accept: application/json <br> <br>> {% <br>client.global.set("auth_token", response.body.result.token); <br>%} <br></code></pre> <blockquote data-tool="mdnice编辑器" style="font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <h4 style="font-weight: bold;color: black;line-height: 1.5em;margin-top: 2.2em;margin-bottom: 4px;font-size: 18px;">注意</h4> <p style="font-size: 16px;line-height: 26px;color: rgb(89, 89, 89);"> <code style="font-size: 14px;overflow-wrap: break-word;border-radius: 4px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(155, 110, 35);padding: 3px;margin: 3px;">response.body.result.token</code>是我按照我登录返回的数据结构写的,不同结构不一样,你也可以是这样的 <code style="font-size: 14px;overflow-wrap: break-word;border-radius: 4px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(155, 110, 35);padding: 3px;margin: 3px;">response.body.token</code>, response.body 之后根据你的数据结构发挥吧</p></blockquote> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">我还是不放心,把我的登录返回结构(项目中怎样设计这种结构,可以参考之前写的Springboot返回统一JSON数据格式是怎么实现的?)粘贴在此处吧,这回理解了吧?</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5228276877761414" src="/upload/e2c7a5e41d55006604a5d7324d0ed859.png" data-type="png" data-w="1358" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">接下来我们就可以愉快的在其他请求上携带这个 Token 了</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.27151051625239003" src="/upload/d19964e6e74c58f823786d8f6527ab37.png" data-type="png" data-w="1046" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <blockquote data-tool="mdnice编辑器" style="font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <h4 style="font-weight: bold;color: black;line-height: 1.5em;margin-top: 2.2em;margin-bottom: 4px;font-size: 18px;">注意</h4> <p style="font-size: 16px;line-height: 26px;color: rgb(89, 89, 89);">这里的Authorization 类型,大家根据自己的实际情况做修改,比如:Authorization: Bearer {{auth_token}}</p></blockquote> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">以上这些已经满足我的日常使用,没有进一步了解更多,更多关于 Response 脚本的用法请大家查看官网 HTTP Response reference吧</p> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">你以为到这里结束了(OMG),还有香料需要和大家分享,搭配上面功能使用更棒哦</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 24px;line-height: 1.5em;margin-top: 2.2em;margin-bottom: 35px;"> <span style="display: inline-block;background-image: linear-gradient(rgb(255, 255, 255) 60%, rgb(255, 177, 27) 40%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;color: rgb(81, 81, 81);padding: 2px 13px;margin-right: 3px;height: 50%;">辅助功能说明</span></h2> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;line-height: 1.4;padding-top: 10px;margin-top: 10px;margin-bottom: 5px;"> <span style="color: rgb(81, 81, 81);font-size: 1em;padding-left: 20px;border-left: 3px solid rgb(249, 191, 69);">RestfulToolkit</span></h3> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">RestfulToolkit 同样是个插件,在插件市场搜索安装即可</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.29868819374369326" src="/upload/5f95bfdc8d5520f5b0027ec2f4e1ef48.png" data-type="png" data-w="1982" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">安装了这个插件后,打开侧边栏,项目的所有接口信息都会展现在此处:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="1.7575187969924813" src="/upload/202654e4b75e0dc17c600b290b7a55ee.png" data-type="png" data-w="1064" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">我常用的功能就是把指定接口生成的JSON数据拷贝到 HTTP request 文件中,免去手写的麻烦了,你说方便不?</p> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">除此之外,使用快捷键 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">cmd+\</code>, 可以根据关键字快速找到接口,回车迅速到达代码接口位置,这也是带来了极大的便利</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.11829134720700986" src="/upload/f2c74eb36cdacfe2c102b2c243e96d31.png" data-type="png" data-w="1826" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;line-height: 1.4;padding-top: 10px;margin-top: 10px;margin-bottom: 5px;"> <span style="color: rgb(81, 81, 81);font-size: 1em;padding-left: 20px;border-left: 3px solid rgb(249, 191, 69);">Live Template</span></h3> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">项目中请求内容各有不同,IDEA标准提供的GET POST 请求案例可能还不能满足我们的需求,这时我们就可以利用 Live Template 定制自己的模版,迅速生成request 内容,像这样:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.3059490084985836" src="/upload/c71c9b54630d86ce2c50979424c7168f.gif" data-type="gif" data-w="1412" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;line-height: 1.4;padding-top: 10px;margin-top: 10px;margin-bottom: 5px;"> <span style="color: rgb(81, 81, 81);font-size: 1em;padding-left: 20px;border-left: 3px solid rgb(249, 191, 69);">JSON Viewer</span></h3> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">JSON Viewer是一款 Chrome浏览器插件,在浏览器 Omini-box 中输入 <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">json-viewer</code>+ <code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">Tab</code>, 粘贴json在此处,就可以对json数据进行格式化了</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.3459983831851253" src="/upload/49a055dc1b3ca541015a37bc85ff9198.png" data-type="png" data-w="2474" style="margin-right: auto;margin-left: auto;width: 100%;border-radius: 5px;display: block;margin-bottom: 15px;"></figure> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">打开开发者工具,在Network下双击某个HTTP请求,会自动在 new tab下格式化返回的json数据,免去了粘贴数据然后格式化的烦恼</p> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">关于自测接口的干货我抖的差不多了,抖抖更健康</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 24px;line-height: 1.5em;margin-top: 2.2em;margin-bottom: 35px;"> <span style="display: inline-block;background-image: linear-gradient(rgb(255, 255, 255) 60%, rgb(255, 177, 27) 40%);background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;color: rgb(81, 81, 81);padding: 2px 13px;margin-right: 3px;height: 50%;">总结</span></h2> <p data-tool="mdnice编辑器" style="margin-bottom: 20px;line-height: 1.8em;color: rgb(58, 58, 58);">再次重申,不做工具党,也没有任何批判之意,工具只是为了让我们更高效的工作,选择适合自己的。从上面的介绍中来看,IDEA HTTP client 搭配我说的几个辅助功能很好的解决了文章开头说明的几个问题,对我个人情况来说,足矣!!</p> </section> </section>
作者:微信小助手
<p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);text-align: center;"><span style="max-width: 100%;color: rgb(255, 41, 65);font-size: 14px;line-height: 22.4px;box-sizing: border-box !important;word-wrap: break-word !important;"></span><span style="orphans: 2;text-align: center;widows: 2;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;max-width: 100%;white-space: pre-wrap;font-size: 14px;color: rgb(255, 41, 65);line-height: 22.4px;box-sizing: border-box !important;overflow-wrap: break-word !important;">(给</span><span style="orphans: 2;text-align: center;widows: 2;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;max-width: 100%;white-space: pre-wrap;font-size: 14px;line-height: 22.4px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">前端大全</span><span style="orphans: 2;text-align: center;widows: 2;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;max-width: 100%;white-space: pre-wrap;font-size: 14px;color: rgb(255, 41, 65);line-height: 22.4px;box-sizing: border-box !important;overflow-wrap: break-word !important;">加星标,提升前端技能</span><span style="orphans: 2;text-align: center;widows: 2;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;max-width: 100%;white-space: pre-wrap;color: rgb(255, 41, 65);font-size: 14px;line-height: 22.4px;box-sizing: border-box !important;overflow-wrap: break-word !important;">)</span></p> <blockquote style="white-space: normal;font-variant-ligatures: normal;orphans: 2;widows: 2;"> <p><span style="font-size: 14px;">作者:Dotnet Plus 公号 / 小码甲 (本文来自作者投稿)</span></p> </blockquote> <p style="white-space: normal;font-variant-ligatures: normal;orphans: 2;widows: 2;"><span style="font-size: 15px;"></span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">Cookie是什么?cookies是你访问网站时创建的数据片段文件,通过保存浏览信息,它们使你的在线体验更加轻松。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">使用cookies,可以使你保持在线登录状态,记录你的站点偏好,并为你提供本地化支持。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 30px;font-weight: bold;font-size: 24px;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 22px;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">First-party cookies or Third-party cookies</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">第一方cookie由你访问的站点创建。该站点指的是地址栏显示的站点;</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">第三方cookie是由其他站点创建的。这些站点拥有你当前访问的网页上部分资源,如广告或图像。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">第一方/第三方cookie不是绝对的标签,而是相对于用户的上下文。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">同一cookie可以是第一方也可以是第三方,这取决于用户当时所在的网站。</p> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;border-width: initial;border-style: none;border-color: initial;color: rgb(136, 136, 136);font-size: 0.9em;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;overflow: auto;background: rgba(0, 0, 0, 0.05);line-height: 1.8;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(85, 85, 85);font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-size: 16px;color: black;line-height: 26px;display: inline;box-sizing: border-box !important;overflow-wrap: break-word !important;">为什么要提第三方cookie,这与下面的cookie的SameSite策略密切相关。</p> </blockquote> <h2 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 30px;font-weight: bold;font-size: 24px;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 22px;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">cookie的常规使用方式</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">web服务端发送给浏览器的cookie,浏览器会存储并在下次请求原服务器的时候回发cookie。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">在HTTP请求模型中以标头的形式体现:Response中<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Set-Cookie</code>标头种植cookie;Request <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Cookie</code>标头携带(该请求允许携带的)cookies</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="padding: 16px;max-width: 100%;overflow-x: auto;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;box-sizing: border-box !important;overflow-wrap: break-word !important;">HTTP/1.0 200 OK<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Content-type: text/html<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Set-Cookie: yummy_cookie=choco<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Set-Cookie: X-BAT-FullTicketId=TGT-969171-******; path=/; samesite=none; httponly<br style="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;">[page content]<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Cookie</code>标头的内容是<strong style="max-width: 100%;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">键值对</strong>(键值对才是具业务含义的cookie);同名cookie覆盖原键值,不同名cookie会追加到键值对。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="padding: 16px;max-width: 100%;overflow-x: auto;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;box-sizing: border-box !important;overflow-wrap: break-word !important;">GET /sample_page.html HTTP/1.1<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Host: www.example.org<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Cookie: yummy_cookie=choco; X-BAT-FullTicketId=TGT-969171-******<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;border-width: initial;border-style: none;border-color: initial;color: rgb(136, 136, 136);font-size: 0.9em;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;overflow: auto;background: rgba(0, 0, 0, 0.05);line-height: 1.8;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(85, 85, 85);font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-size: 16px;color: black;line-height: 26px;display: inline;box-sizing: border-box !important;overflow-wrap: break-word !important;">除了服务端响应时使用<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Set-Cookie</code>标头种植cookie,浏览器javascript也可以种植cookie</p> </blockquote> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 20px;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">cookie的种植面积</h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Domain</code>和<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Path</code>属性定义了cookie的写入范围:哪些url的请求可以携带该cookie。</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style=""> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Domain</code>指定哪些host能被种植该cookie,如果没有指定,默认是当前document location所在的host,不包含子域;如果指定了Domain,那么包括子域。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="padding: 16px;max-width: 100%;overflow-x: auto;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;box-sizing: border-box !important;overflow-wrap: break-word !important;">例如设置了Domain=bat.com, 那么类似于developer.bat.com下的url请求都会种下该cookie.<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style=""> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> Path 指定能携带该cookie的具体url。"/" 是目录分隔符,会匹配子目录. </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="padding: 16px;max-width: 100%;overflow-x: auto;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 例如设置了Path =/doc,下面的目录都会被匹配.<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> - /docs<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">- /docs/web/<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">- /docs/web/http<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 20px;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">cookie的有效时长</h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">一般情况下浏览器关闭,cookie失效;</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">可通过设置特定的Expires或者Max-Age为cookie设置相对较长的有效时间。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="padding: 16px;max-width: 100%;overflow-x: auto;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> Set-Cookie: id= a2faw; Expires=Wed,21 Oct 2015 07:12 GMT<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">当设置了过期时间,这个设置的时间是相对于浏览器而言,而非服务器。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 30px;font-weight: bold;font-size: 24px;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 22px;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">cookie与web安全息息相关</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">因为cookie是站点私有片段数据,与web上各种攻击密切相关,如XSS,CSRF.</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">根据W3c的操作规范,种植cookie时可通过某些属性限制cookie的使用方式。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 20px;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">发送cookie的物理安全</h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Secure</code>指定了发送cookie的物理安全:要求以HTTPS形式回发cookie</p> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;border-width: initial;border-style: none;border-color: initial;color: rgb(136, 136, 136);font-size: 0.9em;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;overflow: auto;background: rgba(0, 0, 0, 0.05);line-height: 1.8;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(85, 85, 85);font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-size: 16px;color: black;line-height: 26px;display: inline;box-sizing: border-box !important;overflow-wrap: break-word !important;">Chrome52+、Firefox52+已经支持Secure指令,再使用http请求已经不会携带<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Secure cookie</code>。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">即便是Secure指令, 敏感信息也不要放在cookie中, 因为他们天生就不安全,https并不能提供足够有效的安全防护。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 18px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">谁能访问cookie?</h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">web上能访问cookie的物件有两种:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style=""> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 浏览器请求 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> JavaScript </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">HttpOnly</code>指示cookie将不能通过JavaScript的<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">document.cookie</code>编程接口访问,这样可以缓解对跨站点脚本(<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">XSS</code>)的攻击。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="padding: 16px;max-width: 100%;overflow-x: auto;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;box-sizing: border-box !important;overflow-wrap: break-word !important;">如:访问会话在浏览器留置的认证cookie就没有必要暴露给JavaScript,可对其设置HttpOnly指令<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Set-Cookie: X-BAT-TicketId=TGT-969171-******; Expires=Wed, 21 Oct 2020 07:28:00 GMT; Secure; HttpOnly<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <h4 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 18px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">哪些浏览器请求能合法携带cookie?</h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">首先科普一下重要的web HTTP知识:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">对页面资源的请求,依据<strong style="max-width: 100%;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">请求发起者的源Origin与资源的源Origin的相等关系</strong>,被划分为4类。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">Http请求中<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Sec-Fetch-Site</code>标头指示了这个属性:</p> <table data-tool="mdnice编辑器" width="657"> <thead style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <tr style="max-width: 100%;border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <th style="word-break: break-all;border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(240, 240, 240);max-width: 100%;text-align: left;overflow-wrap: break-word !important;box-sizing: border-box !important;">Sec-Fetch-Site</th> <th style="word-break: break-all;border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(240, 240, 240);max-width: 100%;text-align: left;overflow-wrap: break-word !important;box-sizing: border-box !important;">描述</th> </tr> </thead> <tbody style="max-width: 100%;border-width: 0px;border-style: initial;border-color: initial;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <tr style="max-width: 100%;border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <td style="word-break: break-all;border-color: rgb(204, 204, 204);max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;">cross-site</td> <td style="word-break: break-all;border-color: rgb(204, 204, 204);max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;">请求的发起源与资源源完全不相同</td> </tr> <tr style="max-width: 100%;border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: rgb(248, 248, 248);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <td style="word-break: break-all;border-color: rgb(204, 204, 204);max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;">same-origin</td> <td style="word-break: break-all;border-color: rgb(204, 204, 204);max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;">请求的发起源与资源源完全相同</td> </tr> <tr style="max-width: 100%;border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <td style="word-break: break-all;border-color: rgb(204, 204, 204);max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;">same-site</td> <td style="word-break: break-all;border-color: rgb(204, 204, 204);max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;">请求的发起源与资源源不完全相同:同一顶级域名下的二级域名站点</td> </tr> <tr style="max-width: 100%;border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: rgb(248, 248, 248);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <td style="word-break: break-all;border-color: rgb(204, 204, 204);max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;">none</td> <td style="word-break: break-all;border-color: rgb(204, 204, 204);max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"><br></td> </tr> </tbody> </table> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;border-width: initial;border-style: none;border-color: initial;color: rgb(136, 136, 136);font-size: 0.9em;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;overflow: auto;background: rgba(0, 0, 0, 0.05);line-height: 1.8;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(85, 85, 85);font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-size: 16px;color: black;line-height: 26px;display: inline;box-sizing: border-box !important;overflow-wrap: break-word !important;">Q1. 源Origin、站Site、域Domain傻傻分不清楚?<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">观察www.cnblog.com任意一篇博文的network,看动图!</p> </blockquote> <p style="max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages __bg_gif" data-ratio="0.5037249283667622" data-s="300,640" data-type="gif" data-w="1745" src="/upload/6d3ad865d3adead0d8cb885299de80c4.gif" style="background-color: rgb(238, 237, 235);border-width: 1px;border-style: solid;border-color: rgb(238, 237, 235);background-size: 22px;background-position: center center;background-repeat: no-repeat;box-sizing: border-box !important;overflow-wrap: break-word !important;height: 331.94px !important;width: 657px !important;"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">在博客页面<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">www.cnblog.com/xxx/p/110.htm</code>上发起的<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <ol data-tool="mdnice编辑器" class="list-paddingleft-2" style=""> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">www.cnblogs.com/xxx/ajax/Follow/GetFollowStatus.aspx</code>是same-origin请求 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">blog-static.cnblogs.com/files/shwee/clock.js</code>是same-site请求 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">www.google-analytics.com/r/collect?v=1&_v=j81&a=38982783&t=pageview&_s=1</code>是cross-site请求 </section></li> </ol> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;border-width: initial;border-style: none;border-color: initial;color: rgb(136, 136, 136);font-size: 0.9em;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;overflow: auto;background: rgba(0, 0, 0, 0.05);line-height: 1.8;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(85, 85, 85);font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-size: 16px;color: black;line-height: 26px;display: inline;box-sizing: border-box !important;overflow-wrap: break-word !important;">Q2. 聊cookie为什么要提到<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Sec-Fetch-Site</code>标头?<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">答:B站页面在请求A站资源时能否携带A站cookie(<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">第三方cookie</code>)不仅是一个道德问题;技术上还牵涉web安全(CSRF)。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">针对以上的请求类型,浏览器针对cookie有<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">SameSite</code>属性,提供针对跨站点请求伪造攻击(<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">CSRF</code>)的保护。<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.65" data-type="png" data-w="600" src="/upload/e6f18af63f6efd1c78d9ec2247839d7f.png" style="margin-right: auto;margin-left: auto;display: block;width: 657px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">在服务端<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Set-Cookie</code>种植cookie时,<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">SmmeSite</code>属性值可指示<strong style="max-width: 100%;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">浏览器是否可在后续的“同一站点”或“跨站点”请求中携带这些cookie</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="padding: 16px;max-width: 100%;overflow-x: auto;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;box-sizing: border-box !important;overflow-wrap: break-word !important;">Set-Cookie: X-BAT-TicketId=<span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">TGT-969171-******</span>; path=/; samesite=none; httponly<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">有如下枚举值:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style=""> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> Lax : 对同源、顶级域的请求才可以携带cookie (等价于same-site) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> Strict: 对同源请求才可以使携带cookie (等价于same-origin) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> None:对于cookie的使用无限制,随便使用 </section></li> </ul> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;border-width: initial;border-style: none;border-color: initial;color: rgb(136, 136, 136);font-size: 0.9em;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;overflow: auto;background: rgba(0, 0, 0, 0.05);line-height: 1.8;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(85, 85, 85);font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-size: 16px;color: black;line-height: 26px;display: inline;box-sizing: border-box !important;overflow-wrap: break-word !important;">最新的IEEF cookie SameSite策略:</p> <ul class="list-paddingleft-2" style=""> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 敦促浏览器版本迁移,使cookie的SameSite默认= Lax </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 如果需要跨域发送cookie,请使用None枚举值选择 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">无SameSite限制</code>, None指令需要搭配 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Secure</code>指令 <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Tip:None枚举值是标准新增枚举值,一些旧浏览器不识别这个枚举值,可能导致一些问题. </section></li> </ul> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">总之,IEEF配合浏览器给cookie的存取、使用、传输、规定了一套策略,环环相扣,促进了web上cookie的平衡应用。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 30px;font-weight: bold;font-size: 24px;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 22px;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;">总结输出</span></h2> <ol data-tool="mdnice编辑器" class="list-paddingleft-2" style=""> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 第一方cookie vs 第三方cookie的认定:取决于 <strong style="max-width: 100%;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">访客所处的上下文</strong> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> cookie的常规用法 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 根据源Origin、站Site、域Domain,请求被划分为4大类,关注HTTP <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">Sec-Fetch-Site</code>标头 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 服务器在种植cookie时,可对cookie设置SameSite属性,故 <strong style="max-width: 100%;color: rgb(71, 193, 168);box-sizing: border-box !important;overflow-wrap: break-word !important;">SameSite作用对象是cookie</strong> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> SameSite属性决定了后续的跨域/跨站请求是否可以携带B站cookie,缓解了CSRF攻击 </section></li> </ol> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;color: rgb(1, 1, 1);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;"> </section> <ul class="list-paddingleft-2" style=""> <li><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies</p></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-Fetch-Site </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> https://web.dev/samesite-cookies-explained </section></li> </ul> <p style="white-space: normal;font-variant-ligatures: normal;orphans: 2;widows: 2;"><span style="font-size: 15px;"></span><br></p> <p style="white-space: normal;font-variant-ligatures: normal;orphans: 2;widows: 2;"><span style="font-size: 15px;"><br></span></p> <section powered-by="xiumi.us" style="white-space: normal;max-width: 100%;box-sizing: border-box;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;font-size: 17px;font-variant-ligatures: normal;letter-spacing: 0.544px;orphans: 2;text-align: justify;widows: 2;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section style="padding-right: 5px;padding-left: 5px;max-width: 100%;box-sizing: border-box;font-size: 14px;letter-spacing: 0px;line-height: 2;overflow-wrap: break-word !important;"> <br> </section> </section> </section> <section donone="shifuMouseDownCard('shifu_c_030')" label="Copyright Reserved by PLAYHUDONG." style="margin-top: 1em;margin-bottom: 1em;white-space: normal;text-align: start;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);border-width: 0px;border-style: initial;border-color: initial;"> <section style="margin-left: 1em;line-height: 1.4;"> <span style="padding: 3px 8px;border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;color: rgb(255, 255, 255);background-color: rgb(255, 105, 31);font-family: inherit;text-align: inherit;text-decoration: inherit;font-size: 16px;">推荐阅读</span> <span style="margin-left: 4px;padding: 3px 8px;border-top-left-radius: 1.2em;border-top-right-radius: 1.2em;border-bottom-right-radius: 1.2em;border-bottom-left-radius: 1.2em;color: rgb(255, 255, 255);line-height: 1.2;background-color: rgb(204, 204, 204);font-family: inherit;text-align: inherit;text-decoration: inherit;border-color: rgb(249, 110, 87);font-size: 12px;">点击标题可跳转</span> </section> <section style="margin-top: -11px;padding: 22px 16px 16px;border-width: 1px;border-style: solid;border-color: rgb(255, 105, 31);color: rgb(51, 51, 51);font-size: 1em;font-family: inherit;text-align: inherit;text-decoration: inherit;"> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651557820&idx=1&sn=dd9595e42c7cfd8f7c5dd4dba2075687&chksm=8025587db752d16bfcf0cb4286d9d2b79488218596e2a6130ae6c7eec668d7dd56cd9ea2da27&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="font-size: 12px;text-decoration: underline;" data-linktype="2"><span style="font-size: 12px;">还分不清 Cookie、Session、Token、JWT?</span></a><br></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651556872&idx=1&sn=c7e363160dc99a5142fa3895131a8b23&chksm=80255bc9b752d2df28963884359886d1cf05a86f49f5e13eb48fdc76af23aa8495e6c81b617b&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="font-size: 12px;text-decoration: underline;" data-linktype="2"><span style="font-size: 12px;">彻底理解 cookie、session、token</span></a><br></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651555989&idx=1&sn=2846c87243761f65ad85384eb3db99cf&chksm=80255f54b752d64281a13cf263cafbfd6770f0b028740a09a252483dc08deddcc5e190f44d7b&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="font-size: 12px;text-decoration: underline;" data-linktype="2"><span style="font-size: 12px;">我遇过的最难的Cookie问题</span></a><br></p> </section> </section> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);text-align: center;"><span style="max-width: 100%;font-size: 14px;color: rgb(255, 169, 0);box-sizing: border-box !important;word-wrap: break-word !important;"><br></span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);text-align: center;"><span style="max-width: 100%;font-size: 14px;color: rgb(255, 169, 0);box-sizing: border-box !important;word-wrap: break-word !important;"><br></span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);text-align: center;"><span style="max-width: 100%;font-size: 14px;color: rgb(255, 169, 0);box-sizing: border-box !important;word-wrap: break-word !important;">觉得本文对你有帮助?请分享给更多人</span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);text-align: center;"><span style="font-size: 15px;"><span style="max-width: 100%;color: rgb(255, 169, 0);box-sizing: border-box !important;word-wrap: break-word !important;">关注「前端大全」加星标,提升前端技能</span></span></p> <p style="text-align: center;"><img data-copyright="0" data-ratio="0.75" data-s="300,640" src="/upload/2099e3111f50ebfc6cfc8f2c36e473d3.png" data-type="png" data-w="600" style=""></p> <p style="text-align: right;"><span style="font-size: 14px;">好文章,我<span style="color: rgb(255, 41, 65);">在看</span>❤️</span></p>
作者:微信小助手
<h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">为什么使用MQ?MQ的优点</h2> <p><strong>简答</strong></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p>异步处理 - 相比于传统的串行、并行方式,提高了系统吞吐量。</p></li> <li><p>应用解耦 - 系统间通过消息通信,不用关心其他系统的处理。</p></li> <li><p>流量削锋 - 可以通过消息队列长度控制请求量;可以缓解短时间内的高并发请求。</p></li> <li><p>日志处理 - 解决大量日志传输。</p></li> <li><p>消息通讯 - 消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。</p></li> </ul> <p><br></p> <p><strong>详答</strong></p> <p>主要是:解耦、异步、削峰。</p> <p><br></p> <p><strong>解耦:</strong>A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃…A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。</p> <p><br></p> <p>就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用是不需要直接同步调用接口的,如果用 MQ 给它异步化解耦。</p> <p><br></p> <p><strong>异步</strong>:A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求。如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms。</p> <p><br></p> <p><strong>削峰</strong>:减少高峰时期对服务器压力。</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">消息队列有什么优缺点?RabbitMQ有什么优缺点?</h2> <p>优点上面已经说了,就是在特殊场景下有其对应的好处,解耦、异步、削峰。</p> <p><br></p> <p>缺点有以下几个:</p> <p><br></p> <p><strong>系统可用性降低</strong></p> <p>本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低;</p> <p><br></p> <p><strong>系统复杂度提高</strong></p> <p>加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。</p> <p><br></p> <p><strong>一致性问题</strong></p> <p>A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。</p> <section style="text-indent: 2em;"> 所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。 </section> <p><br></p> <p><br></p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">你们公司生产环境用的是什么消息中间件?</h2> <p>这个首先你可以说下你们公司选用的是什么消息中间件,比如用的是RabbitMQ,然后可以初步给一些你对不同MQ中间件技术的选型分析。</p> <p><br></p> <p><strong>举个例子:</strong>比如说ActiveMQ是老牌的消息中间件,国内很多公司过去运用的还是非常广泛的,功能很强大。</p> <p><br></p> <p>但是问题在于没法确认ActiveMQ可以支撑互联网公司的高并发、高负载以及高吞吐的复杂场景,在国内互联网公司落地较少。而且使用较多的是一些传统企业,用ActiveMQ做异步调用和系统解耦。</p> <p><br></p> <p>然后你可以说说RabbitMQ,他的好处在于可以支撑高并发、高吞吐、性能很高,同时有非常完善便捷的后台管理界面可以使用。</p> <p><br></p> <p>另外,他还支持集群化、高可用部署架构、消息高可靠支持,功能较为完善。</p> <p><br></p> <p>而且经过调研,国内各大互联网公司落地大规模RabbitMQ集群支撑自身业务的case较多,国内各种中小型互联网公司使用RabbitMQ的实践也比较多。</p> <p><br></p> <p>除此之外,RabbitMQ的开源社区很活跃,较高频率的迭代版本,来修复发现的bug以及进行各种优化,因此综合考虑过后,公司采取了RabbitMQ。</p> <p><br></p> <p>但是RabbitMQ也有一点缺陷,就是他自身是基于erlang语言开发的,所以导致较为难以分析里面的源码,也较难进行深层次的源码定制和改造,毕竟需要较为扎实的erlang语言功底才可以。</p> <p><br></p> <p>然后可以聊聊RocketMQ,是阿里开源的,经过阿里的生产环境的超高并发、高吞吐的考验,性能卓越,同时还支持分布式事务等特殊场景。</p> <p><br></p> <p>而且RocketMQ是基于Java语言开发的,适合深入阅读源码,有需要可以站在源码层面解决线上生产问题,包括源码的二次开发和改造。</p> <p><br></p> <p>另外就是Kafka。Kafka提供的消息中间件的功能明显较少一些,相对上述几款MQ中间件要少很多。</p> <p><br></p> <p>但是Kafka的优势在于专为超高吞吐量的实时日志采集、实时数据同步、实时数据计算等场景来设计。</p> <p><br></p> <p>因此Kafka在大数据领域中配合实时计算技术(比如Spark Streaming、Storm、Flink)使用的较多。但是在传统的MQ中间件使用场景中较少采用。</p> <p><br></p> <p><br></p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?</h2> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.1031055900621118" data-s="300,640" src="/upload/8794f487e219ec0b1693e1a1124237e7.png" data-type="png" data-w="805" style=""></p> <p>一般的业务系统要引入 MQ,最早大家都用 ActiveMQ,但是现在确实大家用的不多了,没经过大规模吞吐量场景的验证,社区也不是很活跃,所以大家还是算了吧,我个人不推荐用这个了;</p> <p><br></p> <p>后来大家开始用 RabbitMQ,但是确实 erlang 语言阻止了大量的 Java 工程师去深入研究和掌控它,对公司而言,几乎处于不可控的状态,但是确实人家是开源的,比较稳定的支持,活跃度也高;</p> <p><br></p> <p>不过现在确实越来越多的公司会去用 RocketMQ,确实很不错,毕竟是阿里出品,但社区可能有突然黄掉的风险(目前 RocketMQ 已捐给 Apache,但 GitHub 上的活跃度其实不算高)对自己公司技术实力有绝对自信的,推荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有活跃的开源社区,绝对不会黄。</p> <p><br></p> <p>所以中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。</p> <p><br></p> <p>如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">MQ 有哪些常见问题?如何解决这些问题?</h2> <p>MQ 的常见问题有:</p> <ol class="list-paddingleft-2" style="list-style-type: decimal;"> <li><p>消息的顺序问题</p></li> <li><p>消息的重复问题</p><p><br></p></li> </ol> <p><strong>消息的顺序问题</strong></p> <p>消息有序指的是可以按照消息的发送顺序来消费。</p> <p><br></p> <p>假如生产者产生了 2 条消息:M1、M2,假定 M1 发送到 S1,M2 发送到 S2,如果要保证 M1 先于 M2 被消费,怎么做?</p> <p><img data-backh="276" data-backw="578" data-ratio="0.478125" src="/upload/eb920f259834690cf838981e0e72ec95.png" data-type="png" data-w="640" style="width: 100%;height: auto;"></p> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">解决方案:</p> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">(1)保证生产者 - MQServer - 消费者是一对一对一的关系</p> <p><img data-ratio="0.4703125" src="/upload/89c3ec79de5560bb19fa45829d65d44c.png" data-type="png" data-w="640"></p> <p><strong>缺陷</strong>:</p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p>并行度就会成为消息系统的瓶颈(吞吐量不够)</p></li> <li><p>更多的异常处理,比如:只要消费端出现问题,就会导致整个处理流程阻塞,我们不得不花费更多的精力来解决阻塞的问题。(2)通过合理的设计或者将问题分解来规避。</p></li> <li><p>不关注乱序的应用实际大量存在</p></li> <li><p>队列无序并不意味着消息无序 所以从业务层面来保证消息的顺序而不仅仅是依赖于消息系统,是一种更合理的方式。</p></li> </ul> <p><br></p> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: border-box;outline: 0px;font-weight: 700;overflow-wrap: break-word;">消息的重复问题</span></p> <p>造成消息重复的根本原因是:网络不可达。</p> <p><br></p> <p>所以解决这个问题的办法就是绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?</p> <p><br></p> <p>消费端处理消息的业务逻辑保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现。利用一张日志表来记录已经处理成功的消息的 ID,如果新到的消息 ID 已经在日志表中,那么就不再处理这条消息。</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">什么是RabbitMQ?</h2> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">RabbitMQ是一款开源的,Erlang编写的,基于AMQP协议的消息中间件</p> <p><strong><span style="font-size: 24px;">rabbitmq 的使用场景</span></strong></p> <p>(1)服务间异步通信</p> <p><br></p> <p>(2)顺序消费</p> <p><br></p> <p>(3)定时任务</p> <p><br></p> <p>(4)请求削峰</p> <p><br></p> <p><strong><span style="font-size: 24px;">RabbitMQ基本概念</span></strong></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p>Broker:简单来说就是消息队列服务器实体</p></li> <li><p>Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列</p></li> <li><p>Queue:消息队列载体,每个消息都会被投入到一个或多个队列</p></li> <li><p>Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来</p></li> <li><p>Routing Key:路由关键字,exchange根据这个关键字进行消息投递</p></li> <li><p>VHost:vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。</p></li> <li><p>Producer:消息生产者,就是投递消息的程序</p></li> <li><p>Consumer:消息消费者,就是接受消息的程序</p></li> <li><p>Channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务</p></li> <li><p>由Exchange、Queue、RoutingKey三个才能决定一个从Exchange到Queue的唯一的线路。</p></li> </ul> <p><br></p> <p><br></p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">RabbitMQ的工作模式</h2> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: border-box;outline: 0px;font-weight: 700;overflow-wrap: break-word;">一.simple模式(即最简单的收发模式)</span></p> <p><img data-ratio="0.37677053824362605" src="/upload/f7165f250ab61d10489135c05724a725.png" data-type="png" data-w="353"></p> <p>1.消息产生消息,将消息放入队列</p> <p><br></p> <p>2.消息的消费者(consumer) 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除(隐患 消息可能没有被消费者正确处理,已经从队列中消失了,造成消息的丢失,这里可以设置成手动的ack,但如果设置成手动ack,处理完后要及时发送ack消息给队列,否则会造成内存溢出)。</p> <p><br></p> <p><span style="box-sizing: border-box;outline: 0px;font-weight: 700;overflow-wrap: break-word;color: rgb(77, 77, 77);font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;font-variant-ligatures: common-ligatures;text-align: start;background-color: rgb(255, 255, 255);">二.work工作模式(资源的竞争)</span></p> <p><br></p> <p><img data-ratio="0.37677053824362605" src="/upload/f7165f250ab61d10489135c05724a725.png" data-type="png" data-w="353"></p> <p>1.消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2同时监听同一个队列,消息被消费。C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息(隐患:高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize) 保证一条消息只能被一个消费者使用)。</p> <p><br></p> <p><br></p> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: border-box;outline: 0px;font-weight: 700;overflow-wrap: break-word;">三.publish/subscribe发布订阅(共享资源)</span></p> <p><br></p> <p><img data-ratio="0.4079601990049751" src="/upload/9e74ff0e9061080bf1f088457f7f3ace.png" data-type="png" data-w="402"></p> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">1、每个消费者监听自己的队列;</p> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">2、生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息。</p> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: border-box;outline: 0px;font-weight: 700;overflow-wrap: break-word;">四.routing路由模式</span></p> <p><br></p> <p><img data-ratio="0.36768149882903983" src="/upload/d3ca69e37278101f3967318fbe9bacf2.png" data-type="png" data-w="427"></p> <p>1.消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息;</p> <p><br></p> <p>2.根据业务功能定义路由字符串</p> <p><br></p> <p>3.从系统的代码逻辑中获取对应的功能字符串,将消息任务扔到对应的队列中。</p> <p><br></p> <p>4.业务场景:error 通知;EXCEPTION;错误通知的功能;传统意义的错误通知;客户通知;利用key路由,可以将程序中的错误封装成消息传入到消息队列中,开发者可以自定义消费者,实时接收错误;</p> <p><br></p> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="box-sizing: border-box;outline: 0px;font-weight: 700;overflow-wrap: break-word;">五.topic 主题模式(路由模式的一种)</span></p> <p><br></p> <p><img data-ratio="0.32238193018480493" src="/upload/1258e3c721741b488e1436ef45718d97.png" data-type="png" data-w="487"></p> <p>1.星号井号代表通配符</p> <p><br></p> <p>2.星号代表多个单词,井号代表一个单词</p> <p><br></p> <p>3.路由功能添加模糊匹配</p> <p><br></p> <p>4.消息产生者产生消息,把消息交给交换机</p> <p><br></p> <p>5.交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费</p> <p>(在我的理解看来就是routing查询的一种模糊匹配,就类似sql的模糊查询方式)</p> <p><br></p> <p><strong><span style="font-size: 24px;">如何保证RabbitMQ消息的顺序性?</span></strong></p> <p>拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,确实是麻烦点;或者就一个 queue 但是对应一个 consumer,然后这个 consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理。</p> <p><br></p> <p><br></p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">消息如何分发?</h2> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息只会分发给一个订阅的消费者(前提是消费者能够正常处理消息并进行确认)。通过路由可实现多消费的功能</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">消息怎么路由?</h2> <p>消息提供方->路由->一至多个队列消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。通过队列路由键,可以把队列绑定到交换器上。消息到达交换器后,RabbitMQ 会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则);</p> <p><br></p> <p>常用的交换器主要分为一下三种:</p> <p><br></p> <p>fanout:如果交换器收到消息,将会广播到所有绑定的队列上</p> <p><br></p> <p>direct:如果路由键完全匹配,消息就被投递到相应的队列</p> <p><br></p> <p>topic:可以使来自不同源头的消息能够到达同一个队列。使用 topic 交换器时,可以使用通配符</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">消息基于什么传输?</h2> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ 使用信道的方式来传输数据。信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制。</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">如何保证消息不被重复消费?或者说,如何保证消息消费时的幂等性?</h2> <p>先说为什么会重复消费:正常情况下,消费者在消费消息的时候,消费完毕后,会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除;</p> <p><br></p> <p>但是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。</p> <p><br></p> <p>针对以上问题,一个解决思路是:保证消息的唯一性,就算是多次传输,不要让消息的多次消费带来影响;保证消息等幂性;</p> <p><br></p> <p>比如:在写入消息队列的数据做唯一标示,消费消息时,根据唯一标识判断是否消费过;</p> <p><br></p> <p>假设你有个系统,消费一条消息就往数据库里插入一条数据,要是你一个消息重复两次,你不就插入了两条,这数据不就错了?但是你要是消费到第二次的时候,自己判断一下是否已经消费过了,若是就直接扔了,这样不就保留了一条数据,从而保证了数据的正确性。</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">如何确保消息正确地发送至 RabbitMQ?如何确保消息接收方消费了消息?</h2> <p><strong>发送方确认模式</strong></p> <p><br></p> <p>将信道设置成 confirm 模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的 ID。</p> <p><br></p> <p>一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一 ID)。</p> <p><br></p> <p>如果 RabbitMQ 发生内部错误从而导致消息丢失,会发送一条 nack(notacknowledged,未确认)消息。</p> <p><br></p> <p>发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。</p> <p><br></p> <p><strong>接收方确认机制</strong></p> <p><br></p> <p>消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ 才能安全地把消息从队列中删除。</p> <p><br></p> <p>这里并没有用到超时机制,RabbitMQ 仅通过 Consumer 的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ 给了 Consumer 足够长的时间来处理消息。保证数据的最终一致性;</p> <p><br></p> <p>下面罗列几种特殊情况</p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p>如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ 会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要去重)</p></li> <li><p>如果消费者接收到消息却没有确认消息,连接也未断开,则 RabbitMQ 认为该消费者繁忙,将不会给该消费者分发更多的消息。</p></li> </ul> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">如何保证RabbitMQ消息的可靠传输?</h2> <p>消息不可靠的情况可能是消息丢失,劫持等原因;</p> <p><br></p> <p>丢失又分为:生产者丢失消息、消息列表丢失消息、消费者丢失消息;</p> <p><br></p> <p><strong>生产者丢失消息:</strong>从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息;</p> <p><br></p> <p>transaction机制就是说:发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务(channel.txCommit())。然而,这种方式有个缺点:吞吐量下降;</p> <p><br></p> <p>confirm模式用的居多:一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后;</p> <p><br></p> <p>rabbitMQ就会发送一个ACK给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了;</p> <p><br></p> <p>如果rabbitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。</p> <p><br></p> <p>消息队列丢数据:消息持久化。</p> <p><br></p> <p>处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。</p> <p><br></p> <p>这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。</p> <p><br></p> <p>这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。</p> <p><br></p> <p>那么如何持久化呢?</p> <p><br></p> <p>这里顺便说一下吧,其实也很容易,就下面两步</p> <p><br></p> <ol class="list-paddingleft-2" style="list-style-type: decimal;"> <li><p>将queue的持久化标识durable设置为true,则代表是一个持久的队列</p></li> <li><p>发送消息的时候将deliveryMode=2</p></li> </ol> <p>这样设置以后,即使rabbitMQ挂了,重启后也能恢复数据</p> <p><br></p> <p>消费者丢失消息:消费者丢数据一般是因为采用了自动确认消息模式,改为手动确认消息即可!</p> <p><br></p> <p>消费者在收到消息之后,处理消息之前,会自动回复RabbitMQ已收到消息;</p> <p><br></p> <p>如果这时处理消息失败,就会丢失该消息;</p> <p><br></p> <p>解决方案:处理消息成功后,手动回复确认消息。</p> <p><br></p> <p><br></p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">为什么不应该对所有的 message 都使用持久化机制?</h2> <p>首先,必然导致性能的下降,因为写磁盘比写 RAM 慢的多,message 的吞吐量可能有 10 倍的差距。</p> <p><br></p> <p>其次,message 的持久化机制用在 RabbitMQ 的内置 cluster 方案时会出现“坑爹”问题。矛盾点在于,若 message 设置了 persistent 属性,但 queue 未设置 durable 属性,那么当该 queue 的 owner node 出现异常后,在未重建该 queue 前,发往该 queue 的 message 将被 blackholed ;若 message 设置了 persistent 属性,同时 queue 也设置了 durable 属性,那么当 queue 的 owner node 异常且无法重启的情况下,则该 queue 无法在其他 node 上重建,只能等待其 owner node 重启后,才能恢复该 queue 的使用,而在这段时间内发送给该 queue 的 message 将被 blackholed 。</p> <p><br></p> <p>所以,是否要对 message 进行持久化,需要综合考虑性能需要,以及可能遇到的问题。若想达到 100,000 条/秒以上的消息吞吐量(单 RabbitMQ 服务器),则要么使用其他的方式来确保 message 的可靠 delivery ,要么使用非常快速的存储系统以支持全持久化(例如使用 SSD)。另外一种处理原则是:仅对关键消息作持久化处理(根据业务重要程度),且应该保证关键消息的量不会导致性能瓶颈。</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">如何保证高可用的?RabbitMQ 的集群</h2> <p>RabbitMQ 是比较有代表性的,因为是基于主从(非分布式)做高可用性的,我们就以 RabbitMQ 为例子讲解第一种 MQ 的高可用性怎么实现。RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式。</p> <p><br></p> <p>单机模式,就是 Demo 级别的,一般就是你本地启动了玩玩儿的?,没人生产用单机模式</p> <p><br></p> <p>普通集群模式,意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。你创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个 queue 的读写操作。</p> <p><br></p> <p>镜像集群模式:这种模式,才是所谓的 RabbitMQ 的高可用模式。跟普通集群模式不一样的是,在镜像集群模式下,你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上。RabbitMQ 有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。这样的话,好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个 queue 的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,第一,这个性能开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!RabbitMQ 一个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的完整数据。</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?</h2> <p>消息积压处理办法:临时紧急扩容:</p> <p><br></p> <p>先修复 consumer 的问题,确保其恢复消费速度,然后将现有 cnosumer 都停掉。</p> <p>新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量。</p> <p>然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。</p> <p>接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据。</p> <p>等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。</p> <p>MQ中消息失效:假设你用的是 RabbitMQ,RabbtiMQ 是可以设置过期时间的,也就是 TTL。如果消息在 queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 mq 里,而是大量的数据会直接搞丢。我们可以采取一个方案,就是批量重导,这个我们之前线上也有类似的场景干过。就是大量积压的时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,比如大家一起喝咖啡熬夜到晚上12点以后,用户都睡觉了。这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出来,然后重新灌入 mq 里面去,把白天丢的数据给他补回来。也只能是这样了。假设 1 万个订单积压在 mq 里面,没有处理,其中 1000 个订单都丢了,你只能手动写程序把那 1000 个订单给查出来,手动发到 mq 里去再补一次。</p> <p><br></p> <p>mq消息队列块满了:如果消息积压在 mq 里,你很长时间都没有处理掉,此时导致 mq 都快写满了,咋办?这个还有别的办法吗?没有,谁让你第一个方案执行的太慢了,你临时写程序,接入数据来消费,消费一个丢弃一个,都不要了,快速消费掉所有的消息。然后走第二个方案,到了晚上再补数据吧。</p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">设计MQ思路</h2> <p>比如说这个消息队列系统,我们从以下几个角度来考虑一下:</p> <p><br></p> <p>首先这个 mq 得支持可伸缩性吧,就是需要的时候快速扩容,就可以增加吞吐量和容量,那怎么搞?设计个分布式的系统呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了?</p> <p><br></p> <p>其次你得考虑一下这个 mq 的数据要不要落地磁盘吧?那肯定要了,落磁盘才能保证别进程挂了数据就丢了。那落磁盘的时候怎么落啊?顺序写,这样就没有磁盘随机读写的寻址开销,磁盘顺序读写的性能是很高的,这就是 kafka 的思路。</p> <p><br></p> <p>其次你考虑一下你的 mq 的可用性啊?这个事儿,具体参考之前可用性那个环节讲解的 kafka 的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务。</p> <p><br></p> <p>能不能支持数据 0 丢失啊?可以的,参考我们之前说的那个 kafka 数据零丢失方案。</p> <p></p> <p><img src="/upload/dc8e3642ddbd4929ec2f7ede5eacac04.png" data-type="png" data-ratio="0.4875207986688852" data-w="601"></p>
作者:微信小助手
<section data-mpa-template="t" mpa-paragraph-type="ignored" style="max-width: 100%;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;white-space: normal;color: rgb(62, 62, 62);font-size: 15px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;" data-mpa-powered-by="yiban.io"> <p data-mpa-powered-by="yiban.io" style="white-space: normal;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;background-color: rgb(255, 255, 255);text-align: center;"><strong style="letter-spacing: 0.544px;color: rgba(0, 0, 0, 0.498);font-size: 15px;widows: 1;"><span style="font-size: 14px;color: rgb(136, 136, 136);">点击上方“JavaGuide</span></strong><strong style="letter-spacing: 0.544px;color: rgba(0, 0, 0, 0.498);font-size: 15px;widows: 1;"><span style="font-size: 14px;color: rgb(136, 136, 136);">”,选择<strong style="color: rgba(0, 0, 0, 0.498);font-size: 15px;letter-spacing: 0.544px;">“</strong><span style="font-size: 15px;letter-spacing: 0.544px;color: rgb(120, 172, 254);"><strong><span style="font-size: 14px;">星标</span></strong></span><strong style="color: rgba(0, 0, 0, 0.498);font-size: 15px;letter-spacing: 0.544px;">”</strong></span></strong></p> <p style="white-space: normal;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;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;widows: 1;text-align: center;"><br></p> <p data-darkmode-color="rgb(230, 230, 230)" data-style="white-space: normal; color: rgb(0, 0, 0); font-family: PingFangSC-Light; font-size: 16px; text-align: center;" class="js_darkmode__2" style="white-space: normal;text-align: center;"><strong style="letter-spacing: 0.544px;color: rgba(0, 0, 0, 0.498);font-size: 15px;widows: 1;"><span style="font-size: 14px;color: rgb(136, 136, 136);">回复”</span></strong><strong style="letter-spacing: 0.544px;color: rgba(0, 0, 0, 0.498);font-size: 15px;widows: 1;"><span style="font-size: 14px;color: rgb(136, 136, 136);"><span style="font-size: 15px;letter-spacing: 0.544px;color: rgb(120, 172, 254);"><strong><span style="letter-spacing: 0.544px;font-size: 14px;">面试突击</span></strong></span></span></strong><strong style="letter-spacing: 0.544px;color: rgba(0, 0, 0, 0.498);font-size: 15px;widows: 1;"><span style="font-size: 14px;color: rgb(136, 136, 136);">“获取Github 68k+ Star项目精华集合而成的《Java面试突击》</span></strong></p> <p style="white-space: normal;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;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;widows: 1;text-align: center;"><br></p> <p style="white-space: normal;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;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;widows: 1;text-align: center;"><strong><span style="font-size: 14px;color: rgb(136, 136, 136);"><img data-ratio="0.6635416666666667" src="/upload/92633b1c470e8527b6061882051d35ec.png" data-type="png" data-w="960" height="554" width="960"></span></strong></p> <section data-mpa-template="t" mpa-paragraph-type="ignored" style="max-width: 100%;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;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 10px;margin-bottom: 5px;max-width: 100%;letter-spacing: 0.544px;color: rgb(62, 62, 62);font-size: 15px;text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;white-space: pre-line;font-size: 12px;color: rgb(178, 178, 178);box-sizing: border-box !important;overflow-wrap: break-word !important;">作者 | likai</span> </section> <section style="margin-top: 5px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;color: rgb(62, 62, 62);font-size: 15px;text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(178, 178, 178);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-size: 12px;white-space: pre-line;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">来源 | https://urlify.cn/EvUj2m</span> </section> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.4620505992010652" data-s="300,640" src="/upload/bbdef139b083bd2237db52b789d1153.png" data-type="png" data-w="1502" style=""></p> </section> <h3 style="margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 20px;text-align: start;white-space: normal;margin-top: 20px;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;"><span style="color: rgb(74, 74, 74);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-size: 16px;white-space: pre-line;letter-spacing: 0.544px;">公司有个渠道系统,专门对接三方渠道使用,没有什么业务逻辑,主要是转换报文和参数校验之类的工作,起着一个承上启下的作用。</span><br></h3> <p style="margin-top: 15px;margin-bottom: 15px;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;">最近在优化接口的响应时间,优化了代码之后,但是时间还是达不到要求;有一个诡异的100ms左右的耗时问题,在接口中打印了请求处理时间后,和调用方的响应时间还有差了100ms左右。比如程序里记录150ms,但是调用方等待时间却为250ms左右。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">下面记录下当时详细的定位&解决流程(其实解决很简单,关键在于怎么定位并找到解决问题的方法)</p> <h3 style="margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 20px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">定位过程</h3> <h4 style="margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 18px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">分析代码</h4> <p style="margin-top: 15px;margin-bottom: 15px;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;">渠道系统是一个常见的spring-boot web工程,使用了集成的tomcat。分析了代码之后,发现并没有特殊的地方,没有特殊的过滤器或者拦截器,所以初步排除是业务代码问题</p> <h4 style="margin-top: 1.5rem;margin-bottom: 1rem;color: rgb(21, 153, 87);line-height: 1.35;font-size: 18px;text-align: start;white-space: normal;font-family: Menlo, Monaco, "Source Code Pro", Consolas, Inconsolata, "Ubuntu Mono", "DejaVu Sans Mono", "Courier New", "Droid Sans Mono", "Hiragino Sans GB", 微软雅黑, monospace !important;">分析调用流程</h4> <p style="margin-top: 15px;margin-bottom: 15px;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;">出现这个问题之后,首先确认了下接口的调用流程。由于是内部测试,所以调用流程较少。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">Nginx -反向代理-> 渠道系统</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">公司是云服务器,网络走的也是云的内网。由于不明确问题的原因,所以用排除法,首先确认服务器网络是否有问题。</p> <p style="margin-top: 15px;margin-bottom: 15px;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;">先确认发送端到Nginx Host是否有问题:</p> <pre style="padding-top: 8px;padding-bottom: 6px;background: rgb(45, 45, 45);border-radius: 0px;overflow-y: auto;color: rgb(80, 97, 109);text-align: start;font-size: 10px;line-height: 12px;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><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">[</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">jboss@VM_0_139_centos </span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">~]</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">$ ping </span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">10.0</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.139</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">PING </span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">10.0</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.139</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">(</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">10.0</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.139</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">)</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">56</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">(</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">84</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">)</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> bytes of data</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">64</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> bytes </span><span style="color: rgb(204, 153, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">from</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">10.0</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.139</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> icmp_seq</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">1</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> ttl</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">64</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> time</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.029</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> ms</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">64</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> bytes </span><span style="color: rgb(204, 153, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">from</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">10.0</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.139</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> icmp_seq</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">2</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> ttl</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">64</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> time</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.041</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> ms</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">64</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> bytes </span><span style="color: rgb(204, 153, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">from</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">10.0</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.139</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> icmp_seq</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">3</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> ttl</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">64</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> time</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.040</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> ms</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">64</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> bytes </span><span style="color: rgb(204, 153, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">from</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> </span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">10.0</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">.</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.139</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">:</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> icmp_seq</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">4</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> ttl</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">64</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> time</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">=</span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">0.040</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"> ms</span></code></span></span></p></li> </ol></pre> <p style="margin-top: 15px;margin-bottom: 15px;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;">从ping结果上看,发送端到Nginx主机的延迟是无问题的,接下来查看Nginx到渠道系统的网络。</p> <pre style="padding-top: 8px;padding-bottom: 6px;background: rgb(45, 45, 45);border-radius: 0px;overflow-y: auto;color: rgb(80, 97, 109);text-align: start;font-size: 10px;line-height: 12px;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><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(153, 153, 153);line-height: 20px;font-size: 13px !important;white-space: inherit !important;"># 由于日志是没问题的,这里直接复制上面日志了</span></code></span></span></p></li> <li><p><span style="color: rgb(74, 74, 74);display: block;line-height: 22px;font-size: 14px !important;word-break: inherit !important;"><span style="line-height: 22px;display: block;word-break: inherit !important;"><code style="margin-left: -20px;display: flex;overflow: initial;line-height: 12px;overflow-wrap: normal;border-width: 0px;border-style: initial;border-color: initial;font-size: 10px;font-family: inherit !important;white-space: pre !important;"><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">[</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">jboss@VM_0_139_centos </span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">~]</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">$ ping </span><span style="color: rgb(249, 145, 87);line-height: 20px;font-size: 13px !important;white-space: inherit !important;">10.0</span><span style="color: rgb(204, 204, 204);line-height: 20px;font-size: 13px !important;white-space: inhe
作者:微信小助手
<p class="p1"><span class="s1"><strong>写在2019年后的蚂蚁、头条、拼多多的面试总结</strong></span></p> <p class="p1"><span class="s1"><strong><br></strong></span></p> <p class="p2"><span class="s1">文章有点长,请耐心看完,绝对有收获!不想听我BB直接进入面试分享:</span></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s3">准备过程</span></p></li> <li><p><span class="s3">蚂蚁金服面试分享</span></p></li> <li><p><span class="s3">拼多多面试分享</span></p></li> <li><p><span class="s3">字节跳动面试分享</span></p></li> <li><p><span class="s4">总结</span></p></li> </ul> <p><br></p> <p class="p2"><span class="s1">说起来开始进行面试是年前倒数第二周,上午9点,我还在去公司的公交上,突然收到蚂蚁的面试电话,其实算不上真正的面试。面试官只是和我聊了下他们在做的事情(主要是做双十一这里大促的稳定性保障,偏中间件吧),说的很详细,然后和我沟通了下是否有兴趣,我表示有兴趣,后面就收到正式面试的通知,最后没选择去蚂蚁表示抱歉。</span></p> <p class="p2"><br></p> <p class="p2"><span class="s1">当时我自己也准备出去看看机会,顺便看看自己的实力。当时我其实挺纠结的,一方面现在部门也正需要我,还是可以有一番作为的,另一方面觉得近一年来进步缓慢,没有以前飞速进步的成就感了,而且业务和技术偏于稳定,加上自己也属于那种比较懒散的人,骨子里还是希望能够突破现状,持续在技术上有所精进。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">在开始正式的总结之前,还是希望各位同仁能否听我继续发泄一会,抱拳!</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">我翻开自己2018年初立的flag,觉得甚是惭愧。其中就有一条是保持一周写一篇博客,奈何中间因为各种原因没能坚持下去。细细想来,主要是自己没能真正静下来心认真投入到技术的研究和学习,那么为什么会这样?说白了还是因为没有确定目标或者目标不明确,没有目标或者目标不明确都可能导致行动的失败。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">那么问题来了,目标是啥?就我而言,短期目标是深入研究某一项技术,比如最近在研究mysql,那么深入研究一定要动手实践并且有所产出,这就够了么?还需要我们能够举一反三,结合实际开发场景想一想日常开发要注意什么,这中间有没有什么坑?可以看出,要进步真的不是一件简单的事,这种反人类的行为需要我们克服自我的弱点,逐渐形成习惯。真正牛逼的人,从不觉得认真学习是一件多么难的事,因为这已经形成了他的习惯,就喝早上起床刷牙洗脸那么自然简单。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">扯了那么多,开始进入正题,先后进行了蚂蚁、拼多多和字节跳动的面试。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p1"><span class="s1"><strong>准备过程</strong></span></p> <p class="p1"><span class="s1"><strong><br></strong></span></p> <p class="p2"><span class="s1">先说说我自己的情况,我2016先在蚂蚁实习了将近三个月,然后去了我现在的老东家,2.5年工作经验,可以说毕业后就一直老老实实在老东家打怪升级,虽说有蚂蚁的实习经历,但是因为时间太短,还是有点虚的。所以面试官看到我简历第一个问题绝对是这样的。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">“哇,你在蚂蚁待过,不错啊”,面试官笑嘻嘻地问到。“是的,还好”,我说。“为啥才三个月?”,面试官脸色一沉问到。“哗啦啦解释一通。。。”,我解释道。“哦,原来如此,那我们开始面试吧”,面试官一本正经说到。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">尼玛,早知道不写蚂蚁的实习经历了,后面仔细一想,当初写上蚂蚁不就给简历加点料嘛。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">言归正传,准备过程其实很早开始了(当然这不是说我工作时老想着跳槽,因为我明白现在的老东家并不是终点,我还需要不断提升),具体可追溯到从蚂蚁离职的时候,当时出来也面了很多公司,没啥大公司,面了大概5家公司,都拿到offer了。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">工作之余常常会去额外研究自己感兴趣的技术以及工作用到的技术,力求把原理搞明白,并且会自己实践一把。此外,买了N多书,基本有时间就会去看,补补基础,什么操作系统、数据结构与算法、mysql、jdk之类的源码,基本都好好温习了(文末会列一下自己看过的书和一些好的资料)。我深知基础就像“木桶效应”的短板,决定了能装多少水。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">此外,在正式决定看机会之前,我给自己列了一个提纲,主要包括Java要掌握的核心要点,有不懂的就查资料搞懂。我给自己定位还是Java工程师,所以Java体系是一定要做到心中有数的,很多东西没有常年的积累面试的时候很容易露馅,学习要对得起自己,不要骗人。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">剩下的就是找平台和内推了,除了蚂蚁,头条和拼多多都是找人内推的,感谢蚂蚁面试官对我的欣赏,以后说不定会去蚂蚁咯😄。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">平台:脉脉、GitHub、v2</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p1"><span class="s1"><strong>蚂蚁金服</strong></span></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.4930747922437673" data-s="300,640" src="/upload/3aabf18df7607ea61ff3af8a318cbc6d.jpg" data-type="jpeg" data-w="722" style=""></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s4">一面</span></p></li> <li><p><span class="s4">二面</span></p></li> <li><p><span class="s4">三面</span></p></li> <li><p><span class="s4">四面</span></p></li> <li><p><span class="s4">五面</span></p></li> <li><p><span class="s4">小结</span></p></li> </ul> <p><span class="s4"></span></p> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>一面</strong></span></p> <p class="p2"><span class="s1">一面就做了一道算法题,要求两小时内完成,给了长度为N的有重复元素的数组,要求输出第10大的数。典型的TopK问题,快排算法搞定。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">算法题要注意的是合法性校验、边界条件以及异常的处理。另外,如果要写测试用例,一定要保证测试覆盖场景尽可能全。加上平时刷刷算法题,这种考核应该没问题的。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p6"><span class="s1"><strong>二面</strong></span></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s1">自我介绍下呗</span></p></li> <li><p><span class="s1">开源项目贡献过代码么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">Dubbo提过一个打印accesslog的bug算么</span></p></li> </ul> <li><p><span class="s1">目前在部门做什么,业务简单介绍下</span></p></li> <li><p><span class="s1">内部有哪些系统,作用和交互过程说下</span></p></li> <li><p><span class="s1">Dubbo踩过哪些坑,分别是怎么解决的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了异常处理时业务异常捕获的问题,自定义了一个异常拦截器</span></p></li> </ul> <li><p><span class="s1">开始进入正题,说下你对线程安全的理解</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">多线程访问同一个对象,如果不需要考虑额外的同步,调用对象的行为就可以获得正确的结果就是线程安全</span></p></li> </ul> <li><p><span class="s1">事务有哪些特性?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">ACID</span></p></li> </ul> <li><p><span class="s1">怎么理解原子性?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">同一个事务下,多个操作要么成功要么失败,不存在部分成功或者部分失败的情况</span></p></li> </ul> <li><p><span class="s1">乐观锁和悲观锁的区别?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">悲观锁假定会发生冲突,访问的时候都要先获得锁,保证同一个时刻只有线程获得锁,读读也会阻塞;乐观锁假设不会发生冲突,只有在提交操作的时候检查是否有冲突</span></p></li> </ul> <li><p><span class="s1">这两种锁在Java和MySQL分别是怎么实现的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">Java乐观锁通过CAS实现,悲观锁通过synchronize实现</span></p></li> <li><p><span class="s1">mysql乐观锁通过MVCC,也就是版本实现,悲观锁可以通过</span><span class="s5">select... for update</span><span class="s1">加上排它锁</span></p></li> </ul> <li><p><span class="s1">HashMap为什么不是线程安全的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">多线程操作无并发控制,顺便说了在扩容的时候多线程访问时会造成死锁,会形成一个环</span></p></li> </ul> <li><p><span class="s1">怎么让HashMap变得线程安全?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">Collections的synchronize方法包装一个线程安全的Map,或者直接用ConcurrentHashMap</span></p></li> </ul> <li><p><span class="s1">两者的区别是什么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">前者直接在put和get方法加了synchronize同步,后者采用了分段锁以及CAS支持更高的并发</span></p></li> </ul> <li><p><span class="s1">jdk1.8对ConcurrentHashMap做了哪些优化?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">插入的时候如果数组元素使用了红黑树,取消了分段锁设计,synchronize替代了Lock锁</span></p></li> </ul> <li><p><span class="s1">为什么这样优化?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">避免冲突严重时链表多长,提高查询效率,时间复杂度从O(N)提高到O(logN)</span></p></li> </ul> <li><p><span class="s1">redis主从机制了解么?怎么实现的?</span></p></li> <li><p><span class="s1">有过GC调优的经历么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">有点虚,答得不是很好</span></p></li> </ul> <li><p><span class="s1">有什么想问的么?</span></p></li> </ul> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>三面</strong></span></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s1">简单自我介绍下</span></p></li> <li><p><span class="s1">监控系统怎么做的,分为哪些模块,模块之间怎么交互的?</span></p></li> <li><p><span class="s1">用的什么数据库?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">mysql</span></p></li> </ul> <li><p><span class="s1">使用什么存储引擎,为什么使用InnnoDB?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">支持事务、聚簇索引、MVCC</span></p></li> </ul> <li><p><span class="s1">订单表有做拆分么,怎么拆的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">垂直拆分和水平拆分</span></p></li> </ul> <li><p><span class="s1">水平拆分后查询过程描述下</span></p></li> <li><p><span class="s1">如果落到某个分片的数据很大怎么办?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">按照某种规则,比如哈希取模、range,将单张表拆分为多张表</span></p></li> </ul> <li><p><span class="s1">哈希取模会有什么问题么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">有的,数据分布不均,扩容缩容相对复杂<span class="Apple-converted-space"> </span></span></p></li> </ul> <li><p><span class="s1">分库分表后怎么解决读写压力?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">一主多从、多主多从</span></p></li> </ul> <li><p><span class="s1">拆分后主键怎么保证惟一?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">UUID、Snowflake算法</span></p></li> </ul> <li><p><span class="s1">Snowflake生成的ID是全局递增唯一么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">不是,只是全局唯一,单机递增</span></p></li> </ul> <li><p><span class="s1">怎么实现全局递增的唯一ID?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">讲了TDDL的一次取一批ID,然后再本地慢慢分配的做法</span></p></li> </ul> <li><p><span class="s1">Mysql的索引结构说下</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了B+树,B+树可以对叶子结点顺序查找,因为叶子结点存放了数据结点且有序</span></p></li> </ul> <li><p><span class="s1">主键索引和普通索引的区别</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">主键索引的叶子结点存放了整行记录,普通索引的叶子结点存放了主键ID,查询的时候需要做一次回表查询</span></p></li> </ul> <li><p><span class="s1">一定要回表查询么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">不一定,当查询的字段刚好是索引的字段或者索引的一部分,就可以不用回表,这也是索引覆盖的原理</span></p></li> </ul> <li><p><span class="s1">你们系统目前的瓶颈在哪里?</span></p></li> <li><p><span class="s1">你打算怎么优化?简要说下你的优化思路</span></p></li> <li><p><span class="s1">有什么想问我么?</span></p></li> </ul> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>四面</strong></span></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s1">介绍下自己</span></p></li> <li><p><span class="s1">为什么要做逆向?</span></p></li> <li><p><span class="s1">怎么理解微服务?</span></p></li> <li><p><span class="s1">服务治理怎么实现的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了限流、压测、监控等模块的实现</span></p></li> </ul> <li><p><span class="s1">这个不是中间件做的事么,为什么你们部门做?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">当时没有单独的中间件团队,微服务刚搞不久,需要进行监控和性能优化</span></p></li> </ul> <li><p><span class="s1">说说Spring的生命周期吧</span></p></li> <li><p><span class="s1">说说GC的过程</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了young gc和full gc的触发条件和回收过程以及对象创建的过程</span></p></li> </ul> <li><p><span class="s1">CMS GC有什么问题?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">并发清除算法,浮动垃圾,短暂停顿</span></p></li> </ul> <li><p><span class="s1">怎么避免产生浮动垃圾?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">记得有个VM参数设置可以让扫描新生代之前进行一次young gc,但是因为gc是虚拟机自动调度的,所以不保证一定执行。但是还有参数可以让虚拟机强制执行一次young gc</span></p></li> </ul> <li><p><span class="s1">强制young gc会有什么问题?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">STW停顿时间变长</span></p></li> </ul> <li><p><span class="s1">知道G1么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">了解一点<span class="Apple-converted-space"> </span></span></p></li> </ul> <li><p><span class="s1">回收过程是怎么样的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">young gc、并发阶段、混合阶段、full gc,说了Remember Set</span></p></li> </ul> <li><p><span class="s1">你提到的Remember Set底层是怎么实现的?</span></p></li> <li><p><span class="s1">有什么想问的么?</span></p></li> </ul> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>五面</strong></span></p> <p class="p2"><span class="s1">五面是HRBP面的,和我提前预约了时间,主要聊了之前在蚂蚁的实习经历、部门在做的事情、职业发展、福利待遇等。阿里面试官确实是具有一票否决权的,很看重你的价值观是否match,一般都比较喜欢皮实的候选人。HR面一定要诚实,不要说谎,只要你说谎HR都会去证实,直接cut了。</span></p> <p class="p2"><span class="s1"><br></span></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s1">之前蚂蚁实习三个月怎么不留下来?</span></p></li> <li><p><span class="s1">实习的时候主管是谁?</span></p></li> <li><p><span class="s1">实习做了哪些事情?(尼玛这种也问?)</span></p></li> <li><p><span class="s1">你对技术怎么看?平时使用什么技术栈?(阿里HR真的是既当爹又当妈,😂)</span></p></li> <li><p><span class="s1">最近有在研究什么东西么</span></p></li> <li><p><span class="s1">你对SRE怎么看</span></p></li> <li><p><span class="s1">对待遇有什么预期么</span></p></li> </ul> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">最后HR还对我说目前稳定性保障部挺缺人的,希望我尽快回复。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p6"><span class="s1"><strong>小结</strong></span></p> <p class="p2"><span class="s1">蚂蚁面试比较重视基础,所以Java那些基本功一定要扎实。蚂蚁的工作环境还是挺赞的,因为我面的是稳定性保障部门,还有许多单独的小组,什么三年1班,很有青春的感觉。面试官基本水平都比较高,基本都P7以上,除了基础还问了不少架构设计方面的问题,收获还是挺大的。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p1"><span class="s1"><strong>拼多多</strong></span></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.38292011019283745" data-s="300,640" src="/upload/112d5f2bef05f595c6c668434391baa.jpg" data-type="jpeg" data-w="363" style=""></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s4">面试前</span></p></li> <li><p><span class="s4">一面</span></p></li> <li><p><span class="s4">二面</span></p></li> <li><p><span class="s4">三面</span></p></li> <li><p><span class="s4">小结</span></p></li> </ul> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>面试前</strong></span></p> <p class="p2"><span class="s1">面完蚂蚁后,早就听闻拼多多这个独角兽,决定也去面一把。首先我在脉脉找了一个拼多多的HR,加了微信聊了下,发了简历便开始我的拼多多面试之旅。这里要非常感谢拼多多HR小姐姐,从面试内推到offer确认一直都在帮我,人真的很nice。</span></p> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>一面</strong></span></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s1">为啥蚂蚁只待了三个月?没转正?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">转正了,解释了一通。。。</span></p></li> </ul> <li><p><span class="s1">Java中的HashMap、TreeMap解释下?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">TreeMap红黑树,有序,HashMap无序,数组+链表</span></p></li> </ul> <li><p><span class="s1">TreeMap查询写入的时间复杂度多少?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">O(logN)</span></p></li> </ul> <li><p><span class="s1">HashMap多线程有什么问题?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">线程安全,死锁</span></p></li> </ul> <li><p><span class="s1">怎么解决?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">jdk1.8用了synchronize + CAS,扩容的时候通过CAS检查是否有修改,是则重试</span></p></li> </ul> <li><p><span class="s1">重试会有什么问题么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">CAS(Compare And Swap)是比较和交换,不会导致线程阻塞,但是因为重试是通过自旋实现的,所以仍然会占用CPU时间,还有ABA的问题</span></p></li> </ul> <li><p><span class="s1">怎么解决?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">超时,限定自旋的次数,ABA可以通过原理变量AtomicStampedReference解决,原理利用版本号进行比较</span></p></li> </ul> <li><p><span class="s1">超过重试次数如果仍然失败怎么办?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">synchronize互斥锁</span></p></li> </ul> <li><p><span class="s1">CAS和synchronize有什么区别?都用synchronize不行么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">CAS是乐观锁,不需要阻塞,硬件级别实现的原子性;synchronize会阻塞,JVM级别实现的原子性。使用场景不同,线程冲突严重时CAS会造成CPU压力过大,导致吞吐量下降,synchronize的原理是先自旋然后阻塞,线程冲突严重仍然有较高的吞吐量,因为线程都被阻塞了,不会占用CPU</span></p></li> </ul> <li><p><span class="s1">如果要保证线程安全怎么办?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">ConcurrentHashMap</span></p></li> </ul> <li><p><span class="s1">ConcurrentHashMap怎么实现线程安全的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">分段锁</span></p></li> </ul> <li><p><span class="s1">get需要加锁么,为什么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">不用,volatile关键字</span></p></li> </ul> <li><p><span class="s1">volatile的作用是什么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">保证内存可见性</span></p></li> </ul> <li><p><span class="s1">底层怎么实现的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了主内存和工作内存,读写内存屏障,happen-before,并在纸上画了线程交互图</span></p></li> </ul> <li><p><span class="s1">在多核CPU下,可见性怎么保证?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">思考了一会,总线嗅探技术</span></p></li> </ul> <li><p><span class="s1">聊项目,系统之间是怎么交互的?</span></p></li> <li><p><span class="s1">系统并发多少,怎么优化?</span></p></li> <li><p><span class="s1">给我一张纸,画了一个九方格,都填了数字,给一个M*N矩阵,从1开始逆时针打印这M*N个数,要求时间复杂度尽可能低</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">(内心OS:之前貌似碰到过这题,最优解是怎么实现来着)思考中。。。</span></p></li> </ul> <li><p><span class="s1">可以先说下你的思路</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">(想起来了),说了什么时候要变换方向的条件,向右、向下、向左、向上,依此循环</span></p></li> </ul> <li><p><span class="s1">有什么想问我的?</span></p></li> </ul> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>二面</strong></span></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s1">自我介绍下</span></p></li> <li><p><span class="s1">手上还有其他offer么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">拿了蚂蚁的offer</span></p></li> </ul> <li><p><span class="s1">部门组织结构是怎样的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">。。。这轮不是技术面么,不过还是老老实实说了</span></p></li> </ul> <li><p><span class="s1">系统有哪些模块,每个模块用了哪些技术,数据怎么流转的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">(面试官有点秃顶,一看级别就很高)给了我一张纸,我在上面简单画了下系统之间的流转情况</span></p></li> </ul> <li><p><span class="s1">链路追踪的信息是怎么传递的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">RpcContext的attachment,说了Span的结构(parentSpanId + curSpanId)</span></p></li> </ul> <li><p><span class="s1">SpanId怎么保证唯一性?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">UUID,说了下内部的定制改动</span></p></li> </ul> <li><p><span class="s1">RpcContext是在什么维度传递的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">线程</span></p></li> </ul> <li><p><span class="s1">Dubbo的远程调用怎么实现的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">讲了读取配置、拼装url、创建Invoker、服务导出、服务注册以及消费者通过动态代理、filter、获取Invoker列表、负载均衡等过程(哗啦啦讲了10多分钟),我可以喝口水么</span></p></li> </ul> <li><p><span class="s1">Spring的单例是怎么实现的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">单例注册表</span></p></li> </ul> <li><p><span class="s1">怎么保证线程安全的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">HashMap + synchronize</span></p></li> </ul> <li><p><span class="s1">为什么要单独实现一个服务治理框架?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了下内部刚搞微服务不久,主要对服务进行一些监控和性能优化</span></p></li> </ul> <li><p><span class="s1">谁主导的?</span></p></li> <li><p><span class="s1">内部还在使用么?<span class="Apple-converted-space"> </span></span></p></li> <li><p><span class="s1">逆向有想过怎么做成通用么?</span></p></li> <li><p><span class="s1">有什么想问的么?</span></p></li> </ul> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>三面</strong></span></p> <p class="p2"><span class="s1">二面老大面完后就直接HR面了,主要问了些职业发展、是否有其他offer、以及入职意向等问题,顺便说了下公司的福利待遇等,都比较常规啦。不过要说的是手上有其他offer或者大厂经历会有一定加分。</span></p> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>小结</strong></span></p> <p class="p2"><span class="s1">拼多多的面试流程就简单许多,毕竟是一个成立三年多的公司。面试难度中规中矩,只要基础扎实应该不是问题。但不得不说工作强度很大,开始面试前HR就提前和我确认能否接受这样强度的工作,想来的老铁还是要做好准备</span></p> <p class="p1"><span class="s1"><strong><br></strong></span></p> <p class="p1"><span class="s1"><strong>字节跳动</strong></span></p> <p style="text-align: center;"><img class="" data-copyright="0" data-ratio="0.5111111111111111" data-s="300,640" src="/upload/cff3dc771d29100c25d525be9d8260ad.jpg" data-type="jpeg" data-w="360" style=""></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s4">面试前</span></p></li> <li><p><span class="s4">一面</span></p></li> <li><p><span class="s4">二面</span></p></li> <li><p><span class="s4">小结</span></p></li> </ul> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>面试前</strong></span></p> <p class="p2"><span class="s1">头条的面试是三家里最专业的,每次面试前有专门的HR和你约时间,确定OK后再进行面试。每次都是通过视频面试,因为都是之前都是电话面或现场面,所以视频面试还是有点不自然。也有人觉得视频面试体验很赞,当然萝卜青菜各有所爱。最坑的二面的时候对方面试官的网络老是掉线,最后很冤枉的挂了(当然有一些点答得不好也是原因之一)。所以还是有点遗憾的。</span></p> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>一面</strong></span></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s1">先自我介绍下</span></p></li> <li><p><span class="s1">聊项目,逆向系统是什么意思</span></p></li> <li><p><span class="s1">聊项目,逆向系统用了哪些技术</span></p></li> <li><p><span class="s1">线程池的线程数怎么确定?</span></p></li> <li><p><span class="s1">如果是IO操作为主怎么确定?</span></p></li> <li><p><span class="s1">如果计算型操作又怎么确定?</span></p></li> <li><p><span class="s1">Redis熟悉么,了解哪些数据结构</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了zset</span></p></li> </ul> <li><p><span class="s1">zset底层怎么实现的</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">跳表</span></p></li> </ul> <li><p><span class="s1">跳表的查询过程是怎么样的,查询和插入的时间复杂度</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了先从第一层查找,不满足就下沉到第二层找,因为每一层都是有序的,写入和插入的时间复杂度都是O(logN)</span></p></li> </ul> <li><p><span class="s1">红黑树了解么,时间复杂度</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了是N叉平衡树,O(logN)</span></p></li> </ul> <li><p><span class="s1">既然两个数据结构时间复杂度都是O(logN),zset为什么不用红黑树</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">跳表实现简单,踩坑成本低,红黑树每次插入都要通过旋转以维持平衡,实现复杂</span></p></li> </ul> <li><p><span class="s1">点了点头,说下Dubbo的原理</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了服务注册与发布以及消费者调用的过程</span></p></li> </ul> <li><p><span class="s1">踩过什么坑没有</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了dubbo异常处理的和打印accesslog的问题</span></p></li> </ul> <li><p><span class="s1">CAS了解么</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了CAS的实现</span></p></li> </ul> <li><p><span class="s1">还了解其他同步机制么</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了synchronize以及两者的区别,一个乐观锁,一个悲观锁</span></p></li> </ul> <li><p><span class="s1">那我们做一道题吧,数组A,2*n个元素,n个奇数、n个偶数,设计一个算法,使得数组奇数下标位置放置的都是奇数,偶数下标位置放置的都是偶数</span></p></li> <li><p><span class="s1">先说下你的思路</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">从0下标开始遍历,如果是奇数下标判断该元素是否奇数,是则跳过,否则从该位置寻找下一个奇数</span></p></li> </ul> <li><p><span class="s1">下一个奇数?怎么找?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">有点懵逼,思考中。。。</span></p></li> </ul> <li><p><span class="s1">有思路么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">仍然是先遍历一次数组,并对下标进行判断,如果下标属性和该位置元素不匹配从当前下标的下一个遍历数组元素,然后替换</span></p></li> </ul> <li><p><span class="s1">你这样时间复杂度有点高,如果要求O(N)要怎么做</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">思考一会,答道“定义两个指针,分别从下标0和1开始遍历,遇见奇数位是是偶数和偶数位是奇数就停下,交换内容”</span></p></li> </ul> <li><p><span class="s1">时间差不多了,先到这吧。你有什么想问我的?</span></p></li> </ul> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>二面</strong></span></p> <ul class="ul1 list-paddingleft-2" style=""> <li><p><span class="s1">面试官和蔼很多,你先介绍下自己吧</span></p></li> <li><p><span class="s1">你对服务治理怎么理解的?</span></p></li> <li><p><span class="s1">项目中的限流怎么实现的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">Guava ratelimiter,令牌桶算法</span></p></li> </ul> <li><p><span class="s1">具体怎么实现的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">要点是固定速率且令牌数有限</span></p></li> </ul> <li><p><span class="s1">如果突然很多线程同时请求令牌,有什么问题?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">导致很多请求积压,线程阻塞</span></p></li> </ul> <li><p><span class="s1">怎么解决呢?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">可以把积压的请求放到消息队列,然后异步处理</span></p></li> </ul> <li><p><span class="s1">如果不用消息队列怎么解决?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了RateLimiter预消费的策略</span></p></li> </ul> <li><p><span class="s1">分布式追踪的上下文是怎么存储和传递的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">ThreadLocal + spanId,当前节点的spanId作为下个节点的父spanId</span></p></li> </ul> <li><p><span class="s1">Dubbo的RpcContext是怎么传递的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">ThreadLocal</span></p></li> </ul> <li><p><span class="s1">主线程的ThreadLocal怎么传递到线程池?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了先在主线程通过ThreadLocal的get方法拿到上下文信息,在线程池创建新的ThreadLocal并把之前获取的上下文信息设置到ThreadLocal中。这里要注意的线程池创建的ThreadLocal要在finally中手动remove,不然会有内存泄漏的问题</span></p></li> </ul> <li><p><span class="s1">你说的内存泄漏具体是怎么产生的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了ThreadLocal的结构,主要分两种场景:主线程仍然对ThreadLocal有引用和主线程不存在对ThreadLocal的引用。第一种场景因为主线程仍然在运行,所以还是有对ThreadLocal的引用,那么ThreadLocal变量的引用和value是不会被回收的。第二种场景虽然主线程不存在对ThreadLocal的引用,且该引用是弱引用,所以会在gc的时候被回收,但是对用的value不是弱引用,不会被内存回收,仍然会造成内存泄漏</span></p></li> </ul> <li><p><span class="s1">线程池的线程是不是必须手动remove才可以回收value?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">是的,因为线程池的核心线程是一直存在的,如果不清理,那么核心线程的threadLocals变量会一直持有ThreadLocal变量</span></p></li> </ul> <li><p><span class="s1">那你说的内存泄漏是指主线程还是线程池?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">主线程<span class="Apple-converted-space"> </span></span></p></li> </ul> <li><p><span class="s1">可是主线程不是都退出了,引用的对象不应该会主动回收么?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">(面试官和内存泄漏杠上了),沉默了一会。。。</span></p></li> </ul> <li><p><span class="s1">那你说下SpringMVC不同用户登录的信息怎么保证线程安全的?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">刚才解释的有点懵逼,一下没反应过来,居然回答成锁了(大脑有点晕了,此时已经一个小时过去了,感觉情况不妙。。。)</span></p></li> </ul> <li><p><span class="s1">这个直接用ThreadLocal不就可以么,你见过SpringMVC有锁实现的代码么</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">有点晕菜。。。</span></p></li> </ul> <li><p><span class="s1">我们聊聊mysql吧,说下索引结构</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了B+树</span></p></li> </ul> <li><p><span class="s1">为什么使用B+树?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">说了查询效率高,O(logN),可以充分利用磁盘预读的特性,多叉树,深度小,叶子结点有序且存储数据</span></p></li> </ul> <li><p><span class="s1">什么是索引覆盖?</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">忘记了。。。<span class="Apple-converted-space"> </span></span></p></li> </ul> <li><p><span class="s1">Java为什么要设计双亲委派模型?</span></p></li> <li><p><span class="s1">什么时候需要自定义类加载器?</span></p></li> <li><p><span class="s1">我们做一道题吧,手写一个对象池</span></p></li> <li><p><span class="s1">有什么想问我的么</span></p></li> <ul class="ul2 list-paddingleft-2" style="list-style-type: square;"> <li><p><span class="s1">感觉我很多点都没答好,是不是挂了(结果真的是)<span class="Apple-converted-space"> </span></span></p></li> </ul> </ul> <p class="p6"><span class="s1"><strong><br></strong></span></p> <p class="p6"><span class="s1"><strong>小结</strong></span></p> <p class="p2"><span class="s1">头条的面试确实很专业,每次面试官会提前给你发一个视频链接,然后准点开始面试,而且考察的点都比较全。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">面试官都有一个特点,会抓住一个值得深入的点或者你没说清楚的点深入下去直到你把这个点讲清楚,不然面试官会觉得你并没有真正理解。二面面试官给了我一点建议,研究技术的时候一定要去研究产生的背景,弄明白在什么场景解决什么特定的问题,其实很多技术内部都是相通的。很诚恳,还是很感谢这位面试官大大。</span></p> <p class="p1"><span class="s1"><strong><br></strong></span></p> <p class="p1"><span class="s1"><strong>总结</strong></span></p> <p class="p2"><span class="s1">从年前开始面试到头条面完大概一个多月的时间,真的有点身心俱疲的感觉。最后拿到了拼多多、蚂蚁的offer,还是蛮幸运的。头条的面试对我帮助很大,再次感谢面试官对我的诚恳建议,以及拼多多的HR对我的啰嗦的问题详细解答。</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">这里要说的是面试前要做好两件事:简历和自我介绍,简历要好好回顾下自己做的一些项目,然后挑几个亮点项目。自我介绍基本每轮面试都有,所以最好提前自己练习下,想好要讲哪些东西,分别怎么讲。此外,简历提到的技术一定是自己深入研究过的,没有深入研究也最好找点资料预热下,不打无准备的仗。</span></p> <p class="p8"><span class="s6"><strong><br></strong></span></p> <p class="p8"><span class="s6"><strong>这些年看过的书</strong>:</span></p> <p class="p8"><span class="s6"><br></span></p> <p class="p2"><span class="s1">《Effective Java》、《现代操作系统》、《TCP/IP详解:卷一》、《代码整洁之道》、《重构》、《Java程序性能优化》、《Spring实战》、《Zookeeper》、《高性能MySQL》、《亿级网站架构核心技术》、《可伸缩服务架构》、《Java编程思想》</span></p> <p class="p2"><span class="s1">说实话这些书很多只看了一部分,我通常会带着问题看书,不然看着看着就睡着了,简直是催眠良药😅。</span></p> <p class="p8"><span class="s6"><strong><br></strong></span></p> <p class="p8"><span class="s6"><strong>分享一些不错的资料</strong>:</span></p> <p class="p8"><span class="s6"><br></span></p> <p class="p2"><span class="s1">极客时间APP、架构师之路(沈大大的公众号)、左耳听风专栏(陈皓的极客时间专栏),里面提了很多很有价值的资料,我统一做了汇总:<span class="s7">左耳听风资料汇总</span></span></p> <p class="p2"><span class="s1"><span class="s7"><br></span></span></p> <p class="p2"><span class="s1">最后,附一张自己面试前准备的脑图:</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p9"><span class="s8">链接:<span class="s9">https://pan.baidu.com/s/1o2l1tuRakBEP0InKEh4Hzw</span> 密码:300d</span></p> <p class="p2"><span class="s1"><br></span></p> <p class="p2"><span class="s1">全文完。</span></p> <p><br></p>