50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

Saleforce 基于 Kotlin 构建数据管道的探索和实践  

  • 2021-08-26
  • 本文字数:2948 字

    阅读完需:约 10 分钟

Saleforce基于Kotlin构建数据管道的探索和实践   

直到最近,我们都和许多公司一样在基于 Java 或 Scala 的那几种技术(包括 Apache Spark、Storm 和 Kafka)中选一种来构建我们的数据管道。但 Java 是一种非常冗长的语言,因此用 Java 编写这些管道时需要大量样板代码。例如,bean 类这么简单的东西也需要编写多个常规的 getter 和 setter 以及多个构造器和/或构建器。一般来说,哈希和相等方法必须用一种很平常但啰嗦的方式覆盖掉。此外,所有函数参数都需要检查是否为“null”,为此需要多个污染代码的分支运算符。分析哪些函数参数可以或不可以为“null”是非常耗时的(而且很麻烦!)。

 

处理那些用 Java 编写的管道出来的数据时,往往需要基于管道数据的类型或值来做分支,但 Java“switch”运算符的限制让人们不得不大量使用庞大的“if-then-elseif-...”构造。最后,大多数数据管道使用不可变数据/集合,但 Java 几乎没有对分离可变和不可变构造的内置支持,于是人们只能编写额外的样板代码。

 

为了解决 Java 在数据管道方面的这些缺点,我们选择了 Kotlin 作为后端开发的替代方案。

为什么是 Kotlin?


我们选择 Kotlin 主要基于如下考虑:

 

  • Kotlin 中对数据 bean 类的丰富支持让我们无需再编写显式的 getter 和 setter。

  • 可选参数和简化的构造器语法让我们无需再编写多个构造器和构建器。

  • “数据类”结构让我们不必再使用简单的样板代码显式覆盖哈希/相等函数。

  • 内置的类型系统空指针安全保证不会跳过任何必要的空指针检查,并且我们会收到关于不必要检查的警告,从而大大减少样板代码。我们切换到 Kotlin 后,几乎没再见过可怕的运行时 NPE 异常。

  • 用于分离可变数据和不可变数据的强大机制允许我们对并行数据处理进行更简单的推理。

  • 通用的“when”运算符允许我们根据数据类型和值编写灵活简洁的分支表达式。

  • 与 Java 的无缝集成让我们能继续使用所有 Java API,无需额外的心智负担。在 Java 中使用 Kotlin 接口也几乎不存在摩擦,并且我们在 Kotlin 中实现的 API 还被其他使用 Java 的团队用上了。

 

下面是 Kotlin 代码的一个简单示例,它展示了上面列举的一些要点:

enum class RequestType {CREATE, DELETE}data class RuleChange(val organizationId: String, val userIds: List<String>, val request: RequestType)
复制代码


Java 中的等效实现如下所示:

enum RequestType {CREATE, DELETE}public final class RuleChange {    final private String orgraniztionId;    final private List<String> userIds;    final private RuleChange ruleChange;    RuleChange(String organizationId, List<String> userIds, RuleChange ruleChange) {        this.orgraniztionId = organizationId;        this.userIds = userIds;        this.ruleChange = ruleChange;    }    final public String getOrgraniztionId() {        return orgraniztionId;    }    final public List<String> getUserIds() {        return Collections.unmodifiableList(userIds);    }    final public RuleChange getRuleChange() {        return ruleChange;    }    @Override    public boolean equals(Object o) {        if (this == o) return true;        if (o == null || getClass() != o.getClass()) return false;        RuleChange that = (RuleChange) o;        return Objects.equals(getOrgraniztionId(), that.getOrgraniztionId()) && Objects.equals(getUserIds(), that.getUserIds()) && Objects.equals(getRuleChange(), that.getRuleChange());    }    @Override    public int hashCode() {        return Objects.hash(getOrgraniztionId(), getUserIds(), getRuleChange());    }}
复制代码


这两段代码做的是几乎完全一样的事情。Kotlin 还有一些好东西我们没放在示例里面,它们需要额外的样板代码才能在 Java 中实现,但是这个示例已经足够说明问题了——Kotlin 代码更加简洁,并且为开发人员提供了很多免费赠品。

Kotlin 中的一个清晰的代码示例


Kotlin 简洁易懂的代码的一个很好的例子是我们的规则更改处理器 Kafka 流作业,它对输入数据进行空安全验证,使用扩展函数反序列化数据,然后使用详尽的模式匹配对数据执行操作。



这里你可以清楚地看到 Kotlin 为我们提供的几个好处:

 

  1. 空值安全性:再也没有难看的的 if/else 空检查了。我们使用了 Kotlin 的内置空值安全性检查,它可以防止 NPE 并让代码更具可读性。

  2. 扩展函数:Kotlin 提供了向现有类添加新函数的能力,添加时无需继承该类。第 4 行的 it.deserialize()是不是看起来比使用一些辅助类来反序列化数据更易读?

  3. 对属性的一流支持:我们不需要编写 get/set 方法,因为 Kotlin 为属性提供了一流的支持,如第 5 行和第 6 行所示。

  4. 使用 when 构造的详尽模式匹配:从第 8 行开始,Kotlin 的 when 表达式对枚举值和 case 类进行详尽的模式匹配。使用 Java 的 switch 构造时我们必须编写 no-op default case,现在再也用不着了。

Kotlin 用于 Salesforce 的活动平台


活动平台(Activity Platform)是我们的一个大数据事件处理引擎,每天摄取和分析 100 多万次客户交互,以自动捕获数据、生成见解推荐



如上图所示,我们广泛采用了 Kotlin 代替 Java 进行跨活动平台的后端开发工作。下面是具体的流程:


  • 我们以流媒体方式处理活动数据,并使用 AI 和机器学习生成智能见解,为 Salesforce 中的多种产品提供支持。

  • 为了处理这些数据并生成见解,我们会运行一些大数据系统(如 Kafka-Streams、Spark 和 Storm)并公开一个 HTTPS GraphQL API 供其他团队消费数据。

  • 我们用 Kotlin 编写所有业务逻辑库。

  • Kafka Streams 作业是用 Kotlin 编写的。我们使用 Kafka Streams 作业进行简单的映射、过滤和写入操作。

  • Apache Storm 拓扑是用 Kotlin 编写的。Storm 拓扑对我们的数据执行通用数据保护条例(GDPR)操作。

  • Spark 作业是用 Scala 编写的,但它们会消费用 Kotlin 编写的库。我们使用这些 Spark 作业运行复杂的 SparkML 模型。

  • GraphQL API 也是用 Kotlin 编写的,同时由一个 Jetty 服务器提供支持。

 

所以基本上来说,我们在所有可以使用 Java 或其他 JVM 语言的地方都改用了 Kotlin。

迁移到 Kotlin 后为我们带来的好处


当其他团队使用我们的库时,Kotlin 的数据类和不变性确保了一致性(防止意外数据损坏)。它的函数式语法和不变性为我们编写数据管道所需的处理流提供了一种优雅的方式。Kotlin 可以在一个文件中拥有多个类,并能够使用顶级函数,这让我们的代码组织起来更轻松了,大大减少了我们需要导航的文件数量。这篇博文中还没具体介绍 Kotlin 中我们喜欢的很多内容,例如扩展函数、类型别名、字符串模板、使用协程和 async-await 的并发代码执行等。

 

使用 Kotlin 构建数据管道可以获得很多好处,尤其是提升开发人员的生产力。让来自不同编程背景(如 Java、Scala、Python)的工程师上手 Kotlin 都是非常轻松的事情,而且他们都喜欢 Kotlin 提供的编程结构。这就是为什么它是 2020 年最受欢迎的编程语言之一。我们将继续扩大其采用范围,同时用它来构建新的管道、并将旧管道也逐渐切换到 Kotlin 上。当 Kotlin 对 Spark 的更稳定支持可用时,我们也有兴趣使用 Kotlin 来构建 Spark 作业。对于所有对构建数据管道感兴趣的读者,我们都建议大家尝试使用 Kotlin,看看它相对于其他编程语言有哪些优势。

 

原文链接:


https://engineering.salesforce.com/building-data-pipelines-using-kotlin-2d70edc0297c

2021-08-26 17:007192

评论

发布
暂无评论
发现更多内容

A “word-wrap” functionality(一个字符串包裹函数)

HoneyMoose

书单 | 月度畅销好书,助你技能满格,摆脱低效,走向财富人生

博文视点Broadview

Redis-技术专区-知识问题总结大全(上篇)

码界西柚

redis 5月日更 问题分析

OAuth 2.0 了解了,OAuth 2.1 呢?

Zhang

OAuth 2.0 认证授权 OAuth 2.1

你的烂代码终于有了解决方案

博文视点Broadview

复杂Gremlin查询的调试方法

Tom(⊙o⊙)

gremlin调试

当你觉得老板的决策是错的,你会怎么做?

石云升

职场经验 5月日更

了解代理服务器

进击的梦清

nginx Linux 运维 代理原理

2021年十大突破性技术

石云升

读书笔记 5月日更

手机屏幕投屏到桌面的离线方案

黄敏

将本地文件/文章上传到 GitHub 的流程

彭宏豪95

git GitHub 效率 编程

鹅厂疯子整理了万字Java笔记!小白:硬核资源基础知识已入门

牛哄哄的java大师

Java Object

本文标题不能描述本文内容

小天同学

读书 哲学 读后感 4月日更

如何选择开源许可证

HoneyMoose

【人间碎片】关于努力这件事

南吕

人生修炼 人生故事

fastadmin+xunsearch题库系统搭建教程

一颗小树

php thinkphp fastadmin xunsearch 题库系统

Excel用户如何学习数据分析语言DAX?

博文视点Broadview

北美亚特兰大一金融服务公司面试总结

HoneyMoose

【LeetCode】员工的重要性Java题解

Albert

算法 LeetCode 5月日更

超硬核!阿里技术大牛肝了2晚整理的Java知识,这也太强了!

飞飞JAva

Java Java泛型

SwiftUI @ Netflix:推动新技术落地是怎样一种体验?

故胤道长

swift 移动开发 iOS Developer SwiftUI

限时白嫖!腾讯内部员工培训Java资料,网友:大厂就是不一样

牛哄哄的java大师

Java

当代软件IT大学生的技术学习之路

Nydia

签约计划

InfoQ & 声网Agora 技术开放日邀请函

Jessie

音视频 声网

网络攻防学习笔记Day1

穿过生命散发芬芳

5月日更 网络攻防

BPF 之巅:洞悉 Linux 系统和应用性能

博文视点Broadview

如何在 GitHub 上面为你的项目选择开源许可证

HoneyMoose

从零搭建一款PC页面编辑器PC-Dooring

徐小夕

大前端 可视化 lowcode 代码编辑器

名可名

顿晓

5月日更 命名

技术探索系列 - 轻松带你掌握 JMM(1)

码界西柚

Java JVM JMM 并发 5月日更

外行在谈论流派,大师在讨论颜料

顿晓

极限编程 5月日更 门道

Saleforce基于Kotlin构建数据管道的探索和实践   _大数据_Saleforce工程博客_InfoQ精选文章