Answer.dev 走進華師大課堂:Answer 專案開發流程詳解

AnswerDev發表於2022-11-22

前不久,Answer.dev 開發團隊受到華東師範大學 CS4ALL 研究中心邀請,為在讀碩士的同學們進行了一次分享,以 Answer.dev 專案開發過程為例,與同學們探討了專案研發管理、開發流程、DevOps 等相關話題。以下為 Answer.dev 兩位核心開發者 @Joyqi 和 @明城 在本次課程上的分享實錄。今天是我們的第四次 DevOps 學習班,大家知道在 2022 年 10 月 24 日, SegmentFault 思否團隊,正式對外開源了其問答社群軟體“ Answer.dev”。 這幾天,登上了 GitHub 的 Trending 總榜單和 Go 語言榜首的位置。

圖片

那麼,今天我們就非常榮幸的邀請到了Answer.dev 團隊的老師們。祁寧和明城(呂峰軍)老師來給大家介紹一下如何透過 Answer.dev 產品來構建 Q&A 社群以及 Answer.dev 研發、軟體研發的管理和流程。

有關祁寧和明城老師的介紹,之前在 GitHub 的 issue 裡面已經有詳細的介紹,這裡就不再這裡多講,那現在就把話筒交給 Answer.dev 團隊的老師們,我們正式開始!


Hello 大家好,我是祁寧,我旁邊是明城,今天由我和他來跟大家分享。我會先講我們專案整個研發的情況,然後明城會具體介紹 Answer.dev 專案的技術細節及實施情況。

我先自我介紹一下,我是祁寧,我的社群 ID 是 @Joyqi,在社交網站及 GitHub 上都可以搜到我。我是 SegmentFault 思否的 CTO ,自己也做開源,且有很長時間了,大學期間就已經開始做開源專案。明城是在大學時就跟我一起合作做開源專案,我們很早就認識了,所以很早就開始進入開源的世界。

Answer.dev 這個專案是我們第一次以公司商業的實體來進行推進的開源專案,跟我們之前以個人興趣為主去推進有所不同。之前的專案規劃可能是以個人時間為主,但現在可能會以公司的一些關鍵節點為主。關於 Answer.dev 專案,大家如果想具體瞭解的話,可以登陸官方網站 answer.dev 檢視詳細,它最近在 GitHub 上很受關注,我們後面也會持續更新。

專案目標

我先來介紹一下 Answer.dev 專案的研發過程,專案在開發的時候就定下了一些目標。

圖片

首先,最簡單的一點就是該專案要非常易用我們的目標是讓非專業人士或非程式設計師們也可以非常簡單地在我們的指導下或在文件的幫助下把這個專案給執行起來。我們知道,目前市面上其實有很多社群軟體或開源產品,但它們在執行的時候都需要一些很專業的知識,比如配置、技術名詞等。但在 Answer.dev  專案中,我們想面向的是一個更廣大的人群,所以在產品設計及文件設計之初,我們就會更多的考慮到了如果你是一個非專業人士,如何很好地上手這個專案。

第二,Answer.dev  是一款開源軟體。我們之前做網際網路產品的創業,可能只會釋出一個最終的產品,直接給使用者用,或釋出給特定商業使用者。而開源專案的話,就會把該專案的直接原始碼給開放出來,讓所有程式設計師都可以看到原始碼,然後可以來參與到我們專案中。

第三,在設計之初就考慮到它是一個國際化的專案。大家如果訪問過我們的官方網站或官方 GitHub 賬戶,你就能看到所有語言是全英文的,我們以國際化標準來開發這個專案,包括後續的文件以及在程式碼中的註釋都是按照國際化的標準來進行,其目的是希望它的受眾足夠廣,希望各個國家的程式設計師都可以以同樣的標準參與到專案中來,而不是單單隻面向中文的使用者和開發者。

第四,我們需要這個專案在釋出的時候是一個可用的狀態,這也是我們釋出的目標。剛剛主持人也說了,我們在 1024 的時候釋出這個專案,釋出時就是可用的狀態,是可以 run 的、可執行程式,而非半成品程式碼。這是我們專案開發之初就定下的專案目標。

專案挑戰

專案在開發之前,我們就把專案可能遇到了一些挑戰給列了出來,讓開發的團隊心裡有數,有些挑戰是我們在開發中才總結出來的。

圖片

第一個挑戰,就是時間週期很短。其實之前討論過很長時間要去做這個專案,但專案正式立項是在今年的 5 月份,然後 6 月初才啟動。如果要在 1024 釋出的話, 9 月底就必須得交付內部預覽版,所以該專案的開發實際上只有三個月不到,時間其實是非常緊的。從 0 開發一個專案,會經歷產品設計階段、技術的選型以及一些磨合,其實過程非常複雜,所以時間是我們遇到的最大挑戰。

後面我們也遇到了一些技術上的挑戰,該專案是我們第一次用 Go 開發的大型的、開源的、Web 專案,所以對程式碼質量要求特別高的我們在開發過程中也遇到了一些挑戰和困難,但都很好的解決了,當然現在還有一些沒有解決的也在解決中,因為開源就是一個不斷完善的過程。

第二,它是一個全新的互動環境,之前我們交付的內容都是使用者端產品或給 B 端或商業使用者用的產品,交付給讓他們使用就可以了。但現在我們互動的是程式碼,程式碼本身也是我們產品的一部分,包括程式碼是否標準,介面是否完善,文件包括它的國際化等。在我們之前做專案的時候是不用考慮的,只需要考慮該專案是否可以 run ,使用者用的時候沒有bug ,這就可以了。但如果是開源專案的話,那程式碼的標準程度,它的測試,以及介面設定是否合理,命名是否規範,都特別有挑戰性。跟我們之前很多開發者本身的程式設計習慣是相悖的。因此在這中間,我們也跟著專案建立了自己的很多程式設計標準,也建立起來一套我們自己的程式碼規範,也是隨著這個開源專案開發不斷完善。

第三,網際網路產品的特性,即產品是隨時調整的。以前在做網際網路開發時,我們也經常遇到這個問題,開發時該產品的需求會有變化,要隨時調整,所以與普通的軟體專案交付有所不同。

專案開發流程

軟體專案的開發流程通常是:我們需求討論確定,然後寫具體的產品說明書,之後就可以交付開發。按照該產品說明書的標準開發,最後交付時一條條校對,確保是否達到標準。但是對網際網路產品而言,開發過程中可能會遇到產品調整,此時可能需要持續整合,需要不斷交付新產品,這也是網際網路開發的一個特點

圖片

在這個專案中,我們就遇到了一些需要調整的問題,儘管並非頻繁調整,但依舊調整了很多,有些增加,有些刪掉,這是持續整合的過程。該專案流程是個比較普遍的流程,與一般產品相差無幾,經過需求的設計討論後會得出產品原型,之後再進行討論,原型是否合理,如合理或拍板定型後,會給出相對固定的、正式的產品設計或詳細說明。據以往的開發流程,此時研發隊伍已可按照該產品說明做專案研發,一般先是交付測試,然後再交付就可以。但對我們來說的話,在研發的過程中會不斷的修改,產品也在不斷調整的過程,不以最後產品交付為主,而是中間設定很多節點持續交付節點。按照該特點,對產品的交付流程做改進

圖片

首先,將功能模組全部按功能拆分,然後變成一個個子任務。右邊可以看到我們的研發管理工具—— ONES ,透過該工具把專案做整理,提取其中一些功能模組,先拆功能模組,再將功能模組按任務拆分成子任務一項項落實,最後再監聽其工時及完成情況。

我們會按周來設立里程碑——將周設為持續交付的節點,每個節點將這些功能模組交付,下一週就會有調整。如果本週功能模組最終驗證完成,那這一週的任務就完成了,還可看交付的百分比進度。我們每週會做定期檢視,會看這周交付的內容有哪些問題,是否需要調整,然後將其做調整,再交到下一週的任務中去,這可能是個持續迭代的過程。

當然,每週任務進行時,我們會有一個總目標,以保證如期完成。必須緊盯總目標,才不會在每週執行時逐漸迷失、將總目標丟失,或做成了另外的專案,這是不允許的。因此在任務排期或任務分配時,會以總目標為最高優先順序來安排工作

圖片

這是我們專案管理的整個預覽,專案開發的啟動為第一週,第二週是正式開始開發,每週都是一個節點。可以看到第 11 周的最終節點,1024 的前夜就是第 11 周,該任務開發階段的任務即終結。後面會進入產品迭代的過程。

圖片

DevOps 要求從開發到專案,從專案管理最開始到任務分配,從產品端到互動再到運維端,全程需要開發者掌控,因此需要一系列工具的支援,也得益於近些年這些工具的發展,才有了 DevOps 概念。如果沒有這種工具,開發者接觸 OPS 端會很難上手,因為可能需要訓練 Linux 或伺服器相關運維知識。但現在,有了這些工具,將工作都用程式碼抽象了出來。對開發者而言,只是編了另一段程式碼,再監控這些任務的執行狀態,就可以完成工作。

我們在做全狀態全鏈路管理時,用了這些工具。最開始是用 ONES 來做專案管理,我們所有程式碼管理放在 GitLab 上,即內部私有倉庫,然後持續整合。這些程式碼的測試和打包、交付都放在 GitLab 本身的 CI/CD 工具,以上是我們的選擇。

如果大家對此感興趣,業界肯定會有類似的選擇,比如使用 GitHub 來做程式碼管理,當然還可以用 drone 或 GitHub 的 Actions 來做持續整合。這是個自動化工具,它會有一些特殊的語法。由於現在 K8S 容器管理平臺的出現,極大的方便了程式設計師最後的交付。以往要交付一個產品,部署之後會很麻煩,需要專業運維人員在不同環境配置、部署程式碼,需要很多專業知識。但現在有容器,後面還有 Docker、Docker 管理工具等,將交付或部署流程給程式碼化抽象了出來。現在,Developer 可以做很多 OPS 工作,這也是我們做 DevOps 的保證。

DevOps 的實施

因為有了這些前置條件,它保證了 DevOps 的實施可以順利進行。之前提到,正如 Kubernetes 抽象了很多的硬體資源,然後 CI/CD 工具又將 OPS 的流程語義化。對開發者而言,寫程式碼是一件很直觀的事情,能把它抽象,就可以做 OPS 。

這對工程師來說也有一些改變,因為他們之前交付的結果可能僅僅是一個程式碼或測試完成的程式碼。但是現在工程師最終的交付結果直接是一個可以線上上執行的容器,或者你可以認為它是一個App,它可以監控這個交付的過程,最後是否成功。這樣就可以把它最終交付的鏈路拉長,之前他無法介入的東西他現在也可以自己去調整,包括你的容器、需要的資源都可以自己去調配。

圖片

右邊是做 CI/CD 的工具流圖形化展示,我們現在用 GitLab 來做 CI/CD,可將 CI/CD 流程以圖形化的形式展現出來,先編碼,然後流程化展現。這裡可以看到,CI/CD 幾個典型的工作流,比如在程式碼 push 到程式碼管理平臺給 GitLab 後,它會做程式碼風格、單元測試並行檢查,都透過後才會到下一步可以部署的階段,此時就由開發者自己選擇部署到哪個平臺。

比如我們 SegmentFault 分了三個平臺,一個是 test 平臺,即測試平臺,還有 product 正式線上釋出的平臺和老平臺。開發者可以選擇執行下一個操作,以 trigger 另一個持續整合的步驟,專門用來上線的地方就可以檢測上線是否成功。如果不成功,會將原因告訴你;如果成功,也會很直觀的顯示出一個綠色的勾,這樣開發者就可以知道從它的程式碼釋出到最終上線,是否符合我們的平臺的標準。

這是我們的 Answer.dev 專案,包括專案管理、以及 DevOps 實施的一些情況。現在我把它交給明城,他來介紹一下我們 Answer.dev 專案的一些具體情況

Answer.dev 是如何安裝部署的

同學們大家好,我主要介紹一下 Answer.dev 是如何安裝部署的,並從工程化及技術角度介紹該專案的一些基本情況。

圖片

這是 Answer.dev 專案在部署之前需要的一些具體的系統需求,我大概列了三點:

1. Linux 環境,其實 Answer.dev 專案是用 Mac OS 開發的,本身就支援在 Linux 和 Mac 上都可執行,但在實際的生產環境裡,會以 Linux 是為主。

  1. 對應多個環境就需要容器化,包括清理。剛才提到,我們有 K8S 環境都可以執行。如果需要編譯,那可能會需要增加對應的開發環境,前後端都需要
  2. 有關資料庫方面的支援,其實我們在開發之初我們就考慮到了多資料庫的支援。因此 MySQL、SQLite、以及 Postgress 都是可以使用並被支援的,但是一般來說推薦同學們使用 MySQL 以及 SQLite,因為它們更加得通用。

圖片

具體部署方面,有兩種方式:一種是用 Docker ,這是我們比較熟悉的容器環境;另一種是裸機部署,直接透過命令列啟動。

Answer.dev 專案採用的是前後端分離的方案,前端使用的是 React 技術棧,同時後端是使用 Golang 編寫。同時,我們編譯生成的 Golang 可執行程式中,嵌入了所有 React 框架生成的靜態資原始檔。但是,我們因為伺服器環境不一致,可能會造成 Answer.dev 執行的使用者許可權不一樣,有些是普通使用者、有些是管理員,所以可能會造成資源訪問的許可權不同,例如能否讀取和寫入本地指定目錄的許可權等等。所以,從部署角度上講,我們可以使用單個可執行檔案即可執行起完整的 Answer.dev 專案。不過推薦使用容器化環境執行 Answer.dev 專案,這樣子可以統一執行環境、以及實現程式和資料方面的隔離。

希望大家能夠透過我們官網的一些文件及安裝步驟,自己一步步 run 起來,這樣對於大家而言會有更加直觀的認識。

https://answer.dev/docs/quick... https://answer.dev/docs/Installation/binary https://answer.dev/docs/Insta...

圖片

現在螢幕展示的是命令列視窗:如果我們透過 Docker 去部署的話,我們官方已經寫好對應的 docker compose 檔案。所以,我們很輕鬆得久可以使用一行命令啟動和部署 answer 應用。下面,我們簡單瞭解下 docker compose 其中的檔案內容:answer-data 是 Docker 其中一個卷,也可以是本地目錄,對映到容器裡面做持久化。然後,預設的資料庫配置可以是 SQLite 也可以是 MySQL,這裡對應的啟動了個 MySQL 的容易用於儲存 Answer.dev 的資料和配置。(注:後期新版本的 answer 使用了 SQLite 作為預設的本地資料庫)。然後,預設不用任何的操作,就可以 init 成功了,我們重新整理一下瀏覽器,然後就可以看到介面 Answer.dev 專案就起來了。

以上,我們可以更直觀的 瞭解到 Answer.dev 整個專案的構成以及它具體是怎麼執行起來的。

編譯和構建 Answer.dev

圖片

Answer.dev 專案本身分成了兩個比較大的專案——前端、後端。前端用 React 編寫,後端用 Golang 編寫,是比較典型的前後端分離的專案。

那麼如何同時構建前後端兩個專案?我們用了 Makefile ,這裡開啟一個指令碼 Makefile,大家有興趣的話可以上 GitHub 登陸我們 Answer.dev 主頁,Makefile 就在我們主頁的根目錄。

簡單說一下,不要求大家能看懂,瞭解我們是如何構建的。 簡單的說,這邊會有一個 npm 然後 install ,把前端的依賴包打完扔給後端、後端會把前端的產出,即靜態的 CSS、HTML 檔案轉到 Golang 裡,然後就編譯完成了。此時,會有一個二進位制的檔案,從部署角度上講是完整的,因為我們有一個可執行的二進位制檔案可以把它執行起來。

如同學們所見,我們多了一個檔案叫 answer,此時我們直接執行起來,就這麼簡單。以前在課程裡也都能用到,比如如何編譯、如何打包程式,如何打成映象,到各種各樣的多容器環境或 Kubernetes 環境裡,這裡就要用到 Dockfile 了。

我們多個方案其實也跟 Makefile  相似,先調 node 打包前端,然後 stage 2 調 Golang ,用 Golang 的映象去打包 Golang  的環境,然後再將 node 產生的 Answer.dev HTML 跟 GS 靜態檔案打到共創的二進位制包裡,再扔到容器的一個環節裡去執行,同時設定入口即可。

正如剛才 @Joyqi 所說,我們可以透過 GitHub Action 或 GitLab CI/CD 執行自動化操作,開發者本身無需關心部署及打包過程,因為過程非常費時費力,且非常容易分心,開發者可以更加專注於自己開發的內容上。

https://answer.dev/
https://github.com/answerdev/...
https://twitter.com/AnswerDev

這是我們的官網主頁,包括我們 GitHub 主頁及我們在 Twitter 的官方賬號,可以隨時與我們互動。大家就有哪些疑問或問題可以直接提出來。

相關文章