LINE 開發社群計畫: 20190423 GolangTW#40@LINE

大家好我是 LINE 台灣的 Technical Evangelist – Evan Lin 。「開發社群計畫」是今年一個開發者關係與技術推廣部門一個重點,將在今年一整年中,在台灣舉辦對內的技術交流、教育訓練,對外的社群聚會、校園演講、開發者徵才日與開發者大會等各式各樣超過30場的活動。我們希望創造更多技術分享與跨國串連的機會,同時,持續招募優秀的人才加入LINE台灣的開發工程團隊。

四月的第二場社群邀請到 Golang Taipei Gathering 社群的朋友來到 LINE 台北辦公室,並且一起來分享與討論 LINE 內部開發流程上針對 Golang 使用上的心得分享。這次的相關資訊可以在 meetup Golang Taipei #40 找到所有的內容介紹,

Go GraphQL in LINE SPOT/ LINE – Denny Tsai

投影片

首先上場的是來自 LINE Spot 的工程師 Denny Tsai 。他也介紹了即將在 LINE 2019 下半年上限的全新服務 – LINE Spot 。提供消費者輕鬆搜尋所在地鄰近的店家資訊,以及店家進行中的特惠活動,消費者想要的資訊、店家想曝光的資訊都可以在 LINE SPOT 一站完成。這樣的服務將在 2019 年的第三季上線,敬請大家期待。

接下來講者開始分享如何透過 Go 跟 GraphQL 來當作微服務( Microservices ) 的 API Gateway 的經驗分享。由於產品的微服務漸漸增加,各個微服務都會提供個別的 API 供前端使用。除了 HTTP 的 API 之外還會多出了其他溝通的介面 (gRPC, Thrift…) ,如此一來造成前端與微服務間的串接複雜度提升。這時候會使用 API Gateway 當作統一進入點 ,進而使用 GraphQL 提供前端更好更有彈性的查詢方式,希望能夠 GraphQL 解決聽眾們經常遇到的問題。

GraphQL 是一個 Query Language 並且具有以下的優點:

  • 單一進入點 (Single Endpoint):
    • 不論是各種的不同的 API 需求,通通透過單一的進入點。
  • 由客戶端來定義需要的資料型態 (Response shape defined by the client):
    • 客戶端(通常指的就是前端)可以修改自己需要的資料型態,順序與排列方式。不需要修改任何的後端代碼。
  • Transport Agnostic:
    • GraphQL 並不是一種語言而是一種標準,可是其實他並沒有限制所使用的傳輸層,因此可以使用任何適合的方式作為 GraphQL 的傳輸層。

此外講者也介紹了許多關於 GraphQL 有用的開發工具:

  • GraphiQL: 一個在瀏覽器上的 IDE 可以讓你查詢與瀏覽 GraphQL 的工具。
  • GraphQL Playground: 開發 GraphQL 的 IDE 與測試工具,提供許多良好的介面與具有互動式的文件。

除了這些工具之外,由於本場分享關於 Golang 的開發者。講者也分享了市面上比較熱門的 GraphQL in Go 的開發套件:

這三套大概是搜尋 Golang 與 GraphQL 最容易被人找到的三個套件(因為 star 數也最高),但是講者最推薦 gqlgen 原因如下:

  • Schema first
  • Type safe
  • Less boilerplate

而使用上也相當直覺,建立 schema 後,透過 gqlgen 初始化之後它會把所以相關需要的框架都建立好。只要進去將相關的 Resolver 內容填寫正確就可以跑起這個 GraphQL server 。

最後 LINE Spot 其實也希望有更多對於 Golang 有熱情的夥伴一起加入。

LINE Now/Spot 相關職缺:

認識 Go 的 morestack/ Lee Xun (SRE@KKTIX)

投影片

(本部分會不截圖,請各位去投影片內部找尋相關內容)

第二位講者是李洵,他所帶來的題目相當的硬但是也相當的有趣。討論的是 Golang 裡面的 morestack ,細節因為相當的硬且深入建議大家還是要去投影片鏈結細讀講者提供的投影片。

首先講者先分享了他自己為什麼喜歡 Golang 的原因: 除了 Goroutine 之外,就是 Golang 是編譯的程式語言。可以很容易地從組合語言來了解程式碼的執行細節。 講者也透過了比對了 C 語言的 Hello world 與 Golang 的 Hello 讓大家了解組合語言解讀的時候, Golang 的編碼上還要複雜的許多。接下來就拿了一個 C 語言與 Go 對於變數生命週期的管理來討論 Golang 在變數生命週期的管理是不同的 (這個在 Golang 裡面稱為 escape)。 由於在 Golang 裡面 :

  • return A{}:將記憶體放在 gstack
  • return &A{} :在 compile 的時候記憶體放在 gheap 之間。

所以 Golang 記憶體的位址並不會因為變數的生命週期結束後,傳回記憶體位置而會拿到已經被佔用的記憶體位置。可以在 func 前面加上 //go:noescape 來關閉這項操作,這樣就會出現和 C 一樣的現象。

接下來講者又丟出了一個大家常有的疑問:「 goroutine 雖然好用,但是有沒有開發者會想了解目前正在執行的 goroutine thread ID? 」 因為在 C 語言中,每次 Create Thread 都可以拿到 thread ID 來清楚知道目前執行的 ID ,那麼 goroutine ID 呢? 接下來講者就分享了如何透過 getgoid() 來取得 TLS (Thread Local Storage) 資料方式,並且講解如合透過 Memory alignment 來解讀目前的資料結構進而找出 getgoid() 。

接下來透過一個 deadloop 的範例程式開始要帶入本次演講的正題: 什麼是 Golang morestack。

在 Gorotine 裡面加入一個 deadloop (也就是 for {} 什麼事情都不做) 發現如果在裡面做記憶體位置處理的話。某些情況下會發現你的 deadloop goroutine 又會被其他 goroutine插隊(preemptive)。 那麼要多大的記憶體操作才會造成整個 goroutine 是可以被插隊呢? 這時候先跳去討論了在不同的平台上面的 GOMAXPROCS ,也講解了不同平台上面如何取得你的CPU 數目的方式。 透過這些處理方式才能了解,由於有 StackGuard 當一個 goroutine 裡面的變數資料大過於 4KBi 由於超過了 gstack的資料空間大小,就會呼叫到 morestack 來搬移資料的方式會有極大的可能判定這些資料是比較少使用的。 就會將該 goroutine 是修改為可以被插隊的。 當 goroutine 內的資料空間大小介於 128Bi 與 4KBi 之間在 morestack 的判斷中,由演算法決定該不該被插隊。反之,比較小的區域變數空間就絕對不會被插隊。

或許這樣的設計也提醒開發者,如果發現 goroutine 本來跑的一些流程莫名其妙被中斷去跑另外一個 Goroutine ,也或許就是因為區域變數佔用太多記憶體而呼叫到 morestack ,造成系統判定該 goroutine 是可以被插隊的。

很有深度,相當硬但是又有趣的分享。

總結

很開心邀請到 Golang 社群來到 LINE 台灣辦公室舉辦 meetup , 也很開心第一次能夠請到 LINE Spot 的工程師來跟社群們分享開發上的經驗。

關於「LINE開發社群計畫」

LINE今年年初在台灣啟動「LINE開發社群計畫」,將長期投入人力與資源在台灣舉辦對內對外、線上線下的開發者社群聚會、徵才日、開發者大會等,預計全年將舉辦30場以上的活動。歡迎讀者們能夠持續回來察看最新的狀況。詳情請看 2019 年LINE 開發社群計畫活動時程表 (持續更新)