自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

顛覆微服務(wù)架構(gòu)?谷歌最新開源Service Weaver初體驗(yàn)

開發(fā) 架構(gòu)
很多語言的很多框架都有依賴注入的功能:定義一個(gè)接口,實(shí)現(xiàn)這個(gè)接口,從IOC容器中獲取這個(gè)接口的實(shí)例。借助依賴注入來實(shí)現(xiàn)依賴解耦,簡化對象創(chuàng)建流程等。

本文轉(zhuǎn)載自微信公眾號「涼涼的知識庫」,作者涼涼的知識庫 。轉(zhuǎn)載本文請聯(lián)系涼涼的知識庫公眾號。

合久必分,分久必合,技術(shù)圈也是如此。在大家紛紛從單體應(yīng)用過渡到微服務(wù)的時(shí)候,谷歌攜帶著新時(shí)代的“單體”應(yīng)用框架Service Weaver來了!代碼倉庫位于:https://github.com/ServiceWeaver/weaver 才發(fā)布沒幾天已經(jīng)超過了2.5k star,不得不感慨谷歌的號召力。

谷歌稱此框架為模塊化單體(modular monolith),谷歌為什么會在這個(gè)時(shí)候提出如此標(biāo)新立異的框架?它究竟有什么獨(dú)特之處?讓我們來速速體驗(yàn)下吧。

安裝

因?yàn)镾ervice Weaver使用了泛型,且聲明的依賴版本為1.19。所以本地安裝的go版本需要大于1.19

$ go install github.com/ServiceWeaver/weaver/cmd/weaver@latest

如果你設(shè)置了正確的$GOPATH/bin路徑到你的PATH中那么你可以直接運(yùn)行

$ weaver --help
USAGE

weaver generate // weaver code generator
weaver single <command> ... // for single process deployments
weaver multi <command> ... // for multiprocess deployments
...

教程

創(chuàng)建項(xiàng)目

$ mkdir hello/
$ cd hello/
$ go mod init github.com/liangwt/serviceweaver/hello

啟動服務(wù)

先來創(chuàng)建一個(gè)最簡單的HTTP服務(wù)。與Go內(nèi)置的HTTP server的使用方式非常類似,唯一的區(qū)別是創(chuàng)建端口監(jiān)聽的方式不同,Service Weaver需要使用github.com/ServiceWeaver/weaver包提供的函數(shù)來創(chuàng)建監(jiān)聽

package main

import (
"context"
"fmt"
"log"
"net/http"

"github.com/ServiceWeaver/weaver"
)

func main() {
// Get a network listener on address "localhost:12345".
root := weaver.Init(context.Background())
opts := weaver.ListenerOptions{LocalAddress: "localhost:12345"}
lis, err := root.Listener("hello", opts)
if err != nil {
log.Fatal(err)
}
fmt.Printf("hello listener available on %v\n", lis)

// Serve the /hello endpoint.
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!\n", r.URL.Query().Get("name"))
})
http.Serve(lis, nil)
}

// 內(nèi)置Go http server使用方式
// func main() {
// lis, err := net.Listen("tcp", "localhost:12345")
// if err != nil {
// log.Fatal(err)
// }

// // Serve the /hello endpoint.
// http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
// fmt.Fprintf(w, "Hello, %s!\n", r.URL.Query().Get("name"))
// })
// http.Serve(lis, nil)
// }

執(zhí)行也和普通的代碼沒有區(qū)別

$ go mod tidy
$ go run .
hello listener available on 127.0.0.1:12345
╭───────────────────────────────────────────────────╮
│ app : hello │
│ deployment : f4bd112d-c90d-409c-a90f-5022fa5a7b3f │
╰───────────────────────────────────────────────────╯

當(dāng)服務(wù)啟動之后我們就可以調(diào)用對應(yīng)端口,直到這里依舊和普通的HTTP server沒有區(qū)別

$ curl 'localhost:12345/hello?name=Weaver' 

Hello, Weaver!

組件(Components)

組件是Service Weaver中一個(gè)獨(dú)特的概念

什么是組件?一個(gè)應(yīng)用會有多個(gè)組件,每一個(gè)組件就是一個(gè)Go的interface。

下面的反轉(zhuǎn)字符串type Reverser interface就是一個(gè)組件,type reverser struct是它的一個(gè)實(shí)現(xiàn)。需要注意一點(diǎn)reverser struct組合了weaver.Implements[Reverser]用以實(shí)現(xiàn)Service Weaver要求的其他接口

// Reverser component.
type Reverser interface {
Reverse(context.Context, string) (string, error)
}

// Implementation of the Reverser component.
type reverser struct{
weaver.Implements[Reverser]
}

func (r *reverser) Reverse(_ context.Context, s string) (string, error) {
runes := []rune(s)
n := len(runes)
for i := 0; i < n/2; i++ {
runes[i], runes[n-i-1] = runes[n-i-1], runes[i]
}
return string(runes), nil
}

組件該怎么用?我們可以用weaver.Get()獲取一個(gè)組件的實(shí)例。例如:

func main() {
// Get a network listener on address "localhost:12345".
...
fmt.Printf("hello listener available on %v\n", lis)

// Get a client to the Reverser component.
reverser, err := weaver.Get[Reverser](root)
if err != nil {
log.Fatal(err)
}

// Serve the /hello endpoint.
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
reversed, err := reverser.Reverse(r.Context(), r.URL.Query().Get("name"))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
fmt.Fprintf(w, "Hello, %s!\n", reversed)
})
http.Serve(lis, nil)
}

這次在運(yùn)行代碼前我們得先執(zhí)行下面命令,文件中會多一個(gè) weaver_gen.go 文件

$ weaver generate .

重新運(yùn)行代碼

$ go run .
hello listener available on 127.0.0.1:12345
╭───────────────────────────────────────────────────╮
│ app : hello │
│ deployment : 7581bbb5-21c1-4cd3-8192-3fa2ac2bfc70 │
╰───────────────────────────────────────────────────╯

調(diào)用對應(yīng)的接口就會獲得反轉(zhuǎn)的字符串響應(yīng)

$ curl 'localhost:12345/hello?name=Weaver' 

Hello, revaeW!

對組件的看法

組件的概念,給我的第一感覺是非常像依賴注入中的IOC容器(不知道什么IOC的同學(xué)可以自行網(wǎng)上搜索充電)。

很多語言的很多框架都有依賴注入的功能:定義一個(gè)接口,實(shí)現(xiàn)這個(gè)接口,從IOC容器中獲取這個(gè)接口的實(shí)例。借助依賴注入來實(shí)現(xiàn)依賴解耦,簡化對象創(chuàng)建流程等

Service Weaver定義組件的概念也有其自身的目的,稍后體驗(yàn)過多進(jìn)程執(zhí)行的之后,會對組件有一點(diǎn)更深的理解

多進(jìn)程執(zhí)行

先創(chuàng)建一個(gè)TOML文件weaver.toml,內(nèi)容如下

[serviceweaver]
binary = "./hello"

編譯并使用weaver multi deploy來運(yùn)行我們的應(yīng)用

$ go build  
$ weaver multi deploy weaver.toml
╭───────────────────────────────────────────────────╮
│ app : hello │
│ deployment : c42d8b31-e6e3-4e41-a56e-6e18956927d3 │
╰───────────────────────────────────────────────────╯
S0308 22:33:22.289059 stdout 451b9a05 ] hello listener available on 127.0.0.1:12345
S0308 22:33:22.289190 stdout 2c79c310 ] hello listener available on 127.0.0.1:12345

調(diào)用對應(yīng)的接口依舊會獲得反轉(zhuǎn)的字符串響應(yīng)

$ curl 'localhost:12345/hello?name=Weaver' 

Hello, revaeW!

你可能會說這和go run .有啥區(qū)別?對于返回的響應(yīng)來說確實(shí)沒有區(qū)別,但在運(yùn)行機(jī)制上兩者已經(jīng)有了巨大的差別。

當(dāng)我們執(zhí)行g(shù)o run .時(shí),我們的應(yīng)用包含所有的組件運(yùn)行在一個(gè)進(jìn)程中,組件的調(diào)用就是Go中的正常的函數(shù)調(diào)用

圖片

當(dāng)我們執(zhí)行weaver multi deploy weaver.toml時(shí),我們的應(yīng)用中的組件會變的像微服務(wù)一樣,運(yùn)行中多個(gè)進(jìn)程中,此時(shí)組件的調(diào)用就通過RPC的方式了

圖片

更進(jìn)一步,既然組件都可以運(yùn)行中在不同的進(jìn)程中,自然也可以運(yùn)行在不同的機(jī)器中

Service Weaver目前僅提供了GKE(Google Kubernetes Engine)的支持。快速將應(yīng)用部署到GKE的不同容器中

$ weaver gke deploy weaver.toml

圖片

對多進(jìn)程的看法

此時(shí)再回顧下對組件的看法,weaver.Get:當(dāng)單進(jìn)程部署時(shí),它返回一個(gè)接口的本地實(shí)例,當(dāng)多進(jìn)程部署時(shí),它返回一個(gè)RPC的client

Service Weaver稱自己為模塊化單體(modular monolith)。通過組件這個(gè)概念讓你寫代碼和部署代碼的動作分離開,你可以按照單體的方式寫代碼,然后在其他進(jìn)程或者機(jī)器按照微服務(wù)的方式運(yùn)行組件的進(jìn)程

總結(jié)

因?yàn)橐彩莿倓偨佑|到這個(gè)框架,很多細(xì)節(jié)還不太理解,目前業(yè)界更是沒有實(shí)踐落地。這里說些我自己的看法,也歡迎大家批評指正

單體向微服務(wù)的演進(jìn)不是由于某個(gè)單一的原因造成,團(tuán)隊(duì)的分工,龐大的代碼,復(fù)雜的依賴等諸多原因造就了現(xiàn)在流行微服務(wù)架構(gòu)。Service Weaver也并沒有要取代傳統(tǒng)微服務(wù),在不同團(tuán)隊(duì)間使用傳統(tǒng)微服務(wù),在同一個(gè)團(tuán)隊(duì)內(nèi)部或者同一功能的服務(wù)使用模塊化單體是一種新的選擇

?? 關(guān)于模塊化單體(modular monolith)中的單體

單體的開發(fā)確實(shí)會降低我們的心智負(fù)擔(dān),我們不用關(guān)心不同模塊之間的RPC協(xié)議,模塊之間的服務(wù)發(fā)現(xiàn),在本地測試的時(shí)候也不需要專門構(gòu)建其他依賴微服務(wù)的模塊

Monorepo 倉庫能到達(dá)一樣的效果么?部分能,我們可以把一套微服務(wù)放到一個(gè)Monorepo中,并使用一個(gè)BFF服務(wù)對外提供統(tǒng)一的訪問入口,能實(shí)現(xiàn)類似于單體開發(fā)的體驗(yàn)。但我們依舊需要關(guān)心RPC協(xié)議、服務(wù)發(fā)現(xiàn)等一系列的問題

?? 關(guān)于模塊化單體(modular monolith)中的模塊

有了Service Weaver我們就可以不用關(guān)心服務(wù)拆分了么?不是的,我們依舊面臨著服務(wù)拆分,傳統(tǒng)的微服務(wù)拆分到不同的代碼倉庫,Service Weaver拆分到了不同的邏輯(組件)。所以傳統(tǒng)的服務(wù)拆分的方法論和經(jīng)驗(yàn),在這里依舊適用

?? 模塊化單體(modular monolith)之外的東西

Service Weaver也提供了Logging、Metrics、Tracing、Profiling的基本能力,這部分沒啥特殊的,絕大部分的RPC框架都集成了類似的能力

Service Weaver提供了Google Kubernetes Engine (GKE) 部署的能力,如果你的公司恰好使用標(biāo)準(zhǔn)的k8s服務(wù),或許不難擴(kuò)展。如果你的公司使用了非標(biāo)準(zhǔn)的k8s,如何與現(xiàn)有的部署系統(tǒng)結(jié)合也是個(gè)需要考慮的問題

責(zé)任編輯:武曉燕 來源: 涼涼的知識庫
相關(guān)推薦

2023-10-12 00:07:27

Service單體微服務(wù)

2009-11-30 10:09:02

谷歌Chrome OS

2024-02-22 09:30:15

Gemma開源模型谷歌

2017-09-05 05:55:24

AWS ES集群大數(shù)據(jù)

2013-04-07 15:51:35

2024-01-10 21:35:29

vivo微服務(wù)架構(gòu)

2021-07-07 07:33:49

開源Keycloak平臺

2012-08-30 11:25:45

開源平臺谷歌Drill

2024-04-07 11:44:53

MagistralaIoT物聯(lián)網(wǎng)平臺

2019-12-26 15:31:17

騰訊框架開源

2009-08-01 09:06:35

UbuntuOneLinux開源操作系統(tǒng)

2009-03-09 15:12:39

XenServer安裝

2023-07-28 09:23:24

微服務(wù)架構(gòu)

2021-09-29 11:03:10

OneNET服務(wù)器MQTT

2024-03-11 09:31:46

開源神經(jīng)網(wǎng)絡(luò)架構(gòu)

2023-07-15 08:01:38

2010-11-22 10:31:17

Sencha touc

2011-05-30 15:12:10

App Invento 初體驗(yàn)

2012-07-10 09:29:44

BigQuery

2022-08-25 14:12:15

Python對象池
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號