我如何在 Hackathon 中使用 Apache Spark 和 Docker 构建天气应用程序

已发表: 2022-03-11

在我之前的两篇文章中,我向读者介绍了 Apache Spark 和 Docker。 是时候向您展示一个包含上述两种技术的全功能应用程序了。

动机“以数据的形式从天而降”,它是由 IBM 组织的黑客马拉松引发的。 Sparkathon 的目标是使用天气数据和 Analytics for Apache Spark for IBM Bluemix 来构建与天气相关的移动应用程序。

IBM 正在大力投资 Spark,最近还收购了 The Weather Channel 的数字部分。 因此,这次活动似乎非常适合他们的宣传。

灵感

您是否曾经抱怨过您所在地区的天气,有一些计划好的休假和花钱,但不知道去哪里? 如果答案是肯定的,那么您会非常喜欢My Perfect Weather应用程序。

图片:应用程序的用例。

只是为了说明如何使用该应用程序,以下是一些用例:

  1. 你有一个孩子,你答应过周放风筝,但你住的地方绝对没有风,你不想食言。
  2. 你和我一样住在一个多风多雨的地方(苏格兰爱丁堡),想要在你的皮肤上感受到温暖,绝对没有雨。
  3. 你有种堆雪人的冲动,在完成之前你不会休息。
  4. 你想去钓鱼,而这一次,你真的很想钓到东西。

它能做什么

该服务背后的想法非常简单。 首先,您要定义在特定时刻完美的天气对您意味着什么。 目前,您可以按温度、风速、降水类型和降水概率进行过滤,如下面的屏幕截图所示。 然后服务会完成剩下的工作,您会看到最匹配的目的地。 结果按完美天数排序,匹配原始查询的天数,为每个城市找到并限制在前五名。 完美的日子也标有不同的背景。

让我们看看如何将服务用于上一节中定义的用例。

  1. 将风速设置在 16 到 32 公里/小时之间,非常适合放风筝,下雨的可能性很小,温度适宜。
  2. 将最低温度设置为对您来说足够温暖,将下雨的可能性设置为 0%。
  3. 将温度设置在0℃左右及以下,降水类型选择雪,降水机会高。
  4. 将风速设置为小于 16 公里/小时,少雨和多云,避免阳光过大,让鱼在水中更深,温度舒适。

如果您愿意,您可以轻松查看如何到达您选择的目的地,因为该应用程序集成了旅行搜索服务 Momondo。

我是如何建造的

基本上,除了外部旅行搜索服务之外的所有内容都在 IBM Bluemix 平台内部运行。

IBM 向黑客马拉松的所有参与者提供免费试用,因此我不必担心在哪里运行该应用程序。

让我们看看数据在应用程序中是如何流动的,以及架构图中呈现的组件是如何组合在一起的。

Play 应用程序托管在 Docker 容器内。 它的一项服务能够联系气象服务并将 10 天预报下载到 Cloudant。 在下载后的一个步骤中,Spark 从 Cloudant 读取原始天气数据,对其进行处理并将其存储回 Cloudant,以便 Play 应用程序快速轻松地访问。

当用户导航到应用程序的主页时,他们会看到一个包含各种控件的表单,以定义他们的完美天气。 他们的输入被提交到后端,后端向 Cloudant 查询包含完美日子的城市。 然后,对上一个查询中返回的城市的所有十天预报进行另一个查询。 将获得的结果呈现给用户,单元格代表每个城市每天的天气状况。 每个城市的最后一个单元格都包含一个到旅行服务的链接。 点击它会将用户带到 Momondo 网站,并且航班搜索表格将预先填充目的地和旅行日期。 如果用户之前使用过该服务(并且它在浏览器中存储了一个 cookie),则可能还会预先填写旅行者的来源和数量。 当然,可以更改此表单上的字段。 例如,可以尝试不同的旅行日期以寻找更好的票价。

这几乎就是应用程序的构建方式。 以下部分将详细介绍某些组件。

图片:天气应用程序的组件。

Spark and Insights for Weather

该项目的第一阶段用于弄清楚 Weather API 和其他 Bluemix 服务是如何工作的,然后是使用 Spark 进行的初始天气数据探索。 它让我了解了数据模型是如何工作的以及如何在应用程序中使用它。

对于此应用程序,仅使用以下 Weather REST API 端点中的第一个:

 GET /v2/forecast/daily/10day - Weather Standard 10-day Daily Forecast GET /v2/forecast/hourly/24hour - Weather Standard Hourly Forecast GET /v2/observations/current - Current Weather Observation GET /v2/observations/timeseries/24hour - Time-Series Observation

端点通过提供一个地理编码参数来查询每个感兴趣城市的天气预报,该参数采用相关地点的纬度和经度。

由于服务的性质,向 Weather API 发出的请求数量与支持的城市数量相关。 我考虑了 Insights for Weather Service 的免费等级限制,即每天 500 个呼叫,并决定出于演示目的,我将选择欧洲 50 个旅游型城市的安全数量。 这让我每天可以为每个城市进行多次调用并处理失败的请求,而不会失去使用 API 的权利。 为了有足够的请求覆盖世界上大多数城市,我必须开始付费。

该项目的最终目标是让 Spark 将全球所有城市(约 50,000 个)的天气数据乘以 10 天的预测数据,并每天执行几次,以使预测尽可能准确。

所有 Spark 代码都驻留在 Jupyter 笔记本中。 到目前为止,还没有其他方法可以执行 Spark 作业。 原始天气数据从 Cloudant DB 读取、处理并写回。

Cloudant NoSQL 数据库

简而言之,我发现使用 Cloudant NoSQL DB 非常愉快。 它易于使用,并具有良好的基于​​浏览器的 UI。 没有这样的驱动程序,但它有一个简单的 REST API,并且可以直接通过 HTTP 进行交互。

但是,Bluemix Spark 包含一个 Cloudant 数据源 API,可用于读取和写入 Cloudant,而无需低级调用。 值得注意的是,无法从 Spark 在 Cloudant 中创建新数据库,因此必须事先创建它,例如使用 Web UI。

播放框架

Web 应用程序是用 Scala 编写的。 这很简单。 控制器使用 AngularJS 和 Bootstrap 为单页应用程序提供服务,该服务与 Weather API 和 Cloudant 交互。

我面临的一个有趣挑战与 IBM Container Service 直接相关。 我的意图是在端口 80 上运行该应用程序,以便用户友好。 但是,我在 Bluemix 中找不到任何方法来使用 Docker 端口转发并将外部端口 80 映射到 Play 应用程序的 Docker 内部端口 9000。 我的解决方法是在容器内以root身份运行(不推荐做法)并编辑 Play 的 application.conf:

 # Production port play.server.http.port = "80"

码头工人

Docker 非常方便,尤其是在部署到 Bluemix 时。 我不需要了解 Cloud Foundry 应用程序,也不需要担心 Scala 构建包或其他任何东西。 我可以推送我的 Docker 映像并查看它正在运行。

为了创建 Docker 映像,我使用了 Typesafe Docker 插件,所以我什至不需要合适的 Dockerfile。

经过简短的初始配置后,只需几个命令即可查看应用程序在云中运行:

 # log in to IBM Bluemix cf login cf ic login # create the image locally sbt docker:publishLocal # rename it docker tag -f my-perfect-weather:1.0-SNAPSHOT registry.ng.bluemix.net/radek1st/my-perfect-weather:1.0 # push it docker push registry.ng.bluemix.net/radek1st/my-perfect-weather:1.0 # and run it cf ic run --name my-perfect-weather -p 80 -m 2048 registry.ng.bluemix.net/radek1st/my-perfect-weather:1.0

值得注意的是,Bluemix 容器服务在图像可以运行之前对其执行漏洞评估。 即使它对我的应用程序没有真正意义,我仍然必须修补父图像的/etc/login.defs ,以便它可以运行。 如果您有兴趣,这里是 Dockerfile。

我遇到的挑战

由于 Spark 仍然是 IBM Bluemix 的新成员,因此它有一定的局限性。 目前,代码只能作为笔记本的一部分执行,因此无法调度运行。 在我参加黑客马拉松的最后一段时间,这是一个相当大的发现。 这对My Perfect Weather的意义在于,如果不手动重新运行 Spark notebook,那么呈现的天气天数将会慢慢过时。 我希望 IBM 能及时解决这个缺点。

我还在 Insights for Weather API 的文档中发现了一个小的不准确之处,在注意到显示的结果存在一些问题后浮出水面。 对于降水类型,唯一的预期值是,但我还找到了第三个值precip 。 从天气上下文来看,它似乎表示下雨有雪,因此为了应用程序的简单性,它被视为雪。

我引以为豪的成就

图片:在天气应用程序中使用 Docker 和 Spark。

我认为我的完美天气是一个很酷的想法,我很自豪我可以很快将所有这些不同的技术融合在一起实现它。 尽管如此,它还是一个 hack,有很多松散的结局,但最重要的是它正在工作!

我学到的是

在这个简短的项目中,我学到了很多东西。 我是 IBM Bluemix 的新手,所以它本身就是一次冒险。

我以前从未听说过 Cloudant DB,但有了 MongoDB 的一些经验,过渡相当容易。

我还了解到我不应该在前端工作。 我本质上是一个后端开发人员,没有让事情看起来不错的天赋,所以使用 Bootstrap 和 CSS 是一个搜索-复制-粘贴-修改练习。 非常感谢我的妻子在设计、视觉效果、演示和一般建议方面的帮助。

我的完美天气的下一步是什么

我想增加更多的天气控制,并在不久的将来将其扩展到世界大部分地区,或者至少覆盖整个欧洲。 随着越来越多的城市/天气符合标准,呈现最完美的日子将更具挑战性,因此可以使用 Spark MLlib 和 Spark Streaming 来处理来自用户会话的数据。

我希望 IBM 能尽快添加调度 Spark 作业的功能,这样服务就可以完全自动化。

结论

您可以通过导航到 myperfectweather.eu 在您的计算机、智能手机或平板电脑上查看应用程序。

如果你想在代码上达到巅峰,它托管在 Github 上。

My Perfect Weather 是 IBM Sparkathon 的一个竞争项目,有近 600 名参与者。 它获得了大奖和粉丝最爱。 如果您想了解更多信息,请查看项目页面。