切換到新語言始終是一大步,尤其是當您的團隊成員只有一個時有該語言的先前經驗?,F在,Stream 的主要編程語言從 Python 切換到了 Go。這篇文章將解釋stream決定放棄 Python 并轉向 Go 的一些原因。
站在用戶的角度思考問題,與客戶深入溝通,找到蒼梧網站設計與蒼梧網站推廣的解決方案,憑借多年的經驗,讓設計與互聯網技術結合,創造個性化、用戶體驗好的作品,建站類型包括:成都做網站、網站制作、企業官網、英文網站、手機端網站、網站推廣、申請域名、虛擬空間、企業郵箱。業務覆蓋蒼梧地區。
Go 非??臁P阅茴愃朴?Java 或 C++。對于用例,Go 通常比 Python 快 40 倍。
對于許多應用程序來說,編程語言只是應用程序和數據庫之間的粘合劑。語言本身的性能通常并不重要。然而,Stream 是一個API 提供商,為 700 家公司和超過 5 億最終用戶提供提要和聊天平臺。多年來,我們一直在優化 Cassandra、PostgreSQL、Redis 等,但最終,您會達到所使用語言的極限。Python 是一門很棒的語言,但對于序列化/反序列化、排名和聚合等用例,它的性能相當緩慢。我們經常遇到性能問題,Cassandra 需要 1 毫秒來檢索數據,而 Python 會花費接下來的 10 毫秒將其轉換為對象。
看看我如何開始 Go 教程中的一小段 Go 代碼。(這是一個很棒的教程,也是學習 Go 的一個很好的起點。)
如果您是 Go 新手,那么在閱讀那個小代碼片段時不會有太多讓您感到驚訝的事情。它展示了多個賦值、數據結構、指針、格式和一個內置的 HTTP 庫。當我第一次開始編程時,我一直喜歡使用 Python 更高級的功能。Python 允許您在編寫代碼時獲得相當的創意。例如,您可以:
這些功能玩起來很有趣,但是,正如大多數程序員會同意的那樣,在閱讀別人的作品時,它們通常會使代碼更難理解。Go 迫使你堅持基礎。這使得閱讀任何人的代碼并立即了解發生了什么變得非常容易。 注意:當然,它實際上有多“容易”取決于您的用例。如果你想創建一個基本的 CRUD API,我仍然推薦 Django + DRF或 Rails。
作為一門語言,Go 試圖讓事情變得簡單。它沒有引入許多新概念。重點是創建一種非常快速且易于使用的簡單語言。它唯一具有創新性的領域是 goroutine 和通道。(100% 正確CSP的概念始于 1977 年,所以這項創新更多是對舊思想的一種新方法。)Goroutines 是 Go 的輕量級線程方法,通道是 goroutines 之間通信的首選方式。Goroutines 的創建非常便宜,并且只需要幾 KB 的額外內存。因為 Goroutine 非常輕量,所以有可能同時運行數百甚至數千個。您可以使用通道在 goroutine 之間進行通信。Go 運行時處理所有復雜性。goroutines 和基于通道的并發方法使得使用所有可用的 CPU 內核和處理并發 IO 變得非常容易——所有這些都不會使開發復雜化。與 Python/Java 相比,在 goroutine 上運行函數需要最少的樣板代碼。您只需在函數調用前加上關鍵字“go”:
Go 的并發方法很容易使用。與 Node 相比,這是一種有趣的方法,開發人員必須密切關注異步代碼的處理方式。Go 中并發的另一個重要方面是競爭檢測器。這樣可以很容易地確定異步代碼中是否存在任何競爭條件。
我們目前用 Go 編寫的最大的微服務編譯需要 4 秒。與以編譯速度慢而聞名的 Java 和 C++ 等語言相比,Go 的快速編譯時間是一項重大的生產力勝利。我喜歡在程序編譯的時候摸魚,但在我還記得代碼應該做什么的同時完成事情會更好。
首先,讓我們從顯而易見的開始:與 C++ 和 Java 等舊語言相比,Go 開發人員的數量并不多。根據StackOverflow的數據, 38% 的開發人員知道 Java, 19.3% 的人知道 C++,只有 4.6% 的人知道 Go。GitHub 數據顯示了類似的趨勢:Go 比 Erlang、Scala 和 Elixir 等語言使用更廣泛,但不如 Java 和 C++ 流行。幸運的是,Go 是一種非常簡單易學的語言。它提供了您需要的基本功能,僅此而已。它引入的新概念是“延遲”聲明和內置的并發管理與“goroutines”和通道。(對于純粹主義者來說:Go 并不是第一種實現這些概念的語言,只是第一種使它們流行起來的語言。)任何加入團隊的 Python、Elixir、C++、Scala 或 Java 開發人員都可以在一個月內在 Go 上發揮作用,因為它的簡單性。與許多其他語言相比,我們發現組建 Go 開發人員團隊更容易。如果您在博爾德和阿姆斯特丹等競爭激烈的生態系統中招聘人員,這是一項重要的優勢。
對于我們這樣規模的團隊(約 20 人)來說,生態系統很重要。如果您必須重新發明每一個小功能,您根本無法為您的客戶創造價值。Go 對我們使用的工具有很好的支持。實體庫已經可用于 Redis、RabbitMQ、PostgreSQL、模板解析、任務調度、表達式解析和 RocksDB。與 Rust 或 Elixir 等其他較新的語言相比,Go 的生態系統是一個重大勝利。它當然不如 Java、Python 或 Node 之類的語言好,但它很可靠,而且對于許多基本需求,你會發現已經有高質量的包可用。
Gofmt 是一個很棒的命令行實用程序,內置在 Go 編譯器中,用于格式化代碼。就功能而言,它與 Python 的 autopep8 非常相似。我們大多數人并不真正喜歡爭論制表符與空格。格式的一致性很重要,但實際的格式標準并不那么重要。Gofmt 通過使用一種正式的方式來格式化您的代碼來避免所有這些討論。
Go 對協議緩沖區和 gRPC 具有一流的支持。這兩個工具非常適合構建需要通過 RPC 通信的微服務。您只需要編寫一個清單,在其中定義可以進行的 RPC 調用以及它們采用的參數。然后從這個清單中自動生成服務器和客戶端代碼。生成的代碼既快速又具有非常小的網絡占用空間并且易于使用。從同一個清單中,您甚至可以為許多不同的語言生成客戶端代碼,例如 C++、Java、Python 和 Ruby。因此,內部流量不再有模棱兩可的 REST 端點,您每次都必須編寫幾乎相同的客戶端和服務器代碼。.
Go 沒有像 Rails 用于 Ruby、Django 用于 Python 或 Laravel 用于 PHP 那樣的單一主導框架。這是 Go 社區內激烈爭論的話題,因為許多人主張你不應該一開始就使用框架。我完全同意這對于某些用例是正確的。但是,如果有人想構建一個簡單的 CRUD API,他們將更容易使用 Django/DJRF、Rails Laravel 或Phoenix。對于 Stream 的用例,我們更喜歡不使用框架。然而,對于許多希望提供簡單 CRUD API 的新項目來說,缺乏主導框架將是一個嚴重的劣勢。
Go 通過簡單地從函數返回錯誤并期望調用代碼來處理錯誤(或將其返回到調用堆棧)來處理錯誤。雖然這種方法有效,但很容易失去問題的范圍,以確保您可以向用戶提供有意義的錯誤。錯誤包通過允許您向錯誤添加上下文和堆棧跟蹤來解決此問題。另一個問題是很容易忘記處理錯誤。像 errcheck 和 megacheck 這樣的靜態分析工具可以方便地避免犯這些錯誤。雖然這些變通辦法效果很好,但感覺不太對勁。您希望該語言支持正確的錯誤處理。
Go 的包管理絕不是完美的。默認情況下,它無法指定特定版本的依賴項,也無法創建可重現的構建。Python、Node 和 Ruby 都有更好的包管理系統。但是,使用正確的工具,Go 的包管理工作得很好。您可以使用Dep來管理您的依賴項,以允許指定和固定版本。除此之外,我們還貢獻了一個名為的開源工具VirtualGo,它可以更輕松地處理用 Go 編寫的多個項目。
我們進行的一個有趣的實驗是在 Python 中使用我們的排名提要功能并在 Go 中重寫它??纯催@個排名方法的例子:
Python 和 Go 代碼都需要執行以下操作來支持這種排名方法:
開發 Python 版本的排名代碼大約花了 3 天時間。這包括編寫代碼、單元測試和文檔。接下來,我們花了大約 2 周的時間優化代碼。其中一項優化是將分數表達式 (simple_gauss(time)*popularity) 轉換為抽象語法樹. 我們還實現了緩存邏輯,可以在未來的特定時間預先計算分數。相比之下,開發此代碼的 Go 版本大約需要 4 天時間。性能不需要任何進一步的優化。因此,雖然 Python 的最初開發速度更快,但基于 Go 的版本最終需要我們團隊的工作量大大減少。另外一個好處是,Go 代碼的執行速度比我們高度優化的 Python 代碼快大約 40 倍?,F在,這只是我們通過切換到 Go 體驗到的性能提升的一個示例。
與 Python 相比,我們系統的其他一些組件在 Go 中構建所需的時間要多得多。作為一個總體趨勢,我們看到 開發 Go 代碼需要更多的努力。但是,我們花更少的時間 優化 代碼以提高性能。
我們評估的另一種語言是Elixir.。Elixir 建立在 Erlang 虛擬機之上。這是一種迷人的語言,我們之所以考慮它,是因為我們的一名團隊成員在 Erlang 方面擁有豐富的經驗。對于我們的用例,我們注意到 Go 的原始性能要好得多。Go 和 Elixir 都可以很好地服務數千個并發請求。但是,如果您查看單個請求的性能,Go 對于我們的用例來說要快得多。我們選擇 Go 而不是 Elixir 的另一個原因是生態系統。對于我們需要的組件,Go 有更成熟的庫,而在許多情況下,Elixir 庫還沒有準備好用于生產環境。培訓/尋找開發人員使用 Elixir 也更加困難。這些原因使天平向 Go 傾斜。Elixir 的 Phoenix 框架看起來很棒,絕對值得一看。
Go 是一種非常高性能的語言,對并發有很好的支持。它幾乎與 C++ 和 Java 等語言一樣快。雖然與 Python 或 Ruby 相比,使用 Go 構建東西確實需要更多時間,但您將節省大量用于優化代碼的時間。我們在Stream有一個小型開發團隊,為超過 5 億最終用戶提供動力和聊天。Go 結合了 強大的生態系統 、新開發人員的 輕松入門、快速的性能 、對并發的 可靠支持和高效的編程環境 ,使其成為一個不錯的選擇。Stream 仍然在我們的儀表板、站點和機器學習中利用 Python 來提供個性化的訂閱源. 我們不會很快與 Python 說再見,但今后所有性能密集型代碼都將使用 Go 編寫。我們新的聊天 API也完全用 Go 編寫。
簡述 etcd 及其特點?
答:etcd 是 CoreOS 團隊發起的開源項目,是一個管理配置信息和服務發現
(service discovery)的項目,它的目標是構建一個高可用的分布式鍵值(key-value)
數據庫,基于 Go 語言實現。
特點:
l 簡單:支持 REST 風格的 HTTP+JSON API
l 安全:支持 HTTPS 方式的訪問
l 快速:支持并發 1k/s 的寫操作
l 可靠:支持分布式結構,基于 Raft 的一致性算法,Raft 是一套通過選舉主節點來
實現分布式系統一致性的算法。
簡述 etcd 適應的場景?
答:etcd 基于其優秀的特點,可廣泛的應用于以下場景:
l 服務發現(Service Discovery):服務發現主要解決在同一個分布式集群中的進程
或服務,要如何才能找到對方并建立連接。本質上來說,服務發現就是想要了解
集群中是否有進程在監聽 udp 或 tcp 端口,并且通過名字就可以查找和連接。
一些配置信息放到 etcd 上進行集中管理。
l 負載均衡:在分布式系統中,為了保證服務的高可用以及數據的一致性,通常都
會把數據和服務部署多份,以此達到對等服務,即使其中的某一個服務失效了,
也不影響使用。etcd 本身分布式架構存儲的信息訪問支持負載均衡。etcd 集群化
以后,每個 etcd 的核心節點都可以處理用戶的請求。所以,把數據量小但是訪問
頻繁的消息數據直接存儲到 etcd 中也可以實現負載均衡的效果。
通過注冊與異步通知機制,實現分布式環境下不同系統之間的通知與協調,從而
對數據變更做到實時處理。
l 分布式鎖:因為 etcd 使用 Raft 算法保持了數據的強一致性,某次操作存儲到集
群中的值必然是全局一致的,所以很容易實現分布式鎖。鎖服務有兩種使用方式,
一是保持獨占,二是控制時序。
l 集群監控與 Leader 競選:通過 etcd 來進行監控實現起來非常簡單并且實時性強。
簡述 Kubernetes 和 Docker 的關系?
答:Docker 提供容器的生命周期管理和,Docker 鏡像構建運行時容器。它的主要優
點是將將軟件/應用程序運行所需的設置和依賴項打包到一個容器中,從而實現了可移
植性等優點。
Kubernetes 用于關聯和編排在多個主機上運行的容器。
簡述 Kubernetes 中什么是 Minikube、Kubectl、Kubelet?
答:Minikube 是一種可以在本地輕松運行一個單節點 Kubernetes 群集的工具。
Kubectl 是一個命令行工具,可以使用該工具控制 Kubernetes 集群管理器,如檢查
群集資源,創建、刪除和更新組件,查看應用程序。
Kubelet 是一個代理服務,它在每個節點上運行,并使從服務器與主服務器通信。
簡述 Kubernetes 常見的部署方式?
答:常見的 Kubernetes 部署方式有:
l kubeadm:也是推薦的一種部署方式;
l 二進制:
l minikube:在本地輕松運行一個單節點 Kubernetes 群集的工具。
簡述 Kubernetes 如何實現集群管理?
答:在集群管理方面,Kubernetes 將集群中的機器劃分為一個 Master 節點和一群工
作節點 Node。其中,在 Master 節點運行著集群管理相關的一組進程 kube
apiserver、kube-controller-manager 和 kube-scheduler,這些進程實現了整個集
群的資源管理、Pod 調度、彈性伸縮、安全控制、系統監控和糾錯等管理能力,并且
都是全自動完成的。
簡述 Kubernetes 相關基礎概念?
答:
l master:k8s 集群的管理節點,負責管理集群,提供集群的資源數據訪問入口。
擁有 Etcd 存儲服務(可選),運行 Api Server 進程,Controller Manager 服務
進程及 Scheduler 服務進程。
l node(worker):Node(worker)是 Kubernetes 集群架構中運行 Pod 的服
務節點,是 Kubernetes 集群操作的單元,用來承載被分配 Pod 的運行,是 Pod
運行的宿主機。運行 docker eninge 服務,守護進程 kunelet 及負載均衡器
kube-proxy。
l pod:運行于 Node 節點上,若干相關容器的組合。Pod 內包含的容器運行在同
一宿主機上,使用相同的網絡命名空間、IP 地址和端口,能夠通過 localhost 進行通信。Pod 是 Kurbernetes 進行創建、調度和管理的最小單位,它提供了比容
器更高層次的抽象,使得部署和管理更加靈活。一個 Pod 可以包含一個容器或者
多個相關容器。
l label:Kubernetes 中的 Label 實質是一系列的 Key/Value 鍵值對,其中 key 與
value 可自定義。Label 可以附加到各種資源對象上,如 Node、Pod、Service、
RC 等。一個資源對象可以定義任意數量的 Label,同一個 Label 也可以被添加到
任意數量的資源對象上去。Kubernetes 通過 Label Selector(標簽選擇器)查詢
和篩選資源對象。
l Replication Controller:Replication Controller 用來管理 Pod 的副本,保證集
群中存在指定數量的 Pod 副本。集群中副本的數量大于指定數量,則會停止指定
數量之外的多余容器數量。反之,則會啟動少于指定數量個數的容器,保證數量
不變。Replication Controller 是實現彈性伸縮、動態擴容和滾動升級的核心。
l Deployment:Deployment 在內部使用了 RS 來實現目的,Deployment 相當
于 RC 的一次升級,其最大的特色為可以隨時獲知當前 Pod 的部署進度。
l HPA(Horizontal Pod Autoscaler):Pod 的橫向自動擴容,也是 Kubernetes
的一種資源,通過追蹤分析 RC 控制的所有 Pod 目標的負載變化情況,來確定是
否需要針對性的調整 Pod 副本數量。
l Service:Service 定義了 Pod 的邏輯集合和訪問該集合的策略,是真實服務的抽
象。Service 提供了一個統一的服務訪問入口以及服務代理和發現機制,關聯多個
相同 Label 的 Pod,用戶不需要了解后臺 Pod 是如何運行。
l Volume:Volume 是 Pod 中能夠被多個容器訪問的共享目錄,Kubernetes 中的
Volume 是定義在 Pod 上,可以被一個或多個 Pod 中的容器掛載到某個目錄下。l Namespace:Namespace 用于實現多租戶的資源隔離,可將集群內部的資源對
象分配到不同的 Namespace 中,形成邏輯上的不同項目、小組或用戶組,便于
不同的 Namespace 在共享使用整個集群的資源的同時還能被分別管理。
簡述 Kubernetes RC 的機制?
答:Replication Controller 用來管理 Pod 的副本,保證集群中存在指定數量的 Pod
副本。當定義了 RC 并提交至 Kubernetes 集群中之后,Master 節點上的 Controller
Manager 組件獲悉,并同時巡檢系統中當前存活的目標 Pod,并確保目標 Pod 實例的數量剛好等于此 RC 的期望值,若存在過多的 Pod 副本在運行,系統會停止一些
Pod,反之則自動創建一些 Pod。
簡述 Kubernetes 中 Pod 的重啟策略?
答:Pod 重啟策略(RestartPolicy)應用于 Pod 內的所有容器,并且僅在 Pod 所處
的 Node 上由 kubelet 進行判斷和重啟操作。當某個容器異常退出或者 健康 檢查失敗
時,kubelet 將根據 RestartPolicy 的設置來進行相應操作。
Pod 的重啟策略包括 Always、OnFailure 和 Never,默認值為 Always。
l Always:當容器失效時,由 kubelet 自動重啟該容器;
l OnFailure:當容器終止運行且退出碼不為 0 時,由 kubelet 自動重啟該容器;
l Never:不論容器運行狀態如何,kubelet 都不會重啟該容器。
同時 Pod 的重啟策略與控制方式關聯,當前可用于管理 Pod 的控制器包括
ReplicationController、Job、DaemonSet 及直接管理 kubelet 管理(靜態 Pod)。
不同控制器的重啟策略限制如下:
l RC 和 DaemonSet:必須設置為 Always,需要保證該容器持續運行;
l Job:OnFailure 或 Never,確保容器執行完成后不再重啟;
l kubelet:在 Pod 失效時重啟,不論將 RestartPolicy 設置為何值,也不會對 Pod
進行 健康 檢查。
簡述 Kubernetes Pod 的 LivenessProbe 探針的常見方式?
答:kubelet 定期執行 LivenessProbe 探針來診斷容器的 健康 狀態,通常有以下三種
方式:
l ExecAction:在容器內執行一個命令,若返回碼為 0,則表明容器 健康 。
l TCPSocketAction:通過容器的 IP 地址和端口號執行 TCP 檢查,若能建立 TCP
連接,則表明容器 健康 。
l HTTPGetAction:通過容器的 IP 地址、端口號及路徑調用 HTTP Get 方法,若響
應的狀態碼大于等于 200 且小于 400,則表明容器 健康 。
. 簡述 Kubernetes Pod 的常見調度方式?
答:Kubernetes 中,Pod 通常是容器的載體,主要有如下常見調度方式:
l Deployment 或 RC:該調度策略主要功能就是自動部署一個容器應用的多份副本,
以及持續監控副本的數量,在集群內始終維持用戶指定的副本數量。
l NodeSelector:定向調度,當需要手動指定將 Pod 調度到特定 Node 上,可以
通過 Node 的標簽(Label)和 Pod 的 nodeSelector 屬性相匹配。
l NodeAffinity 親和性調度:親和性調度機制極大的擴展了 Pod 的調度能力,目前
有兩種節點親和力表達:
l requiredDuringSchedulingIgnoredDuringExecution:硬規則,必須滿足指定
的規則,調度器才可以調度 Pod 至 Node 上(類似 nodeSelector,語法不同)。
l preferredDuringSchedulingIgnoredDuringExecution:軟規則,優先調度至滿
足的 Node 的節點,但不強求,多個優先級規則還可以設置權重值。
l Taints 和 Tolerations(污點和容忍):
l Taint:使 Node 拒絕特定 Pod 運行;
l Toleration:為 Pod 的屬性,表示 Pod 能容忍(運行)標注了 Taint 的 Node。
簡述 Kubernetes DaemonSet 類型的資源特性?
答:DaemonSet 資源對象會在每個 Kubernetes 集群中的節點上運行,并且每個節
點只能運行一個 pod,這是它和 deployment 資源對象的最大也是唯一的區別。因此,
在定義 yaml 文件中,不支持定義 replicas。
它的一般使用場景如下:
l 在去做每個節點的日志收集工作。
l 監控每個節點的的運行狀態。
簡述 Kubernetes Service 分發后端的策略?
答:Service 負載分發的策略有:RoundRobin 和 SessionAffinity
l RoundRobin:默認為輪詢模式,即輪詢將請求轉發到后端的各個 Pod 上。
l SessionAffinity:基于客戶端 IP 地址進行會話保持的模式,即第 1 次將某個客戶
端發起的請求轉發到后端的某個 Pod 上,之后從相同的客戶端發起的請求都將被
轉發到后端相同的 Pod 上。
簡述 Kubernetes Scheduler 使用哪兩種算法將 Pod 綁定到 worker 節點?
答:Kubernetes Scheduler 根據如下兩種調度算法將 Pod 綁定到最合適的工作節點:
l 預選(Predicates):輸入是所有節點,輸出是滿足預選條件的節點。kube
scheduler 根據預選策略過濾掉不滿足策略的 Nodes。如果某節點的資源不足或
者不滿足預選策略的條件則無法通過預選。如“Node 的 label 必須與 Pod 的
Selector 一致”。
l 優選(Priorities):輸入是預選階段篩選出的節點,優選會根據優先策略為通過
預選的 Nodes 進行打分排名,選擇得分最高的 Node。例如,資源越富裕、負載
越小的 Node 可能具有越高的排名。
簡述 Kubernetes Secret 有哪些使用方式?
答:創建完 secret 之后,可通過如下三種方式使用:
l 在創建 Pod 時,通過為 Pod 指定 Service Account 來自動使用該 Secret。
l 通過掛載該 Secret 到 Pod 來使用它。
l 在 Docker 鏡像下載時使用,通過指定 Pod 的 spc.ImagePullSecrets 來引用它。
簡述 Kubernetes 網絡策略原理?
答:Network Policy 的工作原理主要為:policy controller 需要實現一個 API
Listener,監聽用戶設置的 Network Policy 定義,并將網絡訪問規則通過各 Node 的
Agent 進行實際設置(Agent 則需要通過 CNI 網絡插件實現)。
簡述 Kubernetes 集群聯邦?
答:Kubernetes 集群聯邦可以將多個 Kubernetes 集群作為一個集群進行管理。因此,
可以在一個數據中心/云中創建多個 Kubernetes 集群,并使用集群聯邦在一個地方控
制/管理所有集群。
簡述 Kubernetes 如何進行優雅的節點關機維護?
答:由于 Kubernetes 節點運行大量 Pod,因此在進行關機維護之前,建議先使用
kubectl drain 將該節點的 Pod 進行驅逐,然后進行關機維護。
. 簡述 Kubernetes 中,如何使用 EFK 實現日志的統一管理?
答:在 Kubernetes 集群環境中,通常一個完整的應用或服務涉及組件過多,建議對
日志系統進行集中化管理,通常采用 EFK 實現。
EFK 是 Elasticsearch、Fluentd 和 Kibana 的組合,其各組件功能如下:
l Elasticsearch:是一個搜索引擎,負責存儲日志并提供查詢接口;
l Fluentd:負責從 Kubernetes 搜集日志,每個 node 節點上面的 fluentd 監控并
收集該節點上面的系統日志,并將處理過后的日志信息發送給 Elasticsearch;
l Kibana:提供了一個 Web GUI,用戶可以瀏覽和搜索存儲在 Elasticsearch 中的
日志。通過在每臺 node 上部署一個以 DaemonSet 方式運行的 fluentd 來收集每臺 node
上的日志。Fluentd 將 docker 日志目錄/var/lib/docker/containers 和/var/log 目錄
掛載到 Pod 中,然后 Pod 會在 node 節點的/var/log/pods 目錄中創建新的目錄,可
以區別不同的容器日志輸出,該目錄下有一個日志文件鏈接到
/var/lib/docker/contianers 目錄下的容器日志輸出。
近期正在探索前端、后端、系統端各類常用組件與工具,對其一些常見的組件進行再次整理一下,形成標準化組件專題,后續該專題將包含各類語言中的一些常用組件。歡迎大家進行持續關注。
本節分享一個基于Go語言的HTML和CSS網站生成器 hugo ,它針對速度、易用性和可配置性進行了優化。Hugo 獲取一個包含內容和模板的目錄,并將它們呈現為一個完整的 HTML 網站。Hugo 依賴于 Markdown 文件和元數據的前端,你可以從任何目錄運行 Hugo。這適用于您沒有特權帳戶的共享主機和其他系統。例如我們日常編寫一些博客文章,進行快速生成一套靜態頁面進行分享時可以使用它來進行生成一套靜態頁面作為我們的博客部署基礎。
它支持大量的主題模板,我們可以通過 進行選擇相關的主題使用,有興趣的小伙伴可以進行深入研究一下
本文名稱:多租戶組件go語言 多租戶組件go語言怎么改
URL網址:http://m.kartarina.com/article22/dodshjc.html
成都網站建設公司_創新互聯,為您提供網站設計、靜態網站、品牌網站建設、外貿網站建設、網站導航、定制網站
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯