作者:微信小助手
<section data-mpa-powered-by="yiban.io"> <section> <section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="padding: 10px 10px 0px;background-color: rgb(239, 239, 239);box-sizing: border-box;"> <span style="display: inline-block;width: 5%;line-height: 0.8;font-weight: bolder;font-size: 48px;box-sizing: border-box;" title=""> <section style="box-sizing: border-box;"> “ </section></span> <section style="display: inline-block;vertical-align: top;float: right;width: 90%;line-height: 1.5;font-size: 15px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span style="letter-spacing: 1px;">上周我们在团队内部首次采用了 jwt(Json Web Token) token 这种 no-session 的方式来作用户的账号验证。</span></p> </section> <section style="clear: both;box-sizing: border-box;"> <section> <svg viewbox="0 0 1 1" style="float:left;line-height:0;width:0;vertical-align:top;"></svg> </section> </section> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: center;"><img class="rich_pages" data-galleryid="" data-ratio="0.6834462729912875" data-s="300,640" src="/upload/158dcea16c1e8a65501885f887324ac5.png" data-type="png" data-w="1033" style=""></p> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;"><em>图片来自 Pexels</em></span> <br> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我发现网上很多文章对 token 的介绍有误,所以对 cookie,session,token 作了一下对比(文中 token 指 jwt token)相信大家看完肯定有收获!</span></p> <section style="line-height: normal;"> <br> </section> <section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin: 0.5em 0px;line-height: 1.2;box-sizing: border-box;"> <section style="display: inline-block;border-color: rgb(89, 89, 89);border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">Cookie</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">1991 年 HTTP 0.9 诞生了,当时只是为了满足大家浏览 Web 文档的要求 ,所以只有 GET 请求,浏览完了就走了,两个连接之间是没有任何联系的,这也是 HTTP 为无状态的原因,因为它诞生之初就没有这个需求。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但随着交互式 Web 的兴起(所谓交互式就是你不光可以浏览,还可以登录,发评论,购物等用户操作的行为),单纯地浏览 Web 已经无法满足人们的要求。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">比如随着网上购物的兴起,需要记录用户的购物车记录,就需要有一个机制记录每个连接的关系,这样我们就知道加入购物车的商品到底属于谁了,于是 Cookie 就诞生了。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行 Session 跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">工作机制如下:</span> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-galleryid="" data-ratio="0.337248322147651" data-s="300,640" src="/upload/91da132912d0b5fa0fe4233a906716ea.jpg" data-type="jpeg" data-w="596" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">以加入购物车为例,每次浏览器请求后 server 都会将本次商品 id 存储在 Cookie 中返回给客户端,客户端会将 Cookie 保存在本地,下一次再将上次保存在本地的 Cookie 传给 server 就行了。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这样每个 Cookie 都保存着用户的商品 id,购买记录也就不会丢失了。</span> <br> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"> <img class="rich_pages" data-galleryid="" data-ratio="0.47690217391304346" data-s="300,640" src="/upload/99188c886b6f1ccc5df2e412bdb08f5f.jpg" data-type="jpeg" data-w="736" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">仔细观察上图相信你不难发现随着购物车内的商品越来越多,每次请求的 cookie 也越来越大,这对每个请求来说是一个很大的负担。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我只是想将一个商品加入购买车,为何要将历史的商品记录也一起返回给 server?购物车信息其实已经记录在 server 了,浏览器这样的操作岂不是多此一举?怎么改进呢?<br></span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin: 0.5em 0px;line-height: 1.2;box-sizing: border-box;"> <section style="display: inline-block;border-color: rgb(89, 89, 89);border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">Session</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">仔细考虑下,由于用户的购物车信息都会保存在 Server 中,所以在 Cookie 里只要保存能识别用户身份的信息,知道是谁发起了加入购物车操作即可。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这样每次请求后只要在 Cookie 里带上用户的身份信息,请求体里也只要带上本次加入购物车的商品 id,大大减少了 cookie 的体积大小。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们把这种能识别哪个请求由哪个用户发起的机制称为 Session(会话机制),生成的能识别用户身份信息的字符串称为 sessionId。<br></span> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-galleryid="" data-ratio="0.7342931937172775" data-s="300,640" src="/upload/a4607dd1db89a066c7398014fb92c77.jpg" data-type="jpeg" data-w="764" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">它的工作机制如下:</span></p> <ul style="list-style-type: disc;" class=" list-paddingleft-2"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">首先用户登录,server 会为用户生成一个 session,为其分配唯一的 sessionId,这个 sessionId 是与某个用户绑定的。</span></p><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">也就是说根据此 sessionid(假设为 abc) 可以查询到它到底是哪个用户,然后将此 sessionid 通过 cookie 传给浏览器。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">之后浏览器的每次添加购物车请求中只要在 cookie 里带上 sessionId=abc 这一个键值对即可,server 根据 sessionId 找到它对应的用户后,把传过来的商品 id 保存到 server 中对应用户的购物车即可。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">可以看到通过这种方式再也不需要在 cookie 里传所有的购物车的商品 id 了,大大减轻了请求的负担!<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">另外通过上文不难观察出 cookie 是存储在 client 的,而 session 保存在 server,sessionId 需要借助 cookie 的传递才有意义。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin: 0.5em 0px;line-height: 1.2;box-sizing: border-box;"> <section style="display: inline-block;border-color: rgb(89, 89, 89);border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">Session 的痛点</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">看起来通过 cookie+session 的方式是解决了问题, 但是我们忽略了一个问题,上述情况能正常工作是因为我们假设 server 是单机工作的。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但实际在生产上,为了保障高可用,一般服务器至少需要两台机器,通过负载均衡的方式来决定到底请求该打到哪台机器上。<br></span> </section> <section style="text-align: center;margin-bottom: 5px;"> <img class="rich_pages" data-galleryid="" data-ratio="0.6801801801801802" data-s="300,640" src="/upload/f49821c497472a324f06157ba0130cdf.jpg" data-type="jpeg" data-w="444" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如图示:客户端请求后,由负载均衡器(如 Nginx)来决定到底打到哪台机器。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">假设登录请求打到了 A 机器,A 机器生成了 session 并在 cookie 里添加 sessionId 返回给了浏览器。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">那么问题来了:下次添加购物车时如果请求打到了 B 或者 C,由于 session 是在 A 机器生成的,此时的 B,C 是找不到 session 的,那么就会发生无法添加购物车的错误,就得重新登录了,此时请问该怎么办?<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">主要有以下三种方式:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">①session 复制</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">A 生成 session 后复制到 B, C,这样每台机器都有一份 session,无论添加购物车的请求打到哪台机器,由于 session 都能找到,故不会有问题。<br></span> </section> <p style="text-align: center;margin-bottom: 5px;"><img class="rich_pages" data-galleryid="" data-ratio="0.5763358778625954" data-s="300,640" src="/upload/8081c25e8445d457c29020317827e558.jpg" data-type="jpeg" data-w="524" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">这种方式虽然可行,但缺点也很明显:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <ul style="list-style-type: disc;" class=" list-paddingleft-2"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">同一样的一份 session 保存了多份,数据冗余。<br></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果节点少还好,但如果节点多的话,特别是像阿里,微信这种由于 DAU 上亿,可能需要部署成千上万台机器,这样节点增多复制造成的性能消耗也会很大。<br></span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②session 粘连</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这种方式是让每个客户端请求只打到固定的一台机器上,比如浏览器登录请求打到 A 机器后,后续所有的添加购物车请求也都打到 A 机器上,Nginx 的 sticky 模块可以支持这种方式,支持按 ip 或 cookie 粘连等等。<br></span></p> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">如按 ip 粘连方式如下:</span> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span> </section> <section> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin: 0px;padding: 0px;"><code style="white-space:pre-wrap;overflow-wrap: break-word;margin: 0px 2px;line-height: 18px;font-size: 14px;font-weight: normal;word-spacing: 0px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);overflow-x: auto;padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">upstream tomcats {<br> ip_hash;<br> <span style="font-size: inherit;line-height: inherit;margin: 0px;padding: 0px;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">server</span> <span style="font-size: inherit;line-height: inherit;margin: 0px;padding: 0px;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">10.1.1.107</span>:<span style="font-size: inherit;line-height: inherit;margin: 0px;padding: 0px;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">88</span>;<br> <span style="font-size: inherit;line-height: inherit;margin: 0px;padding: 0px;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">server</span> <span style="font-size: inherit;line-height: inherit;margin: 0px;padding: 0px;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">10.1.1.132</span>:<span style="font-size: inherit;line-height: inherit;margin: 0px;padding: 0px;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">80</span>;<br>}<br></code></pre> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-galleryid="" data-ratio="0.5976027397260274" data-s="300,640" src="/upload/72a9d46ebcc33c28cdaeef48dd3a6c10.jpg" data-type="jpeg" data-w="584" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这样的话每个 client 请求到达 Nginx 后,只要它的 ip 不变,根据 ip hash 算出来的值会打到固定的机器上,也就不存在 session 找不到的问题了,当然不难看出这种方式缺点也是很明显,对应的机器挂了怎么办?<br></span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">③session 共享</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这种方式也是目前各大公司普遍采用的方案,将 session 保存在 redis,memcached 等中间件中,请求到来时,各个机器去这些中间件取一下 session 即可。<br></span> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-galleryid="" data-ratio="0.483974358974359" data-s="300,640" src="/upload/f5abffcb40debd758903f2af142f35da.jpg" data-type="jpeg" data-w="624" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">缺点其实也不难发现,就是每个请求都要去 redis 取一下 session,多了一次内部连接,消耗了一点性能。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">另外为了保证 redis 的高可用,必须做集群,当然了对于大公司来说,redis 集群基本都会部署,所以这方案可以说是大公司的首选了。<br></span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin: 0.5em 0px;line-height: 1.2;box-sizing: border-box;"> <section style="display: inline-block;border-color: rgb(89, 89, 89);border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">Token:no session!</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">通过上文分析我们知道通过在服务端共享 session 的方式可以完成用户的身份定位,但是不难发现也有一个小小的瑕疵:搞个校验机制我还得搭个 redis 集群?<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">大厂确实 redis 用得比较普遍,但对于小厂来说可能它的业务量还未达到用 redis 的程度,所以有没有其他不用 server 存储 session 的用户身份校验机制呢,这就是我们今天要介绍的主角:token。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">首先请求方输入自己的用户名,密码,然后 server 据此生成 token,客户端拿到 token 后会保存到本地,之后向 server 请求时在请求头带上此 token 即可。<br></span> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-galleryid="" data-ratio="0.7301324503311258" data-s="300,640" src="/upload/b5ede06ec65c4c94758326d0dce964cf.jpg" data-type="jpeg" data-w="604" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">相信大家看了上图会发现存在两个问题:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">①</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">token 只存储在浏览器中,服务端却没有存储,这样的话我随便搞个 token 传给 server 也行?<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">答:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">server 会有一套校验机制,校验这个 token 是否合法。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">怎么不像 session 那样根据 sessionId 找到 userid 呢,这样的话怎么知道是哪个用户?<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">答:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">token 本身携带 uid 信息。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">第一个问题,如何校验 token 呢?我们可以借鉴 HTTPS 的签名机制来校验。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="color: rgb(71, 193, 168);font-size: 15px;letter-spacing: 1px;">先来看 jwt token 的组成部分:</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"> <img class="rich_pages" data-galleryid="" data-ratio="0.6273006134969326" data-s="300,640" src="/upload/832b97aab2eb5833fb65bc858fa04039.jpg" data-type="jpeg" data-w="652" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">可以看到 token 主要由三部分组成:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <ul style="list-style-type: disc;" class=" list-paddingleft-2"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">header:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">指定了签名算法。<br></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">payload:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">可以指定用户 id,过期时间等非敏感数据。<br></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Signature:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">签名,server 根据 header 知道它该用哪种签名算法,再用密钥根据此签名算法对 head+payload 生成签名,这样一个 token 就生成了。<br></span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">当 server 收到浏览器传过来的 token 时,它会首先取出 token 中的 header+payload,根据密钥生成签名,然后再与 token 中的签名比对,如果成功则说明签名是合法的,即 token 是合法的。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">而且你会发现 payload 中存有我们的 userId,所以拿到 token 后直接在 payload 中就可获取 userid,避免了像 session 那样要从 redis 去取的开销。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">画外音:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">header,payload 实际上是以 base64 的形式存在的,文中为了描述方便,省去了这一步。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">你会发现这种方式确实很妙,只要 server 保证密钥不泄露,那么生成的 token 就是安全的,因为如果伪造 token 的话在签名验证环节是无法通过的,就此即可判定 token 非法。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">可以看到通过这种方式有效地避免了 token 必须保存在 server 的弊端,实现了分布式存储。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">不过需要注意的是,token 一旦由 server 生成,它就是有效的,直到过期,无法让 token 失效,除非在 server 为 token 设立一个黑名单。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在校验 token 前先过一遍此黑名单,如果在黑名单里则此 token 失效,但一旦这样做的话,那就意味着黑名单就必须保存在 server,这又回到了 session 的模式,那直接用 session 不香吗?<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">所以一般的做法是当客户端登出要让 token 失效时,直接在本地移除 token 即可,下次登录重新生成 token 就好。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">另外需要注意的是 token 一般是放在 header 的 Authorization 自定义头里,不是放在 Cookie 里的,这主要是为了解决跨域不能共享 Cookie 的问题 (下文详述)。<br></span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin: 0.5em 0px;line-height: 1.2;box-sizing: border-box;"> <section style="display: inline-block;border-color: rgb(89, 89, 89);border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">Cookie 与 Token 的简单总结</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">Cookie 有哪些局限性?</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">①</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Cookie 跨站是不能共享的,这样的话如果你要实现多应用(多系统)的单点登录(SSO),使用 Cookie 来做需要的话就很困难了(要用比较复杂的 trick 来实现)。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">画外音:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">所谓单点登录,是指在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">但如果用 token 来实现 SSO 会非常简单,如下:</span> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-galleryid="" data-ratio="0.9923664122137404" data-s="300,640" src="/upload/cc09ac3d4222230292050ce6916cb7c9.jpg" data-type="jpeg" data-w="524" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">只要在 header 中的 authorize 字段(或其他自定义)加上 token 即可完成所有跨域站点的认证。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在移动端原生请求是没有 cookie 之说的,而 sessionid 依赖于 cookie,sessionid 就不能用 cookie 来传了。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果用 token 的话,由于它是随着 header 的 authoriize 传过来的,也就不存在此问题,换句话说token 天生支持移动平台,可扩展性好。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">综上所述,token 具有存储实现简单,扩展性好这些特点。</span><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);"><br></span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">token 有哪些缺点?</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">那有人就问了,既然 token 这么好,那为什么各个大公司几乎都采用共享 session 的方式呢,可能很多人是第一次听到 token,token 不香吗?<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">token 有以下两点劣势:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><strong>①token 太长了</strong><br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">token 是 header,payload 编码后的样式,所以一般要比 sessionId 长很多,很有可能超出 cookie 的大小限制(cookie 一般有大小限制的,如 4kb)。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果你在 token 中存储的信息越长,那么 token 本身也会越长,这样的话由于你每次请求都会带上 token,对请求来是个不小的负担。<br></span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②不太安全</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">网上很多文章说 token 更安全,其实不然,细心的你可能发现了,我们说 token 是存在浏览器的,再细问,存在浏览器的哪里?<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">既然它太长放在 cookie 里可能导致 cookie 超限,那就只好放在 local storage 里。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这样会造成安全隐患,因为 local storage 这类的本地存储是可以被 JS 直接读取的。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">另外由上文也提到,token 一旦生成无法让其失效,必须等到其过期才行,这样的话如果服务端检测到了一个安全威胁,也无法使相关的 token 失效。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">所以 token 更适合一次性的命令认证,设置一个比较短的有效期。<br></span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">误解:Cookie 相比 token 更不安全,比如 CSRF 攻击。</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"><br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">首先我们需要解释下 CSRF 攻击是怎么回事。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">由于浏览器曾经认证过(cookie 里带来 sessionId 等身份认证的信息),所以被访问的网站会认为是真正的用户操作而去运行。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">比如用户登录了某银行网站(假设为 http://www.examplebank.com/,并且转账地址为 http://www.examplebank.com/withdraw?amount=1000&transferTo=PayeeName)。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">登录后 cookie 里会包含登录用户的 sessionid,攻击者可以在另一个网站上放置如下代码:<br></span> </section> <section> <pre style="font-size: inherit;color: inherit;line-height: inherit;margin: 0px;padding: 0px;"><code style="white-space:pre-wrap;overflow-wrap: break-word;margin: 0px 2px;line-height: 18px;font-size: 14px;font-weight: normal;word-spacing: 0px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);overflow-x: auto;padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;color: inherit;line-height: inherit;margin: 0px;padding: 0px;word-wrap: inherit !important;word-break: inherit !important;"><<span style="line-height: inherit;margin: 0px;padding: 0px;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">img</span> <span style="line-height: inherit;margin: 0px;padding: 0px;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">src</span>=<span style="line-height: inherit;margin: 0px;padding: 0px;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"http://www.examplebank.com/withdraw?account=Alice&amount=1000&for=Badman"</span>></span><br></code></pre> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">那么如果正常的用户误点了上面这张图片,由于相同域名的请求会自动带上 cookie。<br></span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">而 cookie 里带有正常登录用户的 sessionid,类似上面这样的转账操作在 server 就会成功,会造成极大的安全风险。<br></span> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-galleryid="" data-ratio="0.650709219858156" data-s="300,640" src="/upload/a9c532da85631d3bf7a5cd47b3f278ab.jpg" data-type="jpeg" data-w="564" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">CSRF 攻击的根本原因在于对于同样域名的每个请求来说,它的 cookie 都会被自动带上,这个是浏览器的机制决定的,所以很多人据此认定 cookie 不安全。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">使用 token 确实避免了CSRF 的问题,但正如上文所述,由于 token 保存在 local storage,它会被 JS 读取,从存储角度来看也不安全(实际上防护 CSRF 攻击的正确方式是用 CSRF token)。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">所以不管是 cookie 还是 token,从存储角度来看其实都不安全,都有暴露的风险,我们所说的安全更多的是强调传输中的安全,可以用 HTTPS 协议来传输, 这样的话请求头都能被加密,也就保证了传输中的安全。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">其实我们把 cookie 和 token 比较本身就不合理,一个是存储方式,一个是验证方式,正确的比较应该是 session vs token。<br></span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin: 0.5em 0px;line-height: 1.2;box-sizing: border-box;"> <section style="display: inline-block;border-color: rgb(89, 89, 89);border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">总结</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">session 和 token 本质上是没有区别的,都是对用户身份的认证机制,只是他们实现的校验机制不一样而已(一个保存在 server,通过在 redis 等中间件获取来校验,一个保存在 client,通过签名校验的方式来校验)。<br></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">多数场景上使用 session 会更合理,但如果在单点登录,一次性命令认证上使用 token 会更合适,最好在不同的业务场景中合理选型,才能达到事半功倍的效果。<br></span></p> <section style="line-height: normal;"> <br> </section> <p><span style="max-width: 100%;color: rgb(89, 89, 89);box-sizing: border-box !important;overflow-wrap: break-word !important;letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">作者:坤哥,前独角兽技术专家,现创业者,持续分享个人的成长收获</span></em></span><br></p> <p style="white-space: normal;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;background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;box-sizing: border-box !important;word-wrap: break-word !important;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">编辑:陶家龙</span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></p> <p><span style="max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;box-sizing: border-box !important;word-wrap: break-word !important;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;max-width: 100%;color: rgb(89, 89, 89);letter-spacing: 1px;"><em style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">出处:<span style="font-size: 14px;"><em><span style="max-width: 100%;line-height: 1.75em;color: rgb(89, 89, 89);letter-spacing: 1px;box-sizing: border-box !important;overflow-wrap: break-word !important;">转载自公众号码海(ID:seaofcode)</span></em></span></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></em></span></p> <p style="text-align: center;"><img class="rich_pages" data-galleryid="" data-ratio="0.3939393939393939" src="/upload/68aa3ae08d2acf7c5b3b2bcaeec8a13d.png" data-type="gif" data-w="660" style=""></p> <section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;"> <section style="margin: 0.5em 0px;box-sizing: border-box;"> <section style="font-size: 15px;border-style: solid;border-width: 0px 0px 1px;color: rgb(89, 89, 89);border-bottom: 1px solid rgba(215, 215, 215, 0.96);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span style="letter-spacing: 1px;"><strong>精彩文章推荐:</strong></span></p> </section> </section> </section> <section style="line-height: 2em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655846798&idx=1&sn=43970f8645974a9a68c318d07ee17eb3&chksm=bd754c598a02c54f12f3b3602e00994bde5768a6bbfefaf30e67882b1fa185b0d47a158b020b&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">记住,永远不要在MySQL中使用UTF-8</span></a> </section> <section style="line-height: 2em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655828486&idx=2&sn=eefaf2c12a2eb14cb401cb0cb1633260&chksm=bd74f7d18a037ec7f3f9ba7aa1e95baacda4ce6bfa05c2911723e21d9a7bed6702c9ca872d44&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">不了解Cookie、Session、Token?一文给你整明白</span></a> </section> <section style="line-height: 2em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655846766&idx=1&sn=2948642e86b3dbe4f0e33ea79ded517a&chksm=bd754cb98a02c5afab85019096f9a7368a4c6f0c04b2963ebc0d49c4e76e3cc190d47bf1df66&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">入职第一天,MySQL就崩了...</span></a> <br> </section> </section> </section>
作者:微信小助手
<section style="box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;"> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="140" data-source-title="作者简介 王海龙,SUSE/Rancher中国社区技术经理,负责Rancher中国技术社区的维护和运营。拥有7年的云计算领域经验,经历了OpenStack到Kubernetes的技术变革,无论底层操作系统Linux,还是虚拟化KVM或是Docker容器技术都有丰富的运维和实践经验。"> <section class="js_blockquote_digest"> <section> <p><span style="font-size: 15px;">作者简介</span></p> <p><br></p> <p><span style="font-size: 15px;">王海龙,SUSE/Rancher中国社区技术经理,负责Rancher中国技术社区的维护和运营。拥有7年的云计算领域经验,经历了OpenStack到Kubernetes的技术变革,无论底层操作系统Linux,还是虚拟化KVM或是Docker容器技术都有丰富的运维和实践经验。</span></p> </section> </section> </blockquote> <p><br></p> <section style="text-align: center;margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;width: 10%;height: auto;box-sizing: border-box;"> <img data-ratio="0.8814815" data-w="1080" src="/upload/794d3e6d36874bea041e5f548e29aaf8.jpg" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" width="100%" data-type="jpeg"> </section> </section> <section style="line-height: 2;box-sizing: border-box;" powered-by="xiumi.us"> <p style="text-align: center;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 117, 168);box-sizing: border-box;">前言</span></strong></p> <p style="text-align: center;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 117, 168);box-sizing: border-box;"><br></span></strong></p> <p style="text-align: left;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="font-size: 15px;box-sizing: border-box;">Rancher 从 v2.5.x 开始,单节点 Rancher Server 内置了 K3s 作为 local 集群,该 local 集群除了支撑 Rancher Server 运行以外,还将运行 <span style="color: rgb(0, 117, 168);box-sizing: border-box;">fleet、rancher-webhook、gitjob、coredns</span> 等组件。下图为 Rancher v2.5.8 内置 K3s 集群默认启动的组件和所需的镜像:</span></p> <p style="text-align: left;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="font-size: 15px;box-sizing: border-box;"><br style="box-sizing: border-box;"></span></p> </section> <section style="text-align: center;margin-top: 10px;margin-bottom: 10px;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.4689093" data-w="981" src="/upload/77439bce095336d3d3363b5cfdd86217.jpg" style="vertical-align: middle;max-width: 100%;box-sizing: border-box;" data-type="jpeg"> </section> </section> <section style="line-height: 2;box-sizing: border-box;" powered-by="xiumi.us"> <p style="text-align: left;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="font-size: 15px;box-sizing: border-box;"><br style="box-sizing: border-box;"></span></p> <p style="text-align: left;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="font-size: 15px;box-sizing: border-box;">其中,<span style="color: rgb(0, 117, 168);box-sizing: border-box;">docker.io/rancher/coredns-coredns</span> 和 <span style="color: rgb(0, 117, 168);box-sizing: border-box;">docker.io/rancher/pause </span>为 Rancher Server 内置的镜像,其他镜像需要在 Rancher Server 启动后到 dockerhub 去在线下载。</span></p> <p style="text-align: left;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="font-size: 15px;box-sizing: border-box;"><br style="box-sizing: border-box;"></span></p> <p style="text-align: left;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="font-size: 15px;box-sizing: border-box;">如果你的环境是离线环境,并且是通过 <span style="color: rgb(0, 117, 168);box-sizing: border-box;">docker run</span> 的方式启动 Rancher Server,会报一些镜像下载失败的日志:</span></p> <p style="text-align: left;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="font-size: 15px;box-sizing: border-box;"><br style="box-sizing: border-box;"></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="powershell"><code><span class="code-snippet_outer">E0511 08:39:56.060906 28 pod_workers.go:191] Error syncing pod d0f83155-f023-4ff6-9164-11b6b63ef4d6 ("helm-operation-t8mtl_cattle-</span></code><code><span class="code-snippet_outer">system(d0f83155-f023-4ff6-9164-11b6b63ef4d6)"), skipping: [failed to "StartContainer" for "helm" with ImagePullBackOff: "Back-</span></code><code><span class="code-snippet_outer">off pulling image \"rancher/shell:v0.1.6\"", failed to "StartContainer" for "proxy" with ImagePullBackOff: "Back-off pulling image \"rancher/shell:v0.1.6\""]</span></code></pre> </section> <section> <br> </section> <p style="text-align: left;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="font-size: 15px;box-sizing: border-box;">官网文档<strong>单节点离线安装 Rancher Server</strong></span><span style="font-size: 15px;"><span style="box-sizing: border-box;text-decoration: underline;">(</span><span style="text-decoration: underline;">http://docs.rancher
作者:微信小助手
<p style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;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 style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">点击蓝色“</span><span style="max-width: 100%;letter-spacing: 0.544px;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);box-sizing: border-box !important;overflow-wrap: break-word !important;">”关注我哟</span></span></p> <p style="margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;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 style="max-width: 100%;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);box-sizing: border-box !important;overflow-wrap: break-word !important;">星标</span><span style="max-width: 100%;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”,每天上午 09:25,干货推送!</span></span></p> <p style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;color: rgb(62, 62, 62);font-size: 14px;text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;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" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.jpg" data-type="jpeg" data-w="640" 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;" width="100%"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;text-align: left;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;letter-spacing: 0.544px;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">出处:http://www.woshipm.com/pd/1392102.html</span></span></p> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 19.2px;white-space: normal;max-width: 100%;letter-spacing: 0.544px;text-align: left;line-height: 1.5;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 24px;">概述</span></strong></h3> <section style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <span style="font-size: 16px;color: rgb(63, 63, 63);font-weight: bold;letter-spacing: 0.544px;text-align: left;">本文主</span> <span style="font-size: 16px;color: rgb(63, 63, 63);font-weight: bold;letter-spacing: 0.544px;text-align: left;">要讲述了在传统电商企业中,订单系统应承载的角色,就订单系统所包含的主要功能模块梳理了设计思路,并对订单系统未来的发展做了一些思</span> <span style="font-size: 16px;color: rgb(63, 63, 63);font-weight: bold;letter-spacing: 0.544px;text-align: left;">考</span> <span style="font-size: 16px;color: rgb(63, 63, 63);font-weight: bold;letter-spacing: 0.544px;text-align: left;">。</span> <br> </section> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;line-height: 1.5;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;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></h3> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;line-height: 1.5;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 18px;"><strong>1. 订单系统在企业中的角色</strong></span></h3> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 在搭建企业订单系统之前,需要先梳理企业整体业务系统之间的关系和订单系统上下游关系,只有划分清业务系统边界,才能确定订单系统的职责与功能,进而保证各系统之间高效简洁的工作。 </section> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;line-height: 1.5;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 18px;"><strong>2. 订单系统与各业务系统的关系</strong></span></h3> <section style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;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;text-align: left;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.6710144927536232" src="/upload/e8957f198795acc64de019271c1cec0a.png" data-type="png" data-w="690" style="margin-right: auto;margin-left: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"> </figure> </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> (1)对外系统:所有给企业外部用户使用的系统都在这一层,包括官网、普通用户使用的C端,还包括给商户使用的商家后台和在各个销售渠道进行分销的系统,比如与银行信用卡中心合作、微信合作在合作商的平台露出本企业的产品。这类系统站在与客户接触的最前线,是公司实现商业模式的桥头堡。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> (2)管理中后台:每个C端的业务形态都会有一个对应的系统模块,如负责管理平台交易的订单系统,管理优惠信息的促销系统,管理平台所有产品的产品系统,以及管理所有对外系统显示内容的内容系统等。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> (3)公共服务系统:随着企业的发展,信息化建设到达一定程度后,企业需要将通用功能服务化、平台化,以保证应用架构的合理性,提升服务效率。这类系统主要给其他应用系统提供基础服务能力支持。 </section> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;line-height: 1.5;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 18px;"><strong>3. 订单系统上下游关系</strong></span></h3> <section style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;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;text-align: left;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.33207190160832545" src="/upload/b4092eaf9ca2112d14990f50474126dd.png" data-type="png" data-w="1057" style="margin-right: auto;margin-left: auto;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;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;height: 226.149px !important;visibility: visible !important;width: 677px !important;"> </figure> </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 由此可见,订单系统对上接收用户信息,将用户信息转化为产品订单,同时管理并跟踪订单信息和数据,承载了公司整个交易线的重要对客环节。对下则衔接产品系统、促销系统、仓储系统、会员系统、支付系统等,对整个电商平台起着承上启下的作用。 </section> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;line-height: 1.5;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 18px;"><strong>4. 订单系统的业务架构</strong></span></h3> <section style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;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;text-align: left;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.2254335260115607" src="/upload/360d5948a75c3f05c79b9fd5cd7e73cd.png" data-type="png" data-w="1038" style="margin-right: auto;margin-left: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"> </figure> </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> (1)订单服务该模块的主要功能是用户日常使用的服务和页面,主要有订单列表、订单详情、在线下单等,还包括为公共业务模块提供的多维度订单数据服务。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> (2)订单逻辑订单系统的核心,起着至关重要的作用,在订单系统负责管理订单创建、订单支付、订单生产、订单确认、订单完成、取消订单等订单流程。还涉及到复杂的订单状态规则、订单金额计算规则以及增减库存规则等。在4节核心功能设计中会重点来说。 <span style="max-width: 100%;color: rgb(48, 48, 48);font-family: "Helvetica Neue", "PingFang SC", Verdana, "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans-serif;letter-spacing: 0.544px;white-space: pre-wrap;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">(架构之家公众号:</span> <span style="max-width: 100%;color: rgb(48, 48, 48);font-family: "Helvetica Neue", "PingFang SC", Verdana, "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans-serif;letter-spacing: 0.544px;white-space: pre-wrap;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">itfly8</span> <span style="max-width: 100%;color: rgb(48, 48, 48);font-family: "Helvetica Neue", "PingFang SC", Verdana, "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans-serif;letter-spacing: 0.544px;white-space: pre-wrap;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">)</span> </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> (3)底层服务信息化建设达到一定程度的企业,一般会将公司公共服务模块化,比如:产品,会构建对应的产品系统,代码、数据库,接口等相对独立。但是,这也带来了一个问题,比如:订单创建的场景下需要获取的信息分散在各个系统。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 如果需要从各个公共服务系统调用:一是会花费大量时间,二是代码的维护成本非常高。因此,订单系统接入所需的公共服务模块接口,在订单系统即可完成对接公共系统的服务。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong><span style="max-width: 100%;font-size: 24px;box-sizing: border-box !important;overflow-wrap: break-word !important;">订单系统核心功能</span></strong> </section> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;line-height: 1.5;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">1. 订单中所包含的内容信息</span></strong></h3> <section style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;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;text-align: left;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.689922480620155" src="/upload/15919f2d661dd6cf4f78ed592972c6b3.png" data-type="png" data-w="774" style="margin-right: auto;margin-left: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"> </figure> </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 为了使订单系统能够对订单进行高效、精准的管理和跟踪,订单会储存关于产品、优惠、用户、支付信息等一系列的订单实时数据,来和下游系统,如:促销、仓储、物流进行交互。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 以一个通用B2C商城的订单为例,梳理其包含的信息如下: </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 这里要注意的是订单类型,随着平台业务的不断发展,品类丰富、交易方式丰富后,需要对订单进行多维度的分类管理,同时订单类型利于订单系统的扩展性。每种订单类型将会对应一套流程及一套状态,便于对订单进行分类管理和复用。 </section> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;font-size: 19.2px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;line-height: 1.5;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 18px;">2. 流程引擎</span></strong></h3> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 流程是指从平台角度出发,将订单从创建到完成的整个流转过程进行抽象,从而形成了一套标准流程规则。而不同的产品类型或交易类型在系统中的流程会千差万别,因此为了方便对订单流程进行管理,会组建流程引擎模块。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 每套订单流程中会包含正向流程及逆向流程,正向流程可以比作一次顺利的网购体验过程中,后台系统之间的信息流转。逆向流程则是修改订单、取消订单、退款、退货等各种动作引起的后台系统流程,同时每个流程触发的条件又可分为系统触发和人工触发两种场景。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> (1)正向流程 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 以一个通用B2C商城的订单系统为例,根据其实际业务场景,其订单流程可抽象为5大步骤:订单创建>订单支付>订单生产>订单确认>订单完成。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 而每个步骤的背后,订单是如何在多系统之间交互流转的,可概括如下图: </section> <section style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;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;text-align: left;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.9546296296296296" src="/upload/c4f392ebc8cda7fa6c02b6fe138d9a73.jpg" data-type="jpeg" data-w="1080" style="margin-right: auto;margin-left: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"> </figure> </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 订单创建: </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 用户下单后,系统需要生成订单,此时需要先获取下单中涉及的商品信息,然后获取该商品所涉及到的优惠信息,如果商品不参与优惠信息,则无此环节。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 接着获取该账户的会员权益,这里要注意的是:优惠信息与会员权益的区别,比如:商品满减是优惠信息,SUPER会员全场9.8折指的是会员权益,一个是针对商品,另一个是针对账户。其次就是优惠活动的叠加规则和优先级规则等。 </section> <section style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;line-height: 1.6;color: rgb(63, 63, 63);font-family: &q
作者:微信小助手
<p data-tool="mdnice编辑器" style="padding-top: 23px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 16px;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;color: rgb(74, 74, 74);background-color: rgb(255, 255, 255);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;" data-mpa-powered-by="yiban.io"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">《对线面试官》系列目前已经连载<strong style="max-width: 100%;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">20</strong>篇啦!进度是<strong style="max-width: 100%;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">一周更新两篇</strong>,欢迎持续关注</span></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;max-width: 100%;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247483821&idx=1&sn=e9003410a8d3c8a092de0c4d2002bedd&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】Java注解</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247483823&idx=1&sn=cc887dc2c7e68a69e8d4d141c2ca9b5e&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】Java泛型</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247483854&idx=1&sn=aa450a03ac0d6e8cf12cf13d4719ede3&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】 Java NIO</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247483893&idx=1&sn=af51e626f2c2baec8cae4f4a15425957&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】Java反射 && 动态代理</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247483918&idx=1&sn=ab8550bb284edcf7cf0c6d0b41e0c2f6&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】多线程基础</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247483977&idx=1&sn=1a3aa3aec27073aa3b422bc41d7fbe2d&chksm=fdf0ea16ca8763005aff64834eeb7bef08bf4ee2d8febb7e8d4d8e5d1542336e13fac71e2881&scene=21&cur_album_id=1657204970858872832#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】 CAS</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247483980&idx=1&sn=c9b620834adb889ad8ccedb6afdcaed1&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】synchronized</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484035&idx=1&sn=ccaec352e192f1fd40020d9a984e9461&chksm=fdf0eadcca8763ca5c44bd19118fd00e843c163deb40cda444b3fc08430c57760db15eca1ea6&scene=21&cur_album_id=1657204970858872832#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】AQS&&ReentrantLock</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484036&idx=1&sn=75e9e93a82a811e9c71b8127cf7ac677&chksm=fdf0eadbca8763cd7ab74757f9472d061c0244d2373a1ea85b1cbc833941441fdb1e91ead5b4&scene=21&cur_album_id=1657204970858872832#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】线程池</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484118&idx=1&sn=9526a1dc0d42926dd9bcccfc55e6abc2&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】ThreadLocal</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484363&idx=1&sn=743dcdfb84f83cfc38882407f87c7c6d&chksm=fdf0eb94ca87628296d86d16769f25e10acd052bcd78f4a4608f4218e4948aff610b04a41f60&token=960279204&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】CountDownLatch和CyclicBarrier</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484253&idx=1&sn=532db3941f47502582295cbb003f753d&chksm=fdf0eb02ca8762145c66b33bbb429399f1f0f27b31c22f7cf6c693c235e9a7cffdafb6ce2fdc&token=57394744&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】List</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484280&idx=1&sn=87cfede653dabc26c909823a1dafd615&chksm=fdf0eb27ca876231095ff99f0b3e30acd7b2ee4cdc7ddb16da0bb6a3b02f531e27324059cf58&token=100834666&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】Map</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484064&idx=1&sn=3a59514a8262ab61036fc89cf0b0a27e&chksm=fdf0eaffca8763e90002ce1daf365f717a4bda3e50878f65943f52d14bee78fc65e837ef32f9&token=664255414&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】SpringMVC</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484147&idx=1&sn=ef282cd54351436fc33c47534b4c2ac1&chksm=fdf0eaacca8763ba9b6c69acdba6b0ae8801405c98295842a0b5d891fe80246d76a2a0470bea&token=1998524575&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】Spring基础</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484187&idx=1&sn=8f831c40dca9b2a57fdfbd051e4eab44&chksm=fdf0eb44ca87625253ea831471110860d3f27e04488b2748ba90ad442b079aca3d6b95d31bbe&token=1998524575&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】SpringBean生命周期</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484227&idx=1&sn=4a124a2dd5ef6ce062abdadf247b5cff&chksm=fdf0eb1cca87620a8679473dfdd50421eb6ccba2459a7cb59ae1652138f7bb508558f3d4649e&token=57394744&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】Redis基础</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484323&idx=1&sn=c3306b3f9abb6f880e2672f169202a42&chksm=fdf0ebfcca8762eaf9b4873e79cd3445857b1f4476a854acdf9c19fb81e1a02146c65cff5078&token=610975656&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】Redis持久化</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484387&idx=1&sn=5bb2ba58776e65f53b091a4bcdb73755&chksm=fdf0ebbcca8762aadc359066ecd70274fa23ee846f9ba9114017402dcbed415f25f97d3020a6&token=1131755397&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】Kafka基础</span></a> </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <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;"> <a href="https://mp.weixin.qq.com/s?__biz=MzU4NzA3MTc5Mg==&mid=2247484411&idx=1&sn=9c4aaeb44f4d9e09cc796805ada29921&chksm=fdf0eba4ca8762b234c3f101bb88c5d134554a831cbf4e80b08dc0bfa829e363a4e1e49a8b50&token=649285067&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(30, 107, 184);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【对线面试官】使用Kafka会考虑什么问题?</span></a> </section></li> </ul> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;padding-right: 10px;padding-left: 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="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <br> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/dbf31ee8497b0bf2ebbc030d0ee9fa1f.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/b973f35212b20b2c8f4677828c3745d6.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/43f39174dde19db188105539b3d2ce91.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/95b20e18f836b682eb36acfd79b0b718.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/24e60d027c901ac4567928cf50d3c40e.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/e4250b435f7d4183f45a7a8ae69174ff.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/596e47daa707c064a06fdb9bcfe84e6c.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/74e1d842cf235d09820b8112c49920c2.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/bbd2f77ba690295dc0950d1410a81f67.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/a4eec5d409e7368f3f00463e5e5de2.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/7d64646acc91af434fd47179b86ffc8e.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="color: black;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="1.7786666666666666" src="/upload/e4195b6ba07fbec5252814ca375c3667.jpg" data-type="jpeg" data-w="750" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="color: rgb(89, 89, 89);padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong style="color: rgb(71, 193, 168);">为什么B+树</strong>?数据无法一次load到内存,B+树是多路搜索树,只有叶子节点才存储数据,叶子节点之间链表进行关联。(树矮,易遍历)</p> <p data-tool="mdnice编辑器" style="color: rgb(89, 89, 89);padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong style="color: rgb(71, 193, 168);">什么是回表</strong>?非聚簇索引在叶子节点只存储列值以及主键ID,有条件下尽可能用覆盖索引避免回表操作,提高查询速度</p> <p data-tool="mdnice编辑器" style="color: rgb(89, 89, 89);padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong style="color: rgb(71, 193, 168);">什么是最左匹配原则</strong>?从最左边为起点开始连续匹配,遇到范围查询终止</p> <p data-tool="mdnice编辑器" style="color: rgb(89, 89, 89);padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong style="color: rgb(71, 193, 168);">主键非自增会有什么问题</strong>?插入效率下降,存在移动块的数据问题</p> <section class="mp_profile_iframe_wrp" style="color: black;"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU4NzA3MTc5Mg==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/E44aHibktsKbNnU5S5B6m5yVtNbmfEUsMmf4eqOBEsXzMILa9eAZvBR4mntYwkkp59nicicN1soBWsduGrxLFVzWQ/0?wx_fmt=png" data-nickname="面试造火箭" data-alias="" data-signature="入职拧螺丝" data-from="0"></mpprofile> </section> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;caret-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;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">文章以纯面试的角度去讲解,所以有很多的细节是未铺垫的。</strong><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;caret-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;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">鉴于很多同学反馈没看懂【<strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">对线面试官</strong>】系列,基础相关的知识我确实写过文章讲解过啦,但有的同学就是不爱去翻。<span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(51, 51, 51);box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;caret-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;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">我把这些<strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">上传到网盘</strong>,你们有需要直接下载就好了。<span style="letter-spacing: 0.544px;"></span></p> <figure data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);caret-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: 14px;text-align: left;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.3302387267904509" data-type="jpeg" data-w="1508" src="/upload/e05acdfb7762b54ec9b09e2738219d94.jpg" style="margin-top: 10px;margin-right: auto;margin-left: auto;display: block;box-shadow: rgba(170, 170, 170, 0.48) 0px 0px 6px 0px;border-radius: 4px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);caret-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: 14px;text-align: left;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong style="color: rgb(0, 0, 0);max-width: 100%;text-align: center;font-size: 16px;letter-spacing: 0px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(255, 104, 39);letter-spacing: 0px;box-sizing: border-box !important;overflow-wrap: break-word !important;">怎样偷偷努力 惊艳所有人?</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></strong> <section class="mp_profile_iframe_wrp" style="color: rgb(0, 0, 0);"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU4NzA3MTc5Mg==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/E44aHibktsKbNnU5S5B6m5yVtNbmfEUsMmf4eqOBEsXzMILa9eAZvBR4mntYwkkp59nicicN1soBWsduGrxLFVzWQ/0?wx_fmt=png" data-nickname="面试造火箭" data-alias="" data-signature="入职拧螺丝" data-from="0"></mpprofile> </section> <strong style="max-width: 100%;text-align: center;font-size: 16px;letter-spacing: 0px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;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;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="color:#000000;">点击小卡片关注【</span><span style="color:#ff6827;">面试造火箭</span></span><span style="color: rgb(0, 0, 0);letter-spacing: 0px;max-width: 100%;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">】</span><br></strong> </figure> <figure data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);caret-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: 14px;text-align: left;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong style="max-width: 100%;text-align: center;font-size: 16px;letter-spacing: 0px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(255, 104, 39);box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></strong> </figure> <figure data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);caret-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: 14px;text-align: left;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong style="max-width: 100%;text-align: center;font-size: 16px;letter-spacing: 0px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">关注后回复「</span><strong style="max-width: 100%;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;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0px;color: rgb(255, 104, 39);box-sizing: border-box !important;overflow-wrap: break-word !important;">888</span></strong><span style="max-width: 100%;letter-spacing: 0px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">」还可获取网盘地址哟!</span></strong> </figure> </section>
作者:微信小助手
<section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU5NDg5MzM5NQ==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/BdQKIO6XpMXZa2U8FCySWQFV4y6HRtFxddNQ6d2hDu4cjqr8wOfrtBDKayTeRia44dtR9wJErHNGACdkMz8xvyQ/0?wx_fmt=png" data-nickname="波哥的IT人生" data-alias="itboge" data-signature="十五年IT老兵!全栈开发、运维开发、devops,python、vue等视频教学,IT行业技术与资讯分享!"></mpprofile> </section> <p style="max-width: 100%;min-height: 1em;font-size: 14px;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);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="letter-spacing: 0.544px;"> </span></p> <p style="text-align: center;"><img class="rich_pages" data-galleryid="" data-ratio="0.624" data-s="300,640" src="/upload/20345b639a511db447df6c85f9e7c742.jpg" data-type="jpeg" data-w="500" style=""></p> <p data-source-line="1" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;"><br></p> <p data-source-line="1" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;"> 使用Linux shell是一些程序员每天的基本工作,但我们经常会忘记一些有用的shell命令和技巧。当然,命令我能记住,但我不敢说能记得如何用它执行某个特定任务。需要注意一点的是,有些用法需要在你的Linux系统里安装额外的软件。下面话不多说了,来看看详细的内容吧。</p> <p data-source-line="5" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">检查远程端口是否对bash开放:</p> <pre data-source-line="6" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">echo >/dev/tcp/<span style="box-sizing: border-box;color: teal;">8.8</span><span style="box-sizing: border-box;color: teal;">.8</span><span style="box-sizing: border-box;color: teal;">.8</span>/<span style="box-sizing: border-box;color: teal;">53</span> && echo <span style="box-sizing: border-box;color: rgb(221, 17, 68);">"open"</span></code></pre> <p data-source-line="9" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">让进程转入后台:</p> <pre data-source-line="10" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;"><span style="box-sizing: border-box;color: rgb(153, 0, 0);font-weight: 700;">Ctrl</span> + z</code></pre> <p data-source-line="13" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">将进程转到前台:</p> <pre data-source-line="14" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;"><span style="box-sizing: border-box;color: rgb(0, 134, 179);">fg</span></code></pre> <p data-source-line="17" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">产生随机的十六进制数,其中n是字符数:</p> <pre data-source-line="18" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">openssl <span style="box-sizing: border-box;font-weight: 700;">rand</span> -<span style="box-sizing: border-box;font-weight: 700;">hex</span> n</code></pre> <p data-source-line="21" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">在当前shell里执行一个文件里的命令:</p> <pre data-source-line="22" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">source /home/user/<span style="box-sizing: border-box;color: rgb(68, 85, 136);font-weight: 700;">file</span>.<span style="box-sizing: border-box;">name</span></code></pre> <p data-source-line="25" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">截取前5个字符:</p> <pre data-source-line="26" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">${variable:<span style="box-sizing: border-box;color: teal;">0</span>:<span style="box-sizing: border-box;color: teal;">5</span>}</code></pre> <p data-source-line="29" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">SSH debug 模式:</p> <pre data-source-line="30" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">ssh -vvv user<span style="box-sizing: border-box;">@ip_address</span><br>SSH <span style="box-sizing: border-box;font-weight: 700;">with</span> pem key:<br><br>ssh user<span style="box-sizing: border-box;">@ip_address</span> -i key.pem</code></pre> <p data-source-line="36" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">用wget抓取完整的网站目录结构,存放到本地目录中:</p> <pre data-source-line="37" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;"><span style="box-sizing: border-box;color: rgb(153, 0, 0);font-weight: 700;">wget</span> -r --<span style="box-sizing: border-box;color: rgb(0, 134, 179);">no</span>-parent --reject <span style="box-sizing: border-box;color: rgb(221, 17, 68);">"index.html*"</span> <span style="box-sizing: border-box;">http://hostname/</span> -P /home/user/dirs</code></pre> <p data-source-line="40" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">一次创建多个目录:</p> <pre data-source-line="41" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">mkdir -p /home/user/{<span style="box-sizing: border-box;color: rgb(0, 134, 179);">test</span>,<span style="box-sizing: border-box;color: rgb(0, 134, 179);">test</span>1,<span style="box-sizing: border-box;color: rgb(0, 134, 179);">test</span>2}</code></pre> <p data-source-line="44" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">列出包括子进程的进程树:</p> <pre data-source-line="45" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;"><span style="box-sizing: border-box;color: rgb(153, 0, 0);font-weight: 700;">ps</span> axwef</code></pre> <p data-source-line="48" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">创建 war 文件:</p> <pre data-source-line="49" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">jar -cvf <span style="box-sizing: border-box;">name</span>.war <span style="box-sizing: border-box;color: rgb(68, 85, 136);font-weight: 700;">file</span></code></pre> <p data-source-line="52" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">测试硬盘写入速度:</p> <pre data-source-line="53" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">dd <span style="box-sizing: border-box;font-weight: 700;">if</span>=<span style="box-sizing: border-box;color: rgb(0, 153, 38);">/dev/</span>zero of=<span style="box-sizing: border-box;color: rgb(0, 153, 38);">/tmp/</span>output.img bs=<span style="box-sizing: border-box;color: teal;">8</span>k <span style="box-sizing: border-box;font-weight: 700;">count</span>=<span style="box-sizing: border-box;color: teal;">256</span>k; rm -rf <span style="box-sizing: border-box;color: rgb(0, 153, 38);">/tmp/</span>output.img</code></pre> <p data-source-line="56" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">测试硬盘读取速度:</p> <pre data-source-line="57" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">hdparm -Tt <span style="box-sizing: border-box;color: rgb(0, 153, 38);">/dev/</span>sda</code></pre> <p data-source-line="60" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">获取文本的md5 hash:</p> <pre data-source-line="61" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">echo -n <span style="box-sizing: border-box;color: rgb(221, 17, 68);">"text"</span> <span style="box-sizing: border-box;color: rgb(221, 17, 68);">| md5sum</span></code></pre> <p data-source-line="64" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">检查xml格式:</p> <pre data-source-line="65" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">xmllint <span style="box-sizing: border-box;color: rgb(153, 153, 136);font-style: italic;">--noout file.xml</span></code></pre> <p data-source-line="68" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">将tar.gz提取到新目录里:</p> <pre data-source-line="69" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">tar zxvf package<span style="box-sizing: border-box;">.tar</span><span style="box-sizing: border-box;">.gz</span> -C new_dir</code></pre> <p data-source-line="72" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">使用curl获取HTTP头信息:</p> <pre data-source-line="73" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">curl -I <span style="box-sizing: border-box;color: rgb(221, 17, 68);">http:</span><span style="box-sizing: border-box;color: rgb(153, 153, 136);font-style: italic;">//www.example.com</span></code></pre> <p data-source-line="76" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">修改文件或目录的时间戳(YYMMDDhhmm):</p> <pre data-source-line="77" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;"><span style="box-sizing: border-box;font-weight: 700;">touch</span> -t <span style="box-sizing: border-box;color: teal;">0712250000</span> <span style="box-sizing: border-box;font-weight: 700;">file</span></code></pre> <p data-source-line="80" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">用wget命令执行ftp下载:</p> <pre data-source-line="81" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">wget -m <span style="box-sizing: border-box;color: rgb(221, 17, 68);">ftp:</span><span style="box-sizing: border-box;color: rgb(153, 153, 136);font-style: italic;">//username:password@hostname</span></code></pre> <p data-source-line="84" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">生成随机密码(例子里是16个字符长):</p> <pre data-source-line="85" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">LANG=c < /dev/urandom tr -dc _A-Z-a-z-<span style="box-sizing: border-box;color: teal;">0</span>-<span style="box-sizing: border-box;color: teal;">9</span> | head -c${<span style="box-sizing: border-box;color: teal;">1</span>:-<span style="box-sizing: border-box;color: teal;">16</span>};echo;</code></pre> <p data-source-line="88" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">快速备份一个文件:</p> <pre data-source-line="89" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;"><span style="box-sizing: border-box;color: navy;">cp</span> <span style="box-sizing: border-box;color: navy;">some_file_name</span>{,<span style="box-sizing: border-box;">.bkp</span>}</code></pre> <p data-source-line="92" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">访问Windows共享目录:</p> <pre data-source-line="93" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">smbclient -<span style="box-sizing: border-box;">U </span><span style="box-sizing: border-box;color: rgb(221, 17, 68);">"DOMAIN\user"</span> /<span style="box-sizing: border-box;color: rgb(0, 153, 38);">/dc.domain.com/share</span><span style="box-sizing: border-box;color: rgb(0, 153, 38);">/test/dir</span></code></pre> <p data-source-line="96" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">执行历史记录里的命令(这里是第100行):</p> <pre data-source-line="97" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">!<span style="box-sizing: border-box;color: teal;">100</span></code></pre> <p data-source-line="100" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">解压:</p> <pre data-source-line="101" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">unzip package_name.<span style="box-sizing: border-box;font-weight: 700;">zip</span> -<span style="box-sizing: border-box;font-weight: 700;">d</span> dir_name</code></pre> <p data-source-line="104" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">输入多行文字(CTRL + d 退出):</p> <pre data-source-line="105" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;"><span style="box-sizing: border-box;font-weight: 700;">cat</span> > <span style="box-sizing: border-box;font-weight: 700;">test</span>.txt</code></pre> <p data-source-line="108" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">创建空文件或清空一个现有文件:</p> <pre data-source-line="109" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">\> <span style="box-sizing: border-box;color: navy;">test</span><span style="box-sizing: border-box;">.txt</span></code></pre> <p data-source-line="112" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">与Ubuntu NTP server同步时间:</p> <pre data-source-line="113" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">ntpdate ntp<span style="box-sizing: border-box;">.ubuntu</span><span style="box-sizing: border-box;">.com</span></code></pre> <p data-source-line="116" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">用netstat显示所有tcp4监听端口:</p> <pre data-source-line="117" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">netstat -lnt4 | awk <span style="box-sizing: border-box;color: rgb(221, 17, 68);">'{print $4}'</span> | cut <span style="box-sizing: border-box;">-f</span>2 <span style="box-sizing: border-box;">-d</span>: | grep -o <span style="box-sizing: border-box;color: rgb(221, 17, 68);">'[0-9]*'</span></code></pre> <p data-source-line="120" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">qcow2镜像文件转换:</p> <pre data-source-line="121" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;">qemu-<span style="box-sizing: border-box;color: navy;">img</span> convert -f qcow2 -O raw precise-server-cloudimg-amd64-disk1<span style="box-sizing: border-box;">.img</span> \precise-server-cloudimg-amd64-disk1.raw</code></pre> <p data-source-line="124" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">重复运行文件,显示其输出(缺省是2秒一次):</p> <pre data-source-line="125" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;overflow-wrap: normal;margin-bottom: 16px;padding: 16px;overflow: auto;border-radius: 3px;text-align: start;widows: 1;background-color: rgb(247, 247, 247);"><code style="box-sizing: border-box;display: inline;overflow: visible;font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;border-radius: 3px;word-break: normal;border-width: 0px;border-style: initial;border-color: initial;line-height: inherit;overflow-wrap: normal;background: 0px 0px transparent;"><span style="box-sizing: border-box;color: rgb(153, 0, 0);font-weight: 700;">watch</span> ps -ef</code></pre> <p data-source-line="128" style="box-sizing: border-box;margin-bottom: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size: 14px;font-variant-numeric: normal;font-variant-east-asian: normal;line-height: 21px;text-align: start;white-space: normal;widows: 1;">所有用户列表:</p> <pre data-source-line="129" style="box-sizing: border-box;font-variant-numeric: normal;font-variant-east-asian: normal;font-stretch: normal;font-size: 11.9px;line-height: 1.45;font-family: Co
作者:微信小助手
<blockquote style="" data-mpa-powered-by="yiban.io"> <h2 style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">来自:zeb_perfect的专栏</span></h2> <p style="text-align: left;"><span style="font-size: 12px;color: rgb(136, 136, 136);">链接:https://blog.csdn.net/zeb_perfect/article/details/54135506</span></p> </blockquote> <h2 style=""><br></h2> <h2 style=""><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 18px;">前言</span></strong></span></h2> <p style=""><br></p> <p style=""><span style="font-size: 15px;">设计一个缓存系统,不得不要考虑的问题就是:缓存穿透、缓存击穿与失效时的雪崩效应。<br style="outline: 0px;word-break: break-all;"></span></p> <p style=""><br></p> <h2 style=""><strong><span style="font-size: 18px;color: rgb(171, 25, 66);">缓存穿透</span></strong></h2> <p style=""><br></p> <p style=""><span style="font-size: 15px;">缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。</span></p> <p style=""><br></p> <h3 style=""><strong><span style="font-size: 18px;color: rgb(171, 25, 66);">解决方案</span></strong></h3> <p style=""><br></p> <p style=""><span style="font-size: 15px;">有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。</span></p> <p style=""><br></p> <h2 style=""><strong><span style="font-size: 18px;color: rgb(171, 25, 66);">缓存雪崩</span></strong></h2> <p style=""><br></p> <p style=""><span style="font-size: 15px;">缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。</span></p> <p style=""><br></p> <h3 style=""><strong><span style="font-size: 18px;color: rgb(171, 25, 66);">解决方案</span></strong></h3> <p style=""><br></p> <p style=""><span style="font-size: 15px;">缓存失效时的雪崩效应对底层系统的冲击非常可怕。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线 程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。这里分享一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。</span></p> <p style=""><br></p> <h2 style=""><strong><span style="font-size: 18px;color: rgb(171, 25, 66);">缓存击穿</span></strong></h2> <p style=""><br></p> <p style=""><span style="font-size: 15px;">对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。</span></p> <p style=""><br></p> <p style=""><span style="font-size: 15px;">缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。</span></p> <p style=""><br></p> <h3 style=""><strong><span style="font-size: 18px;color: rgb(171, 25, 66);">解决方案</span></strong></h3> <p style=""><br></p> <h4 style=""><strong><span style="font-size: 15px;">1、使用互斥锁(mutex key)</span></strong></h4> <p style=""><br></p> <p style=""><span style="font-size: 15px;">业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。<br style="outline: 0px;word-break: break-all;"></span></p> <p style=""><br></p> <p style=""><span style="font-size: 15px;">SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。在redis2.6.1之前版本未实现setnx的过期时间,所以这里给出两种版本代码参考:</span></p> <p style=""><br></p> <pre style="letter-spacing: 0.544px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code style="margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;"><span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">//2.6.1前单机版本锁</span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String <span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(<span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String key</span>) </span>{ <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> String <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span> = redis.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span> == <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">null</span>) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (redis.setnx(key_mutex, <span style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"1"</span>)) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">// 3 min timeout to avoid mutex holder crash </span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> redis.expire(key_mutex, <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">3</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">60</span>) <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span> = db.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> redis.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">set</span>(key, <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> redis.delete(key_mutex); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">else</span> { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">//其他线程休息50毫秒后重试 </span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> Thread.sleep(<span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">50</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">}</code></pre> <p style=""><br></p> <p style=""><strong><span style="font-size: 15px;">最新版本代码:</span></strong></p> <p style=""><br></p> <pre style="letter-spacing: 0.544px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code style="margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;"><span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="overflow-wrap: inherit !important;word-break: inherit !important;">public</span> String <span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(<span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">key</span>) </span>{<br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> String <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span> = redis.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key);<br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span> == <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">null</span>) { <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">//代表缓存值过期</span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">//设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db</span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (redis.setnx(key_mutex, <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">1</span>, <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">3</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">60</span>) == <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">1</span>) { <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">//代表设置成功</span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span> = db.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key);<br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> redis.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">set</span>(key, <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span>, expire_secs);<br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> redis.del(key_mutex);<br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">else</span> { <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">//这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可</span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> sleep(<span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">50</span>);<br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">//重试</span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> }<br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">else</span> {<br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span>; <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> }<br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> }</code></pre> <p style=""><br></p> <p style=""><strong><span style="font-size: 15px;">memcache代码:</span></strong></p> <p style=""><br></p> <pre style="letter-spacing: 0.544px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code style="margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;"><span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (memcache.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key) == <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">null</span>) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">// 3 min timeout to avoid mutex holder crash </span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (memcache.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">add</span>(key_mutex, <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">3</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">60</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">1000</span>) == <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">true</span>) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span> = db.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> memcache.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">set</span>(key, <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> memcache.delete(key_mutex); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">else</span> { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> sleep(<span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">50</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> retry(); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">} </code></pre> <p style=""><br></p> <h4 style=""><strong><span style="font-size: 15px;">2、"提前"使用互斥锁(mutex key):</span></strong></h4> <p style=""><br></p> <p style=""><span style="font-size: 15px;">在value内部设置1个超时值(timeout1), timeout1比实际的memcache timeout(timeout2)小。当从cache读取到timeout1发现它已经过期时候,马上延长timeout1并重新设置到cache。然后再从数据库加载数据并设置到cache中。伪代码如下:</span></p> <p style=""><br></p> <pre style="letter-spacing: 0.544px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code style="margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;">v = memcache.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (v == <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">null</span>) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (memcache.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">add</span>(key_mutex, <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">3</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">60</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">1000</span>) == <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">true</span>) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span> = db.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> memcache.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">set</span>(key, <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> memcache.delete(key_mutex); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">else</span> { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> sleep(<span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">50</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> retry(); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">} <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">else</span> { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (v.timeout <= now()) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (memcache.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">add</span>(key_mutex, <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">3</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">60</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">1000</span>) == <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">true</span>) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">// extend the timeout for other threads </span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> v.timeout += <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">3</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">60</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">1000</span>; <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> memcache.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">set</span>(key, v, KEY_TIMEOUT * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">2</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">// load the latest value from db </span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> v = db.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> v.timeout = KEY_TIMEOUT; <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> memcache.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">set</span>(key, <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">value</span>, KEY_TIMEOUT * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">2</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> memcache.delete(key_mutex); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">else</span> { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> sleep(<span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">50</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> retry(); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">} </code></pre> <p style=""><br></p> <h4 style=""><strong><span style="font-size: 15px;">3、"永远不过期": </span></strong></h4> <p style=""><br></p> <p style=""><span style="font-size: 15px;">这里的“永远不过期”包含两层意思:</span></p> <p style=""><br></p> <blockquote style=""> <p>(1) 从redis上看,确实没有设置过期时间,这就保证了,不会出现热点key过期问题,也就是“物理”不过期。</p> <p>(2) 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期</p> </blockquote> <p style=""><br></p> <p style=""><span style="font-size: 15px;">从实战看,这种方法对于性能非常友好,唯一不足的就是构建缓存时候,其余线程(非构建缓存的线程)可能访问的是老数据,但是对于一般的互联网功能来说这个还是可以忍受。</span></p> <p style=""><br></p> <pre style="letter-spacing: 0.544px;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;background-color: rgb(255, 255, 255);"><code style="margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);font-family: Consolas, Inconsolata, Courier, monospace;display: block;overflow-x: auto;letter-spacing: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;"><span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String</span> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">final</span> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String</span> key) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> V v = redis.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String</span> value = v.getValue(); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> long timeout = v.getTimeout(); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (v.timeout <= System.currentTimeMillis()) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">// 异步更新后台异常执行 </span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> threadPool.execute(<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">new</span> Runnable() { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> public <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">void</span> run() { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String</span> keyMutex = <span style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"mutex:"</span> + key; <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (redis.setnx(keyMutex, <span style="font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"1"</span>)) { <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">// 3 min timeout to avoid mutex holder crash </span><br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> redis.expire(keyMutex, <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">3</span> * <span style="font-size: inherit;color: rgb(174, 135, 250);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">60</span>); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String</span> dbValue = db.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">get</span>(key); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> redis.<span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">set</span>(key, dbValue); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> redis.delete(keyMutex); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> }); <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> } <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"> <span style="font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">return</span> value; <br style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">}</code></pre> <p style=""><br></p> <h4 style=""><strong><span style="font-size: 15px;">4、资源保护:</span></strong></h4> <p style=""><br></p> <p style=""><span style="font-size: 15px;">采用netflix的hystrix,可以做资源的隔离保护主线程池,如果把这个应用到缓存的构建也未尝不可。</span></p> <p style=""><br></p> <p style=""><span style="font-size: 15px;">四种解决方案:没有最佳只有最合适</span></p> <p style=""><br></p> <table width="378"> <tbody style="box-sizing: border-box;outline: 0px;border-width: 0px;border-style: initial;border-color: initial;word-break: break-all;"> <tr style="box-sizing: border-box;outline: 0px;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(221, 221, 221);background-color: rgb(41, 195, 243);word-break: break-all;"> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><span style="font-size: 15px;box-sizing: border-box !important;">解决方案</span></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><span style="font-size: 15px;box-sizing: border-box !important;">优点</span></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><span style="font-size: 15px;box-sizing: border-box !important;">缺点</span></td> </tr> <tr style="box-sizing: border-box;outline: 0px;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(221, 221, 221);background-color: rgb(247, 247, 247);word-break: break-all;"> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><span style="font-size: 15px;box-sizing: border-box !important;">简单分布式互斥锁(mutex key)</span></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;"> 1. 思路简单</span></p><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">2. 保证一致性</span></p></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">1. 代码复杂度增大</span></p><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">2. 存在死锁的风险</span></p><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">3. 存在线程池阻塞的风险</span></p></td> </tr> <tr style="box-sizing: border-box;outline: 0px;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(221, 221, 221);word-break: break-all;"> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><span style="font-size: 15px;box-sizing: border-box !important;">“提前”使用互斥锁</span></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><span style="font-size: 15px;box-sizing: border-box !important;"> 1. 保证一致性</span></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><span style="font-size: 15px;box-sizing: border-box !important;">同上 </span></td> </tr> <tr style="box-sizing: border-box;outline: 0px;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(221, 221, 221);background-color: rgb(247, 247, 247);word-break: break-all;"> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><span style="font-size: 15px;box-sizing: border-box !important;">不过期(本文)</span></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">1. 异步构建缓存,不会阻塞线程池</span></p></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">1. 不保证一致性。</span></p><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">2. 代码复杂度增大(每个value都要维护一个timekey)。</span></p><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">3. 占用一定的内存空间(每个value都要维护一个timekey)。</span></p></td> </tr> <tr style="box-sizing: border-box;outline: 0px;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(221, 221, 221);word-break: break-all;"> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><span style="font-size: 15px;box-sizing: border-box !important;">资源隔离组件hystrix(本文)</span></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">1. hystrix技术成熟,有效保证后端。</span></p><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">2. hystrix监控强大。</span></p><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;"> </span></p><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;"> </span></p></td> <td style="padding: 8px;word-break: break-all;box-sizing: border-box;outline: 0px;font-size: 1em;color: rgb(79, 79, 79);line-height: 22px;vertical-align: top;"><p style="box-sizing: border-box !important;"><span style="font-size: 15px;box-sizing: border-box !important;">1. 部分访问存在降级策略。</span></p></td> </tr> </tbody> </table> <p style=""><br style="outline: 0px;word-break: break-all;"></p> <p style=""><span style="font-size: 15px;">四种方案来源网络,详文请链接:</span><span style="color: rgb(80, 125, 201);text-decoration: underline;font-size: 12px;">http://carlosfu.iteye.com/blog/2269687</span><br style="outline: 0px;word-break: break-all;"></p> <h2 style=""></h2> <h2 style=""><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 18px;">总结</span></strong></span></h2> <p style=""><br></p> <p style=""><span style="font-size: 15px;">针对业务系统,永远都是具体情况具体分析,没有最好,只有最合适。</span></p> <p style=""><br></p> <p style=""><span style="font-size: 15px;">最后,对于缓存系统常见的缓存满了和数据丢失问题,需要根据具体业务分析,通常我们采用LRU策略处理溢出,Redis的RDB和AOF持久化策略来保证一定情况下的数据安全。</span></p> <p><br></p>
作者:微信小助手
<section powered-by="xiumi.us"> <section> <section powered-by="xiumi.us"> <section> <br> </section> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU5NDg5MzM5NQ==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/BdQKIO6XpMXZa2U8FCySWQFV4y6HRtFxddNQ6d2hDu4cjqr8wOfrtBDKayTeRia44dtR9wJErHNGACdkMz8xvyQ/0?wx_fmt=png" data-nickname="波哥的IT人生" data-alias="itboge" data-signature="十五年IT老兵!全栈开发、运维开发、devops,python、vue等视频教学,IT行业技术与资讯分享!"></mpprofile> </section> <p style="box-sizing: border-box;margin-top: 1.7em;margin-bottom: 1.7em;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 2px;text-align: start;white-space: normal;word-spacing: 2px;background-color: rgb(255, 255, 255);"><br></p> <p style="box-sizing: border-box;margin-top: 1.7em;margin-bottom: 1.7em;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 2px;text-align: start;white-space: normal;word-spacing: 2px;background-color: rgb(255, 255, 255);">1、list_sys_status.sh<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">显示系统使用的以下信息:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">主机名、IP地址、子网掩码、网关、DNS服务器IP地址信息</p> <pre style="box-sizing: border-box;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;letter-spacing: 2px;text-align: start;word-spacing: 2px;background-color: rgb(255, 255, 255);"><code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);display: block;font-family: Consolas, Inconsolata, Courier, monospace;overflow-x: auto;word-spacing: 0px;letter-spacing: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(91, 218, 237);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#!/bin/bash</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">IP=`ifconfig eth0 | head -2 | tail -1 | awk <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'{print $2}'</span> | awk -F<span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">":"</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'{print $2}'</span>`<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">ZW=` ifconfig eth0 | head -2 | tail -1 | awk <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'{print $3}'</span> | awk -F<span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">":"</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'{print $2}'</span>`<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">GW=`route -n | tail -1 | awk <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'{print $2}'</span>`<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">HN=`hostname`<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">DNS=`head -1 /etc/resolv.conf | awk <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'{print $2}'</span>`<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'此机IP地址是'</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$IP</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'此机子网掩码是'</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$ZW</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'此机网关是'</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$GW</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'此机主机名是'</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$HN</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'此机DNS是'</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$DNS</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"></code></pre> <p style="box-sizing: border-box;margin-top: 1.7em;margin-bottom: 1.7em;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 2px;text-align: start;white-space: normal;word-spacing: 2px;background-color: rgb(255, 255, 255);">2、mysqlbak.sh备份数据库目录脚本</p> <pre style="box-sizing: border-box;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;letter-spacing: 2px;text-align: start;word-spacing: 2px;background-color: rgb(255, 255, 255);"><code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);display: block;font-family: Consolas, Inconsolata, Courier, monospace;overflow-x: auto;word-spacing: 0px;letter-spacing: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(91, 218, 237);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#!/bin/bash</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">DAY=`date +%Y%m%d`<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">SIZE=`du -sh /var/lib/mysql`<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"Date: <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$DAY</span>"</span> >> /tmp/dbinfo.txt<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"Data Size: <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$SIZE</span>"</span> >> /tmp/dbinfo.txt<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">cd</span> /opt/dbbak &> /dev/null || mkdir /opt/dbbak<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">tar zcf /opt/dbbak/mysqlbak-<span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">${DAY}</span>.tar.gz /var/lib/mysql /tmp/dbinfo.txt &> /dev/null<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">rm -f /tmp/dbinfo.txt<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">crontab<span style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">-e</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">55 23 */3 * * /opt/dbbak/dbbak.sh<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"></code></pre> <p style="box-sizing: border-box;margin-top: 1.7em;margin-bottom: 1.7em;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 2px;text-align: start;white-space: normal;word-spacing: 2px;background-color: rgb(255, 255, 255);">3、每周日半夜23点半,对数据库服务器上的webdb库做完整备份<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">每备份文件保存到系统的/mysqlbak目录里<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">用系统日期做备份文件名 webdb-YYYY-mm-dd.sql<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">每次完整备份后都生成新的binlog日志<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">把当前所有的binlog日志备份到/mysqlbinlog目录下</p> <pre style="box-sizing: border-box;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;letter-spacing: 2px;text-align: start;word-spacing: 2px;background-color: rgb(255, 255, 255);"><code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);display: block;font-family: Consolas, Inconsolata, Courier, monospace;overflow-x: auto;word-spacing: 0px;letter-spacing: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#mkdir /mysqlbak </span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#mkdir /mysqlbinlog</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#service mysqld start</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">cd</span> /shell<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#vi webdb.sh</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(91, 218, 237);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#!/bin/bash</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">day=`date +%F`<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">mysqldump -hlocalhost -uroot -p123 webdb > /mysqlbak/webdb-<span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">${day}</span>.sql<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">mysql -hlocalhost -uroot -p -e <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"flush logs"</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">tar zcf /mysqlbinlog.tar.gz /var/lib/mysql/mysqld-bin.0*<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#chmod +x webdb.sh </span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(128, 128, 128);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#crontab -e</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">30 23 * * 7 /shell/webdb.sh<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"></code></pre> <p style="box-sizing: border-box;margin-top: 1.7em;margin-bottom: 1.7em;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 2px;text-align: start;white-space: normal;word-spacing: 2px;background-color: rgb(255, 255, 255);">4、very.ser.sh(检查任意一个服务的运行状态)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">只检查服务vsftpd httpd sshd crond、mysql中任意一个服务的状态<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">如果不是这5个中的服务,就提示用户能够检查的服务名并退出脚本<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">如果服务是运行着的就输出 "服务名 is running"<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;">如果服务没有运行就启动服务</p> <pre style="box-sizing: border-box;font-size: 15px;color: rgb(62, 62, 62);line-height: inherit;letter-spacing: 2px;text-align: start;word-spacing: 2px;background-color: rgb(255, 255, 255);"><code style="box-sizing: border-box;margin-right: 2px;margin-left: 2px;padding: 0.5em;font-size: 14px;color: rgb(169, 183, 198);line-height: 18px;border-radius: 0px;background: rgb(40, 43, 46);display: block;font-family: Consolas, Inconsolata, Courier, monospace;overflow-x: auto;word-spacing: 0px;letter-spacing: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;">方法1:使用<span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">read</span>写脚本<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(91, 218, 237);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">#!/bin/bash</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">read</span> -p <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"请输入你的服务名:"</span> service<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> [ <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$service</span> != <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'crond'</span> -a <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$service</span> != <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'httpd'</span> -a <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$service</span> != <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'sshd'</span> -a <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$service</span> != <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'mysqld'</span> -a <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$service</span> != <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">'vsftpd'</span> ];<span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">then</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"只能够检查'vsftpd,httpd,crond,mysqld,sshd"</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">exit</span> 5<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">fi</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">service <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$service</span> status &> /dev/null<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> [ $? -eq 0 ];thhen<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"服务在线"</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">else</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">service <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$service</span> start<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">fi</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">或<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">方法2:使用位置变量来写脚本<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> [ -z <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$1</span> ];<span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">then</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"You mast specify a servername!"</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"Usage: `basename<span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$0</span>` servername"</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">exit</span> 2<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">fi</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> [ <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$1</span> == <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"crond"</span> ] || [ <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$1</span> == <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"mysql"</span> ] || [ <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$1</span> == <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"sshd"</span> ] || [ <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$1</span> == <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"httpd"</span> ] || [ <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$1</span> == <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"vsftpd"</span> ];<span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">then</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">service <span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$1</span> status &> /dev/null<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">if</span> [ $? -eq 0 ];<span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">then</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="box-sizing: border-box;font-size: inherit;color: rgb(238, 220, 112);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">"<span style="box-sizing: border-box;font-size: inherit;color: rgb(98, 151, 85);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">$1</span> is running"</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="box-sizing: border-box;font-size: inherit;color: rgb(248, 35, 117);line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">else</span><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-br
作者:微信小助手
<section powered-by="xiumi.us"> <section> <section powered-by="xiumi.us"> <section> <br> </section> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU5NDg5MzM5NQ==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/BdQKIO6XpMXZa2U8FCySWQFV4y6HRtFxddNQ6d2hDu4cjqr8wOfrtBDKayTeRia44dtR9wJErHNGACdkMz8xvyQ/0?wx_fmt=png" data-nickname="波哥的IT人生" data-alias="itboge" data-signature="十五年IT老兵!全栈开发、运维开发、devops,python、vue等视频教学,IT行业技术与资讯分享!"></mpprofile> </section> <section style="font-size: 15px;color: rgb(62, 62, 62);line-height: 1.8;word-spacing: 2px;letter-spacing: 2px;font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;"> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><span style="font-size: 14px;"><br>在企业运维工作中,每一步操作完毕后都应该进行快速有效的检查,这是一名合格运维人员的良好习惯。在我们变更,nginx配置重启(包含reload),要会通过调用脚本获取header信息或模拟用户访问URL来自动检查Nginx的启动是否正常。最大限度的保证服务重启后,能够偶快速确定网站情况,而无需手工敲命令查看。这样如果有问题,快速回退上一版本的配置文件(配置前已做备份)。</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;word-spacing: 0px;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(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">#</span><br>[ -f /etc/init.d/<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">functions</span> ] && . /etc/init.d/<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">functions</span><br><br>DATE=$(date +%Y-%m-%d-%H-%M-%S)<br>MAIL=`<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">which</span> mail`<br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># mail name</span><br>NAME=(<br>liujian<br>e_yunwei<br>)<br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># check urls status</span><br>URLS=(<br>http://192.168.99.233:9004/webfof_login/login<br>http://www.aaca.com<br>)<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># curl 获取状态码</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">curl_ip</span></span>() {<br> CURL=$(curl -o /dev/null -s --connect-timeout 5 -w <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">'%{http_code}'</span> <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$1</span>|egrep <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"200|302"</span>|wc -l)<br> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$CURL</span><br>}<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># 邮件</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">mail</span></span>() {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">for</span> m <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">in</span> <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">${NAME[*]}</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;">echo</span> <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"Retry curl <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$1</span> again is Failure,Please check url on <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$DATE</span>"</span> | <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$MAIL</span> -s <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"Service state Warning"</span> <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$m</span>@erichfund.com<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>}<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># 主程序</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">main</span></span>() {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">for</span> n <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">in</span> <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">${URLS[*]}</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> curl_ip <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$n</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> [ $? -eq 1 ];<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">then</span><br> action <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"curl <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$n</span>"</span> /bin/<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;">else</span><br> action <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"curl <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$n</span>"</span> /bin/<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">false</span><br> curl_ip <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$n</span><br> sleep 10<br> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> [ <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$CURL</span> -eq 1 ];<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">then</span><br> action <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"Retry curl <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$n</span> again"</span> /bin/<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;">else</span><br> action <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">"Retry curl <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$n</span> again"</span> /bin/<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">false</span><br> mail <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">$n</span><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> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">fi</span><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>}<br>main<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># crontab 添加定时任务5分钟执行一次。</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># */5 * * * * /bin/bash /server/scripts/chk_url.sh &>/dev/null</span><br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">例如:将百度腾讯阿里网站URL,放置到属组array</p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;word-spacing: 0px;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;">array=(<br><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">http://baidu.com</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">http://qq.com</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">http://taobao.com</span><br>)<br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># chmod +x chk_curl.sh</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;"># sh chk_curl.sh</span><br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">执行结果如下:</p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;word-spacing: 0px;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;">root@localhost scripts</span>]<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);overflow-wrap: inherit !important;word-break: inherit !important;"># sh chk_curl.sh</span><br>curl http:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//baidu.com [ OK ]</span><br>curl http:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//qq.com [ OK ]</span><br>curl http:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//taobao.com [ OK ]</span><br></code></pre> </section> </section> </section> </section> <section powered-by="xiumi.us" style="margin-top: 10px;white-space: normal;max-width: 100%;box-sizing: border-box;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-align: center;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;display: inline-block;width: 250px;height: 95px;vertical-align: top;overflow: hidden;background-position: 50% 50%;background-repeat: no-repeat;background-size: contain;background-attachment: scroll;line-height: 1.6;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/Ydvd7zZ4EMqqV2lZPeR975FIPLeRicCjHDeMHFyE5u2vhfNo0ZA9JMzYbWeUf9KF6yiblumSmkyMX3OhzHqrdiaFw/640?wx_fmt=png");overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="margin-top: 15px;max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 14px;line-height: 1.5;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><span style="font-size: 14px;">关注<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><span style="font-size: 14px;">绝对干货的公众号</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><br></p> </section> </section> </section> </section> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU5NDg5MzM5NQ==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/BdQKIO6XpMXZa2U8FCySWQFV4y6HRtFxddNQ6d2hDu4cjqr8wOfrtBDKayTeRia44dtR9wJErHNGACdkMz8xvyQ/0?wx_fmt=png" data-nickname="波哥的IT人生" data-alias="itboge" data-signature="十五年IT老兵!全栈开发、运维开发、devops,python、vue等视频教学,IT行业技术与资讯分享!"></mpprofile> </section> <section powered-by="xiumi.us" style="white-space: normal;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(227, 46, 46);font-family: PingFangTC-ultralight;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><br></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;">推荐阅读</p> </section> <section powered-by="xiumi.us" style="white-space: normal;max-width: 100%;box-sizing: border-box;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);font-size: 12px;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><br></p> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484673&idx=1&sn=f1c6fd7c00049734ed97121b5c401c6a&chksm=fe7b0a3dc90c832b226d1df991f413a4dfaebce8c4be4549ebd777a688e08f61f651b1bcd337&scene=21#wechat_redirect" textvalue="实战项目--kkitDeploy(客户端版)(强推)" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="color: rgb(0, 0, 0);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">实战项目--kkitDeploy(客户端版)<span style="max-width: 100%;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;box-sizing: border-box !important;overflow-wrap: break-word !important;">(强推<span style="max-width: 100%;letter-spacing: 0.544px;">,已开源</span>)</span></a></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485054&idx=1&sn=76b2afbaa98227a0efb06e1c5e53be17&chksm=fe7b0942c90c8054172c8ca3020ddeb28d32cee3d3807efc6e7c9b063d128ee31dcdc831f457&scene=21#wechat_redirect" textvalue="实战项目--kkitDeploy(PaaS版)(强推)" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="color: rgb(0, 0, 0);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;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;box-sizing: border-box !important;overflow-wrap: break-word !important;">实战项目--kkitDeploy(PaaS版)(强推)</a></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484871&idx=1&sn=eea93b8ec270325f961e41038eade6d4&chksm=fe7b0afbc90c83ed0251453b69c1ac0e48db7444dd27caf8d8830b03235190cb7802058c64b6&scene=21#wechat_redirect" textvalue="实战项目--kkit3.0功能介绍(强推)" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="color: rgb(0, 0, 0);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;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;box-sizing: border-box !important;overflow-wrap: break-word !important;">实战项目--kkit3.0功能介绍(强推)</a></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><span style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;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(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247483880&idx=1&sn=5a38522f8639330a62fd8bd1fe032972&chksm=fe7b0ed4c90c87c26e4444cf21254dc613258082b28b4a6707a041edadb982ab0d13b994749a&scene=21#wechat_redirect" textvalue="实战项目--kkit1.0功能介绍(强推,已开源)" 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;">实战项目--kkit1.0功能介绍(强推,已开源)</a></span></p> </section> </section> <section powered-by="xiumi.us" style="white-space: normal;max-width: 100%;box-sizing: border-box;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;font-size: 16px;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 12px;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;font-size: 16px;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 12px;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484747&idx=1&sn=b49dfe531c0c1331200a7e4947f65976&chksm=fe7b0a77c90c8361f2ac4f3784681c7580c3699bf0f49d930b56999a2bd8e3e62fa3e6c9b521&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">经历贴之---外包接活却坐牢456天完整记录(强推)</a></p> </section> </section> </section> </section> <section powered-by="xiumi.us" style="white-space: normal;max-width: 100%;box-sizing: border-box;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;font-size: 16px;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 12px;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484455&idx=1&sn=da41f73724909d3051343133cd53db74&chksm=fe7b0b1bc90c820d954f649d76be230f651d62431858eb06bae8f5deaa36e66339f515116373&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">脚本之---短信轰炸机</a></p> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><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" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">脚本之---QQ微信轰炸机</a></p> <p style="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=MzU5NDg5MzM5NQ==&mid=2247485248&idx=1&sn=1134c6914570f1b5ad657cb0864d14d1&chksm=fe7b087cc90c816a7b172c552061370bc6db54679af785dbc899580a66d1e4b227c783b66409&scene=21#wechat_redirect" textvalue="ansible---一键搭建redis5.0.5集群" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">ansible---一键搭建redis5.0.5集群</a></p> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247483959&idx=1&sn=f1c132a3f3ef3c2cf53166d92bbb1c81&chksm=fe7b0d0bc90c841d865c6ada6ad1b1747636b2ca719906ce5faf36a4775b595fb83cdcbd7988&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">工具之---地表最强CMDB自动抓取工具</a></p> <p style="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=MzU5NDg5MzM5NQ==&mid=2247486615&idx=1&sn=67bafeb6de2452acee1b39781f0ddc47&chksm=fe7b03abc90c8abd437dd2ec263c1caa8370889ac405358ed53a3e93727b482d6d4ea1ef37ea&scene=21#wechat_redirect" textvalue="elk7.9真集群docker部署文档" data-itemshowtype="0" tab="innerlink" data-linktype="2">elk7.9真集群docker部署文档</a></p> <p style="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=MzU5NDg5MzM5NQ==&mid=2247486678&idx=1&sn=f4b458fe3b1ca373de7b89c14d80e5a7&chksm=fe7b03eac90c8afca4039c96df3dcaa314e1e56e0f10eace62bade73745ebf57ed606db3fa4e&scene=21#wechat_redirect" textvalue="全球最全loki部署及配置文档" data-itemshowtype="0" tab="innerlink" data-linktype="2">全球最全loki部署及配置文档</a></p> </section> </section> <section powered-by="xiumi.us" style="margin-top: 10px;margin-bottom: 10px;white-space: normal;max-width: 100%;box-sizing: border-box;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-align: right;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;display: inline-block;vertical-align: middle;overflow-wrap: break-word !important;"> <section style="margin-bottom: 2px;padding-right: 5px;padding-left: 5px;max-width: 100%;box-sizing: border-box;display: inline-block;vertical-align: bottom;line-height: 1.2em;color: rgb(121, 121, 121);overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;">点小花花,让他们知道你<span style="max-width: 100%;box-sizing: border-box;color: rgb(139, 207, 224);overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;">“在看”</strong></span>我</p> </section> <section style="max-width: 100%;box-sizing: border-box;display: inline-block;vertical-align: bottom;line-height: 0;width: 45.9063px;overflow-wrap: break-word !important;"> <img data-ratio="1.321875" data-w="320" width="100%" data-type="gif" class="__bg_gif" src="/upload/5103810f55f9d6b6b422944c97ec479e.png" style="box-sizing: border-box;vertical-align: middle;overflow-wrap: break-word !important;visibility: visible !important;width: 45.9063px !important;"> </section> </section> </section>
作者:微信小助手
<p data-mpa-powered-by="yiban.io"><img data-backh="361" data-backw="578" data-ratio="0.625" src="/upload/43d5ba1e172303ef4a19d28696eb2c7f.png" data-type="png" data-w="1024" style="width: 100%;height: auto;"></p> <section powered-by="xiumi.us" style=""> <section> <section> <section powered-by="xiumi.us" style="letter-spacing: 0.544px;"> <section> <section label="Copyright Reserved by PLAYHUDONG." donone="shifuMouseDownCard('shifu_c_008')"> <section powered-by="xiumi.us" style="letter-spacing: 0.612px;"> <section> <section> <section powered-by="xiumi.us"> <section powered-by="xiumi.us"> <section label="Copyright Reserved by PLAYHUDONG." donone="shifuMouseDownCard('shifu_c_008')"> <section powered-by="xiumi.us"> <section> <section> <section powered-by="xiumi.us"> <section powered-by="xiumi.us"> <section label="Copyright Reserved by PLAYHUDONG." donone="shifuMouseDownCard('shifu_c_008')" style="margin-right: 0em;margin-left: 0em;padding: 0.5em 1em;border-style: none;background-color: rgb(235, 235, 235);"> <section style="text-align: left;line-height: 1.5em;"> <span style="color: rgb(136, 136, 136);font-size: 14px;">导读:对于异步方法调用,从Spring3开始提供了@Async注解,该注解可以被标在方法上,以便异步地调用该方法。调用者将在调用时立即返回,方法的实际执行将提交给Spring TaskExecutor的任务中,由指定的线程池中的线程执行。</span> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> <p data-lake-id="dbd6f1093c003921bfcf646f921f093a" style="font-size: 15px;color: rgb(64, 64, 64);line-height: 1.74;letter-spacing: 0.008em;outline-style: none;"><strong style="font-family: -apple-system, system-ui, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial;font-size: 18px;text-align: start;color: rgb(51, 51, 51);"></strong></p> <h3 align="left" style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;letter-spacing: 0.5px;">在项目应用中,@Async调用线程池,</span><span style="font-size: 15px;letter-spacing: 0.5px;color: rgb(255, 76, 0);">推荐使用自定义线程池的模式</span><span style="font-size: 15px;letter-spacing: 0.5px;">。自定义线程池常用方案:<strong>重新实现接口AsyncConfigurer</strong>。</span></h3> <h3 align="left" style="font-weight: bold;line-height: 1.5;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;white-space: normal;background-color: rgb(255, 255, 255);margin-top: 20px;margin-bottom: 20px;"><span style="font-size: 17px;"><strong><span style="letter-spacing: 0.5px;color: rgb(255, 76, 0);">应用场景</span></strong></span></h3> <h3 align="left" style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"><span style="color: rgb(0, 0, 0);"><strong><span style="letter-spacing: 0.5px;">同步:</span></strong></span><span style="font-size: 15px;letter-spacing: 0.5px;">同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。</span></span></h3> <h3 align="left" style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"><span style="color: rgb(0, 0, 0);"><strong><span style="color: rgb(0, 0, 0);letter-spacing: 0.5px;">异步:</span></strong></span><span style="font-size: 15px;letter-spacing: 0.5px;">异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。例如, 在某个调用中,需要顺序调用 A, B, C三个过程方法;如他们都是同步调用,则需要将他们都顺序执行完毕之后,方算作过程执行完毕;如B为一个异步的调用方法,则在执行完A之后,调用B,并不等待B完成,而是执行开始调用C,待C执行完毕之后,就意味着这个过程执行完毕了。在Java中,一般在处理类似的场景之时,都是基于创建独立的线程去完成相应的异步调用逻辑,通过主线程和不同的业务子线程之间的执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。</span></span></h3> <h3 style="margin-bottom: 10px;font-weight: bold;line-height: 1.5;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);margin-top: 15px;"><span style="letter-spacing: 0.5px;color: rgb(255, 76, 0);font-size: 17px;">Spring 已经实现的线程池</span></h3> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong><span style="font-size: 15px;letter-spacing: 0.5px;">SimpleAsyncTaskExecutor</span></strong><span style="font-size: 15px;letter-spacing: 0.5px;">:不是真的线程池,这个类不重用线程,默认每次调用都会创建一个新的线程。</span></p></li> <li><p style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong><span style="font-size: 15px;letter-spacing: 0.5px;">SyncTaskExecutor</span></strong><span style="font-size: 15px;letter-spacing: 0.5px;">:这个类没有实现异步调用,只是一个同步操作。只适用于不需要多线程的地方。</span></p></li> <li><p style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong><span style="font-size: 15px;letter-spacing: 0.5px;">ConcurrentTaskExecutor</span></strong><span style="font-size: 15px;letter-spacing: 0.5px;">:Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类。</span></p></li> <li><p style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><strong><span style="font-size: 15px;letter-spacing: 0.5px;">SimpleThreadPoolTaskExecutor</span></strong><span style="font-size: 15px;letter-spacing: 0.5px;">:是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类。</span></p></li> <li><p style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503565&idx=1&sn=a2918c8d0faa260cf645ca64d4adefd9&chksm=fd63de72ca145764dfb4e6d01f03860d8f19306b4fe43916a11604362daa4cd0b591164aa401&scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" data-itemshowtype="0" tab="innerlink" data-linktype="2"><strong><span style="font-size: 15px;letter-spacing: 0.5px;">ThreadPoolTaskExecuto</span></strong></a><span style="font-size: 15px;letter-spacing: 0.5px;">r :最常使用,推荐。其实质是对java.util.concurrent.ThreadPoolExecutor的包装。</span></p></li> </ul> <p style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;letter-spacing: 0.5px;"><strong>异步的方法有</strong></span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;letter-spacing: 0.5px;">最简单的异步调用,返回值为void</span></p></li> <li><p style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;letter-spacing: 0.5px;">带参数的异步调用,异步方法可以传入参数</span></p></li> <li><p style="margin: 10px auto;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 14px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;letter-spacing: 0.5px;"> 存在返回值,常调用返回Future</span></p></li> </ul> <p style="margin-top: 20px;margin-bottom: 10px;"><span style="font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;text-align: start;font-weight: bold;color: rgb(255, 76, 0);font-size: 17px;letter-spacing: 0.5px;">Spring中启用@Async</span></p> <h2 style="margin-top: 5px;margin-bottom: 20px;font-weight: bold;font-size: 21px;white-space: normal;line-height: 1.5;font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;text-align: start;background-color: rgb(255, 255, 255);"><img class="rich_pages" data-backh="343" data-backw="578" data-galleryid="" data-ratio="0.5928659286592866" data-s="300,640" src="/upload/a195c476325cde8fd7d70eebe6e5af18.png" data-type="png" data-w="1626" style="text-align: center;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;width: 100%;height: auto;"></h2> <section style="margin-bottom: 10px;"> <span style="color: rgb(255, 76, 0);font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-weight: 700;text-align: start;font-size: 17px;letter-spacing: 0.5px;">@Async应用默认线程池</span> </section> <p style="min-height: 24px;margin-top: 5px;text-align: left;"><span style="font-size: 15px;">Spring应用默认的线程池,指在@Async注解在使用时,不指定线程池的名称。查看源码,</span><span style="font-size: 15px;color: rgb(255, 76, 0);">@Async的默认线程池为<strong>SimpleAsyncTaskExecutor</strong></span><span style="font-size: 15px;">。</span></p> <ul class="list-paddingleft-2" style="padding-left: 23px;"> <li style="font-size: 15px;"><p style="margin-top: 10px;"><span style="font-size: 15px;"><strong>无返回值调用 </strong></span></p></li> </ul> <p style="min-height: 24px;"><span style="font-size: 15px;">基于@Async无返回值调用,直接在使用类,使用方法(建议在使用方法)上,加上注解。若需要抛出异常,需手动new一个异常抛出。</span></p> <section style="text-align: center;margin-top: 5px;"> <img class="rich_pages" data-backh="274" data-backw="578" data-galleryid="" data-ratio="0.4745972738537794" data-s="300,640" src="/upload/e1e3a6a7bbc2f5815508e1716c036bdd.png" data-type="png" data-w="1614" style="width: 100%;height: auto;"> </section> <ul class="list-paddingleft-2" style="padding-left: 23px;"> <li style="font-size: 15px;"> <section style="margin-top: 10px;"> <span style="font-size: 15px;"><strong>有返回值Future调用</strong></span> </section></li> </ul> <p style="text-align: center;margin-top: 10px;"><img class="rich_pages" data-backh="401" data-backw="578" data-galleryid="" data-ratio="0.6940639269406392" data-s="300,640" src="/upload/229510bdea2d4f5c36c2cf8e10fbea8a.png" data-type="png" data-w="1752" style="width: 100%;height: auto;"></p> <ul class="list-paddingleft-2" style="padding-left: 23px;"> <li style="font-size: 16px;"><p style="margin-top: 10px;"><span style="font-size: 16px;"><strong>有返回值<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247487778&idx=1&sn=c6256d166ca1a95c5fbdbecb67d6725f&chksm=fd60019dca17888bd5b6f931ee10eed89506094e7cddd6f159c2ba404fd96fd26601174cf7e4&scene=21#wechat_redirect" textvalue="CompletableFuture" data-itemshowtype="0" tab="innerlink" data-linktype="2">CompletableFuture</a>调用</strong></span></p></li> </ul> <section style="min-height: 24px;margin-top: 10px;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503565&idx=2&sn=561c817f25a0b1e6ed41c0805b97dfa1&chksm=fd63de72ca145764e2ed147632515fce82f8e45a06c7ed9b31fb84ab71a5317c3b93a9e05346&scene=21#wechat_redirect" textvalue="CompletableFuture" data-itemshowtype="11" tab="innerlink" data-linktype="2" style="color: rgb(255, 76, 0);"><span style="color: rgb(255, 76, 0);"><strong><span style="font-size: 15px;">CompletableFuture</span></strong></span></a> <span style="color: rgb(255, 76, 0);font-size: 15px;"> 并不使用@Async注解,可达到调用系统线程池处理业务的功能</span> <span style="font-size: 15px;">。</span> </section> <p style="min-height: 24px;"><span style="font-size: 15px;">JDK5新增了Future接口,用于描述一个异步计算的结果。虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们的异步编程的初衷相违背,轮询的方式又会耗费无谓的 CPU 资源,而且也不能及时地得到计算结果。</span></p> <ul class="list-paddingleft-2" style="list-style-type: circle;"> <li> <section style="margin-top: 10px;"> <span style="font-size: 15px;">CompletionStage代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另外一个阶段</span> </section></li> <li><p style="margin-top: 10px;"><span style="font-size: 15px;">一个阶段的计算执行可以是一个Function,Consumer或者Runnable。比如:</span></p></li> </ul> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="css"><code><span class="code-snippet_outer">stage.thenApply(x -> square(x)).thenAccept(x -> System.out.print(x)).thenRun(() -> System.out.println())</span></code></pre> </section> <ul class="list-paddingleft-2" style="list-style-type: circle;"> <li style="font-size: 15px;"> <section style="margin-top: 15px;margin-bottom: 10px;"> <span style="font-size: 15px;">一个阶段的执行可能是被单个阶段的完成触发,也可能是由多个阶段一起触发</span> </section></li> </ul> <p style="min-height: 24px;text-align: left;"><span style="font-size: 15px;letter-spacing: 0.5px;">在Java8中,<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503491&idx=2&sn=12f5f4a67aad19a080d05df98d013ebc&chksm=fd63de3cca14572a21a560a3ae093f43e07a506f525ad33676592d58a9313ca50edc606b21ef&scene=21#wechat_redirect" textvalue="CompletableFuture" data-itemshowtype="11" tab="innerlink" data-linktype="2"><strong>CompletableFuture</strong></a> 提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,</span><span style="font-size: 15px;letter-spacing: 0.5px;color: rgb(255, 76, 0);">可以通过回调的方式处理计算结果,也提供了转换和组合 CompletableFuture 的方法</span><span style="font-size: 15px;letter-spacing: 0.5px;">。</span></p> <ul class="list-paddingleft-2" style="list-style-type: circle;"> <li style="font-size: 15px;letter-spacing: 0.5px;"> <section style="text-align: left;margin-top: 10px;"> <span style="font-size: 15px;letter-spacing: 0.5px;">它可能代表一个明确完成的Future,也有可能代表一个完成阶段( CompletionStage ),它支持在计算完成以后触发一些函数或执行某些动作。</span> </section></li> <li style="font-size: 15px;letter-spacing: 0.5px;"><p style="text-align: left;margin-top: 10px;margin-bottom: 10px;"><span style="font-size: 15px;letter-spacing: 0.5px;">它实现了Future和<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503491&idx=2&sn=12f5f4a67aad19a080d05df98d013ebc&chksm=fd63de3cca14572a21a560a3ae093f43e07a506f525ad33676592d58a9313ca50edc606b21ef&scene=21#wechat_redirect" textvalue="CompletionStage" data-itemshowtype="11" tab="innerlink" data-linktype="2">CompletionStage</a>接口</span></p></li> </ul> <p style="text-align: center;margin-top: 10px;"><img class="rich_pages" data-backh="303" data-backw="578" data-galleryid="" data-ratio="0.5248015873015873" data-s="300,640" src="/upload/990b86cced1da9bb451681b31355663b.png" data-type="png" data-w="2016" style="width: 100%;height: auto;"></p> <ul class="list-paddingleft-2" style="padding-left: 23px;"> <li style="font-size: 16px;"> <section style="margin-top: 10px;"> <span style="font-size: 16px;"><strong>默认线程池的弊端</strong></span> </section></li> </ul> <section style="min-height: 24px;margin-top: 10px;"> <span style="font-size: 15px;"><strong><span style="letter-spacing: 0.5px;">在线程池应用中,参考阿里巴巴java开发规范:</span></strong></span> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503565&idx=1&sn=a2918c8d0faa260cf645ca64d4adefd9&chksm=fd63de72ca145764dfb4e6d01f03860d8f19306b4fe43916a11604362daa4cd0b591164aa401&scene=21#wechat_redirect" textvalue="线程池不允许使用Executors去创建" data-itemshowtype="0" tab="innerlink" style="letter-spacing: 0.5px;" data-linktype="2"><span style="letter-spacing: 0.5px;"><strong><span style="font-size: 15px;color: rgb(255, 76, 0);">线程池不允许使用Executors去创建</span></strong></span></a> <span style="font-size: 15px;letter-spacing: 0.5px;">,不允许使用系统默认的线程池,推荐通过ThreadPoolExecutor的方式,这样的处理方式让开发的工程师更加明确线程池的运行规则,规避资源耗尽的风险。Executors各个方法的弊端:</span> </section> <ul class="list-paddingleft-2" style="list-style-type: circle;"> <li><p style="margin-top: 10px;text-align: left;"><span style="font-size: 15px;letter-spacing: 0.5px;">newFixedThreadPool和newSingleThreadExecutor:</span><span style="font-size: 15px;letter-spacing: 0.5px;color: rgb(255, 76, 0);">主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。</span></p></li> <li style="font-size: 15px;letter-spacing: 0.5px;"> <section style="margin-top: 10px;text-align: left;"> <span style="font-size: 15px;letter-spacing: 0.5px;">newCachedThreadPool和newScheduledThreadPool:要问题是线程数最大数是Integer.MAX_VALUE,</span> <span style="font-size: 15px;letter-spacing: 0.5px;color: rgb(255, 76, 0);">可能会创建数量非常多的线程,甚至OOM</span> <span style="font-size: 15px;letter-spacing: 0.5px;">。</span> </section> <section style="margin-top: 10px;"> <br> </section></li> </ul> <p style="min-height: 24px;"><span style="font-size: 15px;letter-spacing: 0.5px;">@Async默认异步配置使用的是SimpleAsyncTaskExecutor,该线程池默认来一个任务创建一个线程,若系统中不断的创建线程,最终会导致系统占用内存过高,引发OutOfMemoryError错误。针对线程创建问题,SimpleAsyncTaskExecutor提供了限流机制,通过concurrencyLimit属性来控制开关,当concurrencyLimit>=0时开启限流机制,默认关闭限流机制即concurrencyLimit=-1,当关闭情况下,会不断创建新的线程来处理任务。基于默认配置,SimpleAsyncTaskExecutor并不是严格意义的线程池,达不到线程复用的功能。</span></p> <h3 style="line-height: 28px;margin-top: 16px;margin-bottom: 10px;"><span style="font-size: 17px;letter-spacing: 0.5px;"><strong><span style="color: rgb(255, 76, 0);">@Async应用自定义线程池</span></strong></span></h3> <p style="min-height: 24px;"><span style="font-size: 15px;letter-spacing: 0.5px;">自定义线程池,可对系统中线程池更加细粒度的控制,方便调整线程池大小配置,线程执行异常控制和处理。在设置系统自定义线程池代替默认线程池时,虽可通过多种模式设置,但替换默认线程池最终产生的线程池有且只能设置一个(不能设置多个类继承AsyncConfigurer)自定义线程池有如下模式:</span></p> <ul class="list-paddingleft-2" style="list-style-type: circle;"> <li><p style="margin-top: 5px;"><span style="font-size: 15px;letter-spacing: 0.5px;">重新实现接口AsyncConfigurer</span></p></li> <li> <section style="margin-top: 10px;"> <span style="font-size: 15px;letter-spacing: 0.5px;">继承AsyncConfigurerSupport</span> </section></li> <li><p style="margin-top: 10px;"><span style="font-size: 15px;letter-spacing: 0.5px;">配置由自定义的TaskExecutor替代内置的任务执行器</span></p></li> </ul> <p style="min-height: 24px;"><span style="font-size: 15px;letter-spacing: 0.5px;"><br></span></p> <p style="min-height: 24px;"><span style="font-size: 15px;letter-spacing: 0.5px;">通过查看Spring源码关于@Async的默认调用规则,</span><span style="font-size: 15px;letter-spacing: 0.5px;color: rgb(255, 76, 0);">会优先查询源码中实现AsyncConfigurer这个接口的类,实现这个接口的类为AsyncConfigurerSupport</span><span style="font-size: 15px;letter-spacing: 0.5px;">。但默认配置的线程池和异步处理方法均为空,所以,无论是继承或者重新实现接口,都需指定一个线程池。且重新实现 public Executor getAsyncExecutor()方法。</span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li style="font-weight: bold;"><h4 style="line-height: 24px;margin-top: 10px;margin-bottom: 5px;"><strong>实现接口AsyncConfigurer</strong></h4></li> </ul> <p style="text-align: center;margin-top: 10px;"><img class="rich_pages" data-backh="653" data-backw="578" data-galleryid="" data-ratio="1.129692832764505" data-s="300,640" src="/upload/1c651e4751807f04b1fd9e76a4bc9d4e.png" data-type="png" data-w="1758" style="width: 100%;height: auto;"></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li style="min-height: 24px;font-weight: bold;"> <section style="min-height: 24px;margin-top: 10px;"> <strong><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">继承AsyncConfigurerSupport</span></strong> </section></li> </ul> <section style="text-align: center;margin-top: 5px;"> <img class="rich_pages" data-backh="478" data-backw="578" data-galleryid="" data-ratio="0.8261851015801355" data-s="300,640" src="/upload/a4a84b372864855bdee7bbd89794a2fb.png" data-type="png" data-w="1772" style="width: 100%;height: auto;"> </section> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li style="font-weight: bold;"> <section style="min-height: 24px;margin-top: 10px;"> <strong><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">配置自定义的TaskExecutor</span></strong> </section></li> </ul> <p style="min-height: 24px;text-align: left;"><span style="font-size: 15px;letter-spacing: 0.5px;">由于AsyncConfigurer的默认线程池在源码中为空,Spring通过beanFactory.getBean(TaskExecutor.class)先查看是否有线程池,未配置时,通过beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class),又查询是否存在默认名称为TaskExecutor的线程池。所以可在项目中,定义名称为TaskExecutor的bean生成一个默认线程池。也可不指定线程池的名称,申明一个线程池,本身底层是基于TaskExecutor.class便可。</span></p> <p style="min-height: 24px;text-align: left;"><br></p> <p style="min-height: 24px;text-align: left;"><span style="font-size: 15px;letter-spacing: 0.5px;">比如:</span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="ruby"><code><span class="code-snippet_outer">Executor.<span class="code-snippet__keyword">class</span><span class="code-snippet__symbol">:ThreadPoolExecutorAdapter->ThreadPoolExecutor->AbstractExecutorService->ExecutorService->Executor</span></span></code></pre> </section> <p style="min-height: 24px;text-align: left;"><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: 15px;letter-spacing: 0.5px;">这样的模式,最终底层为Executor.class,在替换默认的线程池时,需设置默认的线程池名称为TaskExecutor</span><span style="font-size: 15px;letter-spacing: 0.5px;"></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="ruby"><code><span class="code-snippet_outer">TaskExecutor.<span class="code-snippet__keyword">class</span><span class="code-snippet__symbol">:ThreadPoolTaskExecutor->SchedulingTaskExecutor->AsyncTaskExecutor->TaskExecutor</span></span></code></pre> </section> <p style="min-height: 24px;text-align: left;"><span style="font-size: 15px;letter-spacing: 0.5px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">这样的模式,最终底层为TaskExecutor.class,在替换默认的线程池时,可不指定线程池名称。</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: 15px;letter-spacing: 0.5px;"></span></p> <p style="text-align: center;margin-top: 10px;"><img class="rich_pages" data-backh="710" data-backw="578" data-galleryid="" data-ratio="1.2275862068965517" data-s="300,640" src="/upload/e850c4c4ff275c7ef1c0a83857d84195.png" data-type="png" data-w="1740" style="width: 100%;height: auto;"></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style=""> <section style="margin-top: 20px;font-size: 15px;text-align: center;color: rgb(153, 153, 153);border-bottom: 1px solid rgb(238, 238, 238);margin-bottom: 5px;"> - END </section> </section> <section data-recommend-type="list-title" data-recommend-tid="8" data-mpa-template="t" style="width: 100%;display: flex;justify-content: center;align-items: center;" data-mid="" data-from="yb-recommend"> <section style="width: 100%;background: rgb(255, 255, 255);border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(232, 232, 235);padding: 20px 14px;" data-mid=""> <section style="width: 100%;display: flex;justify-content: center;align-items: center;align-items: flex-end;" data-mid=""> <section style="display: flex;justify-content: center;align-items: center;max-width: 100%;background: #fff;margin-bottom: -10px;z-index: 10;" data-mid=""> <section style="width: 10px;height: 10px;border-radius: 50%;border-width: 1px;border-style: solid;border-color: rgb(51, 51, 51);" data-mid=""> <br> </section> <section style="margin: 0 8px;height: 20px;font-size: 14px;font-weight: 500;color: #333333;line-height: 20px;" data-mid=""> <p data-mid="">往期推荐</p> </section> <section style="width: 10px;height: 10px;border-radius: 50%;border-width: 1px;border-style: solid;border-color: rgb(51, 51, 51);" data-mid=""> <br> </section> </section> </section> <section style="width: 100%;height: 1px;background: #333333;margin-bottom: 16px;" data-mid=""> <br> </section> <section style="width: 100%;" data-mid=""> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="8" data-recommend-article-id="2247503642_2" data-recommend-article-time="1622593800" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxFoicenBJB4hwLTZyx7jGwk0FMJhI6UsEyPPuuib312mAVh9wLNKiaypFkT9octY9b3CHeoWEpCUDDpQ/0?wx_fmt=jpeg" data-recommend-article-title="干货分享 | 终于踩到了SQL慢查询的坑!" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503642&idx=2&sn=25213446ddc5bd6ec83194e690e1b3e5&chksm=fd63dfa5ca1456b3049df12d431a952ef8f88786f0185b001dd217748eb3c90b90728427385a#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503642&idx=2&sn=25213446ddc5bd6ec83194e690e1b3e5&chksm=fd63dfa5ca1456b3049df12d431a952ef8f88786f0185b001dd217748eb3c90b90728427385a&scene=21#wechat_redirect" data-linktype="2"> <section data-recommend-title="t" style="width: 100%;background: #f5f5f5;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;padding: 6px 16px 6px;font-size: 13px;font-weight: 400;color: #333333;line-height: 18px;" data-mid=""> <p style="white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width: 100%;" data-mid="">干货分享 | 终于踩到了SQL慢查询的坑!</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="8" data-recommend-article-id="2247503565_1" data-recommend-article-time="1622421000" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxGBDae9PBUicgRkkeftB3NQE9BGVzhn0kAQ5cG4ylTHpWGkhX485OrjGCHibpicLBz1QmsCjL2xAgCpQ/0?wx_fmt=jpeg" data-recommend-article-title="为什么阿里巴巴要禁用Executors创建线程池?" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503565&idx=1&sn=a2918c8d0faa260cf645ca64d4adefd9&chksm=fd63de72ca145764dfb4e6d01f03860d8f19306b4fe43916a11604362daa4cd0b591164aa401#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503565&idx=1&sn=a2918c8d0faa260cf645ca64d4adefd9&chksm=fd63de72ca145764dfb4e6d01f03860d8f19306b4fe43916a11604362daa4cd0b591164aa401&scene=21#wechat_redirect" data-linktype="2"> <section data-recommend-title="t" style="width: 100%;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;padding: 6px 16px 6px;font-size: 13px;font-weight: 400;color: #333333;line-height: 18px;" data-mid=""> <p style="white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width: 100%;" data-mid="">为什么阿里巴巴要禁用Executors创建线程池?</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="8" data-recommend-article-id="2247503565_2" data-recommend-article-time="1622421000" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxGBDae9PBUicgRkkeftB3NQEyQXw4o14hEf2Wc4FU6YZ50VGW6RicbicibBTskEc8s0540PEM1f2FKLHA/0?wx_fmt=jpeg" data-recommend-article-title="源码分析 | CompletableFuture 组合处理 allOf 和 anyOf 太赞了!" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503565&idx=2&sn=561c817f25a0b1e6ed41c0805b97dfa1&chksm=fd63de72ca145764e2ed147632515fce82f8e45a06c7ed9b31fb84ab71a5317c3b93a9e05346#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503565&idx=2&sn=561c817f25a0b1e6ed41c0805b97dfa1&chksm=fd63de72ca145764e2ed147632515fce82f8e45a06c7ed9b31fb84ab71a5317c3b93a9e05346&scene=21#wechat_redirect" data-linktype="2"> <section data-recommend-title="t" style="width: 100%;background: #f5f5f5;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;padding: 6px 16px 6px;font-size: 13px;font-weight: 400;color: #333333;line-height: 18px;" data-mid=""> <p style="white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width: 100%;" data-mid="">源码分析 | CompletableFuture 组合处理 allOf 和 anyOf 太赞了!</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="8" data-recommend-article-id="2247503529_1" data-recommend-article-time="1622161200" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxGO7m47S8Lichxv5Xrb5Lb7x2RgMObJFOtMgAywn0hsrzrE1e0g0JKamxZGdZJwfz1XasNuLTYqouA/0?wx_fmt=jpeg" data-recommend-article-title="源码分析 | BeanWrapper获取Bean属性实现" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503529&idx=1&sn=9db55e840e7bc2c940fc9fad357af940&chksm=fd63de16ca145700c0cfa16527aed70f3f3c58d3723953a389f9104caf20a75d4ef362dc46c8#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503529&idx=1&sn=9db55e840e7bc2c940fc9fad357af940&chksm=fd63de16ca145700c0cfa16527aed70f3f3c58d3723953a389f9104caf20a75d4ef362dc46c8&scene=21#wechat_redirect" data-linktype="2"> <section data-recommend-title="t" style="width: 100%;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;padding: 6px 16px 6px;font-size: 13px;font-weight: 400;color: #333333;line-height: 18px;" data-mid=""> <p style="white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width: 100%;" data-mid="">源码分析 | BeanWrapper获取Bean属性实现</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="8" data-recommend-article-id="2247503529_3" data-recommend-article-time="1622161200" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxEpHUibbwNQfZ9EwkuVZjicJtUOrvrgFy0fI3uQfuDKlfO7aIEGjcib0JpT2FwLCz0XLMY0TqML4ESUg/0?wx_fmt=jpeg" data-recommend-article-title="技术视频更新~" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503529&idx=3&sn=38e4789fd88d7171f5d213389b1d3188&chksm=fd63de16ca145700354db9b4ab9cb844819b7be302c517c98fba8ee8c1f475a1c11efa54865e#rd"> <section data-recommend-title="t" style="width: 100%;background: #f5f5f5;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;padding: 6px 16px 6px;font-size: 13px;font-weight: 400;color: #333333;line-height: 18px;border-bottom:none !important;" data-mid=""> <p style="white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width: 100%;" data-mid=""><a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&mid=2247503529&idx=3&sn=38e4789fd88d7171f5d213389b1d3188&chksm=fd63de16ca145700354db9b4ab9cb844819b7be302c517c98fba8ee8c1f475a1c11efa54865e&scene=21#wechat_redirect" data-linktype="2">技术视频更新~</a></p> </section> </section> </section> </section> </section> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU3OTc1MDM1Mg==" data-headimg="http://mmbiz.qpic.cn/sz_mmbiz_png/d7YzaYDnrxEiaEweMvUlsh4pae7kibN8yKoXZJzNAc9JNibBnENcfn4al4QqdTQwTh4pUKCe5Xg7bsgtN0d6ePHDw/0?wx_fmt=png" data-nickname="码农架构" data-alias="iByteCoding" data-signature="专注于系统架构、高可用、高性能、高并发类技术分享" data-from="0"></mpprofile> </section> <p style="text-align: right;"><span style="font-size: 14px;letter-spacing: 0.544px;text-size-adjust: auto;background-color: rgb(255, 255, 255);caret-color: rgb(63, 74, 89);color: rgb(63, 74, 89);font-family: 微软雅黑;text-align: left;">🧐</span><strong style="letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 15px;background-color: rgb(255, 255, 255);caret-color: rgb(63, 74, 89);color: rgb(63, 74, 89);font-family: 微软雅黑;text-align: left;">分享、点赞、在看</strong><span style="font-size: 14px;letter-spacing: 0.544px;text-size-adjust: auto;background-color: rgb(255, 255, 255);caret-color: rgb(63, 74, 89);color: rgb(63, 74, 89);font-family: 微软雅黑;text-align: left;">,给个</span><strong style="letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 15px;background-color: rgb(255, 255, 255);caret-color: rgb(63, 74, 89);color: rgb(63, 74, 89);font-family: 微软雅黑;text-align: left;">3连击</strong><span style="font-size: 14px;letter-spacing: 0.544px;text-size-adjust: auto;background-color: rgb(255, 255, 255);caret-color: rgb(63, 74, 89);color: rgb(63, 74, 89);font-family: 微软雅黑;text-align: left;">呗</span><strong style="letter-spacing: 0.544px;white-space: normal;text-size-adjust: auto;font-size: 15px;background-color: rgb(255, 255, 255);caret-color: rgb(63, 74, 89);color: rgb(63, 74, 89);font-family: 微软雅黑;text-align: left;">👇</strong><br></p>
作者:微信小助手
<section data-mpa-template="t" mpa-from-tpl="t" data-mpa-powered-by="yiban.io"> <section data-mpa-category="模板" style="display: flex;justify-content: center;align-items: center;padding-top: 20px;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <img data-ratio="1.1485148514851484" src="/upload/7728ee3c0a6c879c41c249702842d924.png" data-type="png" data-w="202" style="width: 50px;height: 58px;"> <img data-ratio="1.2173913043478262" src="/upload/577529c0f58346f7278f51a52fb97b78.png" data-type="gif" data-w="138" style="width: 70px;height: 70px;margin-left: -40.5px;"> <p style="font-size: 14px;font-family: PingFangSC-Semibold, PingFang SC;font-weight: 600;color: #4391fd;line-height: 20px;letter-spacing: 1px;" data-mid="">戳这里,加关注哦~</p> </section> </section> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;line-height: 1.6;letter-spacing: 0.034em;color: rgb(63, 63, 63);font-size: 16px;"> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">通过前面几天文章我们详细的介绍了SpringSecurity的使用,本文我们来看下,结合JWT来实现单点登录操作。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/A0bYOQcma0P0EoThryzeC37QtKrbwWy2tqDNTOuicNepMf7rlJXNXuKmYfmfBfFQd47E7v305gxWUe0hLg1294w/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">一、什么是单点登陆</span></h2> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/A0bYOQcma0P0EoThryzeC37QtKrbwWy2tqDNTOuicNepMf7rlJXNXuKmYfmfBfFQd47E7v305gxWUe0hLg1294w/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">二、简单的运行机制</span></h2> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">单点登录的机制其实是比较简单的,用一个现实中的例子做比较。某公园内部有许多独立的景点,游客可以在各个景点门口单独买票。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">对于需要游玩所有的景点的游客,这种买票方式很不方便,需要在每个景点门口排队买票,钱包拿 进拿出的,容易丢失,很不安全。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">于是绝大多数游客选择在大门口买一张通票(也叫套票),就可以玩遍所有的景点而不需要重新再买票。他们只需要在每个景点门 口出示一下刚才买的套票就能够被允许进入每个独立的景点。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">单点登录的机制也一样,如下图所示,</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img src="/upload/62e1cfa35a867da797e03cae47e0ee76.png" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;" data-type="png" data-ratio="0.5908045977011495" data-w="870"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;font-family: PingFangSC-Light;"> img </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">用户认证:</strong> 这一环节主要是用户向认证服务器发起认证请求,认证服务器给用户返回一个成功的令牌token,主要在认证服务器中完成,即图中的认证系统,注意认证系统只能有一个。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">身份校验:</strong> 这一环节是用户携带token去访问其他服务器时,在其他服务器中要对token的真伪进行检验,主要在资源服务器中完成,即图中的应用系统2 3</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/A0bYOQcma0P0EoThryzeC37QtKrbwWy2tqDNTOuicNepMf7rlJXNXuKmYfmfBfFQd47E7v305gxWUe0hLg1294w/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">三、JWT介绍</span></h2> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;">概念说明</h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">从分布式认证流程中,我们不难发现,这中间起最关键作用的就是token,token的安全与否,直接关系到系统的健壮性,这里我们选择使用JWT来实现token的生成和校验。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">JWT,全称JSON Web Token,官网地址https://jwt.io,是一款出色的分布式身份校验方案。可以生成token,也可以解析检验token。</p> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;">JWT生成的token由三部分组成:</h4> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" 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);"> 载荷:token中存放有效信息的部分,比如用户名,用户角色,过期时间等,但是不要放密码,会泄露! </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 签名:将头部与载荷分别采用base64编码后,用“.”相连,再加入盐,最后使用头部声明的编码类型进行编码,就得到了签名。 </section></li> </ul> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;">JWT生成token的安全性分析</h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">从JWT生成的token组成上来看,要想避免token被伪造,主要就得看签名部分了,而签名部分又有三部分组成,其中头部和载荷的base64编码,几乎是透明的,毫无安全性可言,那么最终守护token安全的重担就落在了加入的盐上面了!</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">试想:如果生成token所用的盐与解析token时加入的盐是一样的。岂不是类似于中国人民银行把人民币防伪技术公开了?大家可以用这个盐来解析token,就能用来伪造token。这时,我们就需要对盐采用非对称加密的方式进行加密,以达到生成token与校验token方所用的盐不一致的安全效果!</p> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;">非对称加密RSA介绍</h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">基本原理:</strong> 同时生成两把密钥:私钥和公钥,私钥隐秘保存,公钥可以下发给信任客户端</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" 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> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">优点:</strong> 安全,难以破解</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">缺点:</strong> 算法比较耗时,为了安全,可以接受</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">历史:</strong> 三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字缩写:RSA。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/A0bYOQcma0P0EoThryzeC37QtKrbwWy2tqDNTOuicNepMf7rlJXNXuKmYfmfBfFQd47E7v305gxWUe0hLg1294w/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">四、SpringSecurity整合JWT</span></h2> <h3 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;margin-top: 1.2em;"><span style="font-size: 17px;display: inline-block;margin-left: 8px;color: rgb(72, 179, 120);">1.认证思路分析</span></h3> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">SpringSecurity主要是通过过滤器来实现功能的!我们要找到SpringSecurity实现认证和校验身份的过滤器!</p> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;">回顾集中式认证流程</h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="">用户认证:</strong>使用<code style="">UsernamePasswordAuthenticationFilter</code>过滤器中<code style="">attemptAuthentication</code>方法实现认证功能,该过滤器父类中<code style="">successfulAuthentication</code>方法实现认证成功后的操作。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="">身份校验:</strong>使用<code style="">BasicAuthenticationFilter</code>过滤器中<code style="">doFilterInternal</code>方法验证是否登录,以决定能否进入后续过滤器。</p> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;">分析分布式认证流程</h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">用户认证:</strong></p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">由于分布式项目,多数是前后端分离的架构设计,我们要满足可以接受异步post的认证请求参数,需要修改<code style="">UsernamePasswordAuthenticationFilter</code>过滤器中<code style="">attemptAuthentication</code>方法,让其能够接收请求体。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">另外,默认<code style="">successfulAuthentication</code>方法在认证通过后,是把用户信息直接放入session就完事了,现在我们需要修改这个方法,在认证通过后生成token并返回给用户。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">身份校验:</strong></p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">原来BasicAuthenticationFilter过滤器中doFilterInternal方法校验用户是否登录,就是看session中是否有用户信息,我们要修改为,验证用户携带的token是否合法,并解析出用户信息,交给SpringSecurity,以便于后续的授权功能可以正常使用。</p> <h3 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;margin-top: 1.2em;"><span style="font-size: 17px;display: inline-block;margin-left: 8px;color: rgb(72, 179, 120);">2.具体实现</span></h3> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">为了演示单点登录的效果,我们设计如下项目结构</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img src="/upload/700cc7f2a070f58cdf8e5f7328fd4ee5.png" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;" data-type="png" data-ratio="0.9791666666666666" data-w="672"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;font-family: PingFangSC-Light;"> img </figcaption> </figure> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;">2.1父工程创建</h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">因为本案例需要创建多个系统,所以我们使用maven聚合工程来实现,首先创建一个父工程,导入springboot的父依赖即可</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><parent><br> <groupId>org.springframework.boot</groupId><br> <artifactId>spring-boot-starter-parent</artifactId><br> <version>2.1.3.RELEASE</version><br> <relativePath/><br></parent><br></code></pre> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;">2.2公共工程创建</h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">然后创建一个common工程,其他工程依赖此系统</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img src="/upload/77987275fefed93be5746d425700edbd.png" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;" data-type="png" data-ratio="0.9608938547486033" data-w="716"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;font-family: PingFangSC-Light;"> img </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">导入JWT相关的依赖</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><dependencies><br> <dependency><br> <groupId>io.jsonwebtoken</groupId><br> <artifactId>jjwt-api</artifactId><br> <version>0.10.7</version><br> </dependency><br> <dependency><br> <groupId>io.jsonwebtoken</groupId><br> <artifactId>jjwt-impl</artifactId><br> <version>0.10.7</version><br> <scope>runtime</scope><br> </dependency><br> <dependency><br> <groupId>io.jsonwebtoken</groupId><br> <artifactId>jjwt-jackson</artifactId><br> <version>0.10.7</version><br> <scope>runtime</scope><br> </dependency><br> <!--jackson包--><br> <dependency><br> <groupId>com.fasterxml.jackson.core</groupId><br> <artifactId>jackson-databind</artifactId><br> <version>2.9.9</version><br> </dependency><br> <!--日志包--><br> <dependency><br> <groupId>org.springframework.boot</groupId><br> <artifactId>spring-boot-starter-logging</artifactId><br> </dependency><br> <dependency><br> <groupId>joda-time</groupId><br> <artifactId>joda-time</artifactId><br> </dependency><br> <dependency><br> <groupId>org.projectlombok</groupId><br> <artifactId>lombok</artifactId><br> </dependency><br> <dependency><br> <groupId>org.springframework.boot</groupId><br> <artifactId>spring-boot-starter-test</artifactId><br> </dependency><br></dependencies><br></code></pre> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">创建相关的工具类</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img src="/upload/3b9fc788eef27b4656602e7916489525.png" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;" data-type="png" data-ratio="0.6150793650793651" data-w="504"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;font-family: PingFangSC-Light;"> img </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">Payload</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * @program: springboot-54-security-jwt-demo<br> * @description:<br> * @author: 波波烤鸭<br> */<br>@Data<br>public class Payload <T>{<br> private String id;<br> private T userInfo;<br> private Date expiration;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">JsonUtils</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">package com.dpb.utils;<br><br>import com.fasterxml.jackson.core.JsonProcessingException;<br>import com.fasterxml.jackson.core.type.TypeReference;<br>import com.fasterxml.jackson.databind.ObjectMapper;<br>import org.slf4j.Logger;<br>import org.slf4j.LoggerFactory;<br><br>import java.io.IOException;<br>import java.util.List;<br>import java.util.Map;<br><br>/**<br> * @author: 波波烤鸭<br> **/<br>public class JsonUtils {<br><br> public static final ObjectMapper mapper = new ObjectMapper();<br><br> private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);<br><br> public static String toString(Object obj) {<br> <span style="color: #c678dd;line-height: 26px;">if</span> (obj == null) {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> null;<br> }<br> <span style="color: #c678dd;line-height: 26px;">if</span> (obj.getClass() == String.class) {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> (String) obj;<br> }<br> try {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> mapper.writeValueAsString(obj);<br> } catch (JsonProcessingException e) {<br> logger.error(<span style="color: #98c379;line-height: 26px;">"json序列化出错:"</span> + obj, e);<br> <span style="color: #e6c07b;line-height: 26px;">return</span> null;<br> }<br> }<br><br> public static <T> T toBean(String json, Class<T> tClass) {<br> try {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> mapper.readValue(json, tClass);<br> } catch (IOException e) {<br> logger.error(<span style="color: #98c379;line-height: 26px;">"json解析出错:"</span> + json, e);<br> <span style="color: #e6c07b;line-height: 26px;">return</span> null;<br> }<br> }<br><br> public static <E> List<E> toList(String json, Class<E> eClass) {<br> try {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, eClass));<br> } catch (IOException e) {<br> logger.error(<span style="color: #98c379;line-height: 26px;">"json解析出错:"</span> + json, e);<br> <span style="color: #e6c07b;line-height: 26px;">return</span> null;<br> }<br> }<br><br> public static <K, V> Map<K, V> toMap(String json, Class<K> kClass, Class<V> vClass) {<br> try {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> mapper.readValue(json, mapper.getTypeFactory().constructMapType(Map.class, kClass, vClass));<br> } catch (IOException e) {<br> logger.error(<span style="color: #98c379;line-height: 26px;">"json解析出错:"</span> + json, e);<br> <span style="color: #e6c07b;line-height: 26px;">return</span> null;<br> }<br> }<br><br> public static <T> T nativeRead(String json, TypeReference<T> <span style="color: #e6c07b;line-height: 26px;">type</span>) {<br> try {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> mapper.readValue(json, <span style="color: #e6c07b;line-height: 26px;">type</span>);<br> } catch (IOException e) {<br> logger.error(<span style="color: #98c379;line-height: 26px;">"json解析出错:"</span> + json, e);<br> <span style="color: #e6c07b;line-height: 26px;">return</span> null;<br> }<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">JwtUtils</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">package com.dpb.utils;<br><br>import com.dpb.domain.Payload;<br>import io.jsonwebtoken.Claims;<br>import io.jsonwebtoken.Jws;<br>import io.jsonwebtoken.Jwts;<br>import io.jsonwebtoken.SignatureAlgorithm;<br>import org.joda.time.DateTime;<br><br>import java.security.PrivateKey;<br>import java.security.PublicKey;<br>import java.util.Base64;<br>import java.util.UUID;<br><br>/**<br> * @author: 波波烤鸭<br> * 生成token以及校验token相关方法<br> */<br>public class JwtUtils {<br><br> private static final String JWT_PAYLOAD_USER_KEY = <span style="color: #98c379;line-height: 26px;">"user"</span>;<br><br> /**<br> * 私钥加密token<br> *<br> * @param userInfo 载荷中的数据<br> * @param privateKey 私钥<br> * @param expire 过期时间,单位分钟<br> * @<span style="color: #e6c07b;line-height: 26px;">return</span> JWT<br> */<br> public static String generateTokenExpireInMinutes(Object userInfo, PrivateKey privateKey, int expire) {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> Jwts.builder()<br> .claim(JWT_PAYLOAD_USER_KEY, JsonUtils.toString(userInfo))<br> .setId(createJTI())<br> .setExpiration(DateTime.now().plusMinutes(expire).toDate())<br> .signWith(privateKey, SignatureAlgorithm.RS256)<br> .compact();<br> }<br><br> /**<br> * 私钥加密token<br> *<br> * @param userInfo 载荷中的数据<br> * @param privateKey 私钥<br> * @param expire 过期时间,单位秒<br> * @<span style="color: #e6c07b;line-height: 26px;">return</span> JWT<br> */<br> public static String generateTokenExpireInSeconds(Object userInfo, PrivateKey privateKey, int expire) {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> Jwts.builder()<br> .claim(JWT_PAYLOAD_USER_KEY, JsonUtils.toString(userInfo))<br> .setId(createJTI())<br> .setExpiration(DateTime.now().plusSeconds(expire).toDate())<br> .signWith(privateKey, SignatureAlgorithm.RS256)<br> .compact();<br> }<br><br> /**<br> * 公钥解析token<br> *<br> * @param token 用户请求中的token<br> * @param publicKey 公钥<br> * @<span style="color: #e6c07b;line-height: 26px;">return</span> Jws<Claims><br> */<br> private static Jws<Claims> parserToken(String token, PublicKey publicKey) {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);<br> }<br><br> private static String <span style="color: rgb(97, 174, 238);line-height: 26px;">createJTI</span>() {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> new String(Base64.getEncoder().encode(UUID.randomUUID().toString().getBytes()));<br> }<br><br> /**<br> * 获取token中的用户信息<br> *<br> * @param token 用户请求中的令牌<br> * @param publicKey 公钥<br> * @<span style="color: #e6c07b;line-height: 26px;">return</span> 用户信息<br> */<br> public static <T> Payload<T> getInfoFromToken(String token, PublicKey publicKey, Class<T> userType) {<br> Jws<Claims> claimsJws = parserToken(token, publicKey);<br> Claims body = claimsJws.getBody();<br> Payload<T> claims = new Payload<>();<br> claims.setId(body.getId());<br> claims.setUserInfo(JsonUtils.toBean(body.get(JWT_PAYLOAD_USER_KEY).toString(), userType));<br> claims.setExpiration(body.getExpiration());<br> <span style="color: #e6c07b;line-height: 26px;">return</span> claims;<br> }<br><br> /**<br> * 获取token中的载荷信息<br> *<br> * @param token 用户请求中的令牌<br> * @param publicKey 公钥<br> * @<span style="color: #e6c07b;line-height: 26px;">return</span> 用户信息<br> */<br> public static <T> Payload<T> getInfoFromToken(String token, PublicKey publicKey) {<br> Jws<Claims> claimsJws = parserToken(token, publicKey);<br> Claims body = claimsJws.getBody();<br> Payload<T> claims = new Payload<>();<br> claims.setId(body.getId());<br> claims.setExpiration(body.getExpiration());<br> <span style="color: #e6c07b;line-height: 26px;">return</span> claims;<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">RsaUtils</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">package com.dpb.utils;<br><br>import java.io.File;<br>import java.io.IOException;<br>import java.nio.file.Files;<br>import java.security.*;<br>import java.security.spec.InvalidKeySpecException;<br>import java.security.spec.PKCS8EncodedKeySpec;<br>import java.security.spec.X509EncodedKeySpec;<br>import java.util.Base64;<br><br>/**<br> * @author 波波烤鸭<br> */<br>public class RsaUtils {<br><br> private static final int DEFAULT_KEY_SIZE = 2048;<br> /**<br> * 从文件中读取公钥<br> *<br> * @param filename 公钥保存路径,相对于classpath<br> * @<span style="color: #e6c07b;line-height: 26px;">return</span> 公钥对象<br> * @throws Exception<br> */<br> public static PublicKey getPublicKey(String filename) throws Exception {<br> byte[] bytes = readFile(filename);<br> <span style="color: #e6c07b;line-height: 26px;">return</span> getPublicKey(bytes);<br> }<br><br> /**<br> * 从文件中读取密钥<br> *<br> * @param filename 私钥保存路径,相对于classpath<br> * @<span style="color: #e6c07b;line-height: 26px;">return</span> 私钥对象<br> * @throws Exception<br> */<br> public static PrivateKey getPrivateKey(String filename) throws Exception {<br> byte[] bytes = readFile(filename);<br> <span style="color: #e6c07b;line-height: 26px;">return</span> getPrivateKey(bytes);<br> }<br><br> /**<br> * 获取公钥<br> *<br> * @param bytes 公钥的字节形式<br> * @<span style="color: #e6c07b;line-height: 26px;">return</span><br> * @throws Exception<br> */<br> private static PublicKey getPublicKey(byte[] bytes) throws Exception {<br> bytes = Base64.getDecoder().decode(bytes);<br> X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);<br> KeyFactory factory = KeyFactory.getInstance(<span style="color: #98c379;line-height: 26px;">"RSA"</span>);<br> <span style="color: #e6c07b;line-height: 26px;">return</span> factory.generatePublic(spec);<br> }<br><br> /**<br> * 获取密钥<br> *<br> * @param bytes 私钥的字节形式<br> * @<span style="color: #e6c07b;line-height: 26px;">return</span><br> * @throws Exception<br> */<br> private static PrivateKey getPrivateKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {<br> bytes = Base64.getDecoder().decode(bytes);<br> PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);<br> KeyFactory factory = KeyFactory.getInstance(<span style="color: #98c379;line-height: 26px;">"RSA"</span>);<br> <span style="color: #e6c07b;line-height: 26px;">return</span> factory.generatePrivate(spec);<br> }<br><br> /**<br> * 根据密文,生存rsa公钥和私钥,并写入指定文件<br> *<br> * @param publicKeyFilename 公钥文件路径<br> * @param privateKeyFilename 私钥文件路径<br> * @param secret 生成密钥的密文<br> */<br> public static void generateKey(String publicKeyFilename, String privateKeyFilename, String secret, int keySize) throws Exception {<br> KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(<span style="color: #98c379;line-height: 26px;">"RSA"</span>);<br> SecureRandom secureRandom = new SecureRandom(secret.getBytes());<br> keyPairGenerator.initialize(Math.max(keySize, DEFAULT_KEY_SIZE), secureRandom);<br> KeyPair keyPair = keyPairGenerator.genKeyPair();<br> // 获取公钥并写出<br> byte[] publicKeyBytes = keyPair.getPublic().getEncoded();<br> publicKeyBytes = Base64.getEncoder().encode(publicKeyBytes);<br> writeFile(publicKeyFilename, publicKeyBytes);<br> // 获取私钥并写出<br> byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();<br> privateKeyBytes = Base64.getEncoder().encode(privateKeyBytes);<br> writeFile(privateKeyFilename, privateKeyBytes);<br> }<br><br> private static byte[] readFile(String fileName) throws Exception {<br> <span style="color: #e6c07b;line-height: 26px;">return</span> Files.readAllBytes(new File(fileName).toPath());<br> }<br><br> private static void writeFile(String destPath, byte[] bytes) throws IOException {<br> File dest = new File(destPath);<br> <span style="color: #c678dd;line-height: 26px;">if</span> (!dest.exists()) {<br> dest.createNewFile();<br> }<br> Files.write(dest.toPath(), bytes);<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">在通用子模块中编写测试类生成rsa公钥和私钥</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">/**<br> * @program: springboot-54-security-jwt-demo<br> * @description:<br> * @author: 波波烤鸭<br> */<br>public class JwtTest {<br> private String privateKey = <span style="color: #98c379;line-height: 26px;">"c:/tools/auth_key/id_key_rsa"</span>;<br><br> private String publicKey = <span style="color: #98c379;line-height: 26px;">"c:/tools/auth_key/id_key_rsa.pub"</span>;<br><br> @Test<br> public void test1() throws Exception{<br> RsaUtils.generateKey(publicKey,privateKey,<span style="color: #98c379;line-height: 26px;">"dpb"</span>,1024);<br> }<br><br>}<br></code></pre> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img src="/upload/58d67cc0a32ece76c730390fc7126987.png" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;" data-type="png" data-ratio="0.1925925925925926" data-w="1080"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;font-family: PingFangSC-Light;"> img </figcaption> </figure> <h4