文章列表

我把「链路追踪」整明白了

作者:微信小助手

<section style="text-align: center;padding: 0px 0.5em;margin-bottom: 5px;" data-mpa-powered-by="yiban.io"> <span style="max-width: 100%;letter-spacing: 0.544px;text-align: center;background-color: rgb(255, 255, 255);font-family: -apple-system, BlinkMacSystemFont, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Segoe UI, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif;font-size: 16px;color: rgb(64, 64, 64);box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="__bg_gif" data-ratio="0.6666666666666666" data-type="gif" data-w="300" src="/upload/bc611ab04bb2305c37bf5328df6fe6bd.png" style="box-sizing: border-box;color: rgb(0, 0, 0);font-family: -webkit-standard;letter-spacing: 0.544px;vertical-align: middle;overflow-wrap: break-word !important;visibility: visible !important;width: 34px !important;">&nbsp;</span> <span style="max-width: 100%;letter-spacing: 0.544px;text-align: center;background-color: rgb(255, 255, 255);font-size: 15px;font-family: -apple-system, BlinkMacSystemFont, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Segoe UI, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">关注<span style="max-width: 100%;color: rgb(64, 64, 64);font-size: 16px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">“</span><span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(120, 172, 254)" data-darkmode-original-color="rgb(120, 172, 254)" style="max-width: 100%;font-size: 16px;letter-spacing: 0.544px;color: rgb(120, 172, 254);box-sizing: border-box !important;overflow-wrap: break-word !important;">脚本之家</span><span style="max-width: 100%;color: rgb(64, 64, 64);font-size: 16px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">”</span>,与百万开发者在一起</span> </section> <p style="text-align: center;padding: 0px 0.5em;"><img class="rich_pages js_insertlocalimg" data-ratio="0.6666666666666666" data-s="300,640" data-type="png" data-w="791" src="/upload/d30363ebec8d1acf382444afa0e9438f.png" style="border-radius: 12px;font-size: 17px;box-shadow: rgb(90, 90, 90) 0em 0em 0.5em 0px;width:auto !important;max-width:100% !important;height:auto !important;"></p> <p data-tool="mdnice编辑器" data-darkmode-color-15906764299112="rgb(230, 230, 230)" data-darkmode-original-color-15906764299112="rgb(0, 0, 0)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-style="background-color: rgb(255, 255, 255); color: rgb(0, 0, 0); font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, PingFang SC, Cambria, Cochin, Georgia, Times, Times New Roman, serif; font-size: 16px; white-space: normal; word-spacing: 0.8px; letter-spacing: 0.75px; text-align: center; visibility: visible;" class="js_darkmode__2" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(0, 0, 0)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(0, 0, 0)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(0, 0, 0)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(0, 0, 0)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(0, 0, 0)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, PingFang SC, Cambria, Cochin, Georgia, Times, Times New Roman, serif;letter-spacing: 0.75px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);font-size: 16px;word-spacing: 0.8px;text-align: right;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span data-darkmode-color-15906764299112="rgb(178, 178, 178)" data-darkmode-original-color-15906764299112="rgb(178, 178, 178)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(178, 178, 178)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-style="color: rgb(178, 178, 178); font-size: 14px; visibility: visible;" class="js_darkmode__3" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(178, 178, 178)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(178, 178, 178)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(178, 178, 178)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(178, 178, 178)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="max-width: 100%;color: rgb(178, 178, 178);font-size: 14px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">作者 | 悟空聊架构</span></p> <p data-tool="mdnice编辑器" data-darkmode-color-15906764299112="rgb(230, 230, 230)" data-darkmode-original-color-15906764299112="rgb(0, 0, 0)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-style="background-color: rgb(255, 255, 255); color: rgb(0, 0, 0); font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, PingFang SC, Cambria, Cochin, Georgia, Times, Times New Roman, serif; font-size: 16px; white-space: normal; word-spacing: 0.8px; letter-spacing: 0.75px; text-align: center; visibility: visible;" class="js_darkmode__4" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(0, 0, 0)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(0, 0, 0)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(0, 0, 0)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(0, 0, 0)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(0, 0, 0)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, PingFang SC, Cambria, Cochin, Georgia, Times, Times New Roman, serif;letter-spacing: 0.75px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);font-size: 16px;word-spacing: 0.8px;text-align: right;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span data-darkmode-color-15906764299112="rgb(178, 178, 178)" data-darkmode-original-color-15906764299112="rgb(178, 178, 178)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(178, 178, 178)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-style="color: rgb(178, 178, 178); font-size: 14px; visibility: visible;" class="js_darkmode__5" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(178, 178, 178)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(178, 178, 178)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(178, 178, 178)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(178, 178, 178)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="max-width: 100%;color: rgb(178, 178, 178);font-size: 14px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">来源 |&nbsp;<span style="letter-spacing: 0.75px;word-spacing: 0.8px;">悟空聊架构</span>(ID:PassJava666)</span></p> <section data-darkmode-color-15906764299112="rgb(230, 230, 230)" data-darkmode-original-color-15906764299112="rgb(0, 0, 0)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-style="margin-bottom: 20px; background-color: rgb(255, 255, 255); color: rgb(0, 0, 0); font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, PingFang SC, Cambria, Cochin, Georgia, Times, Times New Roman, serif; font-size: 16px; white-space: normal; word-spacing: 0.8px; letter-spacing: 0.75px; text-align: center; visibility: visible;" class="js_darkmode__6" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(0, 0, 0)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(0, 0, 0)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(0, 0, 0)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(0, 0, 0)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(0, 0, 0)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="margin-bottom: 20px;max-width: 100%;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, PingFang SC, Cambria, Cochin, Georgia, Times, Times New Roman, serif;letter-spacing: 0.75px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);font-size: 16px;word-spacing: 0.8px;text-align: right;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span data-darkmode-color-15906764299112="rgb(178, 178, 178)" data-darkmode-original-color-15906764299112="rgb(178, 178, 178)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(178, 178, 178)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-style="color: rgb(178, 178, 178); font-size: 14px; visibility: visible;" class="js_darkmode__7" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(178, 178, 178)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(178, 178, 178)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(178, 178, 178)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(178, 178, 178)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="max-width: 100%;color: rgb(178, 178, 178);font-size: 14px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">转载请联系授权(微信ID:PassJava)</span> <span style="letter-spacing: 0px;text-align: left;"></span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding: 0px 0.5em;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;"> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">本篇主要内容</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.6666666666666666" data-s="300,640" data-type="png" data-w="930" src="/upload/61495f4854e5331ff57fdcc7e44637ce.png" style=""></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这篇主要是理论 + 实践相结合。实践部分涉及到如何把链路追踪组件 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Sleuth</code> + <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Zipkin</code> 加到我的 Spring Cloud 《佳必过》开源项目上。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>本篇知识点:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 链路追踪基本原理 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 如何在项目中轻松加入链路追踪中间件 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 如何使用链路追踪排查问题 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">一、为什么要用链路追踪?</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>1.1 因:拆分服务单元<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">微服务</code>架构其实是一个<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">分布式</code>的架构,按照业务划分成了多个服务单元。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">由于服务单元的<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">数量</code>是很多的,有可能几千个,而且业务也会更复杂,如果出现了错误和异常,很难去定位。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>1.2 因:逻辑复杂<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">比如一个请求需要调用多个服务才能完成整个业务闭环,而内部服务的代码逻辑和业务逻辑比较复杂,假如某个服务出现了问题,是难以快速确定那个服务出问题的。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>1.3 果:快速定位<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">而如果我们加上了<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">分布式链路追踪</code>,去跟踪一个请求有哪些服务参与其中,参与的顺序是怎样的,这样我们就知道了每个请求的详细经过,即使出了问题也能快速定位。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">二、链路追踪的核心</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">链路追踪组件有 Twitter 的可视化链路追踪组件 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Zipkin</code>、Google 的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Dapper</code>、阿里的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Eagleeye</code> 等,而 Sleuth 是 Spring Cloud 的组件。Spring Cloud Sleuth 借鉴了 Dapper 的术语。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">本文主要讲解 Sleuth + Zipkin 结合使用来更好地实现链路追踪。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">为什么能够进行整条链路的追踪?<strong>其实就是一个 Trace ID 将 一连串的 Span 信息连起来了</strong>。根据 Span 记录的信息再进行整合就可以获取整条链路的信息。下面是链路追踪的核心概念:</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>2.1 Span(跨度)<span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">大白话:远程调用和 Span &nbsp;<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">一对一</code>。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">基本的工作单元,每次发送一个远程调用服务就会产生一个 Span。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">Span 是一个 64 位的唯一 ID。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">通过计算 Span 的开始和结束时间,就可以统计每个服务调用所花费的时间。</p> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>2.2 Trace(跟踪)<span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">大白话:一个 Trace 对应多个 Span,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">一对多</code>。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">它由一系列 Span 组成,树状结构。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">64 位唯一 ID。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">每次客户端访问微服务系统的 API 接口,可能中间会调用多个微服务,每次调用都会产生一个新的 Span,而多个 Span 组成了 Trace</p> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>2.3 Annotation(注解)<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">链路追踪系统定义了一些核心注解,用来定义一个请求的开始和结束,注意是微服务之间的请求,而不是浏览器或手机等设备。注解包括:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">cs</code> - Client Sent:客户端发送一个请求,描述了这个请求调用的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Span</code> 的开始时间。注意:这里的客户端指的是微服务的调用者,不是我们理解的浏览器或手机等客户端。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">sr</code> - Server Received:服务端获得请求并准备开始处理它,如果将其 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">sr</code> 减去 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">cs</code> 时间戳,即可得到网络传输时间。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">ss</code> - Server Sent:服务端发送响应,会记录请求处理完成的时间, <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">ss</code> 时间戳减去 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">sr</code> 时间戳,即可得到服务器请求的时间。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">cr</code> - Client Received:客户端接收响应,Span 的结束时间,如果 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">cr</code> 的时间戳减去 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">cs</code> 时间戳,即可得到一次微服务调用所消耗的时间,也就是一个 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Span</code> 的消耗的总时间。 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>2.4 链路追踪原理<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">假定三个微服务调用的链路如下图所示:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 1</code> 调用 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 2</code>,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 2</code> 调用 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 3</code> 和 Service 4。</p> <img data-ratio="0.6666666666666666" data-type="png" data-w="822" src="/upload/965ec3c165432b32c15ea0c6e2105cac.png" style="box-sizing: border-box;vertical-align: middle;border-style: none;display: block;margin: 20px auto;max-width: 95%;border-radius: 12px;object-fit: contain;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, PingFang SC, Cambria, Cochin, Georgia, Times, Times New Roman, serif;font-size: 17px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;background-color: rgb(255, 255, 255);box-shadow: rgb(90, 90, 90) 0em 0em 0.5em 0px;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;padding: 0px 0.5em;"> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"> 微服务调用链路图 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">那么链路追踪会在每个服务调用的时候加上 Trace ID 和 Span ID。如下图所示:</p> <img data-ratio="0.6666666666666666" data-type="png" data-w="1170" src="/upload/d5e24ddfae3fd70cbf5b372802599333.png" style="box-sizing: border-box;vertical-align: middle;border-style: none;display: block;margin: 20px auto;max-width: 95%;border-radius: 12px;object-fit: contain;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, PingFang SC, Cambria, Cochin, Georgia, Times, Times New Roman, serif;font-size: 17px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;background-color: rgb(255, 255, 255);box-shadow: rgb(90, 90, 90) 0em 0em 0.5em 0px;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;padding: 0px 0.5em;"> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"> 链路追踪原理图 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>大白话解释:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">大家注意上面的颜色,相同颜色的代表是同一个 Span ID,说明是链路追踪中的一个节点。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">第一步:客户端调用 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 1</code>,生成一个 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Request</code>,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Trace ID</code> 和 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Span ID</code> 为空,那个时候请求还没有到 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 1</code>。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">第二步:请求到达 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 1</code>,记录了 Trace ID = X,Span ID 等于 A。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">第三步:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 1</code> 发送请求给 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 2</code>,Span ID 等于 B,被称作 Client Sent,即客户端发送一个请求。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">第四步:请求到达 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 2</code>,Span ID 等于 B,Trace ID 不会改变,被称作 Server Received,即服务端获得请求并准备开始处理它。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">第五步:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 2</code> 开始处理这个请求,处理完之后,Trace ID 不变,Span ID = C。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">第六步:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 2</code> 开始发送这个请求给 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Service 3</code>,Trace ID 不变,Span ID = D,被称作 Client Sent,即客户端发送一个请求。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;">第七步:<code style="font-size: 14px;padding: 2p

别小看tail 命令,它难倒了技术总监

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" data-mpa-powered-by="yiban.io"> <blockquote data-tool="mdnice编辑器"> <p>来源:小姐姐味道(微信公众号ID:xjjdog)</p> </blockquote> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">tail命令能够看到日志的滚动,非常方便。于是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">xjjdog</code>想,既然我们能够用这个命令,看到所有的日志,那能不能使用tail命令,做日志收集呢?</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">想象归想象,如果你想要一个快速的<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">实时</code>日志收集工具,那tail确实是个非常棒的工具。它比什么flume、logstatsh,比什么filebeat之类的,快捷的多。事实上,在工具缺乏的旧年代,我就曾经这么干过,而且它工作的很好。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">下面是一段使用Java语言书写的代码。我们可以按行读取日志,然后使用自己喜欢的语言,做任何事情。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #569CD6;line-height: 26px;">import</span>&nbsp;java.io.BufferedReader;<br><span style="color: #569CD6;line-height: 26px;">import</span>&nbsp;java.io.InputStreamReader;<br><br><span style="color: #569CD6;line-height: 26px;">public</span>&nbsp;<span style="color: #B8D7A3;line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">class</span>&nbsp;<span style="color: #DCDCDC;line-height: 26px;">TailReader</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">public</span>&nbsp;<span style="color: #569CD6;line-height: 26px;">static</span>&nbsp;<span style="color: #569CD6;line-height: 26px;">void</span>&nbsp;<span style="line-height: 26px;">main</span><span style="line-height: 26px;">(String[]&nbsp;args)</span>&nbsp;<span style="color: #569CD6;line-height: 26px;">throws</span>&nbsp;Exception&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProcessBuilder&nbsp;ps&nbsp;=&nbsp;<span style="color: #569CD6;line-height: 26px;">new</span>&nbsp;ProcessBuilder(<span style="color: #D69D85;line-height: 26px;">"tail"</span>,&nbsp;<span style="color: #D69D85;line-height: 26px;">"-f"</span>,&nbsp;<span style="color: #D69D85;line-height: 26px;">"/tmp/tail0"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">//把错误输出也打印</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.redirectErrorStream(<span style="color: #569CD6;line-height: 26px;">true</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Process&nbsp;process&nbsp;=&nbsp;ps.start();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">//持续读取tail的输出</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #569CD6;line-height: 26px;">try</span>&nbsp;(BufferedReader&nbsp;in&nbsp;=&nbsp;<span style="color: #569CD6;line-height: 26px;">new</span>&nbsp;BufferedReader(<span style="color: #569CD6;line-height: 26px;">new</span>&nbsp;InputStreamReader(process.getInputStream())))&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;line;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #569CD6;line-height: 26px;">while</span>&nbsp;((line&nbsp;=&nbsp;in.readLine())&nbsp;!=&nbsp;<span style="color: #569CD6;line-height: 26px;">null</span>)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setLogToKafka(line);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">//注意这里不要产生异常,否则会打断while循环</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">//模拟发送到kafka,我们这里只简单的打印出来</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #569CD6;line-height: 26px;">static</span>&nbsp;<span style="color: #569CD6;line-height: 26px;">void</span>&nbsp;<span style="line-height: 26px;">setLogToKafka</span><span style="line-height: 26px;">(String&nbsp;line)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(line);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">主要的思想,就是使用Java的Process启动一个子tail进程,一直监控着文件的输出。然后把标准输出和标准错误流,全部定向到BufferedReader中。接下来,你能做你想要做的任何事。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">这有一定的风险,假如tail命令被杀掉了,我们的Java程序就失去了作用。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">程序很简单,但<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">xjjdog</code>在这里讨论的却不是这个简单的收集程序,而是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">tail</code>命令的一些有趣的特性,你可以从中一窥一些日志收集工具对文件的特殊处理。</p> <h2 data-tool="mdnice编辑器" style="line-height: 32px;color: rgb(53, 179, 120);display: inline-block;border-bottom: 0px solid rgb(53, 179, 120);border-top-color: rgb(53, 179, 120);border-right-color: rgb(53, 179, 120);border-left-color: rgb(53, 179, 120);font-size: 23px;margin-top: 1em;margin-bottom: 0rem;padding-top: 0.5em;padding-bottom: 0.5em;font-weight: bold;"><span style="display: none;"></span>你知道tail -f和tail -F的区别么?</h2> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">在回答这个问题之前,我们先回忆一下,Java常用的日志框架,对日志的处理。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">configuration</span>&gt;</span><br>&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">appender</span>&nbsp;<span style="color: #9CDCFE;line-height: 26px;">name</span>=<span style="color: #D69D85;line-height: 26px;">"FILE"</span>&nbsp;<span style="color: #9CDCFE;line-height: 26px;">class</span>=<span style="color: #D69D85;line-height: 26px;">"ch.qos.logback.core.rolling.RollingFileAppender"</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #57A64A;font-style: italic;line-height: 26px;">&lt;!--&nbsp;Support&nbsp;multiple-JVM&nbsp;writing&nbsp;to&nbsp;the&nbsp;same&nbsp;log&nbsp;file&nbsp;--&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">prudent</span>&gt;</span>true<span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">prudent</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">rollingPolicy</span>&nbsp;<span style="color: #9CDCFE;line-height: 26px;">class</span>=<span style="color: #D69D85;line-height: 26px;">"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">fileNamePattern</span>&gt;</span>logFile.%d{yyyy-MM-dd}.log<span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">fileNamePattern</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">maxHistory</span>&gt;</span>30<span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">maxHistory</span>&gt;</span>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">totalSizeCap</span>&gt;</span>3GB<span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">totalSizeCap</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">rollingPolicy</span>&gt;</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">encoder</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">pattern</span>&gt;</span>%-4relative&nbsp;[%thread]&nbsp;%-5level&nbsp;%logger{35}&nbsp;-&nbsp;%msg%n<span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">pattern</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">encoder</span>&gt;</span><br>&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">appender</span>&gt;</span>&nbsp;<br><br>&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">root</span>&nbsp;<span style="color: #9CDCFE;line-height: 26px;">level</span>=<span style="color: #D69D85;line-height: 26px;">"DEBUG"</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;<span style="color: #569CD6;line-height: 26px;">appender-ref</span>&nbsp;<span style="color: #9CDCFE;line-height: 26px;">ref</span>=<span style="color: #D69D85;line-height: 26px;">"FILE"</span>&nbsp;/&gt;</span><br>&nbsp;&nbsp;<span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">root</span>&gt;</span><br><span style="color: #9B9B9B;line-height: 26px;">&lt;/<span style="color: #569CD6;line-height: 26px;">configuration</span>&gt;</span><br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">上面的配置,将在每晚凌晨的时候,滚动形成一个新的文件。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">那这个滚动,是如何做的呢?我们可以收工模拟这个过程。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">mv&nbsp;run.log&nbsp;run.2020-11-02.log<br>touch&nbsp;run.log<br></code></pre> <h2 data-tool="mdnice编辑器" style="line-height: 32px;color: rgb(53, 179, 120);display: inline-block;border-bottom: 0px solid rgb(53, 179, 120);border-top-color: rgb(53, 179, 120);border-right-color: rgb(53, 179, 120);border-left-color: rgb(53, 179, 120);font-size: 23px;margin-top: 1em;margin-bottom: 0rem;padding-top: 0.5em;padding-bottom: 0.5em;font-weight: bold;"><span style="display: none;"></span>测试一下</h2> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">文件滚动,会生成新的文件,那tail命令还能跟踪到么?</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">我们来测试一下。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;"><strong style="color: rgb(53, 179, 120);">第一步,创建要监控的文件</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">touch&nbsp;/tmp/tail0<br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;"><strong style="color: rgb(53, 179, 120);">第二步,启动我们的Java代码</strong></p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;"><strong style="color: rgb(53, 179, 120);">第三步,生成一个不间断的流</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">watch&nbsp;-n&nbsp;1&nbsp;&nbsp;<span style="color: #D69D85;line-height: 26px;">'echo&nbsp;`date`&nbsp;&gt;&gt;&nbsp;/tmp/tail0&nbsp;'</span><br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">上面的命令每隔1秒钟,往我们的文件中打印一下当前的日期,可以看到Java端已经收到了这些数据。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;"><img data-ratio="0.3237139272271016" src="/upload/64068df2c35fdd92150c7f7d7afe942c.png" data-type="png" data-w="797"></p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;"><strong style="color: rgb(53, 179, 120);">第四步,模拟文件滚动</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">mv&nbsp;/tmp/tail0&nbsp;/tmp/tail.bak<br>touch&nbsp;/tmp/tail0<br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">此时,我们可以看到,Java端此时已经接受不到数据了。</p> <h2 data-tool="mdnice编辑器" style="line-height: 32px;color: rgb(53, 179, 120);display: inline-block;border-bottom: 0px solid rgb(53, 179, 120);border-top-color: rgb(53, 179, 120);border-right-color: rgb(53, 179, 120);border-left-color: rgb(53, 179, 120);font-size: 23px;margin-top: 1em;margin-bottom: 0rem;padding-top: 0.5em;padding-bottom: 0.5em;font-weight: bold;"><span style="display: none;"></span>Why?</h2> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">为了看到这是为什么,我们使用两个命令来看一下进程的一些状态。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">首先,使用ps命令,查看当前的tail进程。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">ps&nbsp;-ef|grep&nbsp;tail<br>&nbsp;&nbsp;501&nbsp;21374&nbsp;21373&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;1:51PM&nbsp;??&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0:00.01&nbsp;tail&nbsp;-f&nbsp;/tmp/tail0<br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">这正是我们的命令。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">我们使用lsof命令去查看这个进程所关联的文件。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">lsof&nbsp;-p&nbsp;21374&nbsp;|&nbsp;awk&nbsp;<span style="color: #D69D85;line-height: 26px;">'{print&nbsp;$4&nbsp;"\t"&nbsp;&nbsp;$9}'</span><br>FD&nbsp;NAME<br>cwd&nbsp;/tmp/<br>txt&nbsp;/usr/bin/tail<br>txt&nbsp;/usr/lib/dyld<br>3r&nbsp;/private/tmp/tail.bak<br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">我们看到tail进程所监控的文件,其实是tail.bak文件,已经和tail命令没什么关系了。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">我们尝试像tail.bak输入一点内容。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #4EC9B0;line-height: 26px;">echo</span>&nbsp;<span style="color: #D69D85;line-height: 26px;">"haha:&nbsp;xjjdog,&nbsp;i&nbsp;am&nbsp;from&nbsp;tail.bak"</span>&nbsp;&gt;&gt;&nbsp;/tmp/tail.bak<br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">此时如我们所愿,Java进程有反应了,正常输出了这句话。</p> <h2 data-tool="mdnice编辑器" style="line-height: 32px;color: rgb(53, 179, 120);display: inline-block;border-bottom: 0px solid rgb(53, 179, 120);border-top-color: rgb(53, 179, 120);border-right-color: rgb(53, 179, 120);border-left-color: rgb(53, 179, 120);font-size: 23px;margin-top: 1em;margin-bottom: 0rem;padding-top: 0.5em;padding-bottom: 0.5em;font-weight: bold;"><span style="display: none;"></span>怎么办?</h2> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">就如同我们问题中问的一样,把<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">tail -f</code>换成<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">tail -F</code>就可以了。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">tail -f</code>的意思是,根据文件描述符进行追踪。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">tail -F</code>的意思是,根据文件名进行追踪,它会有重试的动作。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">所以,我们的日志收集程序,毫无疑问是根据日志名称追踪的,应该把<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">f</code>改成<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">F</code>。</p> <h2 data-tool="mdnice编辑器" style="line-height: 32px;color: rgb(53, 179, 120);display: inline-block;border-bottom: 0px solid rgb(53, 179, 120);border-top-color: rgb(53, 179, 120);border-right-color: rgb(53, 179, 120);border-left-color: rgb(53, 179, 120);font-size: 23px;margin-top: 1em;margin-bottom: 0rem;padding-top: 0.5em;padding-bottom: 0.5em;font-weight: bold;"><span style="display: none;"></span>End</h2> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">既然知道了这些小区别,我们就对日常工作中遇到的一些灵异问题有了解释。</p> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">大家都知道rm命令,能够删除一个文件。如果有这个文件,正在被其他进程所使用,那这些文件你看起来像是删掉了,但它的内容却不释放。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">&nbsp;lsof&nbsp;|&nbsp;grep&nbsp;deleted<br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">上面这个命令,能够看到这些失控的文件。一般你kill掉相应的进程,这些句柄也就释放了。但你删除这些文件的本意,就是为了避免重启应用,这可真让人纠结。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #1E1E1E;color: #DCDCDC;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">&nbsp;cat&nbsp;/dev/null&nbsp;&gt;&nbsp;logpath<br></code></pre> <p data-tool="mdnice编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;margin: 1em 4px;">所以我们在删除文件的时候,一般不会使用rm,而应该使用重定向符号。将万物皆空的<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">/dev/null</code>,发向它们。</p> <p><span style="font-size: 15px;color: rgb(136, 136, 136);">作者简介:小姐姐味道 &nbsp;(xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。</span></p> <p style="margin-right: 0.5em;margin-left: 0.5em;font-size: 16px;text-align: left;white-space: normal;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;word-spacing: 2px;line-height: 1.75em;"><br></p> <section style="margin-bottom: 16px;white-space: normal;max-width: 100%;transition: margin 0.1s linear 0s, padding 0.1s linear 0s, width 0.1s linear 0s, height 0.1s linear 0s;font-size: 16px;letter-spacing: 0.5px;background-color: rgb(255, 255, 255);line-height: 1.5em;font-family: &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, &quot;Helvetica Neue&quot;, Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-tools="135编辑器" data-id="93743" style="max-width: 100%;letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;width: 6em;display: inline-block;color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img class="__bg_gif" data-ratio="0.45689655172413796" src="/upload/4e8dd1e064b1921ee86d17cf2bc28c77.png" data-type="gif" data-w="232" data-width="100%" style="display: block;width: 102px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;"> </section> </section> <section data-role="paragraph" style="letter-spacing: 0.544px;box-sizing: border-box;"> <pre ng-bind-html="message.MMActualContent"> <section data-tools="135编辑器" data-id="89197" style="max-width: 100%;letter-spacing: 0.544px;text-align: center;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-right: auto;margin-left: auto;padding: 0.5em 0em;max-width: 100%;width: 320px;overflow: hidden;border-radius: 5px;border-width: 1px;border-style: solid;border-color: rgb(200, 200, 200);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-brushtype="text" style="margin-top: 4px;max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section style="margin-bottom: 1px;max-width: 100%;min-height: 1em;line-height: normal;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;letter-spacing: 2px;caret-color: rgb(255, 0, 0);color: rgb(192, 0, 0);font-family: -apple-system-font, BlinkMacSystemFont, Arial, sans-serif;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> </section> <section style="margin-bottom: 1px;max-width: 100%;min-height: 1em;line-height: normal;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;letter-spacing: 2px;caret-color: rgb(255, 0, 0);background-color: rgb(54, 96, 146);color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, Arial, sans-serif;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;">&nbsp;扫码关注填加客服&nbsp;</strong></span> </section> <section style="margin-bottom: 1px;max-width: 100%;min-height: 1em;line-height: normal;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong style="color: rgb(192, 0, 0);font-family: -apple-system-font, BlinkMacSystemFont, Arial, sans-serif;letter-spacing: 2px;caret-color: rgb(255, 0, 0);max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">长按识别下方二维码进群</strong> <br> </section> </section> <section style="line-height: normal;"> <img class="rich_pages" data-cropselx1="0" data-cropselx2="178" data-cropsely1="0" data-cropsely2="231" data-ratio="1.3293768545994065" data-s="300,640" src="/upload/edac1ae2585a683c879ab60a5bf6dce5.png" data-type="png" data-w="674" style="height: 237px;width: 178px;"> </section> </section> </section> <section data-tools="135编辑器" data-id="92918" style="white-space: normal;max-width: 100%;letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-tools="135编辑器" data-id="91727" style="max-width: 100%;box-sizing: border-box;border-width: 0px;border-style: none;border-color: initial;overflow-wrap: break-word !important;"> <section style="margin-top: 10px;max-width: 100%;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong style="color: rgb(149, 55, 52);letter-spacing: 0.544px;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;text-align: left;font-size: 17px;"><img class="rich_pages" data-ratio="0.01875" data-s="300,640" src="/upload/ec294c8778d7270754ac8543fa15db4a.png" data-type="png" data-w="640" style="text-align: center;"></strong> <br> </section> </section> </section></pre> </section> </section> </section> <section> <section> <section> <section> <section> <section> <section style="padding-right: 0.5em;padding-left: 0.5em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);text-align: left;min-height: 1em;line-height: 2em;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;letter-spacing: 0.544px;min-height: 1em;line-height: 2em;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;letter-spacing: 0.544px;min-height: 1em;line-height: 2em;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;text-align: left;background-color: rgb(255, 255, 255);line-height: 2em;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;color: rgb(149, 55, 52);letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><strong style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"><strong style="max-width: 100%;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">近期精彩内容推荐:</strong><strong style="max-width: 100%;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">&nbsp;</strong><span style="max-width: 100%;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">&nbsp;</span></strong></span></p> <p style="max-width: 100%;min-height: 1em;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;text-align: left;background-color: rgb(255, 255, 255);line-height: 2em;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;font-size: 15px;letter-spacing: 0.5px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><img class="__bg_gif" data-ratio="1" src="/upload/74fabcf0aa7b579e62882ba06aeb689a.jpg" data-type="jpeg" data-w="16" style="top: 0px;left: 0px;right: 0px;bottom: 0px;overflow-wrap: break-word !important;box-sizing: border-box !important;visibility: visible !important;width: 16px !important;"></span><span style="max-width: 100%;font-size: 15px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><strong style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);letter-spacing: 0.5px;overflow-wrap: break-word !important;box-sizing: border-box !important;">&nbsp;</span></strong></span><a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzUyODg4Nzk2MQ==&amp;mid=2247506660&amp;idx=1&amp;sn=7270d938f760a6a80d9bf9b2287a7f18&amp;scene=21#wechat_redirect" textvalue="外包程序员入职蚂蚁金服被质疑,网友:人生污点" tab="innerlink" data-linktype="2" style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;font-size: 15px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-weight: 700;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">外包程序员入职蚂蚁金服被质疑,网友:</span><span style="max-width: 100%;font-size: 15px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-weight: 700;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">人生污点</span></a></p> <p style="max-width: 100%;min-height: 1em;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;text-align: left;background-color: rgb(255, 255, 255);line-height: 2em;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;font-size: 15px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><strong style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;letter-spacing: 0.5px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><img class="__bg_gif" data-ratio="1" src="/upload/74fabcf0aa7b579e62882ba06aeb689a.jpg" data-type="jpeg" data-w="16" style="top: 0px;left: 0px;right: 0px;bottom: 0px;overflow-wrap: break-word !important;box-sizing: border-box !important;visibility: visible !important;width: 16px !important;">&nbsp;</span></strong></span><a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzI1OTQwOTg2Mg==&amp;mid=2247499161&amp;idx=1&amp;sn=aff1ef97f7cec34e2ddbe4d4401a20c5&amp;scene=21#wechat_redirect" textvalue="11 月全国程序员平均工资出炉" tab="innerlink" data-linktype="2" style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;font-size: 15px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-weight: 700;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">11&nbsp;</span><span style="max-width: 100%;font-size: 15px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-weight: 700;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">月</span><span style="max-width: 100%;font-size: 15px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-weight: 700;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">全国程序员平均工资出炉</span></a></p> <p style="max-width: 100%;min-height: 1em;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;text-align: left;background-color: rgb(255, 255, 255);line-height: 2em;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;font-size: 15px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><strong style="max-width: 100%;letter-spacing: 1.5px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;letter-spacing: 0.5px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><img class="__bg_gif" data-ratio="1" src="/upload/74fabcf0aa7b579e62882ba06aeb689a.jpg" data-type="jpeg" data-w="16" height="16" width="16" style="top: 0px;left: 0px;right: 0px;bottom: 0px;overflow-wrap: break-word !important;box-sizing: border-box !important;visibility: visible !important;width: 16px !important;">&nbsp;</span></strong></span><span style="max-width: 100%;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-weight: 700;letter-spacing: 0.544px;font-size: 15px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzU2NDY5ODc3NQ==&amp;mid=2247486973&amp;idx=1&amp;sn=87acd09f1eff65251f2a7fc469cec49e&amp;scene=21#wechat_redirect" textvalue="弃用 Notepad++,还有 5 款更牛逼的选择!" tab="innerlink" data-linktype="2" style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;">弃用 Notepad++,还有 5 款更牛逼的选择!</a></span></p> <p style="max-width: 100%;min-height: 1em;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;text-align: left;background-color: rgb(255, 255, 255);line-height: 2em;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;letter-spacing: 0.5px;font-size: 15px;overflow-wrap: break-word !important;box-sizing: border-box !important;"><img class="__bg_gif" data-ratio="1" src="/upload/74fabcf0aa7b579e62882ba06aeb689a.jpg" data-type="jpeg" data-w="16" style="top: 0px;left: 0px;right: 0px;bottom: 0px;overflow-wrap: break-word !important;box-sizing: border-box !important;visibility: visible !important;width: 16px !important;">&nbsp;</span><a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzIwMDU3MDkzNg==&amp;mid=2651312105&amp;idx=1&amp;sn=9ff75f1e70b3b6a9cfbde744f50a4bd4&amp;scene=21#wechat_redirect" textvalue="福利!手把手教你Python爬取女神套图" tab="innerlink" data-linktype="2" style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;font-size: 15px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-weight: 700;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">福利!</span><span style="max-width: 100%;font-size: 15px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-weight: 700;letter-spacing: 0.544px;overflow-wrap: break-word !important;box-sizing: border-box !important;">手把手教你Python爬取女神套图</span></a></p> <p style="white-space: normal;text-align: center;"><br></p> <p style="white-space: normal;text-align: center;"><img class="rich_pages" data-cropselx1="0" data-cropselx2="561" data-cropsely1="0" data-cropsely2="533" data-ratio="0.7231481481481481" data-s="300,640" src="/upload/ba29b4b52dfc186da06d76d1d1704e17.jpg" data-type="jpeg" data-w="1080" style="height: 418px;width: 578px;"></p> <section style="white-space: normal;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;font-size: 16px;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word;overflow: hidden;font-size: 17px;z-index: 0;visibility: visible;word-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;font-size: 16px;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word;overflow: hidden;font-size: 17px;z-index: 0;visibility: visible;word-wrap: break-word !important;"> <section data-role="paragraph" style="max-width: 100%;letter-spacing: 0.544px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section> <section style="max-width: 100%;min-height: 1em;line-height: 1.75em;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;font-size: 16px;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word;overflow: hidden;font-size: 17px;z-index: 0;visibility: visible;word-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;color: rgb(62, 62, 62);font-size: 15px;text-align: center;widows: 1;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section data-tools="135编辑器" data-id="92689" style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section data-width="100%" style="max-width: 100%;box-sizing: border-box;width: 677px;display: flex;justify-content: center;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section data-width="100%" style="margin-top: 10px;margin-right: auto;margin-left: auto;padding-top: 10px;padding-bottom: 10px;max-width: 100%;box-sizing: border-box;width: 677px;display: flex;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <section data-width="100%" style="margin-right: 5px;max-width: 100%;box-sizing: border-box;width: 323.938px;border-top: 1px solid rgb(156, 155, 156);height: 1px;overflow: hidden;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <br style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> </section> <section style="max-width: 100%;width: 40px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <img data-ratio="1" src="/upload/10b9c04871e4b1f96dd3c28c29fd764e.png" data-type="png" data-w="35" data-width="100%" style="margin-top: -10px;display: block;justify-content: center;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;visibility: visible !important;width: 19.1406px !important;"> </section> <section data-width="100%" style="margin-left: 5px;max-width: 100%;box-sizing: border-box;width: 323.938px;border-top: 1px solid rgb(156, 155, 156);word-wrap: break-word !important;overflow-wrap: break-word !important;"> <br> </section> </section> </section> </section> </section> </section> </section> </section> <p style="max-width: 100%;min-height: 1em;text-align: right;letter-spacing: 0.544px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(227, 108, 9);font-size: 14px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;">在看点这里</strong><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><img class="__bg_gif" data-copyright="0" data-ratio="1.0377358490566038" src="/upload/c82b6435fb6d21d1bdda03cdcf7b22f5.png" data-type="gif" data-w="53" style="max-width: 156.36px;box-sizing: border-box;border-width: 0px;border-style: initial;border-color: rgb(192, 0, 0);left: auto;top: auto;bottom: auto;color: rgb(150, 1, 1);line-height: 25.6px;letter-spacing: 0.54px;clear: none;font-size: 16px;font-variant-numeric: normal;display: inline;z-index: auto;min-height: 0px;max-height: none;min-width: 0px;background-clip: border-box;background-size: auto;background-position: 0% 0%;background-repeat: repeat;word-wrap: break-word !important;overflow-wrap: break-word !important;visibility: visible !important;width: 24px !important;" width="27">好文分享给更多人↓↓</strong></span></p> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section>

接口测试学习之json

作者:测试人生路

在做接口测试的时候,我们需要查看响应值,有的接口还需要调用上一个接口中的响应值中的一些变量,这些返回的响应值大部分是以json格式返回的,今天就给大家介绍一下json的编写格式。 我个人分为三大类。 第一类:object格式,单独键值对格式 对象是一个无序的键值对集合,一个对象以左大括号开始“{”右大括号结束“}”。然后每个键值对以"参数名":"参数值"的格式在大括号中,有多个键值对的时候用逗号“,”分割。注意全部都要用英文格式的标点字符。 例子:{"code": 200, "message": "登录成功","token":"1651AS5a612q547"} ![1.png](/storage/thumbnails/_signature/2NUFO1F0E3M79EL3K90R9BVQ2N.png) 也可以用简单的写法,参数名key和数字可以不用加""号,例子{code: 200, message: '登录成功',token:'1651AS5a612q547'} 第二类:array格式,数组格式 数组是值(value)的有序集合。一个数组是以左中括号开始"["右中括号结束"]"。数组里面的值也是用过分号隔开",". 例子:[ "你好", "name", "阿萨大大"] ![2.png](/storage/thumbnails/_signature/1UETD0ALVB1OMIEQSTH0DDMFCR.png) 第三类:value格式键值对和数组等类型数据混合格式 值(value)可以是各种类型的集合,双引号括起来的字符串(string)、数值(number)、true、false、null、对象(object)或者是数组(array)。这些都可以嵌套使用。 例子:{id:12138,"name":"小明","hobby":["lol","绝地求生","守望先锋"],"like":[["篮球","羽毛球","乒乓球"],["姚明","林丹","张继科"]]} ![3.png](/storage/thumbnails/_signature/3BQAH793RP88ABTH5PL1F5V1D5.png) 以后遇到看不懂的json串是绝大部都是可以按照基本格式类型进行拆分的。也可以是在网上找json串验证工具进行验证。 下一篇文章告诉大家,如何定位响应值json中的key值。 这里使用的接口测试工具是国产的接口测试工具apipost,有兴趣的朋友可以去试用一下,很好用的一款接口测试和接口文档生成工具。 下载地址:[https://www.apipost.cn](https://www.apipost.cn/?dt=20201120)

ZooKeeper集群“脑裂”问题处理大全

作者:微信小助手

<p style="margin-bottom: 10px;color: rgb(62, 62, 62);font-size: 15px;white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);line-height: normal;text-align: center;" data-mpa-powered-by="yiban.io"><span style="font-size: 14px;letter-spacing: 0.544px;word-spacing: 2px;color: rgb(136, 136, 136);">点击蓝色“</span><span style="font-size: 14px;letter-spacing: 0.544px;word-spacing: 2px;color: rgb(0, 128, 255);">架构文摘</span><span style="font-size: 14px;letter-spacing: 0.544px;word-spacing: 2px;color: rgb(136, 136, 136);">”关注我哟</span></p> <p style="margin-bottom: 10px;color: rgb(62, 62, 62);font-size: 15px;white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-size-adjust: auto;word-spacing: 2px;text-align: center;"><span style="font-size: 14px;color: rgb(136, 136, 136);">加个“</span><span style="color: rgb(0, 128, 255);font-size: 14px;">星标</span><span style="font-size: 14px;color: rgb(136, 136, 136);">”,每天上午 09:25,干货推送!</span></p> <p style="color: rgb(62, 62, 62);white-space: normal;letter-spacing: 0.544px;font-size: 14px;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);text-align: center;"><img data-backh="36" data-backw="578" data-ratio="0.0625" data-s="300,640" data-type="jpeg" data-w="640" width="100%" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.jpg" style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;color: rgb(136, 136, 136);box-sizing: border-box !important;visibility: visible !important;width: 677px !important;"></p> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-template="t" mpa-from-tpl="t"> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 本文重点讲解ZooKeeper脑裂问题的处理办法。ZooKeeper是用来协调(同步)分布式进程的服务,提供了一个简单高性能的协调内核,用户可以在此之上构建更多复杂的分布式协调功能。脑裂通常会出现在集群环境中,比如Elasticsearch、ZooKeeper集群,而这些集群环境有一个统一的特点,就是它们有一个大脑,比如Elasticsearch集群中有Master节点,ZooKeeper集群中有Leader节点。 </section> </section> </section> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;" mpa-from-tpl="t" mpa-is-content="t"> ZooKeeper集群节点为什么要部署成奇数 </section> <p><img data-type="png" data-ratio="0.053125" data-w="640" src="/upload/16c3bc26d4547f0344ee22af769e1434.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;"></p> <p><br></p> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-template="t" mpa-from-tpl="t"> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> ZooKeeper容错指的是:当宕掉几个ZooKeeper节点服务器之后,剩下的个数必须大于宕掉的个数,也就是剩下的节点服务数必须大于n/2,这样ZooKeeper集群才可以继续使用,无论奇偶数都可以选举Leader。例如5台ZooKeeper节点机器最多宕掉2台,还可以继续使用,因为剩下3台大于5/2。至于为什么最好为奇数个节点?这样是为了以最大容错服务器个数的条件下,能节省资源。比如,最大容错为2的情况下,对应的ZooKeeper服务数,奇数为5,而偶数为6,也就是6个ZooKeeper服务的情况下最多能宕掉2个服务,所以从节约资源的角度看,没必要部署6(偶数)个ZooKeeper服务节点。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> ZooKeeper集群有这样一个特性:集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的。也就是说如果有2个ZooKeeper节点,那么只要有1个ZooKeeper节点死了,那么ZooKeeper服务就不能用了,因为1没有过半,所以2个ZooKeeper的死亡容忍度为0;同理,要是有3个ZooKeeper,一个死了,还剩下2个正常的,过半了,所以3个ZooKeeper的容忍度为1;同理也可以多列举几个:2-&gt;0、3-&gt;1、4-&gt;1、5-&gt;2、6-&gt;2,就会发现一个规律,2n和2n-1的容忍度是一样的,都是n-1,所以为了更加高效,何必增加那一个不必要的ZooKeeper呢。所以说,根据以上可以得出结论:从资源节省的角度来考虑,ZooKeeper集群的节点最好要部署成奇数个! </section> </section> </section> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;" mpa-from-tpl="t" mpa-is-content="t"> ZooKeeper集群中的“脑裂”场景说明 </section> <p><img data-type="png" data-ratio="0.053125" data-w="640" src="/upload/16c3bc26d4547f0344ee22af769e1434.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;"></p> <p><br></p> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-template="t" mpa-from-tpl="t"> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 对于一个集群,想要提高这个集群的可用性,通常会采用多机房部署,比如现在有一个由6台zkServer所组成的一个集群,部署在了两个机房: </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: center;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <p><img data-ratio="0.5016181229773463" src="/upload/4fb63e816ca8211d23e391093fbd82de.png" data-type="png" data-w="1854" style="margin: 0px;top: 0px;left: 0px;right: 0px;bottom: 0px;"></p> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 正常情况下,此集群只会有一个Leader,那么如果机房之间的网络断了之后,两个机房内的zkServer还是可以相互通信的,如果不考虑过半机制,那么就会出现每个机房内部都将选出一个Leader。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: center;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <p><img data-ratio="0.5005370569280344" src="/upload/dd43de74953357946442183223b849a7.png" data-type="png" data-w="1862" style="margin: 0px;top: 0px;left: 0px;right: 0px;bottom: 0px;"></p> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 这就相当于原本一个集群,被分成了两个集群,出现了两个“大脑”,这就是所谓的“脑裂”现象。对于这种情况,其实也可以看出来,原本应该是统一的一个集群对外提供服务的,现在变成了两个集群同时对外提供服务,如果过了一会,断了的网络突然联通了,那么此时就会出现问题了,两个集群刚刚都对外提供服务了,数据该怎么合并,数据冲突怎么解决等等问题。刚刚在说明脑裂场景时有一个前提条件就是没有考虑过半机制,所以实际上ZooKeeper集群中是不会轻易出现脑裂问题的,原因在于过半机制。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> ZooKeeper的过半机制:在领导者选举的过程中,如果某台zkServer获得了超过半数的选票,则此zkServer就可以成为Leader了。举个简单的例子:如果现在集群中有5台zkServer,那么half=5/2=2,那么也就是说,领导者选举的过程中至少要有三台zkServer投了同一个zkServer,才会符合过半机制,才能选出来一个Leader。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 那么ZooKeeper选举的过程中为什么一定要有一个过半机制验证? </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 因为这样不需要等待所有zkServer都投了同一个zkServer就可以选举出来一个Leader了,这样比较快,所以叫快速领导者选举算法。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> ZooKeeper过半机制中为什么是大于,而不是大于等于?这就是更脑裂问题有关系了,比如回到上文出现脑裂问题的场景(如上图1):当机房中间的网络断掉之后,机房1内的三台服务器会进行领导者选举,但是此时过半机制的条件是“节点数 &gt; 3”,也就是说至少要4台zkServer才能选出来一个Leader,所以对于机房1来说它不能选出一个Leader,同样机房2也不能选出一个Leader,这种情况下整个集群当机房间的网络断掉后,整个集群将没有Leader。而如果过半机制的条件是“节点数 &gt;= 3”,那么机房1和机房2都会选出一个Leader,这样就出现了脑裂。这就可以解释为什么过半机制中是大于而不是大于等于,目的就是为了防止脑裂。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 如果假设我们现在只有5台机器,也部署在两个机房: </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: center;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <p><img data-ratio="0.5005393743257821" src="/upload/df9bae752042404fd8f75dde077d692f.png" data-type="png" data-w="1854" style="margin: 0px;top: 0px;left: 0px;right: 0px;bottom: 0px;"></p> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 此时过半机制的条件是“节点数 &gt; 2”,也就是至少要3台服务器才能选出一个Leader,此时机房件的网络断开了,对于机房1来说是没有影响的,Leader依然还是Leader,对于机房2来说是选不出来Leader的,此时整个集群中只有一个Leader。因此总结得出,有了过半机制,对于一个ZooKeeper集群来说,要么没有Leader,要么只有1个Leader,这样ZooKeeper也就能避免了脑裂问题。 </section> </section> </section> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="margin: 0px;padding: 0px 10px 0px 9px;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;line-height: 1.8;background: rgb(255, 255, 255);z-index: 10000;" mpa-from-tpl="t" mpa-is-content="t"> Zookeeper集群“脑裂”问题处理 </section> <p><img data-type="png" data-ratio="0.053125" data-w="640" src="/upload/16c3bc26d4547f0344ee22af769e1434.png" style="margin-right: 0px;margin-bottom: 0px;margin-left: 0px;padding: 0px;color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;height: auto !important;width: 632px !important;visibility: visible !important;"></p> <p><br></p> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-template="t" mpa-from-tpl="t"> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <strong>什么是脑裂?</strong> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 简单点来说,脑裂(Split-Brain)就是比如当你的cluster里面有两个节点,它们都知道在这个cluster里需要选举出一个master。那么当它们两个之间的通信完全没有问题的时候,就会达成共识,选出其中一个作为master。但是如果它们之间的通信出了问题,那么两个结点都会觉得现在没有master,所以每个都把自己选举成master,于是cluster里面就会有两个master。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 对于ZooKeeper来说有一个很重要的问题,就是到底是根据一个什么样的情况来判断一个节点死亡down掉了?在分布式系统中这些都是有监控者来判断的,但是监控者也很难判定其他的节点的状态,唯一一个可靠的途径就是心跳,ZooKeeper也是使用心跳来判断客户端是否仍然活着。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 使用ZooKeeper来做Leader HA基本都是同样的方式:每个节点都尝试注册一个象征leader的临时节点,其他没有注册成功的则成为follower,并且通过watch机制监控着Leader所创建的临时节点,ZooKeeper通过内部心跳机制来确定Leader的状态,一旦Leader出现意外Zookeeper能很快获悉并且通知其他的follower,其他flower在之后作出相关反应,这样就完成了一个切换,这种模式也是比较通用的模式,基本大部分都是这样实现的。但是这里面有个很严重的问题,如果注意不到会导致短暂的时间内系统出现脑裂,因为心跳出现超时可能是Leader挂了,但是也可能是ZooKeeper节点之间网络出现了问题,导致Leader假死的情况,Leader其实并未死掉,但是与ZooKeeper之间的网络出现问题导致ZooKeeper认为其挂掉了然后通知其他节点进行切换,这样follower中就有一个成为了Leader,但是原本的Leader并未死掉,这时候client也获得Leader切换的消息,但是仍然会有一些延时,ZooKeeper需要通讯需要一个一个通知,这时候整个系统就很混乱可能有一部分client已经通知到了连接到新的leader上去了,有的client仍然连接在老的Leader上,如果同时有两个client需要对Leader的同一个数据更新,并且刚好这两个client此刻分别连接在新老的Leader上,就会出现很严重问题。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 这里做下小总结: </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br mpa-from-tpl="t"> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-template="t" mpa-from-tpl="t" style="color: rgb(51, 51, 51);font-size: 17px;text-align: justify;"> <ul class="list-paddingleft-2" mpa-from-tpl="t" style="padding-left: 2.2em;width: 577.422px;list-style-type: square;"> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">假死:由于心跳超时(网络原因导致的)认为Leader死了,但其实Leader还存活着。</p></li> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">脑裂:由于假死会发起新的Leader选举,选举出一个新的Leader,但旧的Leader网络又通了,导致出现了两个Leader ,有的客户端连接到老的Leader,而有的客户端则连接到新的Leader。</p></li> </ul> </section> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <strong>ZooKeeper脑裂是什么原因导致的?</strong> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 主要原因是ZooKeeper集群和ZooKeeper client判断超时并不能做到完全同步,也就是说可能一前一后,如果是集群先于client发现,那就会出现上面的情况。同时,在发现并切换后通知各个客户端也有先后快慢。一般出现这种情况的几率很小,需要Leader节点与ZooKeeper集群网络断开,但是与其他集群角色之间的网络没有问题,还要满足上面那些情况,但是一旦出现就会引起很严重的后果,数据不一致。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <strong>ZooKeeper是如何解决“脑裂”问题的?</strong> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 要解决Split-Brain脑裂的问题,一般有下面几种方法: </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br mpa-from-tpl="t"> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-template="t" mpa-from-tpl="t" style="color: rgb(51, 51, 51);font-size: 17px;text-align: justify;"> <ul class="list-paddingleft-2" mpa-from-tpl="t" style="padding-left: 2.2em;width: 577.422px;list-style-type: square;"> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">Quorums(法定人数)方式:比如3个节点的集群,Quorums = 2,也就是说集群可以容忍1个节点失效,这时候还能选举出1个lead,集群还可用。比如4个节点的集群,它的Quorums = 3,Quorums要超过3,相当于集群的容忍度还是1,如果2个节点失效,那么整个集群还是无效的。这是ZooKeeper防止“脑裂”默认采用的方法。</p></li> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">采用Redundant communications(冗余通信)方式:集群中采用多种通信方式,防止一种通信方式失效导致集群中的节点无法通信。</p></li> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">Fencing(共享资源)方式:比如能看到共享资源就表示在集群中,能够获得共享资源的锁的就是Leader,看不到共享资源的,就不在集群中。</p></li> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;">仲裁机制方式。</span></p></li> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">启动磁盘锁定方式。</p></li> </ul> </section> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 要想避免ZooKeeper“脑裂”情况其实也很简单,在follower节点切换的时候不在检查到老的Leader节点出现问题后马上切换,而是在休眠一段足够的时间,确保老的Leader已经获知变更并且做了相关的shutdown清理工作了然后再注册成为Master就能避免这类问题了,这个休眠时间一般定义为与ZooKeeper定义的超时时间就够了,但是这段时间内系统可能是不可用的,但是相对于数据不一致的后果来说还是值得的。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <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;">ZooKeeper默认采用了Quorums这种方式来防止“脑裂”现象。</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;">即只有集群中超过半数节点投票才能选举出Leader。</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;">这样的方式可以确保Leader的唯一性,要么选出唯一的一个Leader,要么选举失败。</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;">在ZooKeeper中Quorums作用如下:</span> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br mpa-from-tpl="t"> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-template="t" mpa-from-tpl="t" style="color: rgb(51, 51, 51);font-size: 17px;text-align: justify;"> <ul class="list-paddingleft-2" mpa-from-tpl="t" style="padding-left: 2.2em;width: 577.422px;list-style-type: square;"> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">集群中最少的节点数用来选举Leader保证集群可用。</p></li> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">通知客户端数据已经安全保存前集群中最少数量的节点数已经保存了该数据。一旦这些节点保存了该数据,客户端将被通知已经安全保存了,可以继续其他任务。而集群中剩余的节点将会最终也保存了该数据。</p></li> </ul> </section> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> 假设某个Leader假死,其余的followers选举出了一个新的Leader。这时,旧的Leader复活并且仍然认为自己是Leader,这个时候它向其他followers发出写请求也是会被拒绝的。因为每当新Leader产生时,会生成一个epoch标号(标识当前属于那个Leader的统治时期),这个epoch是递增的,followers如果确认了新的Leader存在,知道其epoch,就会拒绝epoch小于现任leader epoch的所有请求。那有没有follower不知道新的Leader存在呢,有可能,但肯定不是大多数,否则新Leader无法产生。ZooKeeper的写也遵循quorum机制,因此,得不到大多数支持的写是无效的,旧leader即使各种认为自己是Leader,依然没有什么作用。 </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br> </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> ZooKeeper除了可以采用上面默认的Quorums方式来避免出现“脑裂”,还可以采用下面的预防措施: </section> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: justify;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <br mpa-from-tpl="t"> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-template="t" mpa-from-tpl="t" style="color: rgb(51, 51, 51);font-size: 17px;text-align: justify;"> <ul class="list-paddingleft-2" mpa-from-tpl="t" style="padding-left: 2.2em;width: 577.422px;list-style-type: square;"> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">添加冗余的心跳线,例如双线条线,尽量减少“裂脑”发生机会。</p></li> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">启用磁盘锁。正在服务一方锁住共享磁盘,“裂脑”发生时,让对方完全“抢不走”共享磁盘资源。但使用锁磁盘也会有一个不小的问题,如果占用共享盘的一方不主动“解锁”,另一方就永远得不到共享磁盘。现实中假如服务节点突然死机或崩溃,就不可能执行解锁命令。后备节点也就接管不了共享资源和应用服务。于是有人在HA中设计了“智能”锁。即正在服务的一方只在发现心跳线全部断开(察觉不到对端)时才启用磁盘锁。平时就不上锁了。</p></li> <li style="clear: both;"><p style="padding-right: 10px;padding-left: 9px;clear: both;min-height: 1em;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);" mpa-is-content="t">设置仲裁机制。例如设置参考IP(如网关IP),当心跳线完全断开时,2个节点都各自ping一下 参考IP,不通则表明断点就出在本端,不仅"心跳"、还兼对外"服务"的本端网络链路断了,即使启动(或继续)应用服务也没有用了,那就主动放弃竞争,让能够ping通参考IP的一端去起服务。更保险一些,ping不通参考IP的一方干脆就自我重启,以彻底释放有可能还占用着的那些共享资源。</p></li> </ul> </section> </section> <p><br mpa-from-tpl="t"></p> <section mpa-from-tpl="t" mpa-is-content="t" style="padding-right: 10px;padding-left: 9px;text-align: left;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);"> <strong><em>原文链接:https://www.cnblogs.com/kevingrace/p/12433503.html</em></strong> </section> </section> </section> <p><br></p> <section data-mpa-template="t" mpa-from-tpl="t" style="letter-spacing: 0.544px;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);font-size: 16px;text-align: start;widows: 1;caret-color: rgb(0, 0, 0);color: rgb(120, 114, 114);word-spacing: 2px;"> <section data-id="89429" mpa-from-tpl="t" style="border-width: 0px;border-style: none;border-color: initial;"> <section mpa-from-tpl="t" style="text-align: center;height: 50px;"> <section mpa-from-tpl="t" style="margin-right: auto;margin-left: auto;width: 48px;height: 48px;color: rgb(255, 255, 255);line-height: 48px;display: inline-block;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_gif/kiaqiahsnxHd4Zt4378tqib1DnnfKYvZAI7sUNZCYmGN2HCMDFDYV5hLu6HrHIK5BynAAwgHGiafFFU7ibYez6mXL4w/640?wx_fmt=gif&quot;);background-repeat: no-repeat;background-size: 100%;background-position: 0px center;"> <p style="font-weight: bold;"><span style="font-size: 14px;">end</span></p> </section> <section mpa-from-tpl="t" style="margin-top: -26px;height: 2px;background-color: rgb(34, 33, 33);"> <br> </section> </section> </section> </section> <p style="letter-spacing: 0.544px;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 16px;text-align: start;widows: 1;word-spacing: 1px;caret-color: rgb(255, 0, 0);"><br></p> <section mpa-from-tpl="t" style="padding-left: 5px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: medium;text-align: start;widows: 1;caret-color: rgb(0, 0, 0);word-spacing: 2px;border-left: 5px solid rgb(51, 51, 51);line-height: 1.5em;"> <section powered-by="xiumi.us" mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section mpa-from-tpl="t" style="font-size: 18px;"> <p><span style="font-size: 16px;">推荐阅读:</span></p> </section> </section> </section> </section> <p style="letter-spacing: 0.544px;white-space: normal;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;background-color: rgb(255, 255, 255);"><br></p> <ul class="list-paddingleft-2" mpa-from-tpl="t" style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: medium;text-align: start;widows: 1;caret-color: rgb(0, 0, 0);word-spacing: 2px;"> <li style="font-size: 14px;"><p style="margin-top: 5px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&amp;mid=2247493913&amp;idx=1&amp;sn=fdc5f1c6f7d2b68beeaac0f6badaaf90&amp;chksm=9f4485d1a8330cc708313b080b323607433173dabebd49adb4443c4da21b94c60618ad609d3e&amp;scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">如何设计一个牛逼的本地缓存!</a><br></p></li> <li style="font-size: 14px;"><p style="margin-top: 5px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&amp;mid=2247493901&amp;idx=1&amp;sn=eafa9ecce5cf6059d3f58b66f6386378&amp;chksm=9f4485c5a8330cd33509689b1dfd7fcd252b4d765c728cc152dddb8781c4aa59d68157ebfbac&amp;scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">这样设计订单系统,同事直呼 "666"!</a><br></p></li> <li style="font-size: 14px;"><p style="margin-top: 5px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&amp;mid=2247493867&amp;idx=1&amp;sn=cc70b9a3c15c517090afb4efc4db12ec&amp;chksm=9f448423a8330d3524c2b42f5ccf6bbf586f1a9bba757f7dd6b4906e0d974e77a50483335625&amp;scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">ElasticSearch 在数十亿级别数据下,如何提高查询效率?</a><br></p></li> <li style="font-size: 14px;"><p style="margin-top: 5px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&amp;mid=2247493562&amp;idx=1&amp;sn=69cc7740c30877d298281dacf7c74572&amp;chksm=9f448b72a8330264c3932d5735fa39cb8548b7502a63a403617f174f518a69d7a9130381390f&amp;scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">Spring Cloud架构的各个组件的原理分析</a><br></p></li> <li style="font-size: 14px;"><p style="margin-top: 5px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&amp;mid=2247493607&amp;idx=1&amp;sn=71a3bea53bcca4ba1051447abe1cac13&amp;chksm=9f448b2fa8330239dce3dc00fa256d41db52d816ba65c630d00ec12d9ebf279c2a10ff55630b&amp;scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">一口气说出 5 种 IO 模型,蒙圈了!</a><br></p></li> </ul> <p style="margin-top: 5px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;text-align: start;widows: 1;caret-color: rgb(0, 0, 0);word-spacing: 2px;"><br></p> <p style="margin-top: 5px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;widows: 1;caret-color: rgb(0, 0, 0);word-spacing: 2px;text-align: right;"><img class="rich_pages" data-ratio="0.5555555555555556" data-s="300,640" data-type="jpeg" data-w="900" src="/upload/9d786e52e671b1ce4beb338d1e0d1815.jpg" style="letter-spacing: 0.544px;text-align: center;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;box-sizing: border-box !important;visibility: visible !important;width: 677px !important;"><span style="letter-spacing: 0.544px;font-size: 14px;">如有收获,点个在看,诚挚感谢</span><img data-ratio="1" data-type="png" data-w="19" width="19px" src="/upload/5f7454d24a334e968c32b8ce9ae53c5.png" style="font-size: 16px;letter-spacing: 0.544px;display: inline-block;vertical-align: text-bottom;box-sizing: border-box !important;visibility: visible !important;width: 19px !important;"></p>

看看别人后端API接口写得,那叫一个优雅!

作者:微信小助手

<section data-mpa-template="t" mpa-paragraph-type="ignored" style="max-width: 100%;font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);font-size: 15px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;" data-mpa-powered-by="yiban.io"> <section mpa-from-tpl="t" style="white-space: normal;font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;"> <p style="text-align: center;"><span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;font-size: 12px;color: rgb(120, 114, 119);user-select: text !important;">点击上方 "</span><span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;color: rgb(0, 0, 0);font-size: 12px;user-select: text !important;"><strong style="color: rgb(62, 62, 62);font-size: 14px;user-select: text !important;"><span style="letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;color: rgb(61, 170, 214);user-select: text !important;">zhisheng</span></strong></span><span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;font-size: 12px;color: rgb(120, 114, 119);user-select: text !important;">"关注,&nbsp;<span style="letter-spacing: 0.544px;user-select: text !important;">星标或置顶一起成长</span></span><span style="letter-spacing: 0.544px;max-width: 100%;word-spacing: 2px;font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;color: rgb(127, 127, 127);font-size: 14px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> </section> <section mpa-from-tpl="t" style="font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);font-size: 15px;background-color: rgb(255, 255, 255);"> <p style="text-align: center;"><a target="_blank" href="https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&amp;album_id=1337172142412169216&amp;__biz=MzIxMTE0ODU5NQ==#wechat_redirect" textvalue="Flink 从入门到精通" tab="innerlink" data-linktype="2" style="letter-spacing: 0.544px;color: rgb(120, 172, 254);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 13px;line-height: 1.75em;user-select: text !important;"><span style="letter-spacing: 0.544px;line-height: 1.75em;user-select: text !important;">Flink 从入门到精通</span></a><span style="letter-spacing: 0.544px;color: rgb(136, 136, 136);font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 13px;line-height: 1.75em;user-select: text !important;">&nbsp;系列文章</span><span style="letter-spacing: 0.544px;word-spacing: 2px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;color: rgb(127, 127, 127);font-size: 14px;line-height: 1.75em;"></span></p> </section> <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;color: rgb(62, 62, 62);background-color: rgb(255, 255, 255);font-size: 16px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(127, 127, 127);font-size: 14px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <p><img class="rich_pages" data-cropselx1="0" data-cropselx2="574" data-cropsely1="0" data-cropsely2="336" data-ratio="0.667" data-s="300,640" data-type="jpeg" data-w="1000" src="/upload/3a2562628509790892aa342c95d1cb10.jpg" style="height: 383px;white-space: normal;letter-spacing: 0.544px;width: 574px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;" title=""></p> <p style="text-align: left;"><span style="color: rgb(178, 178, 178);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-size: 12px;letter-spacing: 0.544px;text-align: left;white-space: pre-line;background-color: rgb(255, 255, 255);">来源 |&nbsp;r6d.cn/tEvn</span><br></p> <p><br></p> <section data-mpa-template="t" mpa-paragraph-type="ignored" style=""> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style=""> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">在分布式、微服务盛行的今天,绝大部分<span style="">项目</span>都采用的微服务框架,前后端分离方式。<span style="">题外话:</span><span style="">前后端的工作职责越来越明确,现在的前端都称之为大前端,技术栈以及生态圈都已经非常成熟;</span><span style="">以前后端人员瞧不起前端人员,那现在后端人员要重新认识一下前端,前端已经很成体系了。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">一般系统的大致整体架构图如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.8097222222222222" data-type="jpeg" data-w="720" src="/upload/9a63378a3c3da2f8e7883d3d5da4a48e.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;font-size: 16px;word-break: break-word;color: black;line-height: 26px;">需要说明的是,有些小伙伴会回复说,这个架构太简单了吧,太low了,什么网关啊,缓存啊,消息中间件啊,都没有。因为老顾这篇主要介绍的是API接口,所以我们聚焦点,其他的模块小伙伴们自行去补充。</p> </blockquote> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>接口交互<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">前端和后端进行交互,前端按照约定请求URL路径,并传入相关参数,后端服务器接收请求,进行业务处理,返回数据给前端。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;font-size: 16px;word-break: break-word;color: black;line-height: 26px;">针对URL路径的restful风格,以及传入参数的公共请求头的要求(如:app_version,api_version,device等),老顾这里就不介绍了,小伙伴们可以自行去了解,也比较简单。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">着重介绍一下后端服务器如何实现把数据返回给前端?</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>返回格式<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">后端返回给前端我们一般用JSON体方式,定义如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/8Jeic82Or04mLG5Y4kMokaRZia4t6skBhMdG1tHw1HgrCz3VS6uCJ1v4VcgJH2gCj41SC7xpdsVLAlLoBFDt63dg/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><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>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#返回状态码</span><br>&nbsp;&nbsp;&nbsp;&nbsp;code:<span style="color: #e6c07b;line-height: 26px;">integer</span>,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#返回信息描述</span><br>&nbsp;&nbsp;&nbsp;&nbsp;message:string,<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#返回值</span><br>&nbsp;&nbsp;&nbsp;&nbsp;data:object<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;"><strong style="color: black;">CODE状态码</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">code返回状态码,一般小伙伴们是在开发的时候需要什么,就添加什么。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">如接口要返回用户权限异常,我们加一个状态码为101吧,下一次又要加一个数据参数异常,就加一个102的状态码。这样虽然能够照常满足业务,但状态码太凌乱了</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">我们应该可以参考HTTP请求返回的状态码,下面是常见的HTTP状态码:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/8Jeic82Or04mLG5Y4kMokaRZia4t6skBhMdG1tHw1HgrCz3VS6uCJ1v4VcgJH2gCj41SC7xpdsVLAlLoBFDt63dg/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><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;">200&nbsp;-&nbsp;请求成功<br>301&nbsp;-&nbsp;资源(网页等)被永久转移到其它URL<br>404&nbsp;-&nbsp;请求的资源(网页等)不存在<br>500&nbsp;-&nbsp;内部服务器错误<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 data-ratio="0.35555555555555557" data-type="jpeg" data-w="720" src="/upload/ee854ede16d238a3fc843ea18492cc8.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">我们可以参考这样的设计,这样的好处就把错误类型归类到某个区间内,如果区间不够,可以设计成4位数。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/8Jeic82Or04mLG5Y4kMokaRZia4t6skBhMdG1tHw1HgrCz3VS6uCJ1v4VcgJH2gCj41SC7xpdsVLAlLoBFDt63dg/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><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;"><span style="color: #5c6370;font-style: italic;line-height: 26px;">#1000~1999&nbsp;区间表示参数错误</span><br><span style="color: #5c6370;font-style: italic;line-height: 26px;">#2000~2999&nbsp;区间表示用户错误</span><br><span style="color: #5c6370;font-style: italic;line-height: 26px;">#3000~3999&nbsp;区间表示接口异常</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">这样前端开发人员在得到返回值后,根据状态码就可以知道,大概什么错误,再根据message相关的信息描述,可以快速定位。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;"><strong style="color: black;">Message</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">这个字段相对理解比较简单,就是发生错误时,如何友好的进行提示。一般的设计是和code状态码一起设计,如</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.42777777777777776" data-type="jpeg" data-w="720" src="/upload/e7d35d2e1398f4c0089b048fa26028a3.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">再在枚举中定义,状态码</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.9291666666666667" data-type="jpeg" data-w="720" src="/upload/a86d2ec17b53b7dba01fffb90718bba2.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">状态码和信息就会一一对应,比较好维护。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;"><strong style="color: black;">Data</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">返回数据体,JSON格式,根据不同的业务又不同的JSON体。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">我们要设计一个返回体类Result</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.5430555555555555" data-type="jpeg" data-w="720" src="/upload/8618d876ffa2ff661fe22fa8e5a6b2ad.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>控制层Controller<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">我们会在controller层处理业务请求,并返回给前端,以order订单为例</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.5069444444444444" data-type="jpeg" data-w="720" src="/upload/ac247aeb447cab78e6e0bc1dc5a9cb65.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">我们看到在获得order对象之后,我们是用的Result构造方法进行包装赋值,然后进行返回。小伙伴们有没有发现,构造方法这样的包装是不是很麻烦,我们可以优化一下。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>美观优化<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">我们可以在Result类中,加入静态方法,一看就懂</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.8736111111111111" data-type="jpeg" data-w="720" src="/upload/8c8950b0f8602fd51f6cdd6d2777d8d1.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">那我们来改造一下Controller</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.5069444444444444" data-type="jpeg" data-w="720" src="/upload/125c6048b2ba37474112182140db80f4.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">代码是不是比较简洁了,也美观了。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>优雅优化<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">上面我们看到在Result类中增加了静态方法,使得业务处理代码简洁了。但小伙伴们有没有发现这样有几个问题:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">1、每个方法的返回都是Result封装对象,没有业务含义</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">2、在业务代码中,成功的时候我们调用Result.success,异常错误调用Result.failure。是不是很多余</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">3、上面的代码,判断id是否为null,其实我们可以使用hibernate validate做校验,没有必要在方法体中做判断。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">我们最好的方式直接返回真实业务对象,最好不要改变之前的业务方式,如下图</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.4513888888888889" data-type="jpeg" data-w="720" src="/upload/e5782d807b565b715cfec0c3e55924f1.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">这个和我们平时的代码是一样的,非常直观,直接返回order对象,这样是不是很完美。那实现方案是什么呢?</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>实现方案<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">小伙伴们怎么去实现是不是有点思路,在这个过程中,我们需要做几个事情</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">1、定义一个注解@ResponseResult,表示这个接口返回的值需要包装一下</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">2、拦截请求,判断此请求是否需要被@ResponseResult注解</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">3、核心步骤就是实现接口ResponseBodyAdvice和@ControllerAdvice,判断是否需要包装返回值,如果需要,就把Controller接口的返回值进行重写。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;"><strong style="color: black;">注解类</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">用来标记方法的返回值,是否需要包装</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.361244019138756" data-type="jpeg" data-w="836" src="/upload/3230a0a3f87313f0301f9a5d2dc5850c.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;"><strong style="color: black;">拦截器</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">拦截请求,是否此请求返回的值需要包装,其实就是运行的时候,解析@ResponseResult注解</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.5305555555555556" data-type="jpeg" data-w="720" src="/upload/47e237d16d5f07e041321096b34fe170.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">此代码核心思想,就是获取此请求,是否需要返回值包装,设置一个属性标记。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;"><strong style="color: black;">重写返回体</strong></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.45555555555555555" data-type="jpeg" data-w="720" src="/upload/75c1df7ff26a7e60d2b464e40bd776ea.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">上面代码就是判断是否需要返回值包装,如果需要就直接包装。这里我们只处理了正常成功的包装,如果方法体报异常怎么办?处理异常也比较简单,只要判断body是否为异常类。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.26944444444444443" data-type="jpeg" data-w="720" src="/upload/970736feb71c9701a387606c254a24af.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">怎么做全局的异常处理,篇幅原因,老顾这里就不做介绍了,只要思路理清楚了,自行改造就行。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;"><strong style="color: black;">重写Controller</strong></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.4666666666666667" data-type="jpeg" data-w="720" src="/upload/469f55ccfd620c31d64c584253f6a7d.jpg" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">在控制器类上或者方法体上加上@ResponseResult注解,这样就ok了,简单吧。到此返回的设计思路完成,是不是又简洁,又优雅。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>总结<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;word-spacing: 0.1em;letter-spacing: 0.1em;line-height: 1.95;color: rgb(51, 51, 51);word-break: break-word;">这个方案还有没有别的优化空间,当然是有的。如:每次请求都要反射一下,获取请求的方法是否需要包装,其实可以做个缓存,不需要每次都需要解析。</p> </section> <section style="margin-bottom: 15px;white-space: normal;max-width: 100%;font-family: -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;background-color: rgb(255, 255, 255);min-height: 1em;line-height: 1.75em;letter-spacing: 1px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br> </section> <section data-mpa-template="t" mpa-from-tpl="t" style="white-space: normal;"> <section data-mpa-template-id="1480331" data-mpa-color="null" data-mpa-category="收藏" mpa-from-tpl="t"> <section data-tools="135编辑器" data-id="89715" mpa-from-tpl="t" style="font-size: 16px;border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;"> <section data-mpa-template-id="1252" data-mpa-color="#ffffff" data-mpa-category="divider" mpa-from-tpl="t" style="max-width: 100%;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 14px;letter-spacing: 0.5px;word-spacing: 2px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;font-size: 16px;line-height: 1.6;letter-spacing: 0px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" mpa-from-tpl="t" style="max-width: 100%;color: rgb(51, 51, 51);font-size: 17px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-tools="135编辑器" data-id="89428" mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="max-width: 100%;text-align: center;height: 50px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section mpa-from-tpl="t" style="margin-right: auto;margin-left: auto;max-width: 100%;width: 48px;height: 48px;color: rgb(255, 255, 255);line-height: 48px;display: inline-block;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_gif/ncqN8l14plZccK32d6rFjnDsvVhac0rplCGjfGcvjbPic2g9ibvXJrR5iaibPcxeatKCO3fFy17Rq709VnAGqQ1daw/640?wx_fmt=gif&quot;);background-size: 100%;background-position: 0px center;background-repeat: no-repeat;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;font-weight: bold;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></p> </section> </section> </section> </section> </section> </section> </section> </section> <pre style="color: rgb(62, 62, 62);font-size: 15px;letter-spacing: 0.544px;text-align: start;widows: 1;word-spacing: 1px;caret-color: rgb(51, 51, 51);background-color: rgb(255, 255, 255);"><pre style="word-spacing: 2px;letter-spacing: 0.544px;font-size: 16px;color: rgb(89, 89, 89);caret-color: rgb(255, 0, 0);user-select: text !important;"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: -10px;padding-right: 10px;padding-left: 10px;white-space: normal;line-height: 1.6;word-break: break-word;text-align: center;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 15px;letter-spacing: 0.05em;user-select: text !important;"> <img class="rich_pages __bg_gif" data-ratio="0.18524332810047095" data-type="gif" data-w="637" src="/upload/d2a38b8f8a4c599687e2292f14dfd57b.png" style="background-color: rgb(238, 237, 235);border-width: 1px;border-style: solid;border-color: rgb(238, 237, 235);background-size: 22px;background-position: center center;background-repeat: no-repeat;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);color: rgb(62, 62, 62);box-sizing: border-box !important;user-select: text !important;visibility: visible !important;width: 220px !important;"> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: -10px;padding-right: 10px;padding-left: 10px;white-space: normal;line-height: 1.6;word-break: break-word;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 15px;letter-spacing: 0.05em;user-select: text !important;"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: -10px;padding-right: 10px;padding-left: 10px;line-height: 1.6;word-break: break-word;text-align: center;letter-spacing: 0.05em;user-select: text !important;"> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);user-select: text !important;"> <br style="user-select: text !important;"> </section> </section> </section> <section data-mpa-template="t" mpa-paragraph-type="ignored" style="font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);font-size: 15px;user-select: text !important;"> <ul class="list-paddingleft-2" style="width: 577.422px;user-select: text !important;"> <li style="user-select: text !important;"><p style="margin-top: 5px;margin-bottom: 5px;line-height: normal;user-select: text !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMTE0ODU5NQ==&amp;mid=2650239332&amp;idx=1&amp;sn=bd47b1018a7b3e34506a3bacece6c088&amp;chksm=8f5a1b38b82d922e25e6efbbe132d3c7d57e53ae204ecce2db73a8d4633b1c89d90a87b2656b&amp;scene=21#wechat_redirect" 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;user-select: text !important;">基于 Apache Flink 的实时监控告警系统</a></p></li> <li style="user-select: text !important;"><p style="margin-top: 5px;margin-bottom: 5px;line-height: normal;user-select: text !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMTE0ODU5NQ==&amp;mid=2650239535&amp;idx=1&amp;sn=f70cc6fb3ba3559554e68c8735fef442&amp;chksm=8f5a1873b82d916554a2a557a5cf911e9e7e55166677a01c9e915484ef357f98b35a79106963&amp;scene=21#wechat_redirect" 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;user-select: text !important;">关于数据中台的深度思考与总结(干干货)</a></p></li> <li style="user-select: text !important;"><p style="margin-top: 5px;margin-bottom: 5px;line-height: normal;user-select: text !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMTE0ODU5NQ==&amp;mid=2650239084&amp;idx=2&amp;sn=11e5feffe499d9f7e97b2a7af9286e76&amp;chksm=8f5a1a30b82d932696dcb11b547391a3651ccb063d6ebb727e921c9d35e8ff1911cfbf0d6ce0&amp;scene=21#wechat_redirect" 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;user-select: text !important;">日志收集Agent,阴暗潮湿的地底世界</a><br style="user-select: text !important;"></p></li> <li style="user-select: text !important;"><p style="margin-top: 5px;margin-bottom: 5px;line-height: normal;user-select: text !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMTE0ODU5NQ==&amp;mid=2650238911&amp;idx=1&amp;sn=7b384c92896263171a925909dfcf66fb&amp;chksm=8f5a05e3b82d8cf5e33d6034c420ee62474dbf3db18e3ca0f09fc28f2f9d50e98e801bae1995&amp;scene=21#wechat_redirect" 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;user-select: text !important;">2020 继续踏踏实实的做好自己</a></p></li> </ul> </section></pre><p style="font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;white-space: normal;word-spacing: 2px;letter-spacing: 0.544px;text-align: center;caret-color: rgb(255, 0, 0);user-select: text !important;"><img class="rich_pages" data-ratio="0.44" data-s="300,640" data-type="jpeg" data-w="500" src="/upload/95163402322e6a001b2f4d7e3281693.jpg" style="box-sizing: border-box !important;user-select: text !important;visibility: visible !important;width: 500px !important;"></p><p style="font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;white-space: normal;word-spacing: 2px;letter-spacing: 0.544px;text-align: center;caret-color: rgb(255, 0, 0);user-select: text !important;"><br style="user-select: text !important;"></p><p style="font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;white-space: normal;word-spacing: 2px;letter-spacing: 0.544px;text-align: center;caret-color: rgb(255, 0, 0);user-select: text !important;"><br style="user-select: text !important;"></p><p style="font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;white-space: normal;word-spacing: 2px;letter-spacing: 0.544px;text-align: center;caret-color: rgb(255, 0, 0);user-select: text !important;"><img class="rich_pages" data-ratio="0.3310344827586207" data-s="300,640" data-type="png" data-w="1885" src="/upload/cd96652cff648c17bb36ef28b66ef3e3.png" style="box-sizing: border-box !important;user-select: text !important;visibility: visible !important;width: 677px !important;"></p><pre style="word-spacing: 2px;letter-spacing: 0.544px;text-align: center;caret-color: rgb(255, 0, 0);line-height: inherit;user-select: text !important;"> <section class="js_darkmode__75" mpa-from-tpl="t" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" data-style="font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255); color: rgb(62, 62, 62); text-align: start; font-size: 14px; letter-spacing: 0.5px; word-spacing: 2px; user-select: text !important;" style="white-space: normal;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 14px;letter-spacing: 0.5px;user-select: text !important;"> <section data-mpa-template-id="1480331" data-mpa-color="null" data-mpa-category="收藏" mpa-from-tpl="t" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="user-select: text !important;"> <section data-tools="135编辑器" data-id="89715" mpa-from-tpl="t" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="font-size: 16px;border-width: 0px;border-style: none;border-color: initial;user-select: text !important;"> <section data-mpa-template-id="1252" data-mpa-color="#ffffff" data-mpa-category="divider" mpa-from-tpl="t" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="font-size: 14px;user-select: text !important;"> <section mpa-from-tpl="t" data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="user-select: text !important;"> <p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;user-select: text !important;"><br style="user-select: text !important;"></p> <p data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;text-align: left;user-select: text !important;"><span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(230, 230, 230)" data-style="letter-spacing: 0.544px; font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif; font-size: 12px; color: rgb(0, 0, 0); user-select: text !important;" class="js_darkmode__77" style="color: rgb(0, 0, 0);letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 12px;user-select: text !important;">公众号</span><span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 12px;user-select: text !important;">(</span><strong data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;user-select: text !important;"><span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(224, 40, 91)" data-style="font-size: 12px; color: rgb(171, 25, 66); user-select: text !important;" class="js_darkmode__78" style="color: rgb(171, 25, 66);font-size: 12px;user-select: text !important;">zhisheng</span></strong><span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 12px;user-select: text !important;">)</span><span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(230, 230, 230)" data-style="letter-spacing: 0.544px; font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif; font-size: 12px; color: rgb(0, 0, 0); user-select: text !important;" class="js_darkmode__79" style="color: rgb(0, 0, 0);letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 12px;user-select: text !important;">里回复</span><span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 12px;user-select: text !important;">&nbsp;<span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="color: rgb(255, 41, 65);user-select: text !important;">面经、ClickHouse、<span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;user-select: text !important;">ES、<span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;user-select: text !important;">Flink、</span></span></span>&nbsp;<span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="color: rgb(255, 41, 65);letter-spacing: 0.544px;user-select: text !important;">Spring、<span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;user-select: text !important;">Java、<span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;user-select: text !important;">Kafka、<span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(168, 168, 168)" style="letter-spacing: 0.544px;user-select: text !important;">监控&nbsp;</span></span></span></span></span><span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(230, 230, 230)" data-style="letter-spacing: 0.544px; font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif; color: rgb(0, 0, 0); font-size: 12px; user-select: text !important;" class="js_darkmode__80" style="color: rgb(0, 0, 0);letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 12px;user-select: text !important;"><span data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-color="rgb(230, 230, 230)" style="letter-spacing: 0.544px;user-select: text !important;">等关键字</span>可以查看更多关键字对应的文章。</span><br style="user-select: text !important;"></p> </section> </section> </section> </section> </section></pre><pre style="word-spacing: 2px;letter-spacing: 0.544px;font-size: 16px;color: rgb(89, 89, 89);caret-color: rgb(255, 0, 0);user-select: text !important;"> <section mpa-from-tpl="t" style="font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;user-select: text !important;"> <section data-mpa-template-id="1480331" data-mpa-color="null" data-mpa-category="收藏" mpa-from-tpl="t" style="user-select: text !important;"> <section data-tools="135编辑器" data-id="89715" mpa-from-tpl="t" style="border-width: 0px;border-style: none;border-color: initial;user-select: text !important;"> <section data-mpa-template-id="1252" data-mpa-color="#ffffff" data-mpa-category="divider" mpa-from-tpl="t" style="color: rgb(62, 62, 62);font-size: 14px;letter-spacing: 0.5px;user-select: text !important;"> <section mpa-from-tpl="t" style="user-select: text !important;"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding: 10px;font-size: 16px;color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;font-family: PingFangSC-Light;user-select: text !important;"> <section data-role="outer" label="Powered by 135editor.com" style="letter-spacing: 0.544px;user-select: text !important;"> <section data-role="outer" label="Powered by 135editor.com" style="user-select: text !important;"> <section data-tools="135编辑器" data-id="94250" style="user-select: text !important;"> <section data-tools="135编辑器" data-id="91842" style="border-color: currentcolor;border-style: none;border-width: 0px;user-select: text !important;"> <section style="text-align: right;width: auto;user-select: text !important;"> <section style="display: inline-block;clear: both;user-select: text !important;"> <section data-brushtype="text" style="padding: 18px 15px 20px 10px;color: rgb(86, 146, 214);background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/7QRTvkK2qC6hzicPF91rs9ItM18PtNACZj3MJMA9biczdQx5KOicGjX5c8Ty6j7NQ04wQJpM3bZSTp6DrLiaCicxJAw/640?wx_fmt=png&quot;);background-repeat: no-repeat;text-align: center;background-size: 100% 100%;letter-spacing: 1.5px;user-select: text !important;"> <section style="display: flex;justify-content: center;align-items: center;user-select: text !important;"> <section data-brushtype="text" style="font-size: 14px;color: rgb(51, 51, 51);user-select: text !important;"> <span style="letter-spacing: 0.544px;text-align: right;font-size: 16px;white-space: pre-line;caret-color: rgb(63, 63, 63);color: rgb(216, 79, 169);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-weight: bold;">点个赞+在看,少个 bug</span> <span style="letter-spacing: 0.544px;text-align: right;font-size: 16px;color: rgb(63, 63, 63);font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;">&nbsp;</span> <span style="letter-spacing: 0.544px;text-align: right;font-size: 16px;white-space: pre-line;color: rgb(0, 179, 139);font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;font-weight: bold;">👇</span> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section></pre></pre> </section> </section> </section> </section> </section> </section> </section>

牛逼哄哄的布隆过滤器,不了解一下?

作者:微信小助手

<section data-mpa-template="t" mpa-from-tpl="t" data-mpa-powered-by="yiban.io"> <section data-id="94709" mpa-from-tpl="t"> <section data-width="100%" mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section data-autoskip="1" mpa-from-tpl="t"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"> <section> <section donone="shifuMouseDownCard('shifu_c_030')" label="Copyright Reserved by PLAYHUDONG." style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-darkmode-bgcolor="rgb(36, 36, 36)" data-darkmode-original-bgcolor="rgb(255, 255, 255)" data-darkmode-color="rgb(168, 168, 168)" data-darkmode-original-color="rgb(62, 62, 62)" data-style="font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 16px; white-space: normal; letter-spacing: 0.544px; color: rgb(62, 62, 62); text-align: start; widows: 1; word-spacing: 2px; caret-color: rgb(255, 0, 0); background-color: rgb(255, 255, 255); line-height: 1.6; margin-left: 0.5em; margin-right: 0.5em;" class="js_darkmode__98" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section> <section> <span style="font-size: 12px;color: rgb(178, 178, 178);"></span> </section> <section data-mpa-template="t" mpa-paragraph-type="ignored"> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mpa-template="t" mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section powered-by="xiumi.us" mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section powered-by="xiumi.us" mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section mpa-from-tpl="t" style="white-space: normal;font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;"> <p style="text-align: center;"><span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;font-size: 12px;color: rgb(120, 114, 119);user-select: text !important;">点击上方 "</span><span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;color: rgb(0, 0, 0);font-size: 12px;user-select: text !important;"><strong style="color: rgb(62, 62, 62);font-size: 14px;user-select: text !important;"><span style="letter-spacing: 0.544px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;color: rgb(61, 170, 214);user-select: text !important;">zhisheng</span></strong></span><span style="font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;font-size: 12px;color: rgb(120, 114, 119);user-select: text !important;">"关注,&nbsp;<span style="letter-spacing: 0.544px;user-select: text !important;">星标或置顶一起成长</span></span><span style="letter-spacing: 0.544px;max-width: 100%;word-spacing: 2px;font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;color: rgb(127, 127, 127);font-size: 14px;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> </section> <section mpa-from-tpl="t" style="color: rgb(62, 62, 62);font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;font-size: 15px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"> <p style="text-align: center;"><a target="_blank" href="https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&amp;album_id=1337172142412169216&amp;__biz=MzIxMTE0ODU5NQ==#wechat_redirect" textvalue="Flink 从入门到精通" tab="innerlink" data-linktype="2" style="letter-spacing: 0.544px;color: rgb(120, 172, 254);-webkit-tap-highlight-color

Linux网络状态工具ss命令使用详解

作者:微信小助手

<section powered-by="xiumi.us" style="margin-top: 30px;margin-bottom: 20px;max-width: 100%;box-sizing: border-box;white-space: normal;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;display: inline-block;width: 574px;vertical-align: top;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section style="padding: 5px 10px;max-width: 100%;box-sizing: border-box;display: inline-block;width: 574px;vertical-align: top;border-width: 3px;border-radius: 20px;border-style: solid;border-color: rgb(226, 241, 246);overflow: hidden;background-color: rgb(226, 241, 246);overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;transform: translate3d(1px, 0px, 0px);overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;text-align: center;font-size: 14px;color: rgb(149, 187, 202);overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;">文章来源 博客园</p> </section> </section> </section> </section> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"></p> </section> </section> </section> <section powered-by="xiumi.us" style="margin-bottom: -15px;max-width: 100%;box-sizing: border-box;white-space: normal;text-align: left;transform: translate3d(20px, 0px, 0px);overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;display: inline-block;width: 55px;height: 40px;vertical-align: top;overflow: hidden;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;text-align: center;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;vertical-align: middle;display: inline-block;line-height: 0;overflow-wrap: break-word !important;"> <img data-ratio="0.696" data-w="500" data-type="gif" class="__bg_gif" src="/upload/a040d38d88cdcfaed38ea2886a5b9df0.png" style="box-sizing: border-box;vertical-align: middle;overflow-wrap: break-word !important;width: 500px !important;visibility: visible !important;"> </section> </section> </section> </section> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;white-space: normal;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);font-size: 16px;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;text-align: center;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;text-shadow: rgb(195, 134, 234) 2px 0px 7px;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;">点击蓝字:波哥的IT人生,关注我们</strong></span></p> </section> </section> <section powered-by="xiumi.us" style="margin-bottom: 10px;max-width: 100%;box-sizing: border-box;white-space: normal;text-align: right;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;display: inline-block;vertical-align: middle;width: 229.594px;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;text-align: center;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;vertical-align: middle;display: inline-block;line-height: 0;width: 229.594px;overflow-wrap: break-word !important;"> <img data-ratio="0.2106667" data-w="750" width="100%" data-type="gif" class="__bg_gif" src="/upload/9a990984a6b8f7f7b3c167d0a48d8599.png" style="box-sizing: border-box;vertical-align: middle;overflow-wrap: break-word !important;width: 229.594px !important;visibility: visible !important;"> </section> </section> </section> <section style="max-width: 100%;box-sizing: border-box;display: inline-block;vertical-align: middle;width: 143.5px;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="margin-top: 0.5em;margin-bottom: 0.5em;max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;background-color: rgb(29, 29, 29);height: 1px;overflow-wrap: break-word !important;"> <br> </section> </section> </section> </section> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: black;font-size: 15px;letter-spacing: 0.05em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span> </figure> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">ss命令用于显示socket状态. 他可以显示PACKET sockets, TCP sockets, UDP sockets, DCCP sockets, RAW sockets, Unix domain sockets等等统计. 它比其他工具展示等多tcp和state信息. 它是一个非常实用、快速、有效的跟踪IP连接和sockets的新工具.SS命令可以提供如下信息:</span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <ul class="list-paddingleft-2" style="max-width: 100%;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">所有的TCP sockets</span></p></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">所有的UDP sockets</span></p></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">所有ssh/ftp/ttp/https持久连接</span></p></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">所有连接到Xserver的本地进程</span></p></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">使用state(例如:connected, synchronized, SYN-RECV, SYN-SENT,TIME-WAIT)、地址、端口过滤</span></p></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">所有的state FIN-WAIT-1 tcpsocket连接以及更多</span></p></li> </ul> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">很多流行的Linux发行版都支持ss以及很多监控工具使用ss命令.熟悉这个工具有助于您更好的发现与解决系统性能问题.本人强烈建议使用ss命令替代netstat部分命令,例如netsat -ant/lnt等.</span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(255, 41, 65);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;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">展示他之前来做个对比,统计服务器并发连接数</span></strong></span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="properties"><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">netstat</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"># time netstat -ant | grep EST | wc -l</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">3100</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer"><br></span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">real 0m12.960s</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">user 0m0.334s</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">sys 0m12.561s</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"># time ss -o state established | wc -l</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">3204</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer"><br></span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">real 0m0.030s</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">user 0m0.005s</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">sys 0m0.026s</span></code></pre> </section> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">结果很明显ss统计并发连接数效率完胜netstat,在ss能搞定的情况下, 你还会在选择netstat吗, 还在犹豫吗, 看以下例子,或者跳转到帮助页面.</span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(255, 41, 65);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;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">常用ss命令:</span></strong></span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="properties"><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">ss -l 显示本地打开的所有端口</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">ss -pl 显示每个进程具体打开的socket</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">ss -t -a 显示所有tcp socket</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">ss -u -a 显示所有的UDP Socekt</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">ss -o state established '( dport = :smtp or sport = :smtp )' 显示所有已建立的SMTP连接</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">ss -o state established '( dport = :http or sport = :http )' 显示所有已建立的HTTP连接</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">ss -x src /tmp/.X11-unix/* 找出所有连接X服务器的进程</span></code><code style=" white-space:pre-wrap;max-width: 1000%;text-align: left;display: flex; font-family: Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace;box-sizing: border-box !important;overflow-wrap: break-word !important; "><span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">ss -s 列出当前socket详细信息:</span></code></pre> </section> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p>

漫画设计模式:什么是 “职责链模式” ?

作者:微信小助手

<p style="text-align: center;" data-mpa-powered-by="yiban.io"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/c337b5a6db7a30783dc24c3e54a935e0.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/1682671e3815d3f5a6c7e5692eb31320.png" data-type="png" data-w="678" style=""></p> <p style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><br></p> <p style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><strong style="letter-spacing: 0.544px;font-size: 18px;">—————&nbsp; 第二天&nbsp; —————</strong></p> <p style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" data-type="png" data-w="678" src="/upload/7ec85b52ea96fc8b3a68f5aae96d1633.png" style="box-sizing: border-box !important;width: 677px !important;visibility: visible !important;"></p> <p style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" data-type="png" data-w="678" src="/upload/89393923dcb191c4445ca3d54155f7f1.png" style="box-sizing: border-box !important;width: 677px !important;visibility: visible !important;"></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/bf788805014623e608d1f71ae2c81876.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/662be38c0993592c017ecc1e7fb6d425.png" data-type="png" data-w="678" style=""><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/ca4a1e6c396afb67606decc2ec7dbbbb.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/fbe0b6c131f55ccace0e0f98a6a61d81.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/8eeaed562e119c74f486dd93f81c225d.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/a6d078f2bd02e3e053937f2d35409d89.png" data-type="png" data-w="678" style=""></p> <p style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><span style="font-size: 18px;"><br></span></p> <p style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><span style="font-size: 18px;">————————————</span></p> <p style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" data-type="png" data-w="678" src="/upload/df62500d0768bdde1d3b153375c3f8bb.png" style="box-sizing: border-box !important;width: 677px !important;visibility: visible !important;"></p> <p style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" data-type="png" data-w="678" src="/upload/9086f637e57afca2254297051394abe0.png" style="box-sizing: border-box !important;width: 677px !important;visibility: visible !important;"></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/6f8a54c84795511127e7342017ceb220.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/fc6d02220ba84213b9fe732976ebd84a.png" data-type="png" data-w="678" style=""></p> <p><br></p> <p><span style="font-size: 18px;">在一家公司里,有三个程序员,他们的名字分别是小A、小B、小C:</span></p> <p><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.40664556962025317" data-s="300,640" src="/upload/10d9ab9a9ac087a27f9f9f7b8eb6a701.png" data-type="png" data-w="632" style=""></p> <p><br></p> <p><span style="font-size: 18px;">有一天,公司新来的产品经理有一个新需求,但她不知道这个需求应该由谁来负责。于是,她首先找到了小A:</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.644542772861357" data-s="300,640" src="/upload/5f01b2732e9bfee89bc0a8735369e887.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.644542772861357" data-s="300,640" src="/upload/37cb35fe637c85679fba5eb367d75bce.png" data-type="png" data-w="678" style=""></p> <p><br></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;">于是,产品经理又找到了小B:</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.644542772861357" data-s="300,640" src="/upload/7bce6c2d449618d4833a8dc13d8776ef.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.644542772861357" data-s="300,640" src="/upload/5b1108c02027d280a3e837e1dcaa410a.png" data-type="png" data-w="678" style=""></p> <p><br></p> <p><span style="font-size: 18px;">于是,产品经理又找到了小C:</span></p> <p><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.644542772861357" data-s="300,640" src="/upload/c4629bd001011b51b7105cc8b5e2fd7d.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.644542772861357" data-s="300,640" src="/upload/aa5b5357d6e3969bc65490490b3a0c0b.png" data-type="png" data-w="678" style=""></p> <p><br></p> <p><span style="font-size: 18px;">像这样,一个任务从小A转移到小B,从小B转移到小C,再由小C最终处理,形成了一个完整的任务处理链条:</span><br></p> <p><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.3477051460361613" data-s="300,640" src="/upload/307031442852aa17b6a0f35668fc58db.png" data-type="png" data-w="719" style=""></p> <p><br></p> <p><span style="font-size: 18px;">在上面这个链条当中,包含着不同的任务处理者。面对一个新任务,每个任务处理者需要判断自己能否处理该任务,如果能处理,则处理并返回;如果不能处理,则转交给下一个任务处理者,直到某一个任务处理者最终完成处理。这就是<strong>职责链模式</strong>的核心思想。</span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/c0d41d72e1c600ac6bcfb90171dc819e.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.24191461836998707" data-s="300,640" src="/upload/b8871dce7f8cab66c7ac6a6d2c842202.png" data-type="png" data-w="773" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/25d9d5951cc95a5aed40440acf295977.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5737463126843658" data-s="300,640" src="/upload/ce4925600b6d5e89bc5705c4cde5dcda.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/31e9e97f427d314e88c8af690d25034a.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.24191461836998707" data-s="300,640" src="/upload/9b8a048f2c5f47bd76ed1fa1fcd9e2b8.png" data-type="png" data-w="773" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5664233576642336" data-s="300,640" src="/upload/225df6659578dbeb311e011ee3354f3a.png" data-type="png" data-w="685" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.27877237851662406" data-s="300,640" src="/upload/97ca65bdc5e65e632b02bf42757c1afa.png" data-type="png" data-w="782" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/804dd0264d7c8769d8565e4a4dfb13a4.png" data-type="png" data-w="678" style=""><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/433d344e724ebb7a50a895608a83b354.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img data-ratio="0.3810623556581986" src="/upload/4c12d6b072a61604746114df2f8c84e4.jpg" data-type="jpeg" data-w="433" style="width: 578px;height: 220px;"></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/cce2782b167577a2a358596d131d28d4.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/557062d4c8d018c0e91b59bfc18778f1.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;padding: 0.5em;background: rgb(240, 240, 240);color: rgb(68, 68, 68);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">abstract</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">public</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">class</span>&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">Handler</span>&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">protected</span>&nbsp;Handler&nbsp;successor;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">public</span>&nbsp;<span style="color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">void</span>&nbsp;<span style="line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">setSuccessor</span>(<span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">Handler&nbsp;successor</span>)&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">this</span>.successor&nbsp;=&nbsp;successor;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">abstract</span>&nbsp;String&nbsp;<span style="line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">handleRequest</span>(<span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String&nbsp;msg</span>)</span>;<br>}<br></code></pre> </section> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">从上面这个抽象类可以看出,每一个Handler对象都包含着一个successor成员,指向它的下一个任务处理者,就像链表节点的next指针一样。</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/e5487bf290f08f8060bc3a915773c3c4.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;padding: 0.5em;background: rgb(240, 240, 240);color: rgb(68, 68, 68);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">public</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">class</span>&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">HandlerA</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">extends</span>&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">Handler</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(31, 113, 153);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">handleRequest</span><span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">(String&nbsp;msg)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">if</span>(msg.contains(<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">"a"</span>)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg&nbsp;=&nbsp;msg.replace(<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">'a'</span>,&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">'*'</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">else</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">if</span>(<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">this</span>.successor&nbsp;!=&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">null</span>){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg&nbsp;=&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">this</span>.successor.handleRequest(msg);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">return</span>&nbsp;msg;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br><span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">public</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">class</span>&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">HandlerB</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">extends</span>&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">Handler</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(31, 113, 153);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">handleRequest</span><span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">(String&nbsp;msg)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">if</span>(msg.contains(<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">"b"</span>)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg&nbsp;=&nbsp;msg.replace(<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">'b'</span>,&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">'*'</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">else</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">if</span>(<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">this</span>.successor&nbsp;!=&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">null</span>){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg&nbsp;=&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">this</span>.successor.handleRequest(msg);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">return</span>&nbsp;msg;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br><span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">public</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">class</span>&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">HandlerC</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">extends</span>&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">Handler</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(31, 113, 153);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">handleRequest</span><span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">(String&nbsp;msg)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">if</span>(msg.contains(<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">"c"</span>)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg&nbsp;=&nbsp;msg.replace(<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">'c'</span>,&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">'*'</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">else</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">if</span>(<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">this</span>.successor&nbsp;!=&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">null</span>){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg&nbsp;=&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">this</span>.successor.handleRequest(msg);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">return</span>&nbsp;msg;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></code></pre> </section> <p style="text-align: left;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">在这三个Handler实现类中,做了相似的判断:</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">如果传入的消息字符串包含某个字母,则把对应的字母替换成*。一旦某个Handler替换了自己所负责的字母,就直接结束整个链路;如果没有自己所负责的字母,则指定下一个Handler继续处理。</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/c01005c3709bdeb95b392d1d3a65195d.png" data-type="png" data-w="678" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;"></span><br></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;padding: 0.5em;background: rgb(240, 240, 240);color: rgb(68, 68, 68);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">public</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">class</span>&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">Client</span>&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">public</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">static</span>&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">void</span>&nbsp;<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">main</span>(<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">String[]&nbsp;args</span>)&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handler&nbsp;handlerA&nbsp;=&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">new</span>&nbsp;HandlerA();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handler&nbsp;handlerB&nbsp;=&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">new</span>&nbsp;HandlerB();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handler&nbsp;handlerC&nbsp;=&nbsp;<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">new</span>&nbsp;HandlerC();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handlerA.setSuccessor(handlerB);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handlerB.setSuccessor(handlerC);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">out</span>.println(handlerA.handleRequest(<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">"apple"</span>));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">out</span>.println(handlerA.handleRequest(<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">"bicycle"</span>));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.<span style="font-size: inherit;color: inherit;line-height: inherit;font-weight: bold;overflow-wrap: inherit !important;word-break: inherit !important;">out</span>.println(handlerA.handleRequest(<span style="font-size: inherit;line-height: inherit;color: rgb(136, 0, 0);overflow-wrap: inherit !important;word-break: inherit !important;">"color"</span>));<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></code></pre> </section> <p style="text-align: left;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">在客户端代码中,可以灵活设置整个链路和处理者的次序,然后直接调用第一个处理者的handleRequest方法,就相当于启动了整个链路。</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/d4919a5f69576a53c7aa22f9783a0167.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/6c2d3a950be911ad36e036e42f9c1e02.png" data-type="png" data-w="678" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/51f073b3c99e2749a81af941793a45b.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/7185bd4b797ce009ae3dac91b7d41438.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/d22e4e69d832372635734442adc10f1c.png" data-type="png" data-w="678" style=""><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/b6462651ad2dbc94699d2fc95acdebca.png" data-type="png" data-w="678" style=""></p> <p style="text-align: left;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">做过Web开发的小伙伴都知道,当客户端对Web应用发出HTTP请求的时候,会首先经过Tomcat容器的一层层<strong>过滤器(Filter)</strong>,过滤器会针对请求的访问权限、参数合法性等方面进行验证和过滤。</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">这一层一层过滤器的实现,就使用了职责链模式。</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/fbc6ec474bcfeeb2013caf206eb21759.png" data-type="png" data-w="678" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;"></span><br></p> <p style="text-align: left;"><span style="font-size: 18px;">熟悉SpringMVC框架源码的小伙伴应该都知道,客户端的HTTP请求到了Web应用之后,会被SpringMVC框架的<strong>DispatcherServlet</strong>类进行分发,分发给Controller层的具体方法。</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">在进入Controller层的业务逻辑之前,以及执行完业务逻辑之后,该请求都会经过一系列的<strong>拦截器(Interceptor)</strong>。这一系列拦截器的处理流程,也同样是职责链模式的实现。<br></span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.563953488372093" data-s="300,640" src="/upload/ddef8c04d460686fe19c15dc34006782.png" data-type="png" data-w="688" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;"></span><br></p> <p style="white-space: normal;line-height: 28.4444px;text-align: center;"><span style="background-color: rgb(255, 255, 255);font-size: 18px;letter-spacing: 0.544px;">—————END—————</span><br></p> <p style="text-align: center;"><br></p> <p style="white-space: normal;line-height: 28.4444px;text-align: center;"><br></p> <p style="letter-spacing: 0.544px;font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;widows: 1;line-height: 25.6px;text-align: center;"><span style="font-size: 18px;line-height: 28.8px;">喜欢本文的朋友,欢迎关注公众号&nbsp;</span><span style="font-size: 18px;line-height: 28.8px;color: rgb(255, 76, 0);"><strong>程序员小灰</strong></span><span style="font-size: 18px;line-height: 28.8px;">,收看更多精彩内容</span></p> <p style="text-align: center;"><img data-copyright="0" data-ratio="1" data-s="300,640" data-type="jpeg" data-w="344" src="/upload/37f513ecb7627cdbb355876dab88096.jpg" style="font-family: -apple-system-font, system-ui, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;box-sizing: border-box !important;visibility: visible !important;width: 333px !important;"></p> <section powered-by="xiumi.us"> <section> <section> <pre style="font-size: inherit;color: inherit;line-height: inherit;"> <section data-tools="135编辑器" data-id="94250" style="letter-spacing: 0.544px;white-space: normal;border-width: 0px;border-style: none;border-color: initial;"> <section data-tools="135编辑器" data-id="91842" style="border-width: 0px;border-style: none;border-color: initial;"> <section style="text-align: right;width: auto;"> <section style="display: inline-block;clear: both;"> <section data-brushtype="text" style="padding: 18px 15px 20px 10px;color: rgb(86, 146, 214);text-align: center;letter-spacing: 1.5px;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/Pn4Sm0RsAuhpplm16ibb8iaib7RoGQ5iaHEdy66AHd7QqL7A2s5icSBE0aw4iaKOKPnXGYxQPhG7VMpbbYV6VJprSh7w/640?wx_fmt=png&quot;);background-size: 100% 100%;background-repeat: no-repeat;"> <section style="display: flex;justify-content: center;align-items: center;"> <section style="margin-left: 2px;font-size: 16px;word-spacing: 2px;width: 20px;"> <img data-ratio="0.8936170212765957" data-type="png" data-w="47" src="/upload/737696b8734b6f688ae95660c4411917.png" style="margin-bottom: -6px;box-sizing: border-box !important;visibility: visible !important;width: 20px !important;"> </section> <section data-brushtype="text" style="word-spacing: 2px;font-size: 14px;color: rgb(51, 51, 51);"> <span style="font-family: 楷体, 楷体_GB2312, SimKai;">点个[在看],是对小灰最大的支持!</span> </section> <p><br></p> </section> </section> </section> </section> </section> </section></pre> </section> </section> </section>

软件测试系统学习流程和常见面试题

作者:测试人生路

在学习软件测试的时候你是否会感觉到不知从何下手? 今天教导你们软件测试学习的系统流程和面试常见的问题。 ## 学习流程 ## 一、必备技能 1. 编程基础,能看懂前端页面,掌握一门语言:php/python/java等 2.数据库知识,建议准备好sql语言,能掌握高级查询使用基本可以应对了。 3.软件测试理论,这个大家都不陌生,也是必考的了,应该可以轻松应付。要注意准备下web和app测试和性能测试这块,现在做web、app和微信小程序的公司好多。 4.根据公司具体的职位要求可以准备的有linux的命令,CMMI的基础知识,TCP/IP的基础知识等。 ## 二、学习流程 1.功能测试学习 功能是软件测试最基础最本质的工作,就和地基一样,所以功能测试基础一定要打好。在了解基础的功能测试的时候可以看一看《软件测试的艺术》这本书对才学习软件测试的人真的很有用。 2.接口测试 接口是前后端数据交互的通道,接口测试也是测试中很重要的一部分,接口测试的学习包括测试工具的学习:apipost、jmeter、loadrunner等。通信协议,http协议也需要重点学习,推荐看一下《图解网络-小林coding》,可以帮助我们基础了解互联网通信,前端如何传递数据到后端。 3.性能测试 性能测试一般是接口测试的一部分,通过接口对服务器进行的测试,查看服务器各种数值,性能测试包括很多分类测试注重点也不一样,如:压力测试、负载测试、稳定姓测试等。 4.自动化测试 自动化测试可以分为:接口自动化测试和ui自动化测试。 学习自动化测试,需要掌握一门语言,php/python/java等。接口自动化测试要掌握requests框架,ui自动化测试需要掌握:web端需要掌握selenium、app端需要掌握appium。 5.Linux操作系统 学习Linux操作系统是为了自己部署测试环境,方便于自己测试。学习好Linux shell语句也很重要,学习书籍可以看看《鸟哥的linux私房菜》。 6.前端、后端和数据库语言 能够看懂前端页面,知道前端页面是如何编写出来的,ajax传值的方法,后端会一门后端语言,php/python/java等。会数据库基本的sql语句的编写。 常见面试题 一、功能测试 1.说说你以前公司的测试流程。必答题。主要结合自己的项目经验相信讲一个自己做过的项目,从立项到测试结束,当然侧重测试和自己所做的内容。这里面试官一般都会根据你说的再提问。 2.功能测试主要有那些测试方法? 等价类划分、边界值、因果图划分、正交、场景、随机、错误推断、测试大纲 A:等价类划分法: : 1:有效等价类: 2:无效等价类: 案例:比如一个登陆输入框,规定只能输入中文,同时长度为6-10, 通过等价类设计测试用例: 测试用例中重要的三步: 输入 操作 预计结果 如果与预期结果不符合就是bug 有效等价类: 输入:输入长度为6的中文,输入的为王小明,这就是有效等价类 无效等价类: 1: 输入长度为4的中文,输入位小名,点击登录,预计结果长度不符合要求 2: 输入长度为6,但是是英文的,点击登录,预计结果 请输入中文 3: 输入长度为4,而且不是中文的,是数字,1234,点击登录,预计结果请输入中文并且长度为6-10位 4:输入长度为12而且不是中文的,比如qwertyuiopas,点击登录,预计结果请输入中文并且长度为6-10位 B:边界值法: 应用场景:边界值往往和等价类划分法一起使用,形成一套更为完善的测试方案,找到有效数据和无效数据的分界点, 注解边界值一般和有效等价类划分法配合使用: 案例:比如一个登陆输入框,规定只能输入中文,同时长度为6-10, 上面输入框的边界的:如果固定大于等于6,并且小于等于10, 那左边界就是 5和 6 右边界是:10 和 11 测试用例: 1:输入的为王小明,这就是有效等价类和边界值的结合使用 2:输入小名,这就是边界值为5,同时有效等价类 3:输入欧阳致远家,这就是边界值10,同时等价类有效 4:输入欧阳致远啦啦,这就是边界值为11,同时有效等价类 C:因果图及判定表法: 应用场景:在一个界面中有多个控件,如果控件之间有组合关系或者限制关系,不同的控件组合会产生不同的输入结果,为了弄清楚不同的输入组合会产生咋样的输出结果,可以使用因果图及判定表法: 判断是儿童还是青年还是成年人: 条件1:年龄 age 条件2:身高height 条件3:体重weight 输入年龄5,体重80公斤,身高170,查无此人 输入提高80,身高170,输入年龄20,成年人 输入年龄5,体重30,身高60,小孩 D:正交表: 应用场景:在一个界面中有多个控件,每个控件有多个取值,测试时考虑不同的控件不同取值之间的多种组合,但组合数量巨大(>20种,20种以下一般考虑判定表因果图),没有必要全部测试,如何从所有的组合中挑选最少、最优的组合进行测试,可以使用正交排列法。 正交表的测试思想特点: 1)使用每个控件的每个取值参与组合的次数是基本相等的(均匀的) 2)在所有的组合数据中,选取数据时,应该均匀的选取,而不能从局部选取。 3)如果时间允许,尽可能的多测一些组合 正交表:主要针对一个输入框里面可能有多个值,而且数量巨大 年龄 体重 省 市 县 比如:输入年龄 18,体重45,山西 大同 阳高 E:测试大纲法 适用场合:程序包含多个窗口,每个窗口中又有多个功能,这些功能之间又有一定的联系。为了梳理清楚窗口之间以及窗口不同功能之间的联系,使用测试大纲法。 F:场景法 适用场合:大多数的业务比较复杂的软件系统都适合使用场景法(便于将各个功能点串起来,便于形成完整的业务感觉)是一种基于软件业务的测试方法,把自己当成最终用户,尽可能的模拟用户在使用此软件的操作 案例: 场景一:比如买东西:输入袜子,点击查询,出现列表,点击七匹狼,点击进入详情,点击加入购物车,点击去购物车结算,点击收获地址,点击支付,支付成功 场景二:比如买东西:输入袜子,点击查询,出现列表,点击七匹狼,点击进入详情,点击加入购物车,点击去购物车结算,点击收获地址,点击取消支付 G: 错误推断法 基于经验和直觉推测程序中所有可能存在的各种错误 , 从而有针对性的设 计测试用例的方法 在进行灰盒测试的时候经常用到此方法 H:随机测试 随意测试,不考虑任何用例和需求,完全站在一个用户或者的角度对产品进行使用。 适用场景: 1) 所有之前设定的用例已经 执行完毕 2)海量的条件组合无法一遍 历的时候 ## 二.性能测试和接口测试 1.一般使用什么性能测试和接口测试工具 性能测试:jmeter、loadrunner 接口测试:apipost、postman [ApiPost - 可直接生成文档的API调试、管理工具](https://www.apipost.cn/?dt=20201123) 2.如何进行接口测试,接口测试需要注意那些方面 通过apipost、postman等工具,根据接口文档,输入请求方法get、post等方法,输入url,输入需要传递的参数,然后查看响应是否符合接口文档所显示的。需要注意json响应中的参数的类型等 3.性能测试具体指什么 指验证软件的性能可以满足系统规格给定的指定要求的性能指标。性能测试是一个比较大的范围,可以进一步衍生出负载测试、强度测试、压力测试、稳定性测试。通过自动化测试工具模拟多种正常、异常、峰值条件,对系统各项性能指标测试 4.什么是压力测试 压力测试方法测试系统在一定饱和状态下,例如cpu、内存在饱和使用情况下,系统能够处理的会话能力,以及系统是否会出现错误。测试出系统所能承受的最大极限。是指系统在极限下的压力情况,系统在什么样的压力下会导致系统得到失效,无法正常运行。100个用户连续访问1小时可以看做是压力测试,连续访问10小时可以认为是负载测试 ## 三.自动化测试 1.自动化测试指什么 ui界面自动化和接口自动化 ui界面自动化:通过代码模拟人对程序进行的操作 接口自动化;通过代码实现大批量接口测试 2.自动化测试一般使用什么工具 web测试:python+selenium+浏览器驱动 app测试:python+appium

怎么能避免写出慢SQL?

作者:微信小助手

<p data-mpa-powered-by="yiban.io"><span style="caret-color: rgb(64, 64, 64);color: rgb(64, 64, 64);font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.12px;text-align: left;text-size-adjust: auto;background-color: rgb(255, 255, 255);font-size: 14px;">码农架构的读者应该注意到上个周末有分享一篇文章:</span><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492745&amp;idx=1&amp;sn=c9caa6056d282c6ce9796f9c33c3189b&amp;chksm=fd63f436ca147d209474bcbb5570235f18f405174af8f02df76762508dd2b61f1d0aa5a8b3a5&amp;scene=21#wechat_redirect" textvalue="一个几乎每个系统必踩的坑儿:访问数据库超时" data-itemshowtype="0" tab="innerlink" style="caret-color: rgb(64, 64, 64);font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.12px;text-align: left;text-size-adjust: auto;background-color: rgb(255, 255, 255);color: rgb(121, 123, 170);font-size: 14px;" data-linktype="2"><span style="color: rgb(121, 123, 170);font-size: 14px;"><strong><span style="color: rgb(121, 123, 170);caret-color: rgb(64, 64, 64);font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.12px;text-align: left;text-size-adjust: auto;background-color: rgb(255, 255, 255);">一个几乎每个系统必踩的坑儿:访问数据库超时</span></strong></span></a><span style="caret-color: rgb(64, 64, 64);color: rgb(64, 64, 64);font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.12px;text-align: left;text-size-adjust: auto;background-color: rgb(255, 255, 255);font-size: 14px;">,最后对于怎么避免写出慢SQL没有过多赘述,但实际上这个问题我们经常遇到。我们不能等着系统上线,慢 SQL 吃光数据库资源之后,再找出慢 SQL 来改进,那样就晚了。那么,怎样才能在开发阶段尽量避免写出慢 SQL 呢?</span><span style="background-color: rgb(255, 255, 255);color: rgb(47, 47, 47);font-family: Georgia, &quot;Times New Roman&quot;, Times, &quot;Songti SC&quot;, serif;font-size: 14px;font-weight: 700;letter-spacing: 0.544px;text-align: start;caret-color: rgb(64, 64, 64);"></span></p> <p><span style="caret-color: rgb(64, 64, 64);color: rgb(64, 64, 64);font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.12px;text-align: left;text-size-adjust: auto;background-color: rgb(255, 255, 255);font-size: 14px;"><br></span></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;" data-mid="" mpa-from-tpl="t"> <section style="width: 30px;height: 30px;background: rgb(255, 213, 93);border-width: 1px;border-style: solid;border-color: rgb(51, 51, 51);box-shadow: rgb(51, 51, 51) 3px 3px;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <span style="font-size: 16px;font-family: PingFangSC-Semibold, &quot;PingFang SC&quot;;font-weight: bold;line-height: 22px;letter-spacing: 1px;-webkit-text-stroke: 1px rgb(51, 51, 51);" data-mid="">01</span> </section> <section style="padding-left: 7px;margin-bottom: -3.1px;border-bottom: 1px solid black;display: flex;justify-content: center;align-items: flex-end;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, &quot;PingFang SC&quot;;font-weight: bold;line-height: 22px;" data-mid="">定量认识MySQL</p> </section> </section> </section> </section> </section> <p><span style="caret-color: rgb(64, 64, 64);color: rgb(64, 64, 64);font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.12px;text-align: left;text-size-adjust: auto;background-color: rgb(255, 255, 255);font-size: 14px;"></span><br></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;">一台 MySQL 数据库,大致处理能力的极限是,每秒一万条左右的简单 SQL,这里的“简单 SQL”,指的是类似于主键查询这种不需要遍历很多条记录的 SQL。根据服务器的配置高低,可能低端的服务器只能达到每秒几千条,高端的服务器可以达到每秒钟几万条,所以这里给出的一万 TPS 是中位数的经验值。考虑到正常的系统不可能只有简单 SQL,所以实际的 TPS 还要打很多折扣。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;">我的经验数据,一般一台 MySQL 服务器,平均每秒钟执行的 SQL 数量在几百左右,就已经是非常繁忙了,即使看起来 CPU 利用率和磁盘繁忙程度没那么高,你也需要考虑给数据库“减负”了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;">另外一个重要的定量指标是,到底多慢的 SQL 才算慢 SQL。这里面这个“慢”,衡量的单位本来是执行时长,但是时长这个东西,我们在编写 SQL 的时候并不好去衡量。<strong>那我们可以用执行 SQL 查询时,需要遍历的数据行数替代时间作为衡量标准,因为查询的执行时长基本上是和遍历的数据行数正相关的</strong>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;">你在编写一条查询语句的时候,可以依据你要查询数据表的数据总量,估算一下这条查询大致需要遍历多少行数据:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 557.438px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;list-style-type: square;"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 如果遍历行数在百万以内的,只要不是每秒钟都要执行几十上百次的频繁查询,可以认为是安全的。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 遍历数据行数在几百万的,查询时间最少也要几秒钟,你就要仔细考虑有没有优化的办法。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 遍历行数达到千万量级和以上的,我只能告诉你,这种查询就不应该出现在你的系统中。当然我们这里说的都是在线交易系统,离线分析类系统另说。 </section></li> </ul> <p style="padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;margin-bottom: 10px;">遍历行数在千万左右,是 MySQL 查询的一个坎儿。MySQL 中单个表数据量,也要尽量控制在一千万条以下,最多不要超过二三千万这个量级。原因也很好理解,对一个千万级别的表执行查询,加上几个 WHERE 条件过滤一下,符合条件的数据最多可能在几十万或者百万量级,这还可以接受。但如果再和其他的表做一个联合查询,遍历的数据量很可能就超过千万级别了。所以,每个表的数据量最好小于千万级别。<span style="letter-spacing: 0px;"></span></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;" data-mid="" mpa-from-tpl="t"> <section style="width: 30px;height: 30px;background: rgb(255, 213, 93);border-width: 1px;border-style: solid;border-color: rgb(51, 51, 51);box-shadow: rgb(51, 51, 51) 3px 3px;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <span style="font-size: 16px;font-family: PingFangSC-Semibold, &quot;PingFang SC&quot;;font-weight: bold;line-height: 22px;letter-spacing: 1px;-webkit-text-stroke: 1px rgb(51, 51, 51);" data-mid="">02</span> </section> <section style="padding-left: 7px;margin-bottom: -3.1px;border-bottom: 1px solid black;display: flex;justify-content: center;align-items: flex-end;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, &quot;PingFang SC&quot;;font-weight: bold;line-height: 22px;" data-mid="">使用索引避免全表扫描</p> </section> </section> </section> </section> </section> <section style="margin-bottom: 5px;padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;"> <span style="letter-spacing: 0px;"></span> </section> <section style="margin-bottom: 5px;padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;"> <span style="letter-spacing: 0px;">大多数情况下,我们编写的查询语句,都应该使用索引,避免去遍历整张表,也就是通常说的,避免全表扫描。</span> <span style="letter-spacing: 0px;">你在每次开发新功能,需要给数据库增加一个新的查询时,都要评估一下,是不是有索引可以支撑新的查询语句,如果有必要的话,需要新建索引来支持新增的查询。</span> </section> <p style="padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;margin-bottom: 10px;"><span style="letter-spacing: 0px;">增加索引付出的代价是,会降低数据插入、删除和更新的性能。</span><span style="letter-spacing: 0px;">这个也很好理解,增加了索引,在数据变化的时候,不仅要变更数据表里的数据,还要去变更每个索引。</span><span style="letter-spacing: 0px;">所以,对于更新频繁并且对更新性能要求较高的表,可以尽量少建索引。</span><span style="letter-spacing: 0px;">而对于查询较多更新较少的表,可以根据查询的业务逻辑,适当多建一些索引。</span></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;" data-mid="" mpa-from-tpl="t"> <section style="width: 30px;height: 30px;background: rgb(255, 213, 93);border-width: 1px;border-style: solid;border-color: rgb(51, 51, 51);box-shadow: rgb(51, 51, 51) 3px 3px;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <span style="font-size: 16px;font-family: PingFangSC-Semibold, &quot;PingFang SC&quot;;font-weight: bold;line-height: 22px;letter-spacing: 1px;-webkit-text-stroke: 1px rgb(51, 51, 51);" data-mid="">03</span> </section> <section style="padding-left: 7px;margin-bottom: -3.1px;border-bottom: 1px solid black;display: flex;justify-content: center;align-items: flex-end;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, &quot;PingFang SC&quot;;font-weight: bold;line-height: 22px;" data-mid="">分析SQL执行计划<span style="letter-spacing: 0px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;"></span></p> </section> </section> </section> </section> </section> <p style="margin-bottom: 5px;padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;margin-top: 10px;"><span style="letter-spacing: 0px;">在 MySQL 中使用执行计划也非常简单,只要在你的 SQL 语句前面加上 EXPLAIN 关键字,然后执行这个查询语句就可以了。</span></p> <section style="margin-bottom: 5px;padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;"> <span style="letter-spacing: 0px;">比如有一个用户表,包含用户 ID、姓名、部门编号和状态这几个字段:</span> </section> <p><img data-ratio="0.27933450087565675" src="/upload/927742bc83a9bdc9f7b9887a00a8612a.png" data-type="png" data-w="1142" data-backw="558" data-backh="156" style="margin-top: 10px;margin-right: auto;margin-left: auto;white-space: normal;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;display: block;box-shadow: rgba(170, 170, 170, 0.48) 0px 0px 6px 0px;border-radius: 4px;width: 100%;height: auto;"></p> <section style="margin-bottom: 5px;padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;"> <span style="letter-spacing: 0px;">我们希望查询某个二级部门下的所有人,查询条件就是,部门代号以 00028 开头的所有人。</span> <span style="letter-spacing: 0px;">下面这两个 SQL,他们的查询结果是一样的,都满足要求,但是,哪个查询性能更好呢?</span> <span style="letter-spacing: 0px;"></span> </section> <section style="margin-bottom: 5px;padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;"> <span style="letter-spacing: 0px;">我们分别查看一下这两个 SQL 的执行计划:</span> </section> <p><img data-ratio="0.30472854640980734" src="/upload/952a80b25af1b9ce3b7fe26ed87b27a1.png" data-type="png" data-w="1142" data-backw="558" data-backh="170" style="margin-top: 10px;margin-right: auto;margin-left: auto;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;display: block;box-shadow: rgba(170, 170, 170, 0.48) 0px 0px 6px 0px;border-radius: 4px;width: 100%;height: auto;"></p> <section style="margin-bottom: 5px;padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;"> <strong style="letter-spacing: 0px;">row 列</strong> <span style="letter-spacing: 0px;">:<br><span style="font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;color: rgb(1, 1, 1);">MySQL 预估执行这个 SQL 可能会遍历的数据行数。</span><span style="font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;color: rgb(1, 1, 1);">第一个 SQL 遍历了四千多行,这就是整个 User 表的数据条数;</span><span style="font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;color: rgb(1, 1, 1);">第二个 SQL 只有 8 行,这 8 行其实就是符合条件的 8 条记录。</span><span style="font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;color: rgb(1, 1, 1);">显然第二个 SQL 查询性能要远远好于第一个 SQL。</span></span> <span style="color: rgb(1, 1, 1);letter-spacing: 0px;"></span> </section> <p style="padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;margin-bottom: 10px;"><span style="letter-spacing: 0px;"><strong style="color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;">type 列</strong><span style="color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;">:<br></span></span><span style="color: rgb(1, 1, 1);letter-spacing: 0px;"><span style="color: rgb(1, 1, 1);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;">表示这个查询的访问类型。</span><span style="color: rgb(1, 1, 1);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;">ALL 代表全表扫描,这是最差的情况。</span><span style="color: rgb(1, 1, 1);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;">range 代表使用了索引,在索引中进行范围查找,因为第二个 SQL 语句的 WHERE 中有一个 LIKE 的查询条件。</span><span style="color: rgb(1, 1, 1);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;">如果直接命中索引,type 这一列显示的是 index。</span><span style="color: rgb(1, 1, 1);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;">如果使用了索引,可以在 key 这一列中看到,实际上使用了哪个索引。</span></span></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section style="display: flex;justify-content: flex-start;align-items: center;" data-mid="" mpa-from-tpl="t"> <section style="display: flex;justify-content: center;align-items: flex-end;" data-mid="" mpa-from-tpl="t"> <section style="width: 30px;height: 30px;background: rgb(255, 213, 93);border-width: 1px;border-style: solid;border-color: rgb(51, 51, 51);box-shadow: rgb(51, 51, 51) 3px 3px;display: flex;justify-content: center;align-items: center;" data-mid="" mpa-from-tpl="t"> <span style="font-size: 16px;font-family: PingFangSC-Semibold, &quot;PingFang SC&quot;;font-weight: bold;line-height: 22px;letter-spacing: 1px;-webkit-text-stroke: 1px rgb(51, 51, 51);" data-mid="">04<br></span> </section> <section style="padding-left: 7px;margin-bottom: -3.1px;border-bottom: 1px solid black;display: flex;justify-content: center;align-items: flex-end;flex-direction: column;" data-mid="" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="font-size: 16px;font-family: PingFangSC-Semibold, &quot;PingFang SC&quot;;font-weight: bold;line-height: 22px;text-align: center;" data-mid="">总结<span style="letter-spacing: 0px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;"></span></p> </section> </section> </section> </section> </section> <p style="margin-bottom: 5px;padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;white-space: normal;line-height: 26px;margin-top: 10px;"><span style="color: rgb(1, 1, 1);letter-spacing: 0px;"><span style="color: rgb(1, 1, 1);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;text-align: left;"></span></span><span style="letter-spacing: 0px;">在开发阶段,衡量一个 SQL 查询语句查询性能的手段是,估计执行 SQL 时需要遍历的数据行数。</span><span style="letter-spacing: 0px;">遍历行数在百万以内,可以认为是安全的 SQL,百万到千万这个量级则需要仔细评估和优化,千万级别以上则是非常危险的。</span><span style="letter-spacing: 0px;">为了减少慢 SQL 的可能性,每个数据表的行数最好控制在千万以内。</span><span style="letter-spacing: 0px;">索引可以显著减少查询遍历数据的数量,所以提升 SQL 查询性能最有效的方式就是,让查询尽可能多的命中索引,但索引也是一把双刃剑,它在提升查询性能的同时,也会降低数据更新的性能。</span><span style="letter-spacing: 0px;">对于复杂的查询,最好使用 SQL 执行计划,事先对查询做一个分析。</span><span style="letter-spacing: 0px;">在 SQL 执行计划的结果中,可以看到查询预估的遍历行数,命中了哪些索引。</span><span style="letter-spacing: 0px;">执行计划也可以很好地帮助你优化你的查询语句。</span></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="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, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 14px;padding: 10px;"> <section style="font-size: 15px;display: block;text-align: center;color: rgb(153, 153, 153);border-bottom: 1px solid rgb(238, 238, 238);margin-top: 5px;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="2247492793_1" data-recommend-article-time="1606139243" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxF38FnraZYorHUvdVEce8eDS0cZynibtmENlsY0yveCZauLf0YEJeHHBjf4GibIM39pv6HTIBiafJevw/0?wx_fmt=jpeg" data-recommend-article-title="如何防止Redis脑裂导致数据丢失?" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492793&amp;idx=1&amp;sn=2dcc268eb5ede00699a4a2fe99b705e4&amp;chksm=fd63f406ca147d104b9c6a806c9c1242acbdbadd3d5028a0b268aac83aeadbc731d65653bee7#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492793&amp;idx=1&amp;sn=2dcc268eb5ede00699a4a2fe99b705e4&amp;chksm=fd63f406ca147d104b9c6a806c9c1242acbdbadd3d5028a0b268aac83aeadbc731d65653bee7&amp;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="">如何防止Redis脑裂导致数据丢失?</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="8" data-recommend-article-id="2247492745_1" data-recommend-article-time="1606037700" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxFKicXtS14MNY4pEDfLrqjlrGRR9lvLiaKYMbWW1N7NV85JWfzmSicRrCQCAPpfZIVfAcMgxMlCwDTPw/0?wx_fmt=jpeg" data-recommend-article-title="一个几乎每个系统必踩的坑儿:访问数据库超时" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492745&amp;idx=1&amp;sn=c9caa6056d282c6ce9796f9c33c3189b&amp;chksm=fd63f436ca147d209474bcbb5570235f18f405174af8f02df76762508dd2b61f1d0aa5a8b3a5#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492745&amp;idx=1&amp;sn=c9caa6056d282c6ce9796f9c33c3189b&amp;chksm=fd63f436ca147d209474bcbb5570235f18f405174af8f02df76762508dd2b61f1d0aa5a8b3a5&amp;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="">一个几乎每个系统必踩的坑儿:访问数据库超时</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="8" data-recommend-article-id="2247492516_1" data-recommend-article-time="1605616200" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxFUu0wDzlNj5W7b87Xs9h7FwJ5r5ISKiaIKvtIT4SrGvdE3PkGtgpic2raoo6XgazazTe558knwsicCQ/0?wx_fmt=jpeg" data-recommend-article-title="雪花算法的实现思想" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492516&amp;idx=1&amp;sn=14c9f8663a352b59b01a7b53c74d705a&amp;chksm=fd63f31bca147a0d71935ca024a8b733b03dd4a17b6460234adfa5e1fcde9edd01dc0f765846#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492516&amp;idx=1&amp;sn=14c9f8663a352b59b01a7b53c74d705a&amp;chksm=fd63f31bca147a0d71935ca024a8b733b03dd4a17b6460234adfa5e1fcde9edd01dc0f765846&amp;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="">雪花算法的实现思想</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="8" data-recommend-article-id="2247492463_1" data-recommend-article-time="1605519000" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxETqbZ8G18BawJyjPme1N1icjORCFXNTnuWPpQbbicFqXMOzstfNeibs6TZKDPfMRkVFsViaclmCXWu1A/0?wx_fmt=jpeg" data-recommend-article-title="如何保证核心链路稳定性的流控和熔断机制?" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492463&amp;idx=1&amp;sn=7df8b541c7a1a68e572babc9c44b25a1&amp;chksm=fd63f3d0ca147ac6a4be858ce611b9582fc0ce69b3118993c2e3490bd0a53cd3f9d8599ff005#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492463&amp;idx=1&amp;sn=7df8b541c7a1a68e572babc9c44b25a1&amp;chksm=fd63f3d0ca147ac6a4be858ce611b9582fc0ce69b3118993c2e3490bd0a53cd3f9d8599ff005&amp;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="">如何保证核心链路稳定性的流控和熔断机制?</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="8" data-recommend-article-id="2247492745_3" data-recommend-article-time="1606037700" data-recommend-article-cover="http://mmbiz.qpic.cn/sz_mmbiz_jpg/d7YzaYDnrxFKicXtS14MNY4pEDfLrqjlrfS6GgB6ToEISGcsnibW5gCLzxr6A4vItNCfudvh6iarLIHcp1qwL2AVQ/0?wx_fmt=jpeg" data-recommend-article-title="API和SDK有什么区别?" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492745&amp;idx=3&amp;sn=aad52536cd783d82722ac15b6c956ed3&amp;chksm=fd63f436ca147d20210d11094b207839e5d379e67ac8a23a007d20cb5b7d319bd0cbe77846ea#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzU3OTc1MDM1Mg==&amp;mid=2247492745&amp;idx=3&amp;sn=aad52536cd783d82722ac15b6c956ed3&amp;chksm=fd63f436ca147d20210d11094b207839e5d379e67ac8a23a007d20cb5b7d319bd0cbe77846ea&amp;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;border-bottom:none !important;" data-mid=""> <p style="white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width: 100%;" data-mid="">API和SDK有什么区别?</p> </section></a> </section> </section> </section> </section> <section style="margin-top: 10px;"> <img class="rich_pages js_insertlocalimg" data-ratio="0.21328125" data-s="300,640" src="/upload/62e1c66b7ebe4ae627c388db8f4eef36.png" data-type="png" data-w="1280" data-backw="578" data-backh="123" style="text-align: center;text-indent: 0pt;color: rgb(63, 74, 89);font-family: 微软雅黑;font-size: 11pt;letter-spacing: 0.4pt;width: 100%;height: auto;"> <br> </section>