2019-01-02网站基础架构的思考

大部分人认同开发微信小程序或SPA(WEB单页应用)是实现“前后端分离”的。所有业务数据都是“后端应用”通过HTTP接口提供给“前端应用”。一个“完整的应用”被物理隔离为两个独立的应用,并由擅长的开发者负责,从而实现职责分离

前端开发者:负责 View 和 Controller 层。

后端开发者:只负责 Model 层,业务处理/数据等。

“前后端分离”是强调“职责分离”,上面应用分离的例子是为了方便理解接受,可以不应用分离。通常应用分离能大量减少不小心的越界行为。

分离前:前端开发者提供静态页面,后端开发者完成 Controller 和 View 层代码。但前端开发者经常会插一脚修改 Controller 和 View 层代码。

分离后:面向用户的 Controller 和 View 层都由前端开发者做;后端开发者只需复杂 Model 层,提供业务数据接口。

在自己服务器测试两种场景。

服务器配置:

腾讯云服务器(Ubuntu 16.04.1 LTS)

CPU: 2核

内存:4GB

带宽:2M

Node.js环境:

Node.js版本:v8.12.0(Alinode v3.12.0)

框架:Egg.js

worker进程数:2

PHP环境:

PHP版本:7.2.10

框架:Lumen

php-fpm最大子进程数:5

两种场景测试代码:

场景一,直接输出字符串,不做任何IO和计算。

PHP效率比Node.js高

Node.js:

// egg-4asyncfunctiontest(ctx){  ctx.body ='<h1>goddess.daifee.com</h1><p>Egg程序</p>';}

egg-4.png

PHP:

// php-4$router->get('/test',function()use($router){return'<h1>goddess-php.daifee.com</h1><p>这是PHP服务</p>';});

php-4.png

场景二,模拟200ms的网络请求。

Node.js效率比PHP高。相对“场景一”PHP效率下降明显,Node.js不明显。

Node.js:

// egg-4—test2asyncfunctiontest2(ctx){conststart =Date.now();awaitnewPromise(resolve=>{    setTimeout(()=>{      resolve(true);    },200);  });constoffset =Date.now() - start;  ctx.body =`

goddess.daifee.com

Egg程序${offset}

`;}

egg-4-test2.png

PHP:

// ./WeTest_[php-4—test2]_20181014172129.pdf$router->get('/test2',function()use($router){    $start = microtime(true);    usleep(200000);    $offset = microtime(true) - $start;return"<h1>goddess-php.daifee.com</h1><p>这是PHP服务 {$offset}</p>";});

php-4-test2.png

3.2 基于Egg.js框架开发(编码)

下面用Egg.js框架开发一个页面为例(浏览器端开发模式不需要改变)。

开发一个新页面(用户主页页),只需要下面4个步骤:

模板:创建模板文件。

<!-- app/views/user.ejs -->这里是 ejs 模板

数据接口:几行代码封装数据接口。

// app/service/user.jsconst{ Service } =require('egg');module.exports =classUserServiceextendsService{asyncget(userId) {consturl =`https://api.gateway.com/xxx/${userId}`;// http请求/ajaxconstresponse =awaitthis.app.curl(url);returnresponse;  }}

控制器:过滤/验证用户输入、验证权限、调用数据接口、渲染模板。

// app/controller/user.jsconstBaseController =require('./base-controller');module.exports =classUserControllerextendsBaseController{asyncprofile() {const{ params, service } =this.ctx;// 只有自己才能访问自己主页。不是自己就抛出 403 异常this.assertUser(params.userId);    user =awaitservice.user.get(params.userId);awaitthis.render('user', {user: user});  }}

路由:一行代码声明路由。

// app/router.jsmodule.exports =app=>{const{ router, controller, middleware } = app;const{ authorize } = middleware;const{ user } = controller;// 已登录用户才能访问router.get('/users/:userId', authorize.user, user.profile);}

只负责 Controller 和 View 层的Node.js服务端开发非常简单。一个企业应用除了开发,还有其他环节需要做好。

3.3 我们还缺什么?

前端开发者可以在服务端写 Controller 和 View 层代码,但整个生产环节还缺什么?

3.3.1 前端开发者

既然前端开发者需要做更多,能做更多,所以工作量增加。所以缺前端开发者。

同一个项目,编码的工作量增加了。

前端同事需要关注、分析、协助维护Node.js服务器。

肯定会有更多的xxx小程序需求。

3.3.2 适合我们的框架和项目脚手架

确定了web网站应用使用Egg框架,还需为不同业务场景的项目创建拿来即用的脚手架。

未确定React Isomorphic应用的框架。我体验过next.js,是一个不错的选择。

3.3.3 构建/部署服务

目前还没有Node.js项目的构建/部署服务。

基本需求:

构建:开发者只需关注源码,“构建服务”自动构建项目。

发布:支持选择git tag构建,部署到“生产环境”。

发布:支持选择git branch构建,部署到“测试环境”。

回滚:支持指定版本回滚。

重启:支持重启Node.js服务器。

发布:允许测试人员发布“测试版本”。

3.3.4 严谨的git工作流

需要依据“构建/部署服务”定制严谨的git工作流。

3.3.5 风险监控和日志采集

风险监控可以考虑Alinode。

完全免费

支持性能监控、安全提醒、故障排查、性能优化等

支持手动下载性能数据

日志采集接入大数据团队的服务?

关于React Isomrophic

当时用React全家桶做了一个SPA Demo项目,然后用next.js框架再做一个React Isomorphic版。发现可以复用(copy)98%的代码,然后花一点时间将 React Router 替换为 next.js 自带的 Router 即可

基于 next.js 框架 React Isomorphic 应用与 SPA 的开发体验差不多。

毕竟一套代码运行于两个不同环境,React Isomorphic 还是带来了一些坑:

需要意识到哪些代码在2个环境都执行,哪些代码只在其中一个环境执行。

立即执行的代码在2个环境都执行。

React组件生命周期的代码只在Browser环境执行。

Component.getInitialProps()方法在2个环境都执行。

小心使用运行环境的“接口”

next.js自带Router,与“其他Router”肯定存在差异。

某些组件需要用唯一自增ID或随机数,这种做法会使服务端于客户端存在差异。

“服务端”与“客户端”基本只能用cookie共享“状态”,要珍惜cookie资源。

作者:daifee

链接:https://www.jianshu.com/p/1f3f3f70be33

來源:简书

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

个人倒是觉得。如果有条件的话,架构上可以考虑底层接口采用java来提供基层的共性接口,可以保证高并发和稳定性。然后在业务逻辑处理上,采用php进行处理,为前端提供接口服务,而在前端则采用vue来模块化界面。



所以我们就需要有发布系统,发布系统定义了统一的回退操作,所有服务必须遵循发布系统的定义回退操作。 在饿了么对接发布系统是对所有人的强制要求,所有的系统必须全部接入发布系统。发布系统的框架很重要,这个东西其实对于公司是很重要的一件事情,需要放到第一优先级的队列里面去考虑。

四、服务框架

紧接着就是饿了么的服务框架,把一个大的Repo拆分成一个小的Repo,把一个大的服务拆成一个小的服务,让我们的服务尽量独立出去,这需要一套分布式服务框架来支撑。 分布式服务框架包含的服务注册、发现、负载均衡、路由、流控、熔断、降级等功能,这里就不一一展开了。前面已经提及,饿了么是多语言的生态,有 Python的,也有Java的,我们的服务化框架对应也是多语言的。这对我们后来一些中间件的选型是有影响的,比如说DAL层。

五、DAL数据访问层

当业务量越来越大的时候,数据库会变成一个瓶颈。 前期可以通过提升硬件的方式来提升数据库的性能。比如:

升级到一个有更多CPU的机器;

把硬盘改成 SSD 的或者更高级一点的。

但硬件提升终归是有一个容量限制的。而且很多做业务的小伙伴,写代码的时候都直接操作数据库,发生过很多次服务一上线数据库就被打爆的情形。数据库被打爆掉了之后,除非等待数据库恢复,没有任何其它机会可以恢复业务。 如果数据库里面数据是正常的,业务其实都可以补偿出来。所以我们做DAL服务层的时候,第一件事情是限流,其它的东西可以放一放。然后做连接复用,我们Python框架用的多进程单线程加协程的模型。 多进程之间其实是不可以共享一个连接的。比如:一台机器上部署了10个 Python进程,每个进程10个数据库连接。再扩展到10台机器上,就有1000个数据库连接。对数据库来说,连接是一个很昂贵的东西,我们DAL层要做一个连接复用。 这个连接复用讲的不是服务本身的连接复用,而是说DAL层上的连接复用,就是服务有1000个连接到DAL层,经过连接复用后对数据库可能只是保持着十几个连接。一旦发现某个数据库请求是一个事务的话,那么DAL就帮你保留这个连接的对应关系。当这个事务结束之后,就把数据库的连接,放回到共用池里面去,供其他人使用。 然后做冒烟和熔断。数据库也可以熔断的。当数据库发生冒烟时,我们会杀掉一些数据库的请求,保证数据库不至于崩溃。六、服务治理服务框架之后,涉及服务治理的问题。服务治理其实是一个很大的概念。首先是埋点,你要埋很多的监控点。 比如有一个请求,请求成功了或者失败了,请求的响应时间是多少,把所有的监控指标放到监控系统上面去。我们有一个很大的监控屏幕,上面有很多的监控指标。有专门小组72小时去盯着这个屏幕,如果有任何曲线波动了,就找人去解决。另外是报警系统,一个监控屏幕展示的东西总是有限的,只能放那些很重要的关键指标。这个时候就需要有报警系统。 罗马不是一天建成的,基础架构更是一个演进的过程。我们的资源和时间总是有限的,作为架构师和 CTO 来说,如何在这种有限的资源下,产出更重要的东西? 我们做了很多系统,觉得自己做得很不错了,但实则不是,我感觉我们又回到了石器时代,因为问题越来越多,需求也越来越多,总感觉你的系统里还缺点什么东西,想做的功能也一大堆。 比如对于流控系统,现在我们还是需要用户去配一个并发数,那么这个并发数,是不是根本不需要用户去配?是不是可以基于我们服务本身的一个状态自动去控制并发数? 然后是升级方式,SDK升级是个很痛苦的事情。比如说我们服务框架2.0发布的时候是去年12月份,到现在还有人用的是1.0。是不是可以做到SDK的无损感升级,我们自己来控制升级的时间和节奏。 还有,我们现在的监控只支持同一个服务上的汇聚,是不分集群、不分机器的,那是不是以后的指标可以分集群、分机器?举一个最简单的例子,比如一个服务上有10台机器,那么可能只是某一个机器上出了问题,但它所有的指标都会平均分摊到其它的9台机器上去。你只是看到了整个服务延时增加了,但有可能只是某一台机器拖慢了整个服务集群。但我们现在还做不到更多维度的监控。 还有智能化的报警,这个报警,就是要快、全、准,我们现在做到更快了,做到更全了,怎么才能做到更准?每天的报警量高峰时间一分钟一千多个报警发出去。所有的一千报警都是有用的吗?报警多了之后,就相当于没有报警。大家都疲劳了,就不去看了。我怎么能够把这个报警更准确地区分出来?还有更智能化的链路分析?以后是不是我们的监控不要放监控指标,而是放链路分析,这样就能够很清晰地知道,这个问题对应的是哪一个结点上出了问题。 这些问题涉及我们做事的一个原则:东西够用就好,但是要能够未雨绸缪,做一定的超前规划。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容