我如何在 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 名參與者。 它獲得了大獎和粉絲最愛。 如果您想了解更多信息,請查看項目頁面。