前后端分离 - 为什么用Node.js搭建中间层
<div class="cnblogs_code" style="text-align: center"><pre>转自:https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2014.jsconfchina.com/slides/herman-taobaoweb/index.html#/</span>
https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">mp.weixin.qq.com/s/KzumZwo3ITX0TZvTIhq4vg</span></pre>
</div>
<h1 style="text-align: center">为什么用Node.js搭建中间层</h1>
<h2>什么是中间层</h2>
<p>在翻看很多技术文章时,大家都提到“中间层”,在很多大型企业中,Node确实承担了“中间层”的角色,那么,Node为什么被广泛的应用在“中间层”呢? </p>
<p><strong>要回答这个问题,先来陈述下什么是中间层。</strong></p>
<p>通常我们把Web领域分为客户端和服务端,也就是前端和后端,这里的后端就包含了网关,静态资源,接口,缓存,数据库等。而中间层呢,就是在后端这里再抽离一层出来,在业务上处理和客户端衔接更紧密的部分,比如页面渲染(SSR),数据聚合,接口转发等等。</p>
<p>以SSR来说,在服务端将页面渲染好,可以加快用户的首屏加载速度,避免请求时白屏,还有利于网站做SEO,他的好处是比较好理解的。<strong>那么对于数据的聚合,接口转发来说,这样做有什么意义呢?</strong></p>
<h2>用Node的4点意义</h2>
<h3>业务驱动</h3>
<p>Node有个突出的优势,他的开发者可以是前端。 </p>
<p>前端对于页面所需要的数据有更好的理解,每个页面要用到哪些接口,每个接口要用到哪些字段前端是最清楚的。再加上实际业务开发中,前端页面需求经常会发生变化,需要修改字段或者数据结构,所以对接页面的这部分接口由前端直接开发非常合适,可以显著的减少沟通成本。</p>
<h3>架构需要</h3>
<p>面向用户的接口由Node中间层负责以后,真正的服务端可以专注于提供基于领域模型的对内接口,做微服务。</p>
<p>比如可以基于Goods模型,提供所有商品相关的接口;基于Users模型,提供所有用户相关接口。当一个接口需要商品+用户信息时,由Node分别查询组装。从整体业务代码维护角度来说,变得更容易,不会因为业务发展使得每个接口都异常繁杂。</p>
<h3>性能满足</h3>
<p>如果仅仅是架构层面的需求,需要有一个中间层来沉淀业务,那用Java,PHP也可以做到,为什么说Node更适合做呢? </p>
<p>因为Node天生异步!</p>
<p>众所周知,js是一门单线程语言,所以Node在实现的时候,需要借助libuv来实现异步。</p>
<p><img src="https://img2018.cnblogs.com/blog/727602/201908/727602-20190812084436133-1706978856.png" alt=""></p>
<p><img src="https://img2018.cnblogs.com/blog/727602/201908/727602-20190812084448990-1104312229.png" alt=""></p>
<p>如图所示,libuv为Node提供了线程池,事件池,异步I/O等能力。正是因为其中网络I/O的异步能力,可以让Node做接口聚合时,能够更高效的异步并发处理。</p>
<h3>成本较低</h3>
<p>Node使用js开发,只需要学习简单的api,前端开发者就可以无障碍使用,学习成本很低。</p>
<p>而且,Node具有活跃的社区和丰富的模块池,拥有很多现成的功能实现。框架方面,也有成熟的koa,express等基本框架和egg等二次封装框架,可根据需求选择上手也比较方便。</p>
<h2>案例:淘宝前后端分离实践</h2>
<p>为什么要前后端分离</p>
<ul>
<li>关注点分离</li>
<li>职责分离</li>
<li>对的人做对的事</li>
<li>更好的共建模式</li>
<li>快速的反应变化</li>
</ul>
<h3>阶段一:后端MVC</h3>
<p><img src="https://img2018.cnblogs.com/blog/727602/201908/727602-20190812090727758-914731976.png" alt=""></p>
<p><strong>VIEW层的两种维护方式</strong></p>
<p>1.前端写Demo,后端套页面</p>
<p>问题:后端需要写<strong>HTML</strong>,且前端仍然需要确认后端写的HTML。</p>
<p>2.前端写View层,后端只管数据</p>
<p>问题:前端需要熟悉后端语言,且前端需要了解<strong>后端架构</strong>。</p>
<p><strong>问题1:前端代码越来越复杂</strong></p>
<ul>
<li>无法统一协作模式,代码充满了约定</li>
<li>JS跟CSS,依赖于后段产出的HTML</li>
<li>有的数据來自AJAX,有的数据印在DOM上</li>
<li>有的业务逻辑在前端,有的在Model层,更多的是在View层</li>
</ul>
<p><strong>问题2:前后端依旧高度耦合</strong></p>
<ul>
<li>前端依赖服务端开发环境</li>
<li>在服务端View层高度耦合</li>
<li>沟通成本高</li>
<li>职责不清晰</li>
</ul>
<p><strong>问题3:无法良好的支持跨终端</strong></p>
<ul>
<li>业务逻辑散落在应用中</li>
<li>渲染逻辑强依赖后端页面</li>
<li>只能用responsive design硬来</li>
</ul>
<p><strong>问题4:高度耦合的前后端分工</strong></p>
<ul>
<li>沟通成本上升</li>
<li>维护成本上升</li>
<li>无法正确且快速的响应变化</li>
<li><span style="color: rgba(255, 102, 0, 1)">代码的腐烂只是迟早的问题</span></li>
</ul>
<h3>阶段二:CLIENT-SIDE MV*</h3>
<p> <img src="https://img2018.cnblogs.com/blog/727602/201908/727602-20190812091757124-395033798.png" alt="" width="735" height="413"></p>
<p>接口分离, 后端提供数据, 前端自己搞</p>
<ul>
<li>MODEL层 - JAVASCRIPT OBJECT</li>
<li>VIEW层 - JAVASCRIPT TEMPLATE</li>
</ul>
<p>业界满坑满谷的优秀方案:Backbone, EmberJS, KnockoutJS, AngularJS, React, etc.</p>
<p><strong>前后端职责清晰了</strong></p>
<table class="pull-down w100">
<thead>
<tr><th>后端</th><th>前端</th></tr>
</thead>
<tbody>
<tr>
<td>
<ul>
<li>提供数据</li>
<li>处理业务逻辑</li>
<li>Server-side MVC架构</li>
<li>代码跑在服务器上</li>
</ul>
</td>
<td>
<ul>
<li>接收数据,返回数据</li>
<li>处理渲染逻辑</li>
<li>Client-side MV* 架构</li>
<li>代码跑在浏览器上</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p><strong> 问题1:各层职责重叠,并且各玩各的</strong></p>
<ul>
<li>Client-side Model是Server-side Model 的加工</li>
<li>Client-side View跟Server-side是不同层次的东西</li>
<li>Client-side的Controller跟Sever-side的Controller各搞各的</li>
<li>Client-side的Route在Server-side可能没有</li>
</ul>
<p><strong>问题2:性能问题</strong></p>
<ul>
<li>渲染,取值都在客户端进行,有性能的问题</li>
<li>需要等待资源到齐才能进行,会有短暂白屏与闪动</li>
<li>在移动设备低速网路的体验奇差无比</li>
</ul>
<p><strong>问题3:重用问题</strong></p>
<ul>
<li>模版无法重用,造成维护上的麻烦与不一致</li>
<li>逻辑无法重用,前端的校验后端仍须在做一次</li>
<li>路由无法重用,前端的路由在后端未必存在</li>
</ul>
<p><strong>问题4:跨终端问题</strong></p>
<ul>
<li>业务太靠前,导致不同端重复实现</li>
<li>逻辑太靠前,造成维护上的不易</li>
</ul>
<p><strong>问题5:SEO问题</strong></p>
<ul>
<li>渲染都在客户端,模版无法重用,SEO实现麻烦</li>
</ul>
<h3>阶段三:重新定义前后端</h3>
<p>是依照<strong class="strong">工作职责</strong>来划分的前后端,还是依照<strong class="strong">硬体环境</strong>划分的前后端?</p>
<p><strong>传统认知的前后端(按硬体环境划分)</strong></p>
<p><strong><img src="https://img2018.cnblogs.com/blog/727602/201908/727602-20190812092932287-1306682930.png" alt=""></strong></p>
<p><strong>重新定义的前后端(按工作指责划分)</strong></p>
<p><strong><img src="https://img2018.cnblogs.com/blog/727602/201908/727602-20190812093059148-1240096204.png" alt=""></strong></p>
<p><strong><span style="color: rgba(255, 102, 0, 1)">在服务器(JAVA)与浏览器(JS)的中间架了一个中间层(NODEJS)</span></strong></p>
<h3>WHY NODEJS</h3>
<ul class="fragment visible" data-fragment-index="0">
<li>前端熟悉的语言,<strong class="strong">学习成本低</strong></li>
<li>都是JS,可以<strong class="strong">前后端复用</strong></li>
<li>体质适合:<strong class="strong">事件驱动</strong>、<strong class="strong">非阻塞I/O</strong></li>
<li>适合<strong class="strong">IO密集型业务</strong></li>
<li>执行速度也不差</li>
</ul>
<p><strong>指责划分</strong></p>
<table class="pull-down w100">
<thead>
<tr><th class="center">
<h3>后端</h3>
</th><th class="center" colspan="2">
<h3>前端</h3>
</th></tr>
<tr><th class="center" colspan="2">服务器</th><th class="center">浏览器</th></tr>
<tr><th class="center">JAVA</th><th class="center">NodeJS</th><th class="center">JS + HTML + CSS</th></tr>
</thead>
<tbody>
<tr>
<td>
<ul>
<li>服务层</li>
<li>提供数据接口</li>
<li>维持数据稳定</li>
<li>封装业务逻辑</li>
</ul>
</td>
<td>
<ul>
<li>跑在服务<strong class="strong">器</strong>上的JS</li>
<li>转发数据,串接服务</li>
<li>路由设计,控制逻辑</li>
<li>渲染页面,体验优化</li>
<li>更多的可能</li>
</ul>
</td>
<td>
<ul>
<li>跑在<strong class="strong">浏览器</strong>上的JS</li>
<li>CSS、JS加载与运行</li>
<li>DOM操作</li>
<li>任何的前端框架与工具</li>
<li>共用模版、路由</li>
</ul>
</td>
</tr>
</tbody>
</table>
<h3>职责清晰的架构 + 前端范围的扩展 = 更多的可能</h3>
<h2> </h2>
<h2><strong>实际示例1:淘宝首页优化 </strong></h2>
<h3>需求</h3>
<ul>
<li>静态资料展示,方便运营管理</li>
<li>更好的承载密集且庞大的流量</li>
</ul>
<h3>解决方案</h3>
<ul>
<li>页面缓存与定时刷新,返回缓存资料</li>
<li>NodeJS产出静态页面到CDN,定时刷新</li>
</ul>
<p><img src="https://img2018.cnblogs.com/blog/727602/201908/727602-20190812093719165-1233419283.png" alt=""></p>
<h2>实际示例2:淘宝详情页优化 </h2>
<h3>需求</h3>
<ul>
<li>单日四亿PV,页面数据来自各个不同接口</li>
<li>为了不影响体验,先产生页面框架后再发起多个异步请求取数据更新页面。这些多出来的请求带来的影响不小,尤其在无线端</li>
</ul>
<h3>解决方案</h3>
<p>在NodeJS端使用<span style="color: rgba(255, 102, 0, 1)">Bigpiper</span>技术,合并请求,降低负担,分批输出,不影响体验。</p>
<h2>其他优化:</h2>
<p><strong>页面渲染优化</strong></p>
<ul>
<li>前后端共享模版</li>
<li>首屏服务器渲染</li>
<li>次屏浏览器渲染</li>
<li>局部刷新浏览器渲染</li>
</ul>
<p><strong>单页面应用优化</strong></p>
<ul>
<li>前后端共享路由与模版</li>
<li>前端换页,浏览器端渲染</li>
<li>直接输入网址,服务器渲染</li>
<li>SEO问题迎刃而解</li>
</ul>
<p><strong>可靠性优化</strong><br>单元测试,页面测试,回归测试,持续集成。</p>
<p><strong>接口性能优化</strong><br>拆分大接口为独立小接口,并发请求。串行 => 并行,大幅缩短请求时间。</p>
<p><strong>部署优化</strong><br>一台NodeJS对多台JAVA服务器,合理的分配服务器带来最大的产出。</p>
<p> </p>
<p><strong>优化时秉承的思想:</strong><span style="color: rgba(255, 102, 0, 1)"><strong>接口服务化 代码模块化 功能组件化</strong></span></p><br><br>
来源:https://www.cnblogs.com/helios-fz/p/11337894.html
頁:
[1]