【活动回顾】2020-09 Online Scala Meetup 之观众心得

avatar
HR @Tubi

Meetup 回顾--by 彭文杰

有幸于 2020-09-05 参加了 Scala 的线上 Meetup,两小时期间收益良多,应主办方 Tubi 的邀请分享了此次 Meetup 的相关知识总结。就个人而言,为了表达对几位演讲者的感谢,也为了让脑中知识流失稍缓,也方便以后重拾相关内容,便留下了下述简略文字,水平有限,如有误解劳烦各位指正。

个人背景:工作一年的 Java 工程师,对于 Scala 基本上处于只写过基本语法 demo 且有一些遗忘的状态,深表惭愧。此次 Meetup 有如下几个议题,我做了相关总结:

1. Akka: Manage your state, just right - by Evan

首先演讲人介绍了他们的具体业务,主要抽象便是 Tubi 视频平台的广告业务,主要业务点我粗略总结如下:

广告的竞价(向广告商发出竞价请求,根据广告商报价进行筛选,解析广告并播出)

广告处理流程:

  • 请求前:校验,筛选

  • 请求中:拍卖,竞价广告

  • 请求后:广告解码

  • 追踪请求:广告服务器-MQ-DB 之间的交互。

  • 广告已被查看,此时状态的更新会用到 Akka?

Tubi 广告系统面临的挑战,跟互联网大部分业务的难点类似,面临着所有互联网分布式数据密集型系统中,相似的问题,主要有以下几点:

  • 低延迟:为用户提供快速选出合适的广告,要求低延迟,用户无感知

  • 高可用:系统要求高可用,即便广告服务不可用,也不可以影响用户的播放交互

  • 一致性:确保用户的广告体验,比如看过的广告不能再播放、选择用户合适的广告、如何向广告商同步广告播放情况,并提升用户体验与清晰结算广告费用

Akka 的场景

从以上业务理解与难点中,可以看出有很多状态管理的场景,而互联网的本质基本可以理解为信息及数据的同步与表达。如何管理并传达最准确的数据是从始至终的不变目标。

个人对于 Akka 的理解,基本也处于官方文档上的一个简略介绍以及平日在 Scala Meetup 群中,通过一些 Scala 技术专家的会话了解一星半点。因个人工作中接触 Java 微服务较多,故做以类比之,将 Akka 浅显理解如下:

  • Akka:是一种分布式系统的框架

  • Actor:理解其职责为微服务中的一个服务,对比区别在于微服务中的服务是大部分是无状态的,只作为过程的编织网络,将自身与其他服务的过程连接起来;而 Akka 的 Actor 我理解为一个真实的抽象的对象,她会维护一些数据的状态,并且会与其他 Actor 进行通信并处理数据。

  • Node:解为 DDD 中一个简单域的服务集合,可以理解为一个 Pod 或者一个实例,负责了 Actor 的管理

  • Cluster:粗略理解为 Node 的集合

  • Akka 状态管理的优点

  • 数据在 Node 间的同步,对于开发人员是黑盒的。开发人员无需关注不同 Node 间的状态同步,可以将集群数据视为单机,而专注于业务逻辑的开发。数据的最终一致由 Akka 管理并保证

图片

Akka 实战与对比

场景一:内容润色

就演讲人介绍,在此场景下,Tubi 需要对广告商返回的 Metadata 进行广告过滤。而其介绍会使用本地 Actor 作为缓存,接收查询,根据 Actor 中是否维护 ID 来选择直接返回亦或是调用 API,更新缓存。

这种缓存的使用场景很常见,因 Java 微服务中,节点服务是无状态的,故内容不会存储在实例上(即便存在实例上,也会因为请求命中实例不同导致落空),故我在工作中可能会使用 Redis 这种 NoSQL 方式进行维护,托管这部分缓存,通过被动缓存形式,将命中的内容返回,将未命中的数据通过合理的 Timeout 维护在 Redis 上。

而 Akka 能脱离其他中间件工具,以分布式框架的进行数据状态维护,这不得不省了我们很多的时间,可以更高效地工作和学习,真是太好了。

场景二:广告花费控制

同理,是数据同步状态更新。

在 Java 使用较多的我的眼中,可能会使用 MQ + DB + NOSQL 的形式进行数据同步,不过看起来时效与数据同步速度可能是没有 Akka 迅速的。

其他还有很多应用场景就不一一列举了。

2. 算式解析和计算——Parsec 组合子 - by 刘鑫

这个议题的使用场景有很多,比如我们在大学的时候,都被要求过实现一个计算器,比如输入一段文本的计算表达式 “3.14 + 7 * 8 -(2 + 3)”。而如何优雅而健全地计算出结果,则是演讲人刘鑫老师想表达的。

刘鑫老师将文本表达式内容归了下类,方便后续计算:

  • 表达式:数值,引用,运算符都是表达式,括号

  • 实数:符号数,整数,小数,科学计数法,数值表达式

  • 引用:参数表达式

  • 运算符:加减乘除

通过将运算逻辑(优先级别)分别置于以上的不同算子中,构造用于抽象计算的,不同深度的树,来进行递归计算。通过算子是否已知,调整计算的顺序(交换树的位置)。总之具体还是挺复杂的,要真正弄明白还是建议去翻看刘鑫老师的 Parsec 源码。

后面刘鑫老师还介绍了很多“算子”,有很多跟现存算子类似,也有不类似的。通过这些算子的组合,形成不同的“组合子”,  来实现各种想达到的目的。大概这就是传说中的 Monad 吧?!

图片

也许有人就会问到,这个组合子有什么用呢?其实作为一名小白我也是心中有些疑惑的,能想到的作用大概有以下几点:

  • 高度抽象,清晰简洁

  • 复杂表达式或规则的解析

  • DSL:开发属于自己特定业务领域的 DSL,比如为公司运营开发一个业务 DSL,让他们自己折腾,解放产研团队

这一部分其实我听得挺多一知半解的,之后打算看看其他观众的观后感取取经。

3. AST manipulation and Pattern Matching in Scala - by 沈达

这部分又是编译解释相关,不禁感慨是不是技术达人都喜欢研究类编译原理相关知识,让我们倍有压力。

沈达通过一个简单的例子入门,“计算机如何计算1+a+2”,人类第一反应就知道能优先合并 1 + 2,那计算机如何识别呢?那么又为什么要识别呢?直接在 Runtime 计算 b = 1+a, c = b + 2 不好吗?

对于偶尔的一次操作,在 Runtime 计算确实没问题,但要知道,在大数据场景下,若对上亿条数据都计算一次,那么耗费的时间成本和算力可就不少了(省电费多好)。如果在编译时就将计算优化成 a + 3,性能提升肯定效果显著。

接下来,沈达介绍了 ANTLR 语言识别工具,通过生成 Parser,处理表达式。

优化原理,与刘鑫介绍的算式解析很类似,通过构造表达式的语法树,在既定的规则内进行优化。通过以下来达成优化规则:

  • 整理文本:添加括号

  • 计算规则:优先计算括号,交换律,计算优先级

  • 区分节点类型:sci 之间可优化,var 则不可

图片

感受:通过以上三个分享,能发现分享 1 的 QA 阶段,观众提问还比较多;但是分享 2 和 3 的 QA 提问则比较少,对于其他人的情况我无从了解。不过至少对于我而言,在这方面的知识储备真的是比较欠缺,实在提不出什么建设性的问题。需要花时间静下心来学习,多与前辈们交流。

其实从另外一个角度来看,也说明这一现象也很符合现况,高难度专业的知识传播量小(如Scala 技术栈),公众号中一篇关于 Idea 的插件文章的阅读量可能是一篇专业的 Scala 文章的数百倍。

4. ZIO - by 明扬

ZIO:Type-safe, composable asynchronous and concurrent programming for Scala

从官网介绍,可以看出其核心是:

  • 类型安全:说明有明确且舒适的类型系统

  • 可组合:说明灵活,表达能力较强

  • 异步并发:能满足并发以提升性能

那么这么一个优秀的东西,对标的竞品是什么呢,明扬哥通过对比 Scala 的 Future,对比展示了不同场景下的两者代码,能发现 ZIO 对比 Future,有以下优点:

  • 自带串行写法

  • 能控制并行的细粒度(并行数)

  • 识别请求竞争并能及时停止

  • 不具有副作用,纯组合子,在执行时才运行。而 Future 在创建时执行,很难资源安全。

  • 优秀的调度与控制 API

  • 错误栈明确清晰(Future 则相比较效果欠佳)

图片

后面则介绍了一个很厉害的痛点,“移植性与测试性”完美。曾几何时,当我还是一个稚嫩的牛犊时,我曾许诺自己写任何代码都要有测试用例,而公司的测试环境让人无可奈何,本地测试启动时,总有各种奇奇怪怪的依赖,需要配各种环境,处理各种依赖框架,配置各种 host。但是 ZIO,运行起来只启动它会用到的,这太棒了。

“天时不如地利,地利不如人和。三里之城,七里之郭,环而攻之而不胜。夫环而攻之,必有得天时者矣,然而不胜者,是天时不如地利也。” 最后明扬哥旁征博引、富有激情地朗读了一段《孟子》,总结阐述了我们在生产实践中使用 ZIO 的所需的必要条件,完美地将他的分享画上了句号,大家反响热烈。

总结

这次 Meetup 就个人而言还是收获颇多,今后的 Scala Meetup 肯定也会持续参加,文中若有错误,烦请指出,也祝其他小伙伴在学习 Scala 的路上越来越顺利吧!

Meetup 笔记--by 桃子幻象

自我介绍:常用网名桃子幻象,现在在一家小型日企做全栈工程师,主业服务器/客户端开发和运维及 PM,兼做运营等工作。近两年的第一工作语言是 TypeScript。

1. Akka: Manage your state, just right - by Evan

我两年前用过一点 Akka 但是只留下一些粗略印象,而且广告系统的需求和设计离我比较遥远,无法准确评估 Akka 在这点上相对其他方案的优势有多大。但是直觉告诉我,大量 hot 数据 in memory 的时候可能 Actor 模型(相对于自己发明新的框架和模型)会是不错的选择。

另外 Akka 应该是我接触过的第一个从设计上就分布式的框架而言,有丰富的生态系统的框架:

  • Akka 本身: 一个基于 Actor 模型的应用程序框架

  • 围绕 Akka 的配套:

  • Akka-http (http/websocket 服务器)

  • Akka-streams (Reactive Manifesto 的另一种实现。RxJava 那些比较接近“流”,这个的 API 比较接近“图”)

  • Akka-cluster (跨进程跨机器的 Actor 空间)

  • Akka-persistence (Actor 持久化)等

  • Akka 的文档质量相当不错,IMHO 以 Akka 作为分布式开发的入门挺好的。工作中有没有机会用到是另一回事。有兴趣深入了解的可以看看 _Terminology、Concepts(_🔗:doc.akka.io/docs/akka/2… )。

图片

Btw 广告业印象中 Scala 用户挺多的,以前看 CyberAgent 也分享过 Akka 的内容。另外Lightbend (Akka 背后的公司,曾用名 TypeSafe) 的可能最有名的产品 Play Framework 里面用的也是 Akka。

2. 代数组合子和文本解析 - by 刘鑫

这个分享目前我并不是很理解,可能等我实际写过一次 Parser Combinator 再听会有不一样的收获。

图片

3. AST manipulation and Pattern Matching in Scala - by 沈达

一些要点:

  • 用 Antlr4 生成一个算术表达式的 Parser

  • 用 Implicit Conversion 给 Antlr 的 ParseTree 配上 Helper Method

  • 以字符串为中间形式, 变换 AST (如替换一个 Expression,重新生成 AST)

  • 真正在 AST 中实现常量折叠的部分代码是留空的,第二天我尝试写了一下然后没写出来。小部分是因为不熟悉 Antlr 的 ParseTree 的 API,绝大部分还是因为对这部分知识不了解。如果有其他同学写出来也希望能分享一下。

图片

4. ZIO 入门分享 -  by 明扬

这是我感触第一次就听懂了些的部分,可能因为明扬老师的配图和讲解比较生动。

后来又简单看了一下 ZIO 的介绍: ZIO 是一个提供(函数式的依赖组合和依赖注入)和(函数式的异步控制流组合)的库。说是 "库” 但是看来比较侵入式,感觉写起来会更像 DSL。如果有合适机会也想尝试在生产环境中使用。

图片

总结

最后,之前也去过东京的 Scala Matsuri,也了解到广告公司 + DDD 会在生产实践中运用 Scala,简单写了下此次观后感,希望和各位工程师多交流分享实践经验。

我的博客地址如下,欢迎围观:

jokester.github.io/posts/2020-…

非常感谢两位热爱 Scala 的小伙伴务实的心得分享,关于 Scala Meetup 的回放视频可以在 BiliBili 关注“比图科技”公众号即可观看,也欢迎更多喜欢 Scala 的小伙伴一起交流。

图片