Serverless 入门课
蒲松洋(秦粤)
前百度国际化前端组组长
16491 人已学习
新⼈⾸单¥29
Serverless 入门课
15
15
1.0x
00:00/00:00
登录|注册

07 | 后端BaaS化(下):Container Serverless

你好,我是秦粤。上节课,我重点给你讲了业务逻辑的拆和合,拆的话可以借助 DDD 的方法论,也可以用动态网络的思想让微服务自然演进;合的话,我们可以用代码编排,也可以用事件流来驱动。另外,我们还了解了微服务拆解后会带来的安全信任问题,这可以通过微服务的跨域认证 JWT 方案解决。我们还了解了后端应用要支持快速迭代或发布,可以参考微服务搭建灰度发布流水线,也就是发布管道。其实我们在使用 FaaS 过程中遇到的很多问题,都可以借助或参考微服务的解决方案。
现在我们再回顾一下 BaaS 化后的“待办任务”Web 服务,我们已经将后端拆解为用户微服务和待办任务微服务,前端用户访问我们的 FaaS 服务,登录后获取到 JWT,通过数据接口 +JWT 安全地访问我们的微服务。而且我们的 FaaS 和微服务都具备了快速迭代的能力。
BaaS化后的“待办任务”Web服务
到这里,我要指出我之前 rule-faas.js 的一个 Bug,如果你之前亲自动手做过实验的话,估计也有发现。这个 Bug 的直接表现是用户初次请求数据时,如果触发了冷启动,返回的待办任务列表就会为空。
究其原因,是因为冷启动时连接数据库会有延时,这直接导致了第一个请求返回的待办任务列表还未同步到消息队列的数据。要解决这个 bug,我们可以用之前讲过的预热 FaaS 或预留实例的方式,但你也要知道,FaaS 函数扩容时,新启动的函数副本也会出现同样的问题。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Serverless 入门课》
新⼈⾸单¥29
立即购买
登录 后留言

全部留言(13)

  • 最新
  • 精选
  • 我来也
    在完成课后作业时,将docker镜像部署到了本地,阿里云ECI,阿里云k8s,一切都很美好. 但是部署到阿里云serverless k8s的时候,遇到了一个坑,给大家分享一下. 现象: 无法打开todolist页面. 但是控制面板上看pod和容器组状态正常,无重启记录. 排查过程: 1. 使用golang服务制作了一个镜像,端口号也使用3001,部署的服务可以正常访问. (说明操作流程和相关配置无问题) 2. 在控制面板上看,对应的pod运行状态健康,遂在index.js底部添加日志. 发现初始化的日志出来了,说明服务确实是跑起来了. 3. 由于控制面板上无法执行kubectl exec -it 操作进入容器. 顾开启了一个实例,安装了kubectl客户端,登录容器. [由于创建serverless k8s集群时未开通API Server 公网连接端点,所以只能在VPC网络中访问k8s API] 4. 进入容器后,发现curl http://localhost:3001提示连接拒绝. 使用netstat命令提示命令不存在. 在容器内直接使用apt-get update ; apt-get install net-tools 由于网络问题,长时间安装不成功. 5. 修改dockerfile,在制作镜像时执行安装操作. 6. 重新推送镜像,部署服务,进入容器. 发现3001端口果真未监听. 但是netstat -antple中,显示连接了一个阿里云的otsIP地址处于SEND_SYNC阶段.怀疑是网络问题. 结果ping baidu.com果真是ping不通. 7. 尝试还原index.js中监听服务的代码 直接使用: app.listen(PORT, () => console.log(`Example app listening at http://localhost:${PORT}`)) 不再放在client.getRow函数中. 8. 重新推送镜像,部署服务,进入容器. 发现可以正常访问todolist主页,只是没有数据. 9. 猜测是 serverless k8s 默认无法访问公网,需要NAT网关才可以访问公网. 提交工单,得到证实. 需要在创建服务时,添加一个注解,在创建pod时绑定一个eip. 照着工单中的方法,重新还原index.js后部署了一遍,果真可以正常访问todolist首页,且历史记录也有了. 就一个简单的服务不可用,排查起来是相当的麻烦.还要不走弯路. 对[suke]同学留言中的一句话很赞同: "如果想完全hold住serverless 真是的类似全栈这样的工程师来做"

    作者回复: 你领先太多了,我还没介绍到K8s呢。 我们使用很多技术时认知是有一个过程的,一个是理论认知,一个是实践认知。理论认知通过学习就好,实践认知则需要自己去动手碰撞出边界。 这点做得好的,不得不说AWS和Google云了。基本上理论认知和实践认知很接近。国内云由于各种受限,总有很多坑要踩。所以我更希望大家可以自己动手体验一下。可喜的是,国内云的进步也很快,很多大家发现的问题,都在跟进处理。 我也回复了suke同学的提问:我们试过单纯使用Serverless,在日常有合适的事件触发函数场景就可以了,不用hold住全部。但理解Serverless引擎盖下的机制,有助于以后可以我们深入这个领域。

    6
  • Geek_a5c054
    用docker后台运行的时候显示了容器id之后直接就退出了,没在后台运行, 然后,使用docker run -it或者在文件根目录使用npm start的时候显示cannot find module uuid是为什么呀

    作者回复: 可能是你拉取的git分支不对,你可以手动安装一下uuid的npm库。npm install --save uuid。另外如果还有问题,可以加入课程微信群,在微信群里咨询。

    6
    1
  • suke
    老师我觉得,专栏看到这里,如果想完全hold住serverless 真是的类似全栈这样的工程师来做,如果只是让偏前端的工程师开发页面以及简单的业业务逻辑,在真正开发 以及调试的阶段,很难去完全cover ,但是如果把前端页面以外的工作交给后端工程师,实现起来一个是拆分的太细,想想本来一个很简单的列表查询 我不仅要写业务逻辑的查询 我还要把基础的数据查询接口封装到有状态的服务,开发、维护起来很麻烦,后期维护起来排查问题难度都很大,调用链条还变长,怎么看我都觉得serverless有点舍近求远,不知道老师觉得我这个想法有什么问题

    作者回复: 其实我是想通过这门课程也让你了解后端工程师的很多工作。我比较赞同的是解决问题工程师,而不是分前后端。 如果要分前后端,的确如果要hold住整个Serverless架构需要懂运维的全栈工程师。但我们实际使用Serverless协助我们日常的工作并不需要那么深入。你可以理解,你使用FaaS就像可以随时随地调用一个函数处理事件一样。 不过我觉得理解serverless内部的运行原理,对于你日后想深入学习研究,会大有帮助。而不是简单教你如何用Serverless搭建应用,这方面已经有很多课程了。 对于前端工程师来说,理想的状态应该是自己负责前端代码和数据编排接口BFF,也就是SFF。而后端工程师给你提供BaaS。 你的前端资源和数据编排接口一起发布。

    3
    1
  • 神仙朱
    学到这里的确有些吃力了,学完baas我觉得还是不太明白怎么回事。 现在baas是在faas来做,那么肯定最好是无状态的。 正常来说baas应该在哪里做呢。 就是,如果我现在要写一个应用,后端的接口要连数据库,我要怎么做给前端提供接口,难道还是一样直接部署到服务器?

    作者回复: BaaS最佳应该是云服务商来做,例如AWS dynamicDB。目前国内云服务商提供BaaS服务比较少。 BaaS也叫后端即服务,目前在云服务商BaaS服务比较少的场景下,企业可以利用类似于微服务拆解的概念,将后端服务化成API接口。利用FaaS来做服务编排。 未来云服务商提供完备的BaaS服务后,例如Mysql的BaaS,FaaS就可以直接使用了。 BaaS最难解的就是数据库,因为数据库肯定是带状态的,要做成容器化就会遇到CAP的问题。后端接口,需要你封装成RESTFul API。

  • 托尼斯威特
    没有aliyunConfig 文件, 代码没法运行. 看用到aliyunConfig的地方, 读了endpoint, AK/KS, instanceName, tableName, primaryKey. 是不是意味着要想跑这个代码, 我们得自己去见一个tablestore的表格? instanceName填什么?

    作者回复: aliyunConfig文件涉及秘钥,需要同学自己配置一下。在回复区里有具体的表格配置,表格配置内容比较简单,可以多做尝试。也可以看看github仓库的readme。如果还有问题,可以加入我们的微信群里咨询。

    3
  • suke
    老师,这篇文章我看了好几遍,类似java这样的后端服务baas化,冷启动即使是docker容器化启动也是省略不了正常的启动过程的,也就是说无论你从裸机上启动还是docker化启动,时长都差不多呀,这样还是改变不了启动时间很长的问题;另外一种把db服务包装成restful接口,其实这种方式还是需要有状态服务一直存在的,同时,这种方式对于事务问题的解决又带来了新的问题,所以我个人感觉serverless目前局限性很大

    作者回复: 对于Java其实有很多黑科技,例如进程COPY,VM热更新等等。Docker是OS容器,并不会针对Java去做优化,但是云服务商会去用黑科技优化Java启动。 通常我们在业务中是需要结合Serverless和容器技术一起使用来节省成本。目前单依赖Serverless,如果超出了适用的边界,确会受到很大局限。

  • 博弈
    老师,registry.cn-shanghai.aliyuncs.com/jike-serverless/nodejs,这个基础镜像不能拉取,获取不到latest的版本,肿么破

    作者回复: 可能是你的网络问题,建议你开通一下阿里云的镜像仓库服务。https://cr.console.aliyun.com/cn-shanghai/instances/repositories

  • 电光火石
    老师,请问一下,Fass和Bass是不是都可以使用Docker来启动?但是因为Bass会连接数据库,启动时间较长,所以偏向于用Docker启动,而Fass层做服务编排,而且都会提供一项“函数初始化入口”的选项,启动时间会很短,所以是否Docker启动没有那么明显?谢谢了!

    作者回复: 是的,FaaS和BaaS都可以使用Docker启动。仔细看我第一个,你可以发现FaaS和BaaS的底层都是容器。 我后面的课程介绍Knative,就是Container Serverless。作为FaaS和BaaS的实现底层。 云服务商提供的函数初始化入口选项,里面要你提供启动时间的。没有容器Serverless灵活。

  • qinsi
    即便是用了docker,遇到需要编译的npm包,直接复制node_modules目录也可能会因为宿主系统和镜像系统的差异而导致问题吧

    作者回复: 是的,严谨的流程来说是copy时,应该忽略node_module,而重新执行npm install --production安装node_module依赖。 不过大部分的nodejs的库没有依赖底层编译库,除了少部分例如CSS SaaS之类的需要关注操作系统编译。所以目前FaaS,也是支持zip包上传,或者运行构建命令。

  • 我来也
    课后作业: 1. 由于镜像中有aliyunConfig,所以不建议将镜像公开.(即不要推送到默认的 https://hub.docker.com/) 2. 我是在template.yml文件中添加了一行`Initializer: index.initializer`实现了作业1:部署的 rule-faas 函数添加初始化入口 3. 使用阿里云ECI部署时,需要申请弹性公网EIP. 注意: 这里需要指定端口号3001访问服务, 默认的80端口是无法访问到服务的!!! 与本地调试一样,某些操作会触发容器重启. 4. 本地调试时,使用get方法访问`http://localhost:3001/api/rule`可以正常获取结果. 但是完成/删除(使用put/delete方法)时,会提示403"用户得到授权,但是访问是被禁止的。" docker反馈的日志如下: ``` /home/myhome/myapp/node_modules/tablestore/lib/request.js:66 throw err; ^ Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:470:11) at ServerResponse.header (/home/myhome/myapp/node_modules/express/lib/response.js:771:10) at ServerResponse.send (/home/myhome/myapp/node_modules/express/lib/response.js:170:12) at ServerResponse.json (/home/myhome/myapp/node_modules/express/lib/response.js:267:15) at Response.<anonymous> (/home/myhome/myapp/index.js:151:16) at Request.<anonymous> (/home/myhome/myapp/node_modules/tablestore/lib/request.js:162:18) at Request.callListeners (/home/myhome/myapp/node_modules/tablestore/lib/sequential_executor.js:113:20) at Request.emit (/home/myhome/myapp/node_modules/tablestore/lib/sequential_executor.js:81:10) at Request.emit (/home/myhome/myapp/node_modules/tablestore/lib/request.js:189:14) at Request.transition (/home/myhome/myapp/node_modules/tablestore/lib/request.js:57:10) ``` 由于不太懂node.js,所以也不知道如何解决. 之前部署到阿里云FC时是没有遇到过该问题的.

    作者回复: 我刚刚看了一下,是因为JWT token的原因。这个分支加了JWT验证,如果不是浏览器访问请求中带JWT token过来,或者token校验失败,put/post/delete都会报403.

    3
收起评论
显示
设置
留言
13
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部