顾宇:构建Serverless 风格微服务实战解析(上)

向作者提问
埃森哲咨询经理。专注于DevOps、持续交付,微服务以及全功能产品开发团队的设计、实践、落地和推广。
查看本场Chat

2017年9月20日,周三晚上8点30分。专注于 DevOps、微服务及全功能敏捷产品团队发展,拥有丰富的大型系统实战经验,ThoughtWorks高级咨询师顾宇带来了主题为《Serverless 风格微服务的持续交付(上):架构案例》的交流。以下是主持人哈比整理的问答实录,记录了作者和读者问答的精彩时刻。


内容提要:

  • 遗留代码主要会给其他团队带来什么问题?你是建议项目全部完成后再统一删除遗留代码,还是在做的过程中一点点删除?
  • 运行 AWS Lambda 需要用指定的 API 网关、DynamoDB、S3 等服务,一旦在这之上开发出复杂系统,之后就不大可能更换了。迁移成本很大,你怎么看待这一缺点?
  • 请问目前使用 Serverless 架构的成功案例多不多,你知道的有哪些?
  • AWS Lambda 是亚马逊推出的第一个 FaaS 云服务平台,但后来出现了 Microsoft Azure、Google Cloud Platform、IBM Bluemix/Apache OpenWhisk 等 Severless 架构平台,请问我们现在选择架构平台可以从哪几个方面考虑?
  • Serverless 架构怎么规避数据库连接数的限制?
  • 函数都是无状态的,跟其它函数不能共享,这时怎么使用连接池?如果是容器类实现的架构,底层不是用 JVM,实际上就是拼连接数吗?
  • 客户舍不得删除现有的代码,总觉得有些功能现在不用,将来业务还会有用。如何面对这条朋友圈讨论的「不要留着无用的遗留代码」这一实际问题?
  • 请问 Lambda 和传统的计算平台相比,优势有哪些?
  • 如果无服务器服务终将变成类似存储过程的技术,一个原本挺好的想法可能很快欠下一大堆技术债,你怎么看这个问题?
  • 怎么理解 Severless 意味着不需定时维护,并不代表完全去除服务器这句话?
  • 用权限做好流量导向控制,指的是用同一套环境但不同的数据库吗?
  • 以遗留代码为例,有些问题不是技术问题,但混杂在工作中,导致推进困难。问题其实出在人上面,达成共识很重要。但我不太明白的是,如果自己没有那么大能量去左右他人的想法,该怎么办?
  • 如果有线上用户出现问题,测试想要重现问题的话,可能需要用该线上用户的数据来验证,怎么做才不会影响线上数据?

问:遗留代码主要会给其他团队带来什么问题?你是建议项目全部完成后再统一删除遗留代码,还是在做的过程中一点点删除?

答:首先我认为代码的主要作用有两个:

  1. 使计算机能够正确执行期望的功能。

  2. 程序维护者之间的交流和沟通。

代码不光是写给计算机的,也是写给程序员的。所谓好的代码,就是能够传递出好的思考方式。然而,这样的能力对程序员的要求是极高的。

再加上语法灵活的编程语言,例如案例中的 Ruby on Rails 项目。就会导致程序员之间信息传递低效。这会大大降低代码维护的效率,尤其是紧急修复 Bug。TDD 的开发方式解决了以上两个问题。

熟悉 Golden Circle 交流模型的朋友们会知道。沟通从 Why 入手,然后是 How 和 What 的效率很高,这样容易产生共同理解。而 TDD 就是先通过测试把目的抛出来(Why),然后构建测试逻辑(How),最后是代码(What)。正在这个过程中,代码不是最重要的,问题和描述问题的场景是最重要的。

套用以前的一句话:“如果你给我看你的代码,而没有测试,我仍然会迷惑。如果你做了测试,我就不需要你的代码了,因为它是显而易见的。“

换句话说,只要有测试,代码不是必须的。

然而,现在的维护交接都是缺乏测试的代码。这就给了被交接程序员很大的难度,他要去猜测原程序员的意图。这样就浪费了时间。

关于删除遗留代码,一定要是在有自动化测试保护的情况下进行。无论是统一删除,还是过程中一点点删除,这都是一个很有效率的手段。我建议拆出一个模块,只删除掉一个模块原先的代码,这样就能使程序员减少代码阅读和理解的工作量。


问:运行 AWS Lambda 需要用指定的 API 网关、DynamoDB、S3 等服务,一旦在这之上开发出复杂系统,之后就不大可能更换了。迁移成本很大,你怎么看待这一缺点?

答:这也是我担心的问题。任何技术都是一把双刃剑,平台带来了便利性的同时,也形成了技术依赖和技术绑架。就如同手机和移动互联网对我们当今生活产生的重大影响一样。

因此,在做技术选型的时候,一定要面对当前的组织痛点和技术痛点。在文中的案例里,Lambda 并不是我们第一选择,这是由于多重因素共同作用下形成的决定。所以,如果决定使用 Lambda,一定要做好投入产出比分析。


问:请问目前使用 Serverless 架构的成功案例多不多,你知道的有哪些?

答:我认为对于成功的定义有很多很难定义。在本文中,成功被定义为:降低了综合性成本。

主要体现在以下四点:

  1. 减少了运维的负担;

  2. 降低了开发团队的技术门槛;

  3. 降低了环境管理的负担;

  4. 减少了组织中的工作流阻塞。

我知道的另一个案例是澳大利亚的某博彩机构在线应用。这个应用里面有一个算子,这个算子的作用是从概率的角度让该博彩机构从统计上说始终保持盈利。这是一个纯计算的功能,放到 Lambda 里和 Api Gateway 绑定作为一个单独的 API 会非常合适。

当然,Lambda 的应用也有另外一面。下一篇文章我会讲我们在应用 Serverless 中碰到的问题和坑。

其它我了解但没有实际参与的 Serverless 都是小型的应用或功能。目前 Lambda 的应用场景还十分有限,所以都是混合型架构中的一些细微的功能,大规模的使用还没有见到。

我目前所在的项目正在准备大规模使用 Lambda,等上线一段时间之后再和大家分享使用情况。


问:AWS Lambda 是亚马逊推出的第一个 FaaS 云服务平台,但后来出现了 Microsoft Azure、Google Cloud Platform、IBM Bluemix/Apache OpenWhisk 等 Severless 架构平台,请问我们现在选择架构平台可以从哪几个方面考虑?

答:其它的平台我还没有使用过。不过就我目前应用的经验,包括我现在正在做的某客户项目,都采用 AWS Lambda。

在本系列的第三篇,我会和大家分享一下 Serverless 的编程模型概念:服务即状态机,数据即事件,函数即状态转变过程。这样, Serverless 架构就把孤立的云服务资源整合成了一个系统。

目前主要有以下几点因素需要考虑:

  1. 与该云平台其它组件的集成成本。Serverless 的主要目的是最小化云平台组件之间的通信。如果集成成本很高,就没有任何优势。

  2. 编程语言门槛。支持函数式的编程语言都是很好的选择,但是相应的程序员就成为了门槛。所以,目前 Node.js 是一个最佳的选择。其它的诸如 Scala 和 Java 等也都有相应的支持。但不如 js 来的方便。我们在 Aws 上比较了一下, Node.js 的开发效率比较高。且 js 程序员的雇佣成本都是较低的。就是做同样的功能,对 Java 和 Node.js 都不熟的程序员,分别花了多长时间部署一个 Serverless 架构的功能。这个是悉尼的情况。很多前端程序员可以兼后端程序员。js 比 Java 提升的的效率有 4-6 倍不等。java 入门还是需要一段时间的。

  3. 安全。执行 Lambda 是否有权限控制,数据输入输出是否可控制。

  4. 性能。如果性能不好,即便降低了开发的成本,运维的成本也会攀升。所以要对云平台做性能测试。当然,Lambda 也实现了断路器模式。

有关断路器模式,按左耳朵耗子老师的说法就是:缩小爆炸半径。你也可以看看这篇引用:《断路器模式》


问:Serverless 架构怎么规避数据库连接数的限制?

答:简单来说,目前还是采用连接池和缓存。把函数的一次执行看作是一次数据库连接,超出连接数就会排队。当然,这也会让一些函数连接数据库超时返回异常。


问:函数都是无状态的,跟其它函数不能共享,这时怎么使用连接池?如果是容器类实现的架构,底层不是用 JVM,实际上就是拼连接数吗?

答:函数是无状态的,但执行期间会有一个进程,这个进程是有状态的。此外,底层的 JVM 是共享的。

AWS 官方给的编程模型是抽象成容器的,但底层怎么实现确实也没有公布。目前这些都是一种猜测。你说的也完全有道理。


问:客户舍不得删除现有的代码,总觉得有些功能现在不用,将来业务还会有用。如何面对这条朋友圈讨论的「不要留着无用的遗留代码」这一实际问题?

答:首先这个例子对代码的情况是不透明的。其次,无用的代码一定是要验证的。比如通过代码走查,或者通过对应的自动化测试覆盖。

「也许」是一种概率性表述。要通过一些手段把它变成确定性表述,这样才能降低整体的风险。另外,如果成本很大,就建议不要动,把它封存成一个镜像。保持当前状态不再增加新的问题分支。如果客户认为「将来业务还会有用」,这种情况就不是「无用」,而属于「低概率使用」了。我表达的「无用」是「零概率使用」的意思。

你也可以定义一下什么叫做「无用」。我个人认为,类似低使用率的功能这种鸡肋的东西所提供的价值有限。维护成本远远高于收益。所以在这种投资组合下。就以「低投入产出比」作为「无用」的定义好了。

一个系统有多方利益人:使用者,维护者,生产者,获利者。诸多矛盾之间很难有共识。所以最难的问题是达成「无用」的共识。手段反而是其次的。


问:请问 Lambda 和传统的计算平台相比,优势有哪些?

答:和传统的计算平台相比,Lambda 最大的优势是不用搭建运行平台。只需要关心代码如何执行,而不需要关心代码在哪里执行。这样能节省学习和搭建 k8s 的时间。

此外, k8s 仍然受底层资源的限制。你仍然需要监控底层资源。而且 Lambda 是按执行次数和执行时间计费的,这比一直开着服务器要节省不少钱。


问:如果无服务器服务终将变成类似存储过程的技术,一个原本挺好的想法可能很快欠下一大堆技术债,你怎么看这个问题?

答:非常好的洞见。

Lambda 目前通过限制资源,可以将技术债复杂度控制在一定范围内。下一篇我们会讲这些可能出现的技术债如何管理,云平台本身也会成为技术债的一部分。

简单地说,目前我们对采用 Lambda 的场景都很小心,都是小范围和小规模的,因此技术债很有限。我现在所在的项目正在大规模的作为主要架构使用。我很期待这个项目完成后的效果,届时也会分享给大家。


问:怎么理解 Severless 意味着不需定时维护,并不代表完全去除服务器这句话?

答:这句话的引用来自哪里?或者上下文是什么?

我个人认为维护有两个层级:基础设施和应用程序。角度也有两方面:服务提供者和服务使用者。它会形成一个 2 X 2 的矩阵。在这个矩阵里,我认为这句话是站在服务提供者的基础设施管理方面的。我相信 Serverless 的底层肯定是运行在服务器资源之上的。随着虚拟设施的抽象,让服务器资源可以扩展并透明化。这是我对这句话的理解。


问:用权限做好流量导向控制,指的是用同一套环境但不同的数据库吗?

答:是的,也可以是同一数据库不同的用户和不同的分区。目前它还很初级,但未来会越来越多的。因为我们开发到后期就索性直接在生产环境上开发、部署和发布了。


问:以遗留代码为例,有些问题不是技术问题,但混杂在工作中,导致推进困难。问题其实出在人上面,达成共识很重要。但我不太明白的是,如果自己没有那么大能量去左右他人的想法,该怎么办?

答:就我目前的经验来看,很多问题都是披着技术问题外衣的管理问题。真正的技术问题很少。遗留代码的例子就是一种。

另外一点,就是「这个应用属于谁」。对于创造系统的程序员来说,往往有一种追求完美的情愫。但系统是一个矛盾妥协的综合体。所以没有绝对的好与不好。建议试一试做代码库分析或者功能投入产出比分析。

比如,对于某一功能而言。从客户的角度说,系统收益不变的情况下,不删除遗留代码就不投入维护成本。这个投入产出比是最高的,零投入。

但是删除代码就要投入维护成本,「宁可不作为也不能犯错」的制度下,这种情况很常见。所以我说这是管理问题,而管理问题进一步讲是就制度问题。


问:如果有线上用户出现问题,测试想要重现问题的话,可能需要用该线上用户的数据来验证,怎么做才不会影响线上数据?

答:AWS 的数据库有一个 Snapshot 的功能,定时产生一个数据库镜像。这个功能是收费的。我们测试的时候,只要以某一个时间点的镜像创建一个新的实例就可以了。

我指的是 RDS 服务。不过生产环境的数据库权限操作是很严格的。网络是隔离的,镜像是共享的。

如果使用第三方服务,比如调用一个发短信的第三方服务,这种情况就要做一些限制,如黑白名单。让测试环境出去的只有白名单用户可以接收等。


本文首发于 GitChat,未经授权不得转载,转载需与 GitChat 联系。

微信扫描登录