作者:微信小助手
<p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击蓝色“</span><span style="max-width: 100%;letter-spacing: 0.544px;font-size: 14px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">架构文摘</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">”关注我哟</span></p> <p style="margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">加个“</span><span style="max-width: 100%;color: rgb(0, 128, 255);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">星标</span><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”,每天上午 09:25,干货推送!</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 14px;text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-backh="36" data-backw="578" data-ratio="0.0625" data-s="300,640" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.jpg" data-type="jpeg" data-w="640" style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;" width="100%"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;">作者:</span><span style="color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;">神牛003</span><br></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;">原文:cnblogs.com/wangrudong003/p/10502043.html</span></p> <section style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br> </section> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;line-height: 26px;color: rgb(89, 89, 89);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="letter-spacing: 0.544px;">本篇和大家分享的是 Spring Boot 打包并结合 Shell 脚本命令部署,重点在分享一个shell 程序启动工具,希望能便利工作;</span> <br> </section> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;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;text-align: left;overflow-wrap: break-word !important;"> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> profiles指定不同环境的配置 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> maven-assembly-plugin打发布压缩包 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 分享shenniu_publish.sh程序启动工具 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> linux上使用shenniu_publish.sh启动程序 </section></li> </ul> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;color: rgb(89, 89, 89);line-height: normal;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> </section> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;line-height: 26px;color: rgb(89, 89, 89);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong><span style="max-width: 100%;font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">profiles指定不同环境的配置</span></strong> </section> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;line-height: 26px;color: rgb(89, 89, 89);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 通常一套程序分为了很多个部署环境:开发,测试,uat,线上 等,我们要想对这些环境区分配置文件,可以通过两种方式: </section> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;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;text-align: left;overflow-wrap: break-word !important;"> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 通过application.yml中编码指定 profile.active=uat 方式指定 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 通过mvn中profiles来区分不同环境对应的配置文件夹,人工可以手动在idea勾选生成不同环境的包(推荐) </section></li> </ul> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;line-height: 26px;color: rgb(89, 89, 89);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 这里我们要讲的是第二种,首先在mvn中配置如下内容: </section> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);font-size: 16px;text-align: left;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="padding: 15px 16px 16px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 1 <profiles> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 2 <profile> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 3 <id>node</id> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 4 <properties> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 5 <!--传递给脚本的参数值--> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 6 <activeProfile>node</activeProfile> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 7 <package-name> <span style="max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">${scripts_packageName}</span></package-name> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 8 <boot-main> <span style="max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">${scripts_bootMain}</span></boot-main> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 9 </properties> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">10 <activation> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">11 <activeByDefault> <span style="max-width: 100%;color: rgb(86, 182, 194);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">true</span></activeByDefault> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">12 </activation> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">13 </profile> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">14 <profile> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">15 <id>node1</id> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">16 <properties> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">17 <activeProfile>node1</activeProfile> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">18 <package-name> <span style="max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">${scripts_packageName}</span></package-name> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">19 <boot-main> <span style="max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">${scripts_bootMain}</span></boot-main> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">20 </properties> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">21 </profile> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">22 <profile> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">23 <id>node2</id> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">24 <properties> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">25 <activeProfile>node2</activeProfile> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">26 <package-name> <span style="max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">${scripts_packageName}</span></package-name> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">27 <boot-main> <span style="max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">${scripts_bootMain}</span></boot-main> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">28 </properties> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">29 </profile> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">30 </profiles> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> </section></pre> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;line-height: 26px;color: rgb(89, 89, 89);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 节点粗解: </section> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;line-height: 26px;color: rgb(89, 89, 89);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> id:用来指定不同环境配置文件所在的目录,如下我这里: </section> <section style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.287962962962963" src="/upload/fecf0787a4f1d108be2bf3676c8c83a8.png" data-type="png" data-w="1080" style="margin-right: auto;margin-left: auto;background-color: rgb(238, 237, 235);border-width: 1px;border-style: solid;border-color: rgb(238, 237, 235);background-size: 22px;background-position: center center;background-repeat: no-repeat;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 657px !important;visibility: visible !important;"> </figure> </section> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;line-height: 26px;color: rgb(89, 89, 89);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> properties:该节点中的节点是可作为参数传递给其他配置文件,如我这里的package-name节点值就可以在另外的assembly.xml或者shell脚本文件中通过${package-name}获取到,如下: </section> <section style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.15833333333333333" src="/upload/51f6b4c80065cb2afb8e7c15a10bed54.png" data-type="png" data-w="1080" style="margin-right: auto;margin-left: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"> </figure> </section> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;line-height: 26px;color: rgb(89, 89, 89);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> activeByDefault:指定默认环境配置文件夹 </section> <section style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;font-size: 16px;text-align: left;line-height: 26px;color: rgb(89, 89, 89);font-family: "Helvetica Neue", Helvetica, "H
作者:微信小助手
<p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击蓝色“</span><span style="max-width: 100%;letter-spacing: 0.544px;font-size: 14px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">架构文摘</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">”关注我哟</span></p> <p style="margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">加个“</span><span style="max-width: 100%;color: rgb(0, 128, 255);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">星标</span><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”,每天上午 09:25,干货推送!</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 14px;text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-backh="36" data-backw="578" data-ratio="0.0625" data-s="300,640" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.jpg" data-type="jpeg" data-w="640" style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;" width="100%"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">作者:狂乱的贵公子</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">来源:cnblogs.com/cjsblog/p/14516909.html</span></p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 18px;"><strong style="max-width: 100%;color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">概述</strong></span></p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.4459016393442623" src="/upload/bdd520d7518ed8c43a385bdecb5c2a0e.png" data-type="png" data-w="610" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;overflow-wrap: break-word !important;width: 610px !important;visibility: visible !important;"></p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">如图是一个简化的下单流程,首先是提交订单,然后是支付。支付的话,一般是走支付网关(支付中心),然后支付中心与第三方支付渠道(微信、支付宝、银联)交互,支付成功以后,异步通知支付中心,支付中心更新自身支付订单状态,再通知业务应用,各业务再更新各自订单状态。</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">这个过程中经常可能遇到的问题是掉单,无论是超时未收到回调通知也好,还是程序自身报错也好,总之由于各种各样的原因,没有如期收到通知并正确的处理后续逻辑等等,都会造成用户支付成功了,但是服务端这边订单状态没更新,这个时候有可能产生投诉,或者用户重复支付。</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">由于③⑤造成的掉单称之为外部掉单,由④⑥造成的掉单我们称之为内部掉单</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 18px;"><strong style="max-width: 100%;color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">为了防止掉单,这里可以这样处理:</strong></span></p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">1、支付订单增加一个中间状态“支付中”,当同一个订单去支付的时候,先检查有没有状态为“支付中”的支付流水,当然支付(prepay)的时候要加个锁。支付完成以后更新支付流水状态的时候再讲其改成“支付成功”状态。</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">2、支付中心这边要自己定义一个超时时间(比如:30秒),在此时间范围内如果没有收到支付成功回调,则应调用接口主动查询支付结果,比如10s、20s、30s查一次,如果在最大查询次数内没有查到结果,应做异常处理</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">3、支付中心收到支付结果以后,将结果同步给业务系统,可以发MQ,也可以直接调用,直接调用的话要加重试(比如:SpringBoot Retry)</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">4、无论是支付中心,还是业务应用,在接收支付结果通知时都要考虑接口幂等性,消息只处理一次,其余的忽略</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">5、业务应用也应做超时主动查询支付结果</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">对于上面说的超时主动查询可以在发起支付的时候将这些支付订单放到一张表中,用定时任务去扫</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 18px;"><strong style="max-width: 100%;color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">为了防止订单重复提交,可以这样处理:</strong></span></p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">1、创建订单的时候,用订单信息计算一个哈希值,判断redis中是否有key,有则不允许重复提交,没有则生成一个新key,放到redis中设置个过期时间,然后创建订单。其实就是在一段时间内不可重复相同的操作</p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 18px;"><strong style="max-width: 100%;color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">附上微信支付最佳实践:</strong></span></p> <p style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(80, 97, 109);font-family: Helvetica, Arial, sans-serif;font-size: 15px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.78" src="/upload/553d8a12ef644484b5e917bdacd0675e.png" data-type="png" data-w="750" style="box-sizing: border-box;border-width: 2px;border-style: solid;border-color: rgb(238, 238, 238);border-radius: 6px;overflow-wrap: break-word !important;width: 677px !important;visibility: visible !important;"></p> <section data-mpa-template="t" mpa-from-tpl="t" style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;caret-color: rgb(0, 0, 0);color: rgb(120, 114, 114);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-id="89429" mpa-from-tpl="t" style="max-width: 100%;border-width: 0px;border-style: none;border-color: initial;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("https://mmbiz.qpic.cn/mmbiz_gif/kiaqiahsnxHd4Zt4378tqib1DnnfKYvZAI7sUNZCYmGN2HCMDFDYV5hLu6HrHIK5BynAAwgHGiafFFU7ibYez6mXL4w/640?wx_fmt=gif");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;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">end</span></p> </section> <section mpa-from-tpl="t" style="margin-top: -26px;max-width: 100%;height: 2px;background-color: rgb(34, 33, 33);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> </section> </section> </section> </section> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <section data-recommend-type="list-title" data-recommend-tid="6" data-mpa-template="t" data-mid="" data-from="yb-recommend" style="max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);width: 677px;display: flex;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-mid="" style="padding: 14px;max-width: 100%;width: 677px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(232, 232, 235);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-mid="" style="max-width: 100%;width: 647px;display: flex;justify-content: center;align-items: flex-end;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-mid="" style="margin-bottom: -14px;padding: 4px 22px;max-width: 100%;height: 28px;font-size: 14px;color: rgb(19, 52, 86);line-height: 20px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/sUbvrqLicbpzB81mjeBxPuxnYdalGxNnJo30L2Hq3WwGficcq8w5YJkLeXnsNHocN53k55TfN5mBpCdicGRyfDg1g/640?wx_fmt=png");background-repeat: no-repeat;background-size: 100% 100%;z-index: 10;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">往期推荐</p> </section> </section> <section data-mid="" style="padding: 17px 16px 9px;max-width: 100%;width: 647px;border-width: 1px;border-style: solid;border-color: rgb(198, 226, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496425_1" data-recommend-article-time="1615605007" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/UtWdDgynLdbNxCVbibjnwGOWpFELTfVT52dm2EvMZ5993UibU4V6j5ACXaaDbrd9aibPMiaQaicG01ZToHZ32mdEnpw/0?wx_fmt=jpeg" data-recommend-article-title="你知道怎么分库分表吗?如何做到永不迁移数据和避免热点吗?" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496425&idx=1&sn=17bfbcf179e4af37933863365df5348c&chksm=9f449e21a8331737b594e3fdcd34b2a9eeea63e78ea6b860588d6dd4ab119c8e52286a407cba#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247497551&idx=1&sn=3dd414a10cbc702645a9c58287906265&chksm=9f449b87a833129147fa266afb5f21518d2f771390dfcfc97a73401850f762eb0e52c404aa51&scene=21#wechat_redirect" textvalue="微信小程序商城项目(Java版),拿去毕设又省2千块" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">微信小程序商城项目(Java版),拿去毕设又省2千块</a></p> </section> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496333_1" data-recommend-article-time="1615425900" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/Baq5lYpIw7Wno7a8LbEOfmgfgFclhreqPhibwpEs5H2enMdY7g5rnRDREu23MePuwvP2SnwdEibZoDBhLU5eicpdw/0?wx_fmt=jpeg" data-recommend-article-title="民生银行在云原生领域的数据中台实践!" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496333&idx=1&sn=42e01a34356795aae51fd450ee19977a&chksm=9f449e45a8331753eb37b23244e5ae7250e137d6304e4d61111c628eb4ab8f41457cd3d65794#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496333&idx=1&sn=42e01a34356795aae51fd450ee19977a&chksm=9f449e45a8331753eb37b23244e5ae7250e137d6304e4d61111c628eb4ab8f41457cd3d65794&scene=21#wechat_redirect" data-linktype="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;">民生银行在云原生领域的数据中台实践!</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496262_1" data-recommend-article-time="1615339500" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/Baq5lYpIw7W9QiacOWpVUVIl7zibdLGfwHMhmAibf3CWRZqMZY7bSD5AQcazk0ic6VwsGaThbU19tEC2r05kPm7fTg/0?wx_fmt=jpeg" data-recommend-article-title="高级程序员必知的 7 种软件架构模式!" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496262&idx=1&sn=14721dad7a6618efe786d1060d8b113f&chksm=9f449e8ea8331798f25e9da321fc2dfef5f890f5cae3a90ffc4c11879a65ec0bba8645f4dea3#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496262&idx=1&sn=14721dad7a6618efe786d1060d8b113f&chksm=9f449e8ea8331798f25e9da321fc2dfef5f890f5cae3a90ffc4c11879a65ec0bba8645f4dea3&scene=21#wechat_redirect" data-linktype="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;">高级程序员必知的 7 种软件架构模式!</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496245_1" data-recommend-article-time="1615168879" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/Baq5lYpIw7VlU8smlzOSNeV4pp9CTlojdgP2B6qcb3sLppBccSicgruXg2pwCSW2ZlzOmlUP4GmDko9ARXHHhHQ/0?wx_fmt=jpeg" data-recommend-article-title="【震惊】小伙在公司用了个insert into select 居然被开除了。。。" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496245&idx=1&sn=9e8b0154bbb0954f73a213c17368011d&chksm=9f449efda83317eb07d3dcec2acc8000182c032977407476da7b4779cadef02fe0e0712bcfa9#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496245&idx=1&sn=9e8b0154bbb0954f73a213c17368011d&chksm=9f449efda83317eb07d3dcec2acc8000182c032977407476da7b4779cadef02fe0e0712bcfa9&scene=21#wechat_redirect" data-linktype="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;">【震惊】小伙在公司用了个insert into select 居然被开除了。。。</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496228_1" data-recommend-article-time="1615084897" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/A1HKVXsfHNmbOes2txMV7GF3IMRHg4DBbaev8yryC4CeAWwU0icRdX5ibbxlA3jJLaDvsFtibBviaFtIRjjpTJSFXA/0?wx_fmt=jpeg" data-recommend-article-title="主流微服务全链路监控系统之战" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496228&idx=1&sn=9bfffabec05e53ec4ed22135c0ceaaa3&chksm=9f449eeca83317fa66421027e2e1ab272749af4fd272a53e563502a902a9af8c7b90b6e92049#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496228&idx=1&sn=9bfffabec05e53ec4ed22135c0ceaaa3&chksm=9f449eeca83317fa66421027e2e1ab272749af4fd272a53e563502a902a9af8c7b90b6e92049&scene=21#wechat_redirect" data-linktype="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;border-bottom: none !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;">主流微服务全链路监控系统之战</p> </section></a> </section> </section> </section> </section> <section style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(63, 63, 63);font-size: 16px;word-spacing: 1px;caret-color: rgb(255, 0, 0);text-align: center;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;">关注公众号《Java派》</strong> </section> <section style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(63, 63, 63);font-size: 16px;word-spacing: 1px;caret-color: rgb(255, 0, 0);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">回复 </strong> <span style="max-width: 100%;color: rgb(255, 104, 39);box-sizing: border-box !important;overflow-wrap: break-word !important;">1027 </span> <strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">获取三本 </strong> <span style="max-width: 100%;color: rgb(136, 136, 136);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 style="max-width: 100%;color: rgb(255, 104, 39);letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">DDD领域驱动设计</strong></strong><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;color: rgb(63, 63, 63);letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> </strong></strong></span> <strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">电子书</strong> </section> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzA5MTU0OTY0Ng==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/zc3KLDBfJlmPt0J5PXYOoiaG8wsQPZrLevbxMZSfgQ0YypNYaicnbS0P9UicluuOySLSP4CjTcRUVHCZzYeXQ9WlA/0?wx_fmt=png" data-nickname="Java派" data-alias="" data-signature="专注Java相关技术栈:Spring全家筒、Docker、k8s、Mysql、集群、微服务、中间件等知识。" data-from="0"></mpprofile> </section> <pre style="max-width: 100%;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section 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;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages" data-ratio="0.5555555555555556" data-s="300,640" src="/upload/9d786e52e671b1ce4beb338d1e0d1815.jpg" data-type="jpeg" data-w="900" style="font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);font-size: 15px;font-weight: 700;widows: 1;word-spacing: 2px;caret-color: rgb(0, 0, 0);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"></p> <p style="max-width: 100%;min-height: 1em;text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-weight: 700;widows: 1;word-spacing: 2px;caret-color: rgb(0, 0, 0);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">如有收获,点个在看,诚挚感谢</span><img data-ratio="1" src="/upload/5f7454d24a334e968c32b8ce9ae53c5.png" data-type="png" data-w="19" style="letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-weight: 700;widows: 1;word-spacing: 2px;caret-color: rgb(0, 0, 0);font-size: 16px;display: inline-block;vertical-align: text-bottom;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 19px !important;" width="19px"></p> </section> </section> </section> </section> </section></pre>
作者:微信小助手
<p style="text-align: center;" data-mpa-powered-by="yiban.io"><span style="color: rgb(136, 136, 136);font-family: Georgia, "Times New Roman", Times, "Songti SC", serif;letter-spacing: 0.544px;font-size: 16px;"></span></p> <p style="text-align: center;"><img class="rich_pages" data-galleryid="85417269999484928" data-gallerysupplier="4" data-ratio="0.66640625" data-s="300,640" src="/upload/aa405c165cfb3724824f0ff13c426075.jpg" data-type="jpeg" data-w="1280" style=""></p> <p style="max-width: 100%;min-height: 1em;white-space: normal;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: left;overflow-wrap: break-word !important;box-sizing: border-box !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(178, 178, 178);font-family: Optima-Regular, PingFangTC-light;font-size: 13px;overflow-wrap: break-word !important;box-sizing: border-box !important;">作者 | ask_the_sky<br style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"></span></p> <section style="margin-bottom: 15px;max-width: 100%;white-space: normal;text-align: left;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);overflow-wrap: break-word !important;box-sizing: border-box !important;"> <span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(178, 178, 178);font-family: Optima-Regular, PingFangTC-light;font-size: 13px;overflow-wrap: break-word !important;box-sizing: border-box !important;">来源 |<span style="max-width: 100%;white-space: pre-line;overflow-wrap: break-word !important;box-sizing: border-box !important;"> https://juejin.cn/post/6940976355097985032</span></span> </section> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">前几天看了一个二维码的视频,写的不错,这里总结下。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">在日常生活中,二维码出现在很多场景,比如超市支付、系统登录、应用下载等等。了解二维码的原理,可以为技术人员在技术选型时提供新的思路。对于非技术人员呢,除了解惑,还可以引导他更好地辨别生活中遇到的各种二维码,防止上当受骗。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">二维码,大家再熟悉不过了</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">购物扫个码,吃饭扫个码,坐公交也扫个码</p> <p style="text-align: center;"><img class="rich_pages" data-backh="424" data-backw="579" data-galleryid="" data-ratio="0.7333333333333333" data-s="300,640" src="/upload/dd860aef10f0ed650c1c7d05203b86c6.png" data-type="png" data-w="885" style="width: 100%;height: auto;"></p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);"><img data-backh="800" data-backw="480" data-ratio="1.6666666666666667" src="/upload/de2839ee8d14c5bc9c7d61d9d2ccf684.png" data-type="png" data-w="480" style="width: 100%;height: auto;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247530377&idx=1&sn=e1060b81b9534e49c4961858d7ae82fa&chksm=9bd3da11aca453070745a60582479a1440a8e2551f3be3c04b20d2e310e5d6b6443c4eb939fd&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="color: rgb(178, 178, 178);font-size: 14px;" data-linktype="2"><span style="color: rgb(178, 178, 178);font-size: 14px;">继Elastic怒喷云服务商白嫖之后,AWS 终于退出ES的开源分支:OpenSearch!</span></a></p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">在扫码的过程中,大家可能会有疑问:这二维码安全吗?会不会泄漏我的个人信息?更深度的用户还会考虑:我的系统是不是也可以搞一个二维码来推广呢?</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">这时候就需要了解一下二维码背后的技术和逻辑了!</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">二维码最常用的场景之一就是通过手机端应用扫描 PC 或者 WEB 端的二维码,来登录同一个系统。比如手机微信扫码登录 PC 端微信,手机淘宝扫码登录 PC 端淘宝。那么就让我们来看一下,二维码登录是怎么操作的!</p> <h3 style="margin-top: 1.2em;margin-bottom: 1em;color: rgb(53, 179, 120);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">二维码登录的本质</h3> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">二维码登录本质上也是一种登录认证方式。既然是登录认证,要做的也就两件事情!</p> <ol style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 告诉系统我是谁 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 向系统证明我是谁 </section></li> </ol> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">比如账号密码登录,账号就是告诉系统我是谁, 密码就是向系统证明我是谁; 比如手机验证码登录,手机号就是告诉系统我是谁,验证码就是向系统证明我是谁;</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">那么扫码登录是怎么做到这两件事情的呢?我们一起来考虑一下</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">手机端应用扫 PC 端二维码,手机端确认后,账号就在 PC 端登录成功了!这里,PC 端登录的账号肯定与手机端是同一个账号。不可能手机端登录的是账号 A,而扫码登录以后,PC 端登录的是账号 B。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">所以,第一件事情,告诉系统我是谁,是比较清楚的!</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">通过扫描二维码,把手机端的账号信息传递到 PC 端,至于是怎么传的,我们后面再说</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">第二件事情,向系统证明我是谁。扫码登录过程中,用户并没有去输入密码,也没有输入验证码,或者其他什么码。那是怎么证明的呢?</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">有些同学会想到,是不是扫码过程中,把密码传到了 PC 端呢?但这是不可能的。因为那样太不安全的,客户端也根本不会去存储密码。我们仔细想一下,其实手机端 APP 它是已经登录过的,就是说手机端是已经通过登录认证。所说只要<strong style="color: rgb(53, 179, 120);">扫码确认是这个手机且是这个账号操作的,其实就能间接证明我谁。</strong></p> <h3 style="margin-top: 1.2em;margin-bottom: 1em;color: rgb(53, 179, 120);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">认识二维码</h3> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">那么如何做确认呢?我们后面会详细说明,在这之前我们需要先认识一下二维码!在认识二维码之前我们先看一下一维码!</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);"><img src="/upload/f6e097c7a2ed90d856c37744abed2ff9.png" data-type="png" data-ratio="0.4357142857142857" data-w="280" data-backw="280" data-backh="121" style="width: 100%;height: auto;"></p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">所谓一维码,也就是条形码,超市里的条形码--这个相信大家都非常熟悉,条形码实际上就是一串数字,它上面存储了商品的序列号。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">二维码其实与条形码类似,只不过它存储的不一定是数字,还可以是任何的字符串,你可以认为,它就是字符串的另外一种表现形式,</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">在搜索引擎中搜索二维码,你可以找到很多在线生成二维码的工具网站,这些网站可以提供字符串与二维码之间相互转换的功能,比如 <strong style="color: rgb(53, 179, 120);">草料二维码网站</strong>[2]</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);"><img src="/upload/6051c3fc774b6bcab30a1280c8ef19d7.jpg" data-type="jpeg" data-ratio="0.3880597014925373" data-w="1072" data-backw="570" data-backh="221" style="width: 100%;height: auto;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247530377&idx=3&sn=2824152510496c632c60c31c10c5f50a&chksm=9bd3da11aca453078ff64c605c3fdfe17e5059c8e19e73a3da52c02dc517e1e1ace985ed2b11&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="color: rgb(178, 178, 178);font-size: 14px;" data-linktype="2"><span style="color: rgb(178, 178, 178);font-size: 14px;">HDFS技术原理(下)-总结太全面了!!!</span></a></p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">在左边的输入框就可以输入你的内容,它可以是文本、网址,文件........。然后就可以生成代表它们的二维码</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">你也可以把二维码上传,进行”解码“,然后就可以解析出二维码代表的含义</p> <h3 style="margin-top: 1.2em;margin-bottom: 1em;color: rgb(53, 179, 120);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">系统认证机制</h3> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">认识了二维码,我们了解一下移动互联网下的系统认证机制。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">前面我们说过,为了安全,手机端它是不会存储你的登录密码的。但是在日常使用过程中,我们应该会注意到,只有在你的应用下载下来后,第一次登录的时候,才需要进行一个账号密码的登录, 那之后呢 即使这个应用进程被杀掉,或者手机重启,都是不需要再次输入账号密码的,它可以自动登录。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">其实这背后就是一套基于 token 的认证机制,我们来看一下这套机制是怎么运行的,</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);"><img src="/upload/8f0cf907a787919c0fdaf53bc9d02c62.jpg" data-type="jpeg" data-ratio="0.44136191677175285" data-w="793" data-backw="570" data-backh="252" style="width: 100%;height: auto;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247530285&idx=1&sn=e0c8a61f61e7e54fb8bae3f93f1d2d73&chksm=9bd3dab5aca453a34146274ddc814494b2f11db97a35047bcc8941bc53bf1c12f5bd85f5955b&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="color: rgb(178, 178, 178);font-size: 14px;" data-linktype="2"><span style="color: rgb(178, 178, 178);font-size: 14px;">用低代码平台开发比用IDEA还牛逼吗?</span></a></p> <ol style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 账号密码登录时,客户端会将设备信息一起传递给服务端, </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 如果账号密码校验通过,服务端会把账号与设备进行一个绑定,存在一个数据结构中,这个数据结构中包含了账号 ID,设备 ID,设备类型等等 </section></li> </ol> <pre style="font-size: 15px;font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;margin-top: 10px;margin-bottom: 10px;overflow: auto;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;color: rgb(89, 89, 89);letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);"><code style="font-size: 12px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;display: -webkit-box;overflow-x: auto;padding: 15px 16px 16px;color: rgb(171, 178, 191);background: rgb(40, 44, 52);border-radius: 5px;">const token = {<br> acountid:<span style="color: rgb(152, 195, 121);line-height: 26px;">'账号ID'</span>,<br> deviceid:<span style="color: rgb(152, 195, 121);line-height: 26px;">'登录的设备ID'</span>,<br> deviceType:<span style="color: rgb(152, 195, 121);line-height: 26px;">'设备类型,如 iso,android,pc......'</span>,<br>}<br><br></code></pre> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">然后服务端会生成一个 token,用它来映射数据结构,这个 token 其实就是一串有着特殊意义的字符串,它的意义就在于,通过它可以找到对应的账号与设备信息,</p> <ol style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 客户端得到这个 token 后,需要进行一个本地保存,每次访问系统 API 都携带上 token 与设备信息。 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 服务端就可以通过 token 找到与它绑定的账号与设备信息,然后把绑定的设备信息与客户端每次传来的设备信息进行比较, 如果相同,那么校验通过,返回 AP 接口响应数据, 如果不同,那就是校验不通过拒绝访问 </section></li> </ol> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">从前面这个流程,我们可以看到,客户端不会也没必要保存你的密码,相反,它是保存了 token。可能有些同学会想,这个 token 这么重要,万一被别人知道了怎么办。实际上,知道了也没有影响, 因为设备信息是唯一的,只要你的设备信息别人不知道, 别人拿其他设备来访问,验证也是不通过的。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">可以说,客户端登录的目的,就是获得属于自己的 token。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">那么在扫码登录过程中,PC 端是怎么获得属于自己的 token 呢?不可能手机端直接把自己的 token 给 PC 端用!token 只能属于某个客户端私有,其他人或者是其他客户端是用不了的。在分析这个问题之前,我们有必要先梳理一下,扫描二维码登录的一般步骤是什么样的。这可以帮助我们梳理清楚整个过程,</p> <h3 style="margin-top: 1.2em;margin-bottom: 1em;color: rgb(53, 179, 120);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">扫描二维码登录的一般步骤</h3> <h4 style="margin-top: 30px;margin-bottom: 15px;color: black;font-weight: bold;font-size: 18px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">大概流程</h4> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);"><img src="/upload/cb164dcf126ef37621c91d94071965c6.jpg" data-type="jpeg" data-ratio="0.5583756345177665" data-w="591" data-backw="570" data-backh="319" style="width: 100%;height: auto;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247530285&idx=3&sn=df897eddd22c8a76b35e6995c7bf1fd0&chksm=9bd3dab5aca453a3f46dddf9bfec293f8d407329d41c84f8dfa2dcc4ad62d9aae83bcaa6e4dd&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="color: rgb(178, 178, 178);font-size: 14px;" data-linktype="2"><span style="color: rgb(178, 178, 178);font-size: 14px;">HDFS技术原理(上)</span></a></p> <ol style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 扫码前,手机端应用是已登录状态,PC 端显示一个二维码,等待扫描 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 手机端打开应用,扫描 PC 端的二维码,扫描后,会提示"已扫描,请在手机端点击确认" </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 用户在手机端点击确认,确认后 PC 端登录就成功了 </section></li> </ol> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">可以看到,二维码在中间有三个状态, 待扫描,已扫描待确认,已确认。那么可以想象</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);"><img src="/upload/894f20476666b7b3974e89a60d6f3592.jpg" data-type="jpeg" data-ratio="0.43236409608091025" data-w="791" data-backw="570" data-backh="247" style="width: 100%;height: auto;"></p> <ol style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 二维码的背后它一定存在一个唯一性的 ID,当二维码生成时,这个 ID 也一起生成,并且绑定了 PC 端的设备信息 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 手机去扫描这个二维码 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 二维码切换为 已扫描待确认状态, 此时就会将账号信息与这个 ID 绑定 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 当手机端确认登录时,它就会生成 PC 端用于登录的 token,并返回给 PC 端 </section></li> </ol> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">好了,到这里,基本思路就已经清晰了,接下来我们把整个过程再具体化一下</p> <h4 style="margin-top: 30px;margin-bottom: 15px;color: black;font-weight: bold;font-size: 18px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">二维码准备</h4> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">按二维码不同状态来看, 首先是等待扫描状态,用户打开 PC 端,切换到二维码登录界面时。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);"><img src="/upload/953b6964702f07c12483a2168ae9f4a7.jpg" data-type="jpeg" data-ratio="0.48250728862973763" data-w="686" data-backw="570" data-backh="275" style="width: 100%;height: auto;"></p> <ol style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> PC 端向服务端发起请求,告诉服务端,我要生成用户登录的二维码,并且把 PC 端设备信息也传递给服务端 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 服务端收到请求后,它生成二维码 ID,并将二维码 ID 与 PC 端设备信息进行绑定 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 然后把二维码 ID 返回给 PC 端 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> PC 端收到二维码 ID 后,生成二维码(二维码中肯定包含了 ID) </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 为了及时知道二维码的状态,客户端在展现二维码后,PC 端不断的轮询服务端,比如每隔一秒就轮询一次,请求服务端告诉当前二维码的状态及相关信息 </section></li> </ol> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">二维码已经准好了,接下来就是扫描状态</p> <h4 style="margin-top: 30px;margin-bottom: 15px;color: black;font-weight: bold;font-size: 18px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">扫描状态切换</h4> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);"><img src="/upload/ba61242736d959ece6cf30b4e6de1f2.jpg" data-type="jpeg" data-ratio="0.40581542351453853" data-w="791" data-backw="570" data-backh="231" style="width: 100%;height: auto;"></p> <ol style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 用户用手机去扫描 PC 端的二维码,通过二维码内容取到其中的二维码 ID </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 再调用服务端 API 将移动端的身份信息与二维码 ID 一起发送给服务端 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 服务端接收到后,它可以将身份信息与二维码 ID 进行绑定,生成临时 token。然后返回给手机端 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 因为 PC 端一直在轮询二维码状态,所以这时候二维码状态发生了改变,它就可以在界面上把二维码状态更新为已扫描 </section></li> </ol> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">那么为什么需要返回给手机端一个临时 token 呢?临时 token 与 token 一样,它也是一种身份凭证,不同的地方在于它只能用一次,用过就失效。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">在第三步骤中返回临时 token,为的就是手机端在下一步操作时,可以用它作为凭证。以此确保扫码,登录两步操作是同一部手机端发出的,</p> <h4 style="margin-top: 30px;margin-bottom: 15px;color: black;font-weight: bold;font-size: 18px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">状态确认</h4> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">最后就是状态的确认了。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);"><img src="/upload/b29aa8171385030affb56c1aeebee867.jpg" data-type="jpeg" data-ratio="0.4603174603174603" data-w="693" data-backw="570" data-backh="262" style="width: 100%;height: auto;"></p> <ol style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 手机端在接收到临时 token 后会弹出确认登录界面,用户点击确认时,手机端携带临时 token 用来调用服务端的接口,告诉服务端,我已经确认 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 服务端收到确认后,根据二维码 ID 绑定的设备信息与账号信息,生成用户 PC 端登录的 token </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 这时候 PC 端的轮询接口,它就可以得知二维码的状态已经变成了"已确认"。并且从服务端可以获取到用户登录的 token </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 到这里,登录就成功了,后端 PC 端就可以用 token 去访问服务端的资源了 </section></li> </ol> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">扫码动作的基础流程都讲完了,有些细节还没有深入介绍,</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">比如二维码的内容是什么?</p> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 可以是二维码 ID </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 可以是包含二维码 ID 的一个 url 地址 </section></li> </ul> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">在扫码确认这一步,用户取消了怎么处理?这些细节都留给大家思考</p> <h3 style="margin-top: 1.2em;margin-bottom: 1em;color: rgb(53, 179, 120);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">总结</h3> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);"><img src="/upload/a2a7652be62575d1aed8b32e9e444c8.jpg" data-type="jpeg" data-ratio="0.43505674653215637" data-w="793" data-backw="570" data-backh="248" style="width: 100%;height: auto;"></p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">我们从登陆的本质触发,探索二维码扫码登录是如何做到的</p> <ol style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 告诉系统我是谁 </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 向系统证明我谁 </section></li> </ol> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">在这个过程中,我们先简单讲了两个前提知识,</p> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 一个是二维码原理, </section></li> <li> <section style="margin-top: 10px;margin-bottom: 10px;line-height: 26px;color: rgb(1, 1, 1);"> 一个是基于 token 的认证机制。 </section></li> </ul> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">然后我们以二维码状态为轴,分析了这背后的逻辑: 通过 token 认证机制与二维码状态变化来实现扫码登录.</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">需要指出的是,前面的讲的登录流程,它适用于同一个系统的 PC 端,WEB 端,移动端。</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">平时我们还有另外一种场景也比较常见,那就是通过第三方应用来扫码登录,比如极客时间/掘金 都可以选择微信/QQ 等扫码登录,那么这种通过第三方应用扫码登录又是什么原理呢?</p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">感兴趣的同学可以思考研究一下,欢迎在评论区留下你的见解。</p> <h3 style="margin-top: 1.2em;margin-bottom: 1em;color: rgb(53, 179, 120);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">参考资料</h3> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">[1]极客时间一个二维码的视频: <em>https://time.geekbang.org/dailylesson/detail/100044032?utm_source=u_nav_web&utm_medium=u_nav_web&utm_term=u_nav_web</em></p> <p style="margin: 1em 4px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);">[2]草料二维码网站: <em>https://cli.im/</em></p> <section data-recommend-type="list-title" data-recommend-tid="6" data-mpa-template="t" data-mid="" data-from="yb-recommend" style="width: 578px;display: flex;justify-content: center;align-items: center;"> <section data-mid="" style="padding: 14px;width: 578px;background: rgb(255, 255, 255);border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(232, 232, 235);"> <section data-mid="" style="width: 548px;display: flex;justify-content: center;align-items: flex-end;"> <section data-mid="" style="margin-bottom: -14px;padding: 4px 22px;height: 28px;font-size: 14px;color: rgb(19, 52, 86);line-height: 20px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/sUbvrqLicbpzB81mjeBxPuxnYdalGxNnJo30L2Hq3WwGficcq8w5YJkLeXnsNHocN53k55TfN5mBpCdicGRyfDg1g/640?wx_fmt=png");background-repeat: no-repeat;background-size: 100% 100%;z-index: 10;"> <p data-mid="">往期推荐</p> </section> </section> <section data-mid="" style="padding: 17px 16px 9px;width: 548px;border-width: 1px;border-style: solid;border-color: rgb(198, 226, 255);"> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247531726_1" data-recommend-article-time="1619933460" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/R3InYSAIZkGhSBnK7s9Ipgz2oWbUIAiaKc4uEBV3GlowEnc9sxuuT6eiaO52IGfSz5P9OBImlGbH9WtOXjicLqdiag/0?wx_fmt=jpeg" data-recommend-article-title="来给IDEA换个酷炫的主题吧!这几个都有点哇塞啊!" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531726&idx=1&sn=bfc817dc35418fa115750def0d2c9c49&chksm=9bd3d156aca458404f811a4057beb2f3c2e008828bfb5a6d91995e606d973639a5f1ff30dc66#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531726&idx=1&sn=bfc817dc35418fa115750def0d2c9c49&chksm=9bd3d156aca458404f811a4057beb2f3c2e008828bfb5a6d91995e606d973639a5f1ff30dc66&scene=21#wechat_redirect" data-linktype="2"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;width: 514px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;"> <p data-mid="" style="overflow: hidden;text-overflow: ellipsis;">来给IDEA换个酷炫的主题吧!这几个都有点哇塞啊!</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247531726_2" data-recommend-article-time="1619933460" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/R3InYSAIZkFAph5vkJibyH1SEe89IBHKZNA9q1mAQDqJdDNk7N4LxubkoXxC9T3ElicY5FcUEu5cpzIjmykZRC8w/0?wx_fmt=jpeg" data-recommend-article-title="除了 k8s,留给 k 和 s 中间的数字不多了!" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531726&idx=2&sn=95533d8d2ac9cf7866dd3ef86140a946&chksm=9bd3d156aca45840ec70310f1ce6739cffc1f492dceddc6fb5fb668ba5dcec5b1353e4c0afe7#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531726&idx=2&sn=95533d8d2ac9cf7866dd3ef86140a946&chksm=9bd3d156aca45840ec70310f1ce6739cffc1f492dceddc6fb5fb668ba5dcec5b1353e4c0afe7&scene=21#wechat_redirect" data-linktype="2"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;width: 514px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;"> <p data-mid="" style="overflow: hidden;text-overflow: ellipsis;">除了 k8s,留给 k 和 s 中间的数字不多了!</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247531708_1" data-recommend-article-time="1619874300" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/R3InYSAIZkFG1SND6g08fQhgUkGu5UiaZGEy71gwsjNHM1ZssIicXYIHrWtsutzp1TYfAL2vibOflIJjCwLJ7zjmQ/0?wx_fmt=jpeg" data-recommend-article-title="一二线城市都有哪些互联网公司是大家都想去的?" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531708&idx=1&sn=dc7a8d63956fde55838c752634dccc33&chksm=9bd3d124aca4583275c199ccf3873d311de04a95e0d36a2b0a93a0c16e300b710374dc270715#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531708&idx=1&sn=dc7a8d63956fde55838c752634dccc33&chksm=9bd3d124aca4583275c199ccf3873d311de04a95e0d36a2b0a93a0c16e300b710374dc270715&scene=21#wechat_redirect" data-linktype="2"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;width: 514px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;"> <p data-mid="" style="overflow: hidden;text-overflow: ellipsis;">一二线城市都有哪些互联网公司是大家都想去的?</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247531708_2" data-recommend-article-time="1619874300" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/R3InYSAIZkFAph5vkJibyH1SEe89IBHKZWXgPiamsuSG54teOjOQTKw6G9ibloavuupHFfHErx56jh603jLrdcoZw/0?wx_fmt=jpeg" data-recommend-article-title="跳槽季最狗血的面试经历,没有之一..." data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531708&idx=2&sn=5305f8c79543f231a2085b99cec11e88&chksm=9bd3d124aca45832acb36c29dc9f2a88eeb3b77b103a6351d82b043231e1e118c6af1853b1fa#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531708&idx=2&sn=5305f8c79543f231a2085b99cec11e88&chksm=9bd3d124aca45832acb36c29dc9f2a88eeb3b77b103a6351d82b043231e1e118c6af1853b1fa&scene=21#wechat_redirect" data-linktype="2"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;width: 514px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;"> <p data-mid="" style="overflow: hidden;text-overflow: ellipsis;">跳槽季最狗血的面试经历,没有之一...</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247531443_1" data-recommend-article-time="1619656260" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/R3InYSAIZkEgLicfsicbbbiaQnaoKPRYO4IAOCHCYYgAbIIC5W7HxfFtI8tpUmxiciab0sEFnNBg0IPbVccuNJwrSsg/0?wx_fmt=jpeg" data-recommend-article-title="这是我见过最蛋疼的注册中心与API网关实践!" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531443&idx=1&sn=4b0d0c0e645cfd84d6b7f79eae2ec8c2&chksm=9bd3d62baca45f3d8ea51a3b9c0fba12afee0b9909b51d4dedb6a5bdc00f6bd904a105b0201c#rd"> <a href="http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247531443&idx=1&sn=4b0d0c0e645cfd84d6b7f79eae2ec8c2&chksm=9bd3d62baca45f3d8ea51a3b9c0fba12afee0b9909b51d4dedb6a5bdc00f6bd904a105b0201c&scene=21#wechat_redirect" data-linktype="2"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;width: 514px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;border-bottom: none !important;"> <p data-mid="" style="overflow: hidden;text-overflow: ellipsis;">这是我见过最蛋疼的注册中心与API网关实践!</p> </section></a> </section> </section> </section> </section> <p><br style="white-space: normal;"></p> <section> <br> </section> <section style="max-width: 100%;text-align: center;margin-bottom: 5px;margin-top: 5px;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;">如果你喜欢本文,欢迎关注我,订阅更多精彩内容</span> <br> </section> <section style="max-width: 100%;text-align: center;margin-bottom: 5px;margin-top: 5px;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;"><span style="text-align: center;">关注我回复「</span><span style="text-align: center;color: rgb(255, 76, 0);"><strong>加群</strong></span><span style="text-align: center;">」,加入Spring技术交流群</span></span> </section> <section class="mp_profile_iframe_wrp" style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzAxODcyNjEzNQ==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/R3InYSAIZkFgVUuoib3ib7u92WFR247awDicxibIsB4H6gy610wyzicNVf03JIPC63Tu4lHV3iaAc4vDiczQr57kJDJew/0?wx_fmt=png" data-nickname="程序猿DD" data-alias="didispace" data-signature="一线技术工作者的学习、生活与见闻" style="max-width: 100%;width: 575.109px;overflow-wrap: break-word !important;box-sizing: border-box !important;"></mpprofile> </section>
作者:微信小助手
<p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击蓝色“</span><span style="max-width: 100%;letter-spacing: 0.544px;font-size: 14px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">架构文摘</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">”关注我哟</span></p> <p style="margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">加个“</span><span style="max-width: 100%;color: rgb(0, 128, 255);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">星标</span><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”,每天上午 09:25,干货推送!</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 14px;text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-backh="36" data-backw="578" data-ratio="0.0625" data-s="300,640" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.jpg" data-type="jpeg" data-w="640" style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;" width="100%"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;">来源:</span><span style="color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;">my.oschina.net/editorial-story/blog/1808757</span><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;">本文是学习大型分布式网站架构的技术总结。对架构一个高性能、高可用、可伸缩及可扩展的分布式网站进行了概要性描述,并给出一个架构参考。文中一部分为读书笔记,一部分是个人经验总结,对大型分布式网站架构有较好的参考价值。</p> <h1 data-tool="mdnice编辑器"><strong><span style="font-size: 20px;">一、大型分布式网站架构技术</span></strong></h1> <h2 data-tool="mdnice编辑器"><br></h2> <h2 data-tool="mdnice编辑器"><span style="font-size: 18px;"><strong>1、大型网站的特点</strong></span></h2> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;max-width: 100%;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;overflow-wrap: break-word !important;"> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 用户多,分布广泛 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 大流量,高并发 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 海量数据,服务高可用 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 安全环境恶劣,易受网络攻击 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 功能多,变更快,频繁发布 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 从小到大,渐进发展 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 以用户为中心 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 免费服务,付费体验 </section></li> </ul> <h2 data-tool="mdnice编辑器"><strong><span style="font-size: 18px;">2、大型网站架构目标</span></strong></h2> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;max-width: 100%;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;overflow-wrap: break-word !important;"> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 高性能:提供快速的访问体验。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 高可用:网站服务一直可以正常访问。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 可伸缩:通过硬件增加/减少,提高/降低处理能力。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 安全性:提供网站安全访问和数据加密、安全存储等策略。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 扩展性:方便地通过新增/移除方式,增加/减少新的功能/模块。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 敏捷性:随需应变,快速响应; </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.48518518518518516" src="/upload/efb08b436091ee356447bba1b4331de3.jpg" data-type="jpeg" data-w="540" style="margin-right: auto;margin-left: auto;background-color: rgb(238, 237, 235);border-width: 1px;border-style: solid;border-color: rgb(238, 237, 235);background-size: 22px;background-position: center center;background-repeat: no-repeat;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;height: 263.03px !important;width: 540px !important;"> </figure> <h2 data-tool="mdnice编辑器"><strong><span style="font-size: 18px;">3、大型网站架构模式</span></strong></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.37398373983739835" src="/upload/8d241a6044f749e876da7525f23bbde7.jpg" data-type="jpeg" data-w="615" style="margin-right: auto;margin-left: auto;background-color: rgb(238, 237, 235);border-width: 1px;border-style: solid;border-color: rgb(238, 237, 235);background-size: 22px;background-position: center center;background-repeat: no-repeat;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;height: 231.252px !important;width: 615px !important;"> </figure> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;max-width: 100%;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;overflow-wrap: break-word !important;"> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 分层:一般可分为应用层、服务层、数据层、管理层与分析层; </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 分割:一般按照业务/模块/功能特点进行划分,比如应用层分为首页、用户中心。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 分布式:将应用分开部署(比如多台物理机),通过远程调用协同工作。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 集群:一个应用/模块/功能部署多份(如:多台物理机),通过负载均衡共同提供对外访问。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 缓存:将数据放在距离应用或用户最近的位置,加快访问速度。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 异步:将同步的操作异步化。客户端发出请求,不等待服务端响应,等服务端处理完毕后,使用通知或轮询的方式告知请求方。一般指:请求——响应——通知模式。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 冗余:增加副本,提高可用性、安全性与性能。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 安全:对已知问题有有效的解决方案,对未知/潜在问题建立发现和防御机制。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 自动化:将重复的、不需要人工参与的事情,通过工具的方式,使用机器完成。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 敏捷性:积极接受需求变更,快速响应业务发展需求。 </section></li> </ul> <h2 data-tool="mdnice编辑器"><strong><span style="font-size: 18px;">4、高性能架构</span></strong></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;">以用户为中心,提供快速的网页访问体验。主要参数有较短的响应时间、较大的并发处理能力、较高的吞吐量与稳定的性能参数。</p> <p data-tool="mdnice编辑器" style="margin-top: 16px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;">可分为前端优化、应用层优化、代码层优化与存储层优化。</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;max-width: 100%;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;overflow-wrap: break-word !important;"> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 前端优化:网站业务逻辑之前的部分; </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 浏览器优化:减少HTTP请求数,使用浏览器缓存,启用压缩,CSS JS位置,JS异步,减少Cookie传输;CDN加速,反向代理; </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 应用层优化:处理网站业务的服务器。使用缓存,异步,集群 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 代码优化:合理的架构,多线程,资源复用(对象池,线程池等),良好的数据结构,JVM调优,单例,Cache等; </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 存储优化:缓存、固态硬盘、光纤传输、优化读写、磁盘冗余、分布式存储(HDFS)、NoSQL等。 </section></li> </ul> <h2 data-tool="mdnice编辑器"><strong><span style="font-size: 18px;">5、高可用架构</span></strong></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;">大型网站应该在任何时候都可以正常访问,正常提供对外服务。因为大型网站的复杂性,分布式,廉价服务器,开源数据库,操作系统等特点,要保证高可用是很困难的,也就是说网站的故障是不可避免的。</p> <p data-tool="mdnice编辑器" style="margin-top: 16px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;">如何提高可用性,就是需要迫切解决的问题。首先,需要从架构级别考虑,在规划的时候,就考虑可用性。行业内一般用几个9表示可用性指标,比如四个9(99.99),一年内允许的不可用时间是53分钟。</p> <p data-tool="mdnice编辑器" style="margin-top: 16px;padding-top: 8px;padding-bottom: 8px;max-width: 100%;min-height: 1em;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;">不同层级使用的策略不同,一般采用冗余备份和失效转移解决高可用问题。</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;max-width: 100%;font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;overflow-wrap: break-word !important;"> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 应用层:一般设计为无状态的,对于每次请求,使用哪一台服务器处理是没有影响的。一般使用负载均衡技术(需要解决Session同步问题)实现高可用。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;max-width: 100%;color: rgb(1, 1, 1);line-height: 2;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 服务层:负载均衡,分级管理,快速失败(超时设置),异步调用,服务降级,幂等设计等。 </section></li> <li style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section st
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;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;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;" data-mpa-powered-by="yiban.io"> <section> <span style="letter-spacing: 0.8px;word-spacing: 0.8px;">这是[码哥]Kafka 系列文章的第二篇,码哥将从原理、实践和源码角度为大家深入剖析并实践 Kafka。此系列包括[原理篇]、[实践篇]和[源码篇]。这篇是[原理篇]的第二篇,主要讲解 Kafka 的架构和实现原理。</span> <br> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">读者可以回顾之前的文章《Kafka 性能篇:为何 Kafka 这么"快"?》。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">今天我们来深入讲解 Kafka 的架构和实现原理。[码哥]将从架构和细节入手,以生动的图深入讲解 Kafka 的实现原理。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我想很多同学之前可能已经看过很多 Kafka 原理相关的文章,但往往看时"牛逼"声连连,激情满满,总觉得自己又学习到了各种“吊炸天”的技术。但很多同学往往是不觉明厉,把文章结合面试题背一背还能应付一下半吊子面试官。可以遇到老司机面试官,或是进入实战,却对很多概念和实现摸棱两可。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">所以,[码哥]决定图解 Kakfa,却让很多半懂不懂的同学可以加深对 Kafka 实现原理的理解。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">同时建议读者同学结合 Kafka 的配置去了解 Kafka 的实现原理,Kafka 有大量的配置,这也是 Kafka 高度扩展的一个表现,很多同学对 Kafka 的配置也不敢轻易改动。所以理解这些配置背后的实现原理,可以让我们在实践中懂得如何使用和优化 Kafka。既可面试造火箭,也可以实战造火箭。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Kafka 配置说明链接:https://kafka.apache.org/documentation</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">下面是本文的主要的内容:</span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.4244031830238727" src="/upload/117c1eb889bdeed7174dbb5500a7134d.png" data-type="png" data-w="1131" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">由于内容太多,怕步子迈太大扯着蛋,[码哥]决定将文章分成三篇。此文只会涉及上面图中"橙色"的部分。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">从本文你将学习到:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Kafka 架构设计哲学和原理 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Kafka 中 zookeeper 的作用 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Kafka Controller 实现原理 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Kafka Network 原理 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">开篇寄语</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">尽可能做一些产品出来,有一个作品很重要,这是别人了解你的窗口。如果可能,给自己开一个公众号或者一个博客,记录自己每天的见闻思考。刚开始记会很凌乱没有逻辑,但坚持下去一定会有很大价值。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">Architecture</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">理解 Kafka 架构,就是理解 Kafka 的各种组件的概念,以及这些组件的关系。先简单看一下各组件及其简单说明。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>不要去尝试记忆他们<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">Producer:</span> 生产者,发送消息的一方。生产者负责创建消息,然后将其发送到 Kafka。<br><span style="font-weight: 700;color: rgb(248, 57, 41);">Consumer:</span> 消费者,接受消息的一方。消费者连接到 Kafka 上并接收消息,进而进行相应的业务逻辑处理。<br><span style="font-weight: 700;color: rgb(248, 57, 41);">Consumer Group:</span> 一个消费者组可以包含一个或多个消费者。使用多分区 + 多消费者方式可以极大提高数据下游的处理速度,同一消费组中的消费者不会重复消费消息,同样的,不同消费组中的消费者消息消息时互不影响。Kafka 就是通过消费组的方式来实现消息 P2P 模式和广播模式。<br><span style="font-weight: 700;color: rgb(248, 57, 41);">Broker:</span> 服务代理节点。Broker 是 Kafka 的服务节点,即 Kafka 的服务器。<br><span style="font-weight: 700;color: rgb(248, 57, 41);">Topic:</span> Kafka 中的消息以 Topic 为单位进行划分,生产者将消息发送到特定的 Topic,而消费者负责订阅 Topic 的消息并进行消费。<br><span style="font-weight: 700;color: rgb(248, 57, 41);">Partition:</span> Topic 是一个逻辑的概念,它可以细分为多个分区,每个分区只属于单个主题。同一个主题下不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset)。<br><span style="font-weight: 700;color: rgb(248, 57, 41);">Offset:</span> offset 是消息在分区中的唯一标识,Kafka 通过它来保证消息在分区内的顺序性,不过 offset 并不跨越分区,也就是说,Kafka 保证的是分区有序性而不是主题有序性。<br><span style="font-weight: 700;color: rgb(248, 57, 41);">Replication:</span> 副本,是 Kafka 保证数据高可用的方式,Kafka 同一 Partition 的数据可以在多 Broker 上存在多个副本,通常只有主副本对外提供读写服务,当主副本所在 broker 崩溃或发生网络异常,Kafka 会在 Controller 的管理下会重新选择新的 Leader 副本对外提供读写服务。<br><span style="font-weight: 700;color: rgb(248, 57, 41);">Record:</span> 实际写入 Kafka 中并可以被读取的消息记录。每个 record 包含了 key、value 和 timestamp。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>我们理解了也就自然记住了<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们应该通过理解的方式去记忆它们。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>生产者-消费者<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><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(255, 93, 108);">生产者</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(255, 93, 108);">消费者</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(255, 93, 108);">生产者</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(255, 93, 108);">消费者</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(255, 93, 108);">中间组件</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(255, 93, 108);">生产者</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(255, 93, 108);">中间组件</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(255, 93, 108);">消费者</code>消费数据。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">就像 65 哥读书时给小芳写情书,这里 65 哥就是<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(255, 93, 108);">生产者</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(255, 93, 108);">消息</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(255, 93, 108);">消费者</code>。但有时候小芳不在,或者比较忙,65 哥也比较害羞,不敢直接将情书塞小芳手里,于是将情书塞在小芳抽屉中。所以抽屉就是这个<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(255, 93, 108);">中间组件</code>。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/3e9f400f2e0cb8178da5abd9687c46f6.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">在程序中我们通常使用<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(255, 93, 108);">Queue</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(255, 93, 108);">中间组件</code>。可以使用多线程向队列中写入数据,另外的消费者线程依次读取队列中的数据进行消费。模型如下图所示:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/91898323ac23fed2be774665d4deb1dd.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><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(255, 93, 108);">生产者</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(255, 93, 108);">消费者</code>模式通过添加一个中间层,不仅可以解耦生产者和消费者,使其易于扩展,还可以异步化调用、缓冲消息等。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>分布式队列<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">后来 65 哥和小芳异地了,65 哥在<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(255, 93, 108);">卷都</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(255, 93, 108);">魔都</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(255, 93, 108);">邮局</code>寄暧昧信了。这样 65 哥、邮局和小芳就成了<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(255, 93, 108);">分布式</code>的了。65 哥将信件发给邮局,小芳从邮局拿到 65 哥写的信,再回去慢慢看。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/8d683cc5e5c9862f1b5ce79873c95b57.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Kafka 的消息<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(255, 93, 108);">生产者</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(255, 93, 108);">Producer</code>,上游消费者进程添加 Kafka Client 创建 Kafka Producer,向 Broker 发送消息,Broker 是集群部署在远程服务器上的 Kafka Server 进程,下游消费者进程引入 Kafka Consumer API 持续消费队列中消息。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">因为 Kafka Consumer 使用 Poll 的模式,需要 Consumer 主动拉去消息。所有小芳只能定期去邮局拿信件了(呃,果然主动权都在小芳手上啊)。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/22e4563d06f2ec0c7085dcdc432492ba.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>主题<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">邮局不能只为 65 哥服务,虽然 65 哥一天写好几封信。但也无法挽回邮局的损失。所以邮局是可以供任何人寄信。只需要寄信人写好地址(主题),邮局建有两地的通道就可以发收信件了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Kafka 的 Topic 才相当于一个队列,Broker 是所有队列部署的机器。可以按业务创建不同的 Topic,Producer 向所属业务的 Topic 发送消息,相应的 Consumer 可以消费并处理消息。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/82fbdd66cf34bc2745e9ec8b725d9f58.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>分区<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">由于 65 哥写的信太多,一个邮局已经无法满足 65 哥的需求,邮政公司只能多建几个邮局了,65 哥将信件按私密度分类(分区策略),从不同的邮局寄送。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/796a70adc10dec0e3568cbf7bc1ff684.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">同一个 Topic 可以创建多个分区。理论上分区越多并发度越高,Kafka 会根据分区策略将分区尽可能均衡的分布在不同的 Broker 节点上,以避免消息倾斜,不同的 Broker 负载差异太大。分区也不是越多越好哦,毕竟太多邮政公司也管理不过来。具体的原因可以参考[码哥]之前的文章<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU3NDkwMjAyOQ==&mid=2247486579&idx=1&sn=c8ca8243624f0bf87ed8d9ca60ca9922&chksm=fd2a1611ca5d9f07bb420b81c28e8cf2bf6d47059326ceca80a702603905a67dfa85295bac20&scene=21#wechat_redirect" textvalue="《Kafka 性能篇:为何 Kafka 这么"快"?》" data-itemshowtype="0" tab="innerlink" data-linktype="2">《Kafka 性能篇:为何 Kafka 这么"快"?》</a></p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>副本<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">为防止由于邮局的问题,比如交通断啦,邮车没油啦。导致 65 哥的暧昧信无法寄到小芳手上,使得 65 哥晚上远程跪键盘。邮局决定将 65 哥的信件复制几份发到多个正常的邮局,这样只要有一个邮局还在,小芳就可以收到 65 哥的信了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Kafka 采用分区副本的方式来保证数据的高可用,每个分区都将建立指定数量的副本数,kakfa 保证同一分区副本尽量分布在不同的 Broker 节点上,以防止 Broker 宕机导致所有副本不可用。Kafka 会为分区的多个副本选举一个作为主副本(Leader),主副本对外提供读写服务,从副本(Follower)实时同步 Leader 的数据。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/49d78e69db6fdde42b8b8f408aa246ec.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>多消费者<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">哎,65 哥的信件满天飞,小芳天天跑邮局,还要一一拆开看,65 哥写的信又臭又长,让小芳忙得满身<span style="text-decoration:line-through;">大汉</span>大汗。于是小芳啪的一下,很快啊,变出多个分身去不同的邮局取信,这样小芳终于可以挤出额外的时间逛街了。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>广播消息<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">邮局最近提供了定制明信片业务,每个人都可以设计明信片,同一个身份只能领取一种明信片。65 哥设计了一堆,广播给所有漂亮的小妹妹都可以来领取,美女啪变出的分身也可以来领取,但是同一个身份的多个分身只能取一种明信片。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Kafka 通过 Consumer Group 来实现广播模式消息订阅,即不同 group 下的 consumer 可以重复消费消息,相互不影响,同一个 group 下的 consumer 构成一个整体。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">最后我们完成了 Kafka 的整体架构,如下:</span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/6a8ed91977670a27cd4baa9a40776904.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">Zookeeper</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Zookeeper 是一个成熟的分布式协调服务,它可以为分布式服务提供分布式配置服、同步服务和命名注册等能力.。对于任何分布式系统,都需要一种协调任务的方法。Kafka 是使用 ZooKeeper 而构建的分布式系统。但是也有一些其他技术(例如 Elasticsearch 和 MongoDB)具有其自己的内置任务协调机制。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Kafka 将 Broker、Topic 和 Partition 的元数据信息存储在 Zookeeper 上。通过在 Zookeeper 上建立相应的数据节点,并监听节点的变化,Kafka 使用 Zookeeper 完成以下功能:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Kafka Controller 的 Leader 选举 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Kafka 集群成员管理 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Topic 配置管理 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 分区副本管理 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们看一看 Zookeeper 下 Kafka 创建的节点,即可一目了然的看出这些相关的功能。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.46" src="/upload/9d4f7df82525ab6116a5c2afcd895f0d.png" data-type="png" data-w="1450" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">Controller</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Controller 是从 Broker 中选举出来的,负责分区 Leader 和 Follower 的管理。当某个分区的 leader 副本发生故障时,由 Controller 负责为该分区选举新的 leader 副本。当检测到某个分区的 ISR(In-Sync Replica)集合发生变化时,由控制器负责通知所有 broker 更新其元数据信息。当使用<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(255, 93, 108);">kafka-topics.sh</code>脚本为某个 topic 增加分区数量时,同样还是由控制器负责分区的重新分配。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Kafka 中 Contorller 的选举的工作依赖于 Zookeeper,成功竞选为控制器的 broker 会在 Zookeeper 中创建<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(255, 93, 108);">/controller</code>这个临时(EPHEMERAL)节点。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">选举过程</span><span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/b3ca7997f6822f9476e19d0b41828da3.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Broker 启动的时候尝试去读取<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(255, 93, 108);">/controller</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(255, 93, 108);">brokerid</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(255, 93, 108);">brokerid</code>的值不等于-1,则表明已经有其他的 Broker 成功成为 Controller 节点,当前 Broker 主动放弃竞选;如果不存在<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(255, 93, 108);">/controller</code>节点,或者 brokerid 数值异常,当前 Broker 尝试去创建<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(255, 93, 108);">/controller</code>这个节点,此时也有可能其他 broker 同时去尝试创建这个节点,只有创建成功的那个 broker 才会成为控制器,而创建失败的 broker 则表示竞选失败。每个 broker 都会在内存中保存当前控制器的 brokerid 值,这个值可以标识为 activeControllerId。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">实现</span><span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/fee37e0f032b2590fd36ff5ade482228.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Controller 读取 Zookeeper 中的节点数据,初始化上下文(Controller Context),并管理节点变化,变更上下文,同时也需要将这些变更信息同步到其他普通的 broker 节点中。Controller 通过定时任务,或者监听器模式获取 zookeeper 信息,事件监听会更新更新上下文信息,如图所示,Controller 内部也采用生产者-消费者实现模式,Controller 将 zookeeper 的变动通过事件的方式发送给事件队列,队列就是一个<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(255, 93, 108);">LinkedBlockingQueue</code>,事件消费者线程组通过消费消费事件,将相应的事件同步到各 Broker 节点。这种队列 FIFO 的模式保证了消息的有序性。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">职责</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Controller 被选举出来,作为整个 Broker 集群的管理者,管理所有的集群信息和元数据信息。它的职责包括下面几部分:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 处理 Broker 节点的上线和下线,包括自然下线、宕机和网络不可达导致的集群变动,Controller 需要及时更新集群元数据,并将集群变化通知到所有的 Broker 集群节点; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 创建 Topic 或者 Topic 扩容分区,Controller 需要负责分区副本的分配工作,并主导 Topic 分区副本的 Leader 选举。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 管理集群中所有的副本和分区的状态机,监听状态机变化事件,并作出相应的处理。Kafka 分区和副本数据采用状态机的方式管理,分区和副本的变化都在状态机内会引起状态机状态的变更,从而触发相应的变化事件。 </section></li> </ol> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <span style="display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;">65 哥:状态机啊,听起来好复杂。</p> <span style="float: right;display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">”</span> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Controller 管理着集群中所有副本和分区的状态机。大家不要被<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(255, 93, 108);">状态机</code>这个词唬住了。理解状态机很简单。先理解模型,即这是什么关于什么模型,然后就是模型的状态有哪些,模型状态之间如何转换,转换时发送相应的变化事件。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Kafka 的分区和副本状态机很简单。我们先理解,这分别是管理 Kafka Topic 的分区和副本的。它们的状态也很简单,就是 CRUD,具体说来如下:</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>分区状态机<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">PartitionStateChange,管理 Topic 的分区,它有以下 4 种状态:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> NonExistentPartition:该状态表示分区没有被创建过或创建后被删除了。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> NewPartition:分区刚创建后,处于这个状态。此状态下分区已经分配了副本,但是还没有选举 leader,也没有 ISR 列表。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> OnlinePartition:一旦这个分区的 leader 被选举出来,将处于这个状态。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> OfflinePartition:当分区的 leader 宕机,转移到这个状态。 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们用一张图来直观的看看这些状态是如何变化的,以及在状态发生变化时 Controller 都有哪些操作:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/cfd2963abec4f17820fc3ca5bb3e487f.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>副本状态机<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">ReplicaStateChange,副本状态,管理分区副本信息,它也有 4 种状态:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> NewReplica: 创建 topic 和分区分配后创建 replicas,此时,replica 只能获取到成为 follower 状态变化请求。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> OnlineReplica: 当 replica 成为 parition 的 assingned replicas 时,其状态变为 OnlineReplica, 即一个有效的 OnlineReplica。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> OfflineReplica: 当一个 replica 下线,进入此状态,这一般发生在 broker 宕机的情况下; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> NonExistentReplica: Replica 成功删除后,replica 进入 NonExistentReplica 状态。 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">副本状态间的变化如下图所示,Controller 在状态变化时会做出相应的操作:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/f1d4a0de130048d4800f24c4fadca572.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">Network</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Kafka 的网络通信模型是基于 NIO 的 Reactor 多线程模型来设计的。其中包含了一个<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(255, 93, 108);">Acceptor</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(255, 93, 108);">Acceptor</code> 有 N 个 <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(255, 93, 108);">Processor</code> 线程 select 和 read socket 请求,N 个 <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(255, 93, 108);">Handler</code> 线程处理请求并相应,即处理业务逻辑。下面就是 KafkaServer 的模型图:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.5625" src="/upload/e35a052d8503f5d9e7de677bbf4ef88e.png" data-type="png" data-w="1600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">之后的 Kafka 源码篇,[码哥]将从源码的角度来讲解这些原理在代码上的具体实现,各位敬请期待啊。</p> <p style="text-align: center;"><img class="rich_pages" data-galleryid="" data-ratio="0.41875" data-s="300,640" src="/upload/f71e3ea25788782989ffe06ecf607928.jpg" data-type="jpeg" data-w="1280" style=""></p> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;padding-right: 10px;padding-left: 10px;word-break: break-word;overflow-wrap: break-word;text-align: left;margin-top: -10px;line-height: 1.25;color: rgb(43, 43, 43);font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;letter-spacing: 2px;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.04) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.04) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;"> <h3 data-tool="mdnice编辑器" style="color: black;font-size: 17px;font-weight: bold;text-align: center;margin-top: 20px;margin-bottom: 20px;"><span style="display: none;"></span><span style="border-bottom: 2px solid RGBA(79, 177, 249, .65);color: #2b2b2b;padding-bottom: 2px;"><span style="width: 30px;height: 30px;display: block;background-image: url("https://mmbiz.qpic.cn/sz_mmbiz_png/zTfAIs5rNXiajlShmOBdxgxXDUkof9TiaPTf73XrIrBQ95VNDQXwHEtibu48rQqkAO1Fu7dez7228P9jvicjnHcOWQ/640?wx_fmt=png");background-position: center center;background-size: 30px;margin: auto auto -8px;opacity: 1;background-repeat: no-repeat;"></span>持续坚持原创输出,点击蓝字关注我吧</span><span style="display: none;"></span></h3> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.4255555555555556" data-s="300,640" src="/upload/9228db87c34c3c4a33729681f9a4ac4b.jpg" data-type="jpeg" data-w="900" style=""></p> <p><span style="max-width: 100%;font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;letter-spacing: 2px;text-align: left;color: rgb(136, 136, 136);font-size: 12px;word-spacing: 2px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">作者:小傅哥</span><br style="max-width: 100%;color: rgb(43, 43, 43);font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;letter-spacing: 2px;text-align: left;white-space: normal;font-size: 14px;word-spacing: 2px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;letter-spacing: 2px;text-align: left;color: rgb(136, 136, 136);font-size: 12px;word-spacing: 2px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">博客:https://bugstack.cn</span><span style="border-bottom: 2px solid RGBA(79, 177, 249, .65);color: #2b2b2b;padding-bottom: 2px;"></span><br></p> <blockquote data-tool="mdnice编辑器" style="font-size: 0.9em;overflow: auto;padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;text-size-adjust: 100%;line-height: 1.55em;border-radius: 6px;color: rgb(89, 89, 89);box-sizing: inherit;border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgba(64, 184, 250, 0.4);background: rgba(64, 184, 250, 0.1);"> <span style="color: RGBA(64, 184, 250, .5);font-size: 34px;line-height: 1;font-weight: 700;">❝</span> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 14px;word-spacing: 2px;line-height: 26px;">沉淀、分享、成长,让自己和他人都能有所收获!😜</p> <span style="float: right;color: RGBA(64, 184, 250, .5);">❞</span> </blockquote> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;text-align: left;font-family: PingFangSC-Light;"> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(14, 136, 235);font-size: 1.4em;text-align: center;"><span style="display: none;"></span><span style="font-size: 1.4em;display: inline-block;color: rgb(14, 136, 235);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">目录</span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><br></p> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li><p>一、前言</p></li> <li><p>二、面试题</p></li> <li><p>三、什么是循环依赖?</p></li> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: square;" class="list-paddingleft-2"> <li><p>1. 问题描述</p></li> <li><p>2. 问题体现</p></li> <li><p>3. 问题处理</p></li> </ul> <li><p>四、源码分析</p></li> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: square;" class="list-paddingleft-2"> <li><p>1. 说说细节</p></li> <li><p>2. 处理过程</p></li> <li><p>3. 依赖解析</p></li> </ul> <li><p>五、总结</p></li> <li><p>六、系列推荐</p></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><br></p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">一、前言</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">延迟满足能给你带来什么?</code></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">大学有四年时间,但几乎所有人都是临近毕业才发现找一份好工作费劲,尤其是我能非常熟悉的软件开发行业,即使是毕业了还需要额外花钱到培训机构,在学一遍编程技术才能出去找工作。<em style="color: rgb(14, 136, 235);letter-spacing: 0.3em;">好像在校这几年压根就没学到什么!</em></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">就我个人而言可能是因为上学期间喜欢编程,也从师哥、师姐那里听到一些关于毕业后找工作的不容易,也了解了一些社会上对程序员开发技能的要求级别。也就是得到了这些消息,又加上自己乐于折腾,我给自己定了一个每天都能完成的小目标:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">红尘世界几个王,我自不服迎头上。<br>日敲代码两百行,冲进世界五百强。<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><strong style="font-weight: border;color: #0e88eb;">哈哈哈</strong>,就这么每天两百行代码,一个月就是6千行,一年就是6万行,三年后开始实习就有18万行,一个应届实习生有将近20万行代码的敲击量,几乎已经可以非常熟练的完成各类简单的工作,在加上实习中对整个项目流程真正的断链后,找一个<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">正经</code>的开发工作,还是很容易的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">而这时候找工作的容易,就来自于你一直以来的学习和沉淀,但如果你没经过这些努力,可能等毕业后就会变得非常慌乱,最后没办法,只能去一些机构再学习一遍。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">二、面试题</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">谢飞机,小记!</code>,以前感觉Spring没啥,看过一篇getBean,我的
作者:微信小助手
<section style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn"> <br> </section> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击蓝色“</span><span style="max-width: 100%;letter-spacing: 0.544px;font-size: 14px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">架构文摘</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">”关注我哟</span></p> <p style="margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">加个“</span><span style="max-width: 100%;color: rgb(0, 128, 255);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">星标</span><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”,每天上午 09:25,干货推送!</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 14px;text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-backh="36" data-backw="578" data-ratio="0.0625" data-s="300,640" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.jpg" data-type="jpeg" data-w="640" style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;" width="100%"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">作者:miaowenting</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">原文:https://miaowenting.site/2020/03/24/%E5%85%B3%E4%BA%8E%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%8F%B0%E7%9A%84%E6%80%9D%E8%80%83%E4%B8%8E%E6%80%BB%E7%BB%93/</span></p> <h3 style="margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;font-weight: bold;font-size: 1.1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(63, 63, 63);line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;border-left: 3px solid rgb(0, 152, 116);box-sizing: border-box !important;overflow-wrap: break-word !important;">数据中台</h3> <p style="text-align: center;"><img class="rich_pages" data-galleryid="" data-ratio="0.9598930481283422" data-s="300,640" src="/upload/3d646cc2112682031e75629a5ea6e963.png" data-type="png" data-w="748" style=""></p> <h3 style="margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;font-weight: bold;font-size: 1.1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(63, 63, 63);line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;border-left: 3px solid rgb(0, 152, 116);box-sizing: border-box !important;overflow-wrap: break-word !important;">数据汇聚<br></h3> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">数据汇聚是数据中台必须提供的核心工具,把各种异构网络、异构数据源的数据方便地采集到数据中台中进行集中存储,为后续的加工建模做准备。数据汇聚方式一般有数据库同步、埋点、网络爬虫、消息队列等;从汇聚的时效性来分,有离线批量汇聚和实时采集。</p> <h3 style="margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;font-weight: bold;font-size: 1.1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(63, 63, 63);line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;border-left: 3px solid rgb(0, 152, 116);box-sizing: border-box !important;overflow-wrap: break-word !important;">数据采集工具</h3> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">Canal、DataX、Sqoop</p> <h3 style="margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;font-weight: bold;font-size: 1.1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(63, 63, 63);line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;border-left: 3px solid rgb(0, 152, 116);box-sizing: border-box !important;overflow-wrap: break-word !important;">数据开发</h3> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">数据开发模块主要面向开发人员、分析人员,提供离线、实时、算法开发工具。</p> <h3 style="margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;font-weight: bold;font-size: 1.1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(63, 63, 63);line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;border-left: 3px solid rgb(0, 152, 116);box-sizing: border-box !important;overflow-wrap: break-word !important;">离线开发</h3> <h4 style="margin: 2em 8px 0.5em;font-weight: bold;font-size: 1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(0, 152, 116);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">作业调度</h4> <p style="padding-left: 1em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;list-style: circle;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>依赖调度:所有父作业运行完成后,当前作业才能开始运行。图64中的作业B,只有父作业A和C运行完成后,才能开始被调度。</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>时间调度:可指定作业的调度开始时间。图64中的作业B,只有到达05:00后才能开始被调度。</span></p> <h4 style="margin: 2em 8px 0.5em;font-weight: bold;font-size: 1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(0, 152, 116);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">基线控制</h4> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">在大数据离线作业中,作业执行时间较长,经常遇到急着用数据发现数据还没出来的情况。采用算法对作业完成时间进行智能预测,根据预测,当作业无法正常产出且动态调整无法完成时,调度中心会及时通过监控告警通知运维值班人员提前介入处理,为大数据作业执行留出充裕的时间。</p> <h4 style="margin: 2em 8px 0.5em;font-weight: bold;font-size: 1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(0, 152, 116);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">异构存储</h4> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">企业内部的存储计算引擎呈多元化趋势。离线开发中心针对每种类型的计算引擎会开发不同的组件,例如,针对Oracle开发Oracle插件,针对Hadoop体系分别开发出Hive、Spark、MR等插件。用户在界面新建各种作业类型,在执行时自动根据作业的类型寻找相应的插件来运行作业。</p> <h4 style="margin: 2em 8px 0.5em;font-weight: bold;font-size: 1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(0, 152, 116);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">代码校验</h4> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">对于常见的SQL任务类型,SQL检查器会做好严格的管控,做到事前发现问题。</p> <h4 style="margin: 2em 8px 0.5em;font-weight: bold;font-size: 1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(0, 152, 116);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">多环境级联</h4> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">通过环境级联的方式灵活支持企业的各类环境需求,方便对资源、权限进行控制和隔离。每个环境有独立的Hive数据库、Yarn调度队列,甚至不同的Hadoop集群。常见的环境如下:</p> <p style="padding-left: 1em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;list-style: circle;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>单一环境:只有一个生产环境,内部管理简单。</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>经典环境:开发环境中存放脱敏数据、供开发测试使用,上生产环境走发布流程,用于真实数据生产。</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>任务、资源和函数必须在开发环境下进行新建、修改或删除,再经过提交、创建发布包、同意发布三个操作后,才能同步到生产环境。</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>复杂环境:企业有外部人员和内部人员,会给外部人员提供一个脱敏管控的环境,外部人员开发完的数据模型经过测试后发布到内部开发环境。</span></p> <h4 style="margin: 2em 8px 0.5em;font-weight: bold;font-size: 1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(0, 152, 116);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">推荐依赖</h4> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">随着业务的不断深入,数据开发人员需要开发的作业会不断累加。既能保证准确找到需要定位的上游作业,又能保证不会形成环路。</p> <p style="text-align: center;"><img class="rich_pages" data-galleryid="" data-ratio="0.4706601466992665" data-s="300,640" src="/upload/60c055d8ccced5a666e00cba4610bfe3.png" data-type="png" data-w="818" style=""></p> <p style="padding-left: 1em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;list-style: circle;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>获取推荐依赖的核心原理在于上下游作业输入和输出的表级血缘依赖图;</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>通过血缘分析当前作业的输入和输出,找到合适的上游作业;</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>对合适的作业进行环路检测,剔除存在闭环的作业;</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>返回合适的节点列表。</span></p> <h4 style="margin: 2em 8px 0.5em;font-weight: bold;font-size: 1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(0, 152, 116);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">数据权限</h4> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">企业内部计算引擎多样化,数据权限管理面临如下问题:</p> <p style="padding-left: 1em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;list-style: circle;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>部分引擎拥有独立的权限管理系统(例如Oracle、HANA、LibrA),导致权限申请需要到每一种引擎上单独操作,让使用变得复杂。</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>同一种计算引擎,不同厂商的权限系统有多种,例如Hadoop自身无数据权限系统,由不同厂商各自去实现,目前主要有两种策略:<span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>RBAC(Role-Based Access Control):如Cloudera用的是Sentry,华为的FI也是类似的机制</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>PBAC(Policy-Based Access Control):如Hortonworks用的Ranger</span></span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>数据权限是由大数据集群或数据库运维人员管理的,开发人员无法直接操作或者接触,所有的权限申请都需要运维人员开通,造成运维人员负担过重。在实际开发中,一般需要运维人员把整个库的权限授权给某个开发负责人,然后库里面的表、字段、函数的权限管理由开发负责人负责就行。</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>数据权限管理中心提供界面化操作,数据申请方直接在页面上进行各种权限的申请,数据管理方在界面上审核权限,执行同意或拒绝操作。同时,所有权限的申请、审批都会有记录,便于进行权限审计。在统一数据权限服务中,会对接底层的各种权限管理系统,例如Sentry、Ranger、Oracle,同时对数据权限管理中心提供服务,执行权限的申请、授权、撤销等操作。</span></p> <h3 style="margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;font-weight: bold;font-size: 1.1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(63, 63, 63);line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;border-left: 3px solid rgb(0, 152, 116);box-sizing: border-box !important;overflow-wrap: break-word !important;">实时开发</h3> <p style="padding-left: 1em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;list-style: circle;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>元数据管理</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>SQL驱动</span><span style="margin: 0.2em 8px;max-width: 100%;line-height: 1.75;text-indent: -1em;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 10px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">•</span>组件化开发</span></p> <h3 style="margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;font-weight: bold;font-size: 1.1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(63, 63, 63);line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;border-left: 3px solid rgb(0, 152, 116);box-sizing: border-box !important;overflow-wrap: break-word !important;">智能运维</h3> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">任务的管理、代码发布、运维、监控、告警等一系列集成工具,方便使用,提升效率。重跑、重跑下游、补数据。</p> <h3 style="margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;font-weight: bold;font-size: 1.1em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;color: rgb(63, 63, 63);line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;border-left: 3px solid rgb(0, 152, 116);box-sizing: border-box !important;overflow-wrap: break-word !important;">数据体系</h3> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">有了数据汇聚、数据开发模块,中台已经具备传统数据仓库(后面简称:数仓)平台的基本能力,可以做数据的汇聚以及各种数据开发,就可以建立企业的数据体系。之前说数据体系是中台的血肉,开发、管理、使用的都是数据。</p> <p style="margin: 1.5em 8px;max-width: 100%;min-height: 1em;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">中台数据体系应具备以下特征:</p> <p style="padding-left: 1em;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;font-size: 14px;text-align: left;color: rgb(63, 63, 63);line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Aria
作者:微信小助手
<section style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn" data-mpa-powered-by="yiban.io"> <br> </section> <blockquote style="color: rgb(62, 62, 62);line-height: 25.6px;font-size: 16px;white-space: normal;font-family: 微软雅黑;word-break: normal !important;"> <p style="text-align: left;word-break: normal !important;"><strong style="color: rgb(0, 82, 255);word-break: normal !important;"><span style="line-height: 18px;text-align: -webkit-auto;font-size: 14px;word-break: normal !important;"><strong style="word-break: normal !important;"><span style="text-align: -webkit-auto;word-break: normal !important;"><strong style="word-break: normal !important;">来自:IT技术控</strong></span></strong></span></strong></p> <p style="text-align: left;word-break: normal !important;"><span style="font-size: 12px;text-align: right;">原文链接地址:https://www.zhihu.com/question/344856665/answer/816270460</span></p> </blockquote> <section> <h3 style="line-height: inherit;margin-top: 1rem;font-size: 1.1em;color: rgb(65, 105, 225);font-weight: bold;border-bottom: 2px solid rgb(65, 105, 225);margin-bottom: 20px;"><span style="font-size: inherit;color: inherit;line-height: inherit;display: inline-block;">观点一(灵剑):</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1em;margin-bottom: 1em;"><span style="font-size: 15px;">前期迭代懒得优化,来一个需求,加一个if,久而久之,就串成了一座金字塔。</span></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img data-ratio="0.6825127334465195" src="/upload/706b89ac8c6dc261df117430a52a0653.png" data-type="png" data-w="1178" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.2) 0px 4px 6px 0px, rgba(0, 0, 0, 0.19) 0px 6px 8px 0px;background-color: white;" title=""> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1em;margin-bottom: 1em;"><span style="font-size: 15px;">当代码已经复杂到难以维护的程度之后,只能狠下心重构优化。那,有什么方案可以优雅的优化掉这些多余的if/else?</span></p> <h4 style="color: inherit;line-height: inherit;margin-top: 1rem;margin-bottom: 1rem;font-size: 1em;font-weight: bold;"><span style="font-size: inherit;color: inherit;line-height: inherit;">1. 提前return</span></h4> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1em;margin-bottom: 1em;"><span style="font-size: 15px;">这是判断条件取反的做法,代码在逻辑表达上会更清晰,看下面代码:</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;padding: 0.5em;background: rgb(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (condition) {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">//</span> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">do</span> something<br>} <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">else</span> {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> xxx;<br>}<br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1em;margin-bottom: 1em;"><span style="font-size: 15px;">其实,每次看到上面这种代码,我都心里抓痒,完全可以先判断</span><code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(65, 105, 225);background: rgb(242, 247, 251);">!condition</code>,<span style="font-size: 15px;">干掉else。</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;padding: 0.5em;background: rgb(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (!condition) {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> xxx;<br><br>} <br><span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">// do something</span><br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1rem;margin-bottom: 1rem;font-size: 1em;font-weight: bold;"><span style="font-size: inherit;color: inherit;line-height: inherit;">2. 策略模式</span></h4> <p style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"><span style="font-size: 15px;">有这么一种场景,根据不同的参数走不同的逻辑,其实这种场景很常见。<br>最一般的实现:</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;padding: 0.5em;background: rgb(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (strategy.<span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">equals</span>(<span style="font-size: inherit;line-height: inherit;color: rgb(106, 135, 89);overflow-wrap: inherit !important;word-break: inherit !important;">"fast"</span>)) {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">// 快速执行</span><br>} <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">else</span> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (strategy.<span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">equals</span>(<span style="font-size: inherit;line-height: inherit;color: rgb(106, 135, 89);overflow-wrap: inherit !important;word-break: inherit !important;">"normal"</span>)) {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">// 正常执行</span><br>} <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">else</span> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (strategy.<span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">equals</span>(<span style="font-size: inherit;line-height: inherit;color: rgb(106, 135, 89);overflow-wrap: inherit !important;word-break: inherit !important;">"smooth"</span>)) {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">// 平滑执行</span><br>} <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">else</span> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (strategy.<span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">equals</span>(<span style="font-size: inherit;line-height: inherit;color: rgb(106, 135, 89);overflow-wrap: inherit !important;word-break: inherit !important;">"slow"</span>)) {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">// 慢慢执行</span><br>}<br></code></pre> <p style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"><span style="font-size: 15px;">看上面代码,有4种策略,有两种优化方案。</span></p> <h4 style="color: inherit;line-height: inherit;margin-top: 1rem;margin-bottom: 1rem;font-size: 1em;font-weight: bold;"><span style="font-size: inherit;color: inherit;line-height: inherit;">2.1 多态</span></h4> <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(43, 43, 43);color: rgb(186, 186, 186);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;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">interface</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">Strategy</span> </span>{<br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">throws</span> Exception</span>;<br>}<br><br><span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">class</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">FastStrategy</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">implements</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">Strategy</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">throws</span> Exception </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">// 快速执行逻辑</span><br> }<br>}<br><br><span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">class</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">NormalStrategy</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">implements</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">Strategy</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">throws</span> Exception </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">// 正常执行逻辑</span><br> }<br>}<br><br><span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">class</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">SmoothStrategy</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">implements</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">Strategy</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">throws</span> Exception </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">// 平滑执行逻辑</span><br> }<br>}<br><br><span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">class</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">SlowStrategy</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">implements</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">Strategy</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">throws</span> Exception </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">// 慢速执行逻辑</span><br> }<br>}<br></code></pre> <p style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"><span style="font-size: 15px;">具体策略对象存放在一个Map中,优化后的实现</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;padding: 0.5em;background: rgb(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">Strategy strategy = <span style="font-size: inherit;line-height: inherit;color: rgb(224, 196, 108);overflow-wrap: inherit !important;word-break: inherit !important;">map</span>.get(param);<br>strategy.run();<br></code></pre> <p style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"><span style="font-size: 15px;">上面这种优化方案有一个弊端,为了能够快速拿到对应的策略实现,需要map对象来保存策略,当添加一个新策略的时候,还需要手动添加到map中,容易被忽略。</span></p> <h4 style="color: inherit;line-height: inherit;margin-top: 1rem;margin-bottom: 1rem;font-size: 1em;font-weight: bold;"><span style="font-size: inherit;color: inherit;line-height: inherit;">2.2 枚举</span></h4> <p style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"><span style="font-size: 15px;">发现很多同学不知道在枚举中可以定义方法,这里定义一个表示状态的枚举,另外可以实现一个run方法。</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;padding: 0.5em;background: rgb(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">public</span> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">enum</span> Status {<br> NEW(<span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">0</span>) {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">//do something </span><br> }<br> },<br> RUNNABLE(<span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">1</span>) {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">//do something </span><br> }<br> };<br><br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">public</span> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">int</span> statusCode;<br><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">abstract</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span></span>;<br><br> Status(<span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">int</span> statusCode){<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">this</span>.statusCode = statusCode;<br> }<br>}<br></code></pre> <p style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"><span style="font-size: 15px;">重新定义策略枚举</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;padding: 0.5em;background: rgb(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">public</span> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">enum</span> Strategy {<br> FAST {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">//do something </span><br> }<br> },<br> NORMAL {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">//do something </span><br> }<br> },<br><br> SMOOTH {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">//do something </span><br> }<br> },<br><br> SLOW {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">@Override</span><br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span> </span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(127, 127, 127);overflow-wrap: inherit !important;word-break: inherit !important;">//do something </span><br> }<br> };<br> <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">abstract</span> <span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">void</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">run</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">()</span></span>;<br>}<br></code></pre> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"> <span style="font-size: 15px;">通过枚举优化之后的代码如下</span> </section> <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(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">Strategy strategy = Strategy.valueOf(param);<br>strategy.run();<br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1rem;margin-bottom: 1rem;font-size: 1em;font-weight: bold;"><span style="font-size: inherit;color: inherit;line-height: inherit;">3. 学会使用 Optional</span></h4> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"> <span style="font-size: 15px;">Optional主要用于非空判断,由于是jdk8新特性,所以使用的不是特别多,但是用起来真的爽。</span> </section> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"> <span style="font-size: 15px;">使用之前:</span> </section> <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(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (user == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">null</span>) {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">//</span><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">do</span> action <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">1</span><br>} <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">else</span> {<br> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">//</span><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">do</span> action2<br>}<br></code></pre> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"> <span style="font-size: 15px;">如果登录用户为空,执行action1,否则执行action 2,使用Optional优化之后,让非空校验更加优雅,间接的减少if操作</span> </section> <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(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">Optional</span><User> userOptional = <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">Optional</span>.ofNullable(user);<br>userOptional.map(action1).<span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">orElse</span>(action2);<br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1rem;margin-bottom: 1rem;font-size: 1em;font-weight: bold;"><span style="font-size: inherit;color: inherit;line-height: inherit;">4. 数组小技巧</span></h4> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"> <span style="font-size: 15px;">来自google解释,这是一种编程模式,叫做表驱动法,本质是从表里查询信息来代替逻辑语句,比如有这么一个场景,通过月份来获取当月的天数,仅作为案例演示,数据并不严谨。</span> </section> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"> <span style="font-size: 15px;">一般的实现:</span> </section> <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(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">int getDays(int month){<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">1</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">2</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">29</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">3</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">4</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">30</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">5</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">6</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">30</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">7</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">8</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">9</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">30</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">10</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">11</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">30</span>;<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">if</span> (month == <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">12</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>;<br>}<br></code></pre> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;text-align: left;line-height: 1.75em;"> <span style="font-size: 15px;">优化后的代码</span> </section> <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(43, 43, 43);color: rgb(186, 186, 186);overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">int</span> monthDays[<span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">12</span>] = {<span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">29</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">30</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">30</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">30</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">30</span>, <span style="font-size: inherit;line-height: inherit;color: rgb(104, 150, 186);overflow-wrap: inherit !important;word-break: inherit !important;">31</span>};<br><span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">int</span> <span style="color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">getDays</span><span style="line-height: inherit;color: rgb(185, 185, 185);overflow-wrap: inherit !important;word-break: inherit !important;">(<span style="line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">int</span> month)</span></span>{<br> <span style="font-size: inherit;line-height: inherit;color: rgb(203, 120, 50);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> monthDays[--month];<br>}<br></code></pre> <h4 style="color: inherit;line-height: inherit;margin-top: 1rem;margin-bottom: 1rem;font-size: 1em;font-weight: bold;"><span style="font-size: inherit;color: inherit;line-height: inherit;">结束</span></h4> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;line-height: 1.75em;text-align: left;"> <span style="font-size: 15px;">if else作为每种编程语言都不可或缺的条件语句,在编程时会大量的用到。一般建议嵌套不要超过三层,如果一段代码存在过多的if else嵌套,代码的可读性就会急速下降,后期维护难度也大大提高。</span> </section> <h3 style="line-height: inherit;margin-top: 1rem;font-size: 1.1em;color: rgb(65, 105, 225);font-weight: bold;border-bottom: 2px solid rgb(65, 105, 225);margin-bottom: 20px;"><span style="font-size: inherit;color: inherit;line-height: inherit;display: inline-block;">观点二(IT技术控):</span></h3> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;text-align: left;line-height: 1.75em;"> <span style="font-size: 15px;">不要去过度关注if/else的层数,而要关注接口语义是否足够清晰;单纯减少if/else的层数,然后拆出一堆do_logic1, do_logic2…这样的接口是毫无帮助的。</span> </section> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;text-align: left;line-height: 1.75em;"> <span style="font-size: 15px;">任何一个接口的执行过程都可以表示为:输入 + 内部状态 -> 输出这样的形式,我们分以下几种情况来讨论:</span> </section> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;text-align: left;line-height: 1.75em;"> <span style="font-size: 15px;">输入、内部状态、输出都很简单,但中间逻辑复杂。比如说一个精心优化过的数值计算程序,可能需要根据输入在不同的取值范围采取不同的策略,还有很多逻辑用来处理会引发问题(比如除0)的边界值,这种情况下if/else数量多是难以避免的,根据步骤拆分出一些内部方法有一定帮助,但也不能完全解决问题。这种情况下最好的做法是写一篇详细的文档,从最原始的数学模型开始,然后表明什么情况下采取什么样的计算策略,策略如何推导,知道得到代码中使用的具体形式,然后给整个方法加上注释附上文档地址,并且在每个分支的地方加上注释指明对应到文档中哪个公式。这种情况下虽然方法很复杂,但是语义是清晰的,如果不修改实现的话理解语义就行了,如果要修改实现那么需要参考对照文档中的公式。</span> </section> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;text-align: left;line-height: 1.75em;"> <span style="font-size: 15px;">输入过于复杂,比如输入带有一堆不同的参数,或者有各种奇怪的flag,每个flag有不同作用。这种情况下首先需要提高接口的抽象层次:如果接口有多个不同作用,需要拆分成不同接口;如果接口内部根据不同参数进不同分支,需要将这些参数和对应分支包在Adapter里,使用参数的地方改写成Adapter的接口,根据传入的Adapter类型不同进入不同的实现;如果接口内部有复杂的参数转换关系,需要改写成查找表。这种情况下的主要问题是接口本身抽象的有问题,有更清晰的抽象之后,实现也自然没有那么多if/else了。</span> </section> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;text-align: left;line-height: 1.75em;"> <span style="font-size: 15px;">输出过于复杂,为了省事一个过程计算出了太多东西,又为了性能加了一堆flag控制是否计算之类。这种情况下需要果断将方法拆分成多个不同方法,每个方法只返回自己需要的内容。如果不同计算之间有共用的内部结果呢?如果这个内部结果计算并不形成瓶颈,只要提取出内部方法然后在不同过程中分别调用即可;如果希望避免重复计算,可以增加一个额外的cache对象作为参数,cache内容对用户不透明,用户只保证相同输入使用同一个cache对象即可,在计算中将中间结果保存到cache中,下次计算前先检查有没有已经得到的结果,就可以避免重复计算了。</span> </section> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;text-align: left;line-height: 1.75em;"> <span style="font-size: 15px;">内部状态过于复杂。首先检查状态设置的是否合理,是不是有一些本来应该作为输入参数的东西被放到了内部状态中(比如用来隐式地在两个不同方法调用之间传递参数)?其次,这些状态分别控制哪些方面,是否可以分组然后实现到不同的StateManager里面?第三,画出状态转移图,尝试将内部状态分成单层分支,然后分别实现到on_xxx_state这样的方法里面,然后通过单层的switch或者查找表来调用。</span> </section> <section style="font-size: inherit;color: inherit;margin-top: 1em;margin-bottom: 1em;text-align: left;line-height: 1.75em;"> <span style="font-size: 15px;">其实通常需要优化的都是整体接口抽象,而不是单个接口的实现,单个接口实现不清晰通常是因为接口实现和需求不同构造成的。</span> </section> <figure style="font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;"> <span style="text-align: justify;">--- EOF ---</span> <br> </figure> <p style="font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);"><br></p> <section style="letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 53, 53);text-align: start;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;"> <section powered-by="xiumi.us" style="font-size: 15px;"> <section style="color: rgb(0, 0, 0);font-size: 16px;font-variant-numeric: normal;letter-spacing: 0.544px;text-align: center;"> <section style="letter-spacing: 0.544px;color: rgb(89, 89, 89);font-size: 15px;text-align: left;"> <section> <section> <section> <section> <section> <section> <section> <section> <section> <section> <section> <section style="font-variant-numeric: normal;letter-spacing: 0.544px;color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;word-spacing: 2px;widows: 1;line-height: 27.2px;"> <section> <section style="margin-top: 10px;margin-bottom: 10px;text-align: center;"> <section style="padding-right: 1em;padding-left: 1em;display: inline-block;"> <span style="padding: 0.3em 0.5em;display: inline-block;border-radius: 0.5em;font-size: 14.08px;color: rgb(255, 255, 255);background-color: rgb(249, 110, 87);"> <section> <span style="font-size: 16px;"><strong>推荐↓↓↓</strong></span> </section></span> </section> <section style="margin-top: -1em;padding: 20px 10px 10px;border-width: 1px;border-style: solid;border-color: rgb(192, 200, 209);background-color: rgb(239, 239, 239);"> <section> <section> <section style="text-align: left;"> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzI5ODExMDQzNw==" data-headimg="http://mmbiz.qpic.cn/sz_mmbiz_png/5vSHRsw9GOPEHU5v9h9nbTGa96JOGG9wCrvMVFI5nHiciaE7r9XpsLf2RvfyBw8RIWhl9e7ic5nnibFRPPGqXaGjgA/0?wx_fmt=png" data-nickname="程序员数学之美" data-alias="MathBeauty" data-signature="程序员数学学习,锻炼数学逻辑思维。包含高等数学、线性代数、概率论与数理统计、离散数学、数值分析等课程学习知识。" data-from="0"></mpprofile> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section> </section>
作者:微信小助手
<p style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击蓝色“</span><span style="max-width: 100%;letter-spacing: 0.544px;font-size: 14px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">架构文摘</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">”关注我哟</span></p> <p style="margin-bottom: 10px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">加个“</span><span style="max-width: 100%;color: rgb(0, 128, 255);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">星标</span><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”,每天上午 09:25,干货推送!</span></p> <p style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;color: rgb(62, 62, 62);font-size: 14px;text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-backh="36" data-backw="578" data-ratio="0.0625" data-s="300,640" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.jpg" data-type="jpeg" data-w="640" style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;" width="100%"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);min-height: 1em;text-align: left;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;font-size: 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;">来源:toutiao.com/i6914469326074479108/</span></p> <section style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <br> </section> <section data-mpa-template="t" mpa-from-tpl="t" style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: -apple-system, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-mpa-template="t" mpa-from-tpl="t" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="padding-right: 10px;padding-left: 9px;max-width: 100%;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;caret-color: rgb(60, 60, 60);font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;">在我之前谈API网关的时候曾经谈到过快速开发平台,即将API快速开发的一些内容放入到API网关中,实际来看围绕API全生命周期管理,本身包括了开发态,运行态,运维态。</span> </section> <section style="padding-right: 10px;padding-left: 9px;max-width: 100%;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;caret-color: rgb(60, 60, 60);font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span> </section> <section style="padding-right: 10px;padding-left: 9px;max-width: 100%;font-size: 15px;letter-spacing: 1px;line-height: 1.8;color: rgb(60, 60, 60);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 16px;">对于API网关更多的是解决运行态的问题,API网关本身应该轻量化设计,不做太多的协议转换,适配,数据映射等工作,这些工作应该放到API开发平台来完成。API开发平台最终就是开发完成并暴露一个标准的Http API接口,并将接口注册和接入到API网关。</span> </section> </section> </section> <section style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br> </section> <section data-mpa-template="t" mpa-from-tpl="t" style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-family: -apple-system, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="padding-right: 10px;padding-left: 9px;max-width: 100%;color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;line-height: 1.8;z-index: 10000;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong><span styl
作者:微信小助手
<section style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn"> <br> </section> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">点击蓝色“</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">架构文摘</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”关注我哟</span></span></p> <p style="margin-bottom: 10px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 15px;text-size-adjust: auto;word-spacing: 2px;text-align: center;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;"><span style="max-width: 100%;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">加个“</span><span style="max-width: 100%;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">星标</span><span style="max-width: 100%;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”,每天上午 09:25,干货推送!</span></span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);font-size: 14px;text-align: right;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-backh="36" data-backw="578" data-ratio="0.0625" data-s="300,640" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.jpg" data-type="jpeg" data-w="640" style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;" width="100%"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(136, 136, 136);font-family: Optima-Regular, PingFangTC-light;letter-spacing: 0.544px;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">来源:woshipm.com/pmd/1065960.html</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;"><br></span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 20px;"><strong>一、基于抽象和复杂对产品经理个人能力的一些思考</strong></span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">日常的工作中,假如你身边坐了一个女程序猿,为了让乏味的工作氛围增加点提神的荷尔蒙,文艺又懂点技术的你可能会对她说:小姐姐,我能把世间万物抽象成一个类,但唯独不能抽象你,你在我眼里美的那么具体。然后她开心的接过了你改了又改的需求。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">上面提到了“抽象”的概念,抽象是指从具体事物抽出、概括出它们共同的方面、本质属性与关系等,而将个别的、非本质的方面、属性与关系舍弃,这种思维过程,称为抽象。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">抽象思维是个人能力模型当中很重要的一种软能力,它不像文档能力,Axure能力等的硬能力,只需要通过时间的积累和实践学习就能获得。许多伟大且高级的知识&理论,以及深度的思考,都具有高度的抽象性。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">很多经典的公式:欧拉公式、麦克斯韦方程、质能方程;以及理论:亚里士多德的三段论表述,牛顿的三定律表述,达尔文的进化论表述等。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.37916666666666665" src="/upload/a351e727c974e980103d0198863347c9.jpg" data-type="jpeg" data-w="480" height="133" style="margin-right: auto;margin-left: auto;border-width: 0px;border-style: initial;border-color: initial;display: block;cursor: pointer;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 351px !important;visibility: visible !important;" width="351"></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">基于以上我们都能得出一个结论:<span style="max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">思考越复杂,形式越简单,反之亦然。</span></span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.8771739130434782" src="/upload/efc997b9ce1283ef8ac181ebf1b97cb7.png" data-type="png" data-w="920" height="387" style="margin-right: auto;margin-left: auto;background-color: rgb(238, 237, 235);border-width: 0px;border-style: initial;border-color: initial;background-size: 22px;background-position: center center;background-repeat: no-repeat;display: block;cursor: pointer;box-sizing: border-box !important;overflow-wrap: break-word !important;height: 386.834px !important;width: 441px !important;" width="441"></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">架构图是一个产品经理对整个产品,服务&商业模式有一个高阶抽象理解后的可视化的表达方式,同时也是产品研发初期最应该去规划设计的东西。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;"><br></span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 20px;"><strong>二、产品架构图的设计思考与画法</strong></span></p> <h3 style="margin-top: 30px;margin-bottom: 10px;padding-left: 15px;font-weight: 700;font-size: 18px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.4;color: rgba(0, 0, 0, 0.68);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">2.1 为什么要画</span></h3> <ul class="list-paddingleft-2" style="padding-left: 40px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.6);list-style: none;font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <li style="margin-bottom: 5px;padding-left: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;"><span style="max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">梳理自己对产品方向的判断:</span>思考这张图如何设计的过程,也是帮助你梳理“半年内自己的产品该往何处去?需求应该如何分期和落地?和其他产品的依赖 & 竞争关系是什么?未来的可拓展性在哪里 ?”等问题的过程。</span></p></li> <li style="margin-bottom: 5px;padding-left: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;"><span style="max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">为技术 & 运营的输出形成支撑:</span>当这张图被设计出来后,按照产品架构图的结构和路径,项目的里程碑(RoadMap)就可以被清晰的拆解出来,同时项目成员也可以根据这张架构图,产出运营计划、技术系统架构方案等,强依赖产品方向的方案。</span></p></li> <li style="margin-bottom: 5px;padding-left: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;"><span style="max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">让他人可视化的理解你的产品架构:</span>能较为清晰简单的呈现自己的思路,明确自己的产品边界,指明发展的方向,常用于在项目规划或项目总结中进行演示,帮助不了解你的产品的人快速的建立对你的产品结构、功能、复杂度的认知。</span></p></li> </ul> <h3 style="margin-top: 30px;margin-bottom: 10px;padding-left: 15px;font-weight: 700;font-size: 18px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.4;color: rgba(0, 0, 0, 0.68);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">2.2 何时需要画</span></h3> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;"><span style="max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">建议在复杂项目开始前写:</span>当你要开始设计一个系统性、完整的需求时,如果跳过画产品架构图的步骤,直接开始画原型、写 PRD、kick off,就很容易发生 “改了又改”、“做了一版需求然后又推翻”的情况。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;"><span style="max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">但“种一棵树最好的时间是十年前,其次是现在 ”:</span>如果你的项目已经进行到一半,自己却从未产出过这张图,那么就从此刻开始,按照下文的步骤尝试为自己的产品产出一张产品架构图吧。</span></p> <h3 style="margin-top: 30px;margin-bottom: 10px;padding-left: 15px;font-weight: 700;font-size: 18px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.4;color: rgba(0, 0, 0, 0.68);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">2.3 如何画</span></h3> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-weight: 700;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;">2.3.1 架构图的分类与画法</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">(1)基于技术&功能的产品架构图</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.5767366720516963" src="/upload/e0bcb2eec1640550a640c80cd1586005.jpg" data-type="jpeg" data-w="619" height="316" style="margin-right: auto;margin-left: auto;border-width: 0px;border-style: initial;border-color: initial;display: block;cursor: pointer;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 548px !important;visibility: visible !important;" width="548"></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">这个是相对简单的产品功能架构图,列出产品已经拥有或初期产品规划阶段,应该拥有的功能进行抽象归类,描述出模块结构和关联关系。例如:一些小功能附属于某些大功能,一些功能的前提是拥有另一些功能作为支撑等。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.6791187739463601" src="/upload/45ef25f833cf78769a6253ac253fcf2a.png" data-type="png" data-w="1044" height="383" style="margin-right: auto;margin-left: auto;border-width: 0px;border-style: initial;border-color: initial;display: block;cursor: pointer;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 564px !important;visibility: visible !important;" width="564"></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">当然以上的“技术”都被产品模块封装的很好,没必要展示和强调,有些架构图中会可以强调某些重要的技术。例如:OCR等。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">(2)基于产品,技术和功能的服务架构图</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">下图是阿里云互联网金融解决方案服务架构图,基于现有产品以及产品所承载的功能,提供的服务构成了整套的解决方案架构。对基本的功能和产品进行抽象归类,划分模块。模型框架选用底层,中层,表层来表达。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">说道模型和框架又是一项很重要的能力,工作中我们要去积累遇到的一些框架和模型,理解后有利于参与架构图的设计,也有利于锻炼我们的抽象思维,架构的概念更多的被软件工程所引用。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">例如:</span></p> <ul class="list-paddingleft-2" style="padding-left: 40px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.6);list-style: none;font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <li style="margin-bottom: 5px;padding-left: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">计算机系统的:输入-计算-输出 模型;</span></p></li> <li style="margin-bottom: 5px;padding-left: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">MVC框架的:模型(model)-视图(view)-控制器(controller) 模型;</span></p></li> <li style="margin-bottom: 5px;padding-left: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">互联网的七层协议模型:7 应用层、6 表示层 、5 会话层、 4 传输层 、3 网络层 、2 数据链路层 、1 物理层 ;</span></p></li> <li style="margin-bottom: 5px;padding-left: 20px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">软件系统架构的分层模型:第一层数据存储层, 第二层数据交换层,第三层应用支撑层,第四层应用层,第五层展现层,第六层用户层,等。</span></p></li> </ul> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.9648648648648649" src="/upload/c60c7ef172bef9cf7cd8585c1adf194e.png" data-type="png" data-w="1480" height="572" style="margin-right: auto;margin-left: auto;border-width: 0px;border-style: initial;border-color: initial;display: block;cursor: pointer;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 593px !important;visibility: visible !important;" width="593"></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">(3)基于功能,技术,产品与服务的系生态&商业模式架构图</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">功能基于技术,产品基于功能,服务基于产品,生态系统和商业模式基于所有。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.5544430538172715" src="/upload/769bb86da51a524aa9d97d0c8f48d77e.jpg" data-type="jpeg" data-w="799" height="323" style="margin-right: auto;margin-left: auto;border-width: 0px;border-style: initial;border-color: initial;display: block;cursor: pointer;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 583px !important;visibility: visible !important;" width="583"></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">例如:上图就包含了技术、产品、服务等一系列形成了生态架构或者说商业模式。</span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.8324175824175825" src="/upload/16b67a3ab1edbe04a1b64ed99f5ae49c.png" data-type="png" data-w="1092" height="489" style="margin-right: auto;margin-left: auto;border-width: 0px;border-style: initial;border-color: initial;display: block;cursor: pointer;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 588px !important;visibility: visible !important;" width="588"></p> <h3 style="margin-top: 30px;margin-bottom: 10px;padding-left: 15px;font-weight: 700;font-size: 18px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.4;color: rgba(0, 0, 0, 0.68);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">2.4 回顾总结如何画架构图</span></h3> <ol class="list-paddingleft-2" style="padding-left: 50px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.6);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <li style="margin-bottom: 5px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">搞清楚要画的架构图的类型;</span></p></li> <li style="margin-bottom: 5px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">确认要元素(技术、产品、服务);</span></p></li> <li style="margin-bottom: 5px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">简单架构的关联关系:包含、支撑、同级并列……;复杂架构的关联关系:引用合适的架构和模型,分层后在逐层按照简单架构的关联关系处理;</span></p></li> <li style="margin-bottom: 5px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 16px;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">输出逻辑结构,关联关系清晰的架构图。</span></p></li> </ol> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 20px;"><strong>写在最后</strong></span></p> <p style="margin-bottom: 18px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgba(0, 0, 0, 0.84);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", Helvetica, Arial, sans-serif;font-size: medium;text-align: start;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 16px;">形式简单的东西,往往背后蕴含着巨大的复杂,这部分复杂被转移到思考的层面。爱伊斯坦说过:如果你不能把复杂的东西用最简单的方式表达,那说明你还没有足够的理解它。如果你不用开起来复杂的原型图,流程图就能把一个产品,服务,生态和商业模式讲清楚,那么你就真的理解了。</span></p> <section data-mpa-template="t" mpa-from-tpl="t" style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;caret-color: rgb(0, 0, 0);color: rgb(120, 114, 114);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-id="89429" mpa-from-tpl="t" style="max-width: 100%;border-width: 0px;border-style: none;border-color: initial;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("https://mmbiz.qpic.cn/mmbiz_gif/kiaqiahsnxHd4Zt4378tqib1DnnfKYvZAI7sUNZCYmGN2HCMDFDYV5hLu6HrHIK5BynAAwgHGiafFFU7ibYez6mXL4w/640?wx_fmt=gif");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;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">end</span></p> </section> <section mpa-from-tpl="t" style="margin-top: -26px;max-width: 100%;height: 2px;background-color: rgb(34, 33, 33);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> </section> </section> </section> </section> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <section data-recommend-type="list-title" data-recommend-tid="6" data-mpa-template="t" data-mid="" data-from="yb-recommend" style="max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);width: 677px;display: flex;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-mid="" style="padding: 14px;max-width: 100%;width: 677px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(232, 232, 235);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-mid="" style="max-width: 100%;width: 647px;display: flex;justify-content: center;align-items: flex-end;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-mid="" style="margin-bottom: -14px;padding: 4px 22px;max-width: 100%;height: 28px;font-size: 14px;color: rgb(19, 52, 86);line-height: 20px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/sUbvrqLicbpzB81mjeBxPuxnYdalGxNnJo30L2Hq3WwGficcq8w5YJkLeXnsNHocN53k55TfN5mBpCdicGRyfDg1g/640?wx_fmt=png");background-repeat: no-repeat;background-size: 100% 100%;z-index: 10;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">往期推荐</p> </section> </section> <section data-mid="" style="padding: 17px 16px 9px;max-width: 100%;width: 647px;border-width: 1px;border-style: solid;border-color: rgb(198, 226, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496425_1" data-recommend-article-time="1615605007" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/UtWdDgynLdbNxCVbibjnwGOWpFELTfVT52dm2EvMZ5993UibU4V6j5ACXaaDbrd9aibPMiaQaicG01ZToHZ32mdEnpw/0?wx_fmt=jpeg" data-recommend-article-title="你知道怎么分库分表吗?如何做到永不迁移数据和避免热点吗?" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496425&idx=1&sn=17bfbcf179e4af37933863365df5348c&chksm=9f449e21a8331737b594e3fdcd34b2a9eeea63e78ea6b860588d6dd4ab119c8e52286a407cba#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247497989&idx=1&sn=69f5a27fc5e2a046d4343369356cbb2c&chksm=9f4495cda8331cdb71f52a2436d386cdc02a5150064b7da0aabfb767103db776d7bc967ff80e&scene=21#wechat_redirect" textvalue="推荐一个Nginx 可视化配置神器" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">推荐一个Nginx 可视化配置神器</a></p> </section> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496333_1" data-recommend-article-time="1615425900" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/Baq5lYpIw7Wno7a8LbEOfmgfgFclhreqPhibwpEs5H2enMdY7g5rnRDREu23MePuwvP2SnwdEibZoDBhLU5eicpdw/0?wx_fmt=jpeg" data-recommend-article-title="民生银行在云原生领域的数据中台实践!" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496333&idx=1&sn=42e01a34356795aae51fd450ee19977a&chksm=9f449e45a8331753eb37b23244e5ae7250e137d6304e4d61111c628eb4ab8f41457cd3d65794#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247497551&idx=1&sn=3dd414a10cbc702645a9c58287906265&chksm=9f449b87a833129147fa266afb5f21518d2f771390dfcfc97a73401850f762eb0e52c404aa51&scene=21#wechat_redirect" textvalue="微信小程序商城项目(Java版),拿去毕设又省2千块" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">微信小程序商城项目(Java版),拿去毕设又省2千块</a><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p data-mid="" style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;overflow: hidden;text-overflow: ellipsis;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 data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;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> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496262_1" data-recommend-article-time="1615339500" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/Baq5lYpIw7W9QiacOWpVUVIl7zibdLGfwHMhmAibf3CWRZqMZY7bSD5AQcazk0ic6VwsGaThbU19tEC2r05kPm7fTg/0?wx_fmt=jpeg" data-recommend-article-title="高级程序员必知的 7 种软件架构模式!" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496262&idx=1&sn=14721dad7a6618efe786d1060d8b113f&chksm=9f449e8ea8331798f25e9da321fc2dfef5f890f5cae3a90ffc4c11879a65ec0bba8645f4dea3#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496262&idx=1&sn=14721dad7a6618efe786d1060d8b113f&chksm=9f449e8ea8331798f25e9da321fc2dfef5f890f5cae3a90ffc4c11879a65ec0bba8645f4dea3&scene=21#wechat_redirect" data-linktype="2" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;">高级程序员必知的 7 种软件架构模式!</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496245_1" data-recommend-article-time="1615168879" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/Baq5lYpIw7VlU8smlzOSNeV4pp9CTlojdgP2B6qcb3sLppBccSicgruXg2pwCSW2ZlzOmlUP4GmDko9ARXHHhHQ/0?wx_fmt=jpeg" data-recommend-article-title="【震惊】小伙在公司用了个insert into select 居然被开除了。。。" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496245&idx=1&sn=9e8b0154bbb0954f73a213c17368011d&chksm=9f449efda83317eb07d3dcec2acc8000182c032977407476da7b4779cadef02fe0e0712bcfa9#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496245&idx=1&sn=9e8b0154bbb0954f73a213c17368011d&chksm=9f449efda83317eb07d3dcec2acc8000182c032977407476da7b4779cadef02fe0e0712bcfa9&scene=21#wechat_redirect" data-linktype="2" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;border-bottom: 1px dashed rgb(198, 226, 255);font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;">【震惊】小伙在公司用了个insert into select 居然被开除了。。。</p> </section></a> </section> <section data-mpa-template="t" data-recommend-article-type="list-title" data-recomment-template-id="6" data-recommend-article-id="2247496228_1" data-recommend-article-time="1615084897" data-recommend-article-cover="http://mmbiz.qpic.cn/mmbiz_jpg/A1HKVXsfHNmbOes2txMV7GF3IMRHg4DBbaev8yryC4CeAWwU0icRdX5ibbxlA3jJLaDvsFtibBviaFtIRjjpTJSFXA/0?wx_fmt=jpeg" data-recommend-article-title="主流微服务全链路监控系统之战" data-recommend-article-content-url="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496228&idx=1&sn=9bfffabec05e53ec4ed22135c0ceaaa3&chksm=9f449eeca83317fa66421027e2e1ab272749af4fd272a53e563502a902a9af8c7b90b6e92049#rd" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <a href="http://mp.weixin.qq.com/s?__biz=MzA3ODIxNjYxNQ==&mid=2247496228&idx=1&sn=9bfffabec05e53ec4ed22135c0ceaaa3&chksm=9f449eeca83317fa66421027e2e1ab272749af4fd272a53e563502a902a9af8c7b90b6e92049&scene=21#wechat_redirect" data-linktype="2" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section data-recommend-title="t" data-recommend-content="t" data-mid="" style="padding: 6px;max-width: 100%;width: 613px;display: flex;justify-content: center;align-items: center;flex-wrap: nowrap;font-size: 13px;color: rgb(44, 95, 149);line-height: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;border-bottom: none !important;"> <p data-mid="" style="max-width: 100%;min-height: 1em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;box-sizing: border-box !important;overflow-wrap: break-word !important;">主流微服务全链路监控系统之战</p> </section></a> </section> </section> </section> </section> <section style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(63, 63, 63);font-size: 16px;word-spacing: 1px;caret-color: rgb(255, 0, 0);text-align: center;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;">关注公众号《Java派》</strong> </section> <section style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(63, 63, 63);font-size: 16px;word-spacing: 1px;caret-color: rgb(255, 0, 0);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">回复 </strong> <span style="max-width: 100%;color: rgb(255, 104, 39);box-sizing: border-box !important;overflow-wrap: break-word !important;">1027 </span> <strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">获取三本 </strong> <span style="max-width: 100%;color: rgb(136, 136, 136);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 style="max-width: 100%;color: rgb(255, 104, 39);letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">DDD领域驱动设计</strong></strong><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;color: rgb(63, 63, 63);letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> </strong></strong></span> <strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">电子书</strong> </section> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzA5MTU0OTY0Ng==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/zc3KLDBfJlmPt0J5PXYOoiaG8wsQPZrLevbxMZSfgQ0YypNYaicnbS0P9UicluuOySLSP4CjTcRUVHCZzYeXQ9WlA/0?wx_fmt=png" data-nickname="Java派" data-alias="javapai" data-signature="专注Java相关技术栈:Spring全家筒、Docker、k8s、Mysql、集群、微服务、中间件等知识。" data-from="0"></mpprofile> </section> <section style="margin-top: 15px;margin-bottom: 15px;max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(63, 63, 63);font-size: 16px;word-spacing: 1px;caret-color: rgb(255, 0, 0);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br> <strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></strong> </section> <pre style="max-width: 100%;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section 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;"><img class="rich_pages" data-ratio="0.5555555555555556" data-s="300,640" src="/upload/9d786e52e671b1ce4beb338d1e0d1815.jpg" data-type="jpeg" data-w="900" style="font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);font-size: 15px;font-weight: 700;widows: 1;word-spacing: 2px;caret-color: rgb(0, 0, 0);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !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;text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-weight: 700;widows: 1;word-spacing: 2px;caret-color: rgb(0, 0, 0);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">如有收获,点个在看,诚挚感谢</span><img data-ratio="1" src="/upload/5f7454d24a334e968c32b8ce9ae53c5.png" data-type="png" data-w="19" style="letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-weight: 700;widows: 1;word-spacing: 2px;caret-color: rgb(0, 0, 0);font-size: 16px;display: inline-block;vertical-align: text-bottom;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 19px !important;" width="19px"></p> </section> </section> </section> </section> </section></pre>