欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

用Go語言編寫一個(gè)簡(jiǎn)單的分布式系統(tǒng)

 更新時(shí)間:2023年08月01日 11:41:15   作者:uccs  
這篇文章主要介紹了用Go語言編寫一個(gè)簡(jiǎn)單的分布式系統(tǒng),文中的代碼示例講解的非常詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴跟著小編一起來看看吧

分布式

  • 注冊(cè)服務(wù):RegistryService
  • 日志服務(wù):LogService
  • 其他服務(wù):GradingServiceportal

RegistryService

RegistryService 提供的服務(wù):

  • 提供 /services 接口,用于其他服務(wù)在啟動(dòng)或者停止時(shí)告知
    • POST:告訴 RegistryService,我啟動(dòng)了一個(gè)服務(wù),調(diào)用 add 方法
    • DELETE:告訴 RegistryService,我停止了一個(gè)服務(wù),調(diào)用 remove 方法
  • 通過 add 函數(shù)將服務(wù)添加到 registrations 列表中
    • r.registrations = append(r.registrations, reg)
  • 通過 remove 函數(shù)將服務(wù)從 registrations 列表中移除
    • r.registrations = append(r.registrations[:i], r.registrations[i+1:]...)
  • 這里需要注意的是:要保證線程安全,也就是在 append 時(shí),需要使用到鎖
mutex.Lock()
append(xxx, xxx)
mutex.UnLock()
  • 服務(wù)發(fā)現(xiàn):

    比如說 GradingService 依賴 LogService,那么 GradingService 就需要知道 LogService 的地址

    這個(gè)時(shí)候 RegistryService 就可以通過 registrations 列表來通知 GradingService,LogService 的地址

    RegistryService 是通過 ServiceUpdateURL 來通知的,GradingService,LogService 的地址

  • 服務(wù)發(fā)現(xiàn)需要分兩步進(jìn)行

    如果 GradingService 啟動(dòng)時(shí),如果 LogService 已經(jīng)啟動(dòng)了,那么 RegistryService 就可以直接通知 GradingService,LogService 的地址(r.sendRequiredServices(reg) 方法)

    如果 GradingService 啟動(dòng)時(shí),如果 LogService 還沒有啟動(dòng),那么 RegistryService 就不會(huì)通知 GradingService,LogService 的地址,等到 LogService 啟動(dòng)后,RegistryService 才會(huì)通知 GradingService,LogService 的地址(notify 方法)

RegistryService 對(duì)外只需要提供 RegisterService 方法,其他服務(wù)調(diào)用這個(gè)函數(shù),就能夠獲取 RegistryService 提供的服務(wù)

  • 調(diào)用 RegisterService 提供的接口 /services,將服務(wù)注冊(cè)到 RegistryService
  • 為注冊(cè)的服務(wù)添加路由:ServiceUpdateURL
  • 為注冊(cè)的服務(wù)添加 ServeHTTP 方法,用于處理 ServiceUpdateURL 的請(qǐng)求,這個(gè)請(qǐng)求在方法 sendRequiredServices 調(diào)用時(shí)相應(yīng),更新 providers 中的 service
  • 為每個(gè)注冊(cè)的服務(wù)提供健康檢查

最后在提供一個(gè) ShutdownService 用于像 /services 接口發(fā)送 delete 請(qǐng)求,告知 RegistryService,我停止了一個(gè)服務(wù)

LogService

LogService 服務(wù)是對(duì)日志進(jìn)行管理,將其他服務(wù)的日志進(jìn)行收集、存儲(chǔ),提供 /log 接口,用于其他服務(wù)將日志發(fā)送給 LogService

GradingService 和 Portal

這兩個(gè)是業(yè)務(wù)服務(wù)

  • 在啟動(dòng)服務(wù)時(shí)調(diào)用方法 RegistryService,將自己注冊(cè)到 RegistryService
  • 在停止服務(wù)時(shí)調(diào)用方法 ShutdownService,將自己從 RegistryService 中移除

api

os.OpenFile

用于指定模式打開文件,并返回文件的指針

func OpenFile(name string, flag int, perm FileMode) (*File, error)

flag 參數(shù):

  • os.O_RDONLY:只讀模式打開文件
  • os.O_WRONLY:只寫模式打開文件
  • os.O_RDWR:讀寫模式打開文件
  • os.O_APPEND:追加模式,寫入內(nèi)容時(shí)將數(shù)據(jù)附加到文件尾部
  • os.O_CREATE:如果文件不存在,則創(chuàng)建一個(gè)新文件

perm 參數(shù):

- 0:無權(quán)限
- 1:執(zhí)行權(quán)限
- 2:寫權(quán)限
- 3:寫和執(zhí)行權(quán)限
- 4:讀權(quán)限
- 5:讀和執(zhí)行權(quán)限
- 6:讀和寫權(quán)限
- 7:讀、寫和執(zhí)行權(quán)限

  • 0644:表示文件的所有者可以讀取和寫入文件,文件所屬組和其他用戶只能讀取文件。這是比較常見的設(shè)置
  • 0600:表示文件的所有者可以讀取和寫入文件,但是文件所屬組和其他用戶不能訪問該文件。這種權(quán)限安全性較高

ioutil.ReadAll

可以將整個(gè)文件內(nèi)容讀取到內(nèi)存中,可以將請(qǐng)求體的內(nèi)容讀取到內(nèi)存中

ps:將整個(gè)文件的內(nèi)容或者請(qǐng)求體一次性讀取到內(nèi)存中,對(duì)于非常大的文件或者請(qǐng)求體,內(nèi)存占用過高

fmt.Scanln

會(huì)阻塞程序的執(zhí)行,直到用戶在終端輸入一行內(nèi)容并按下回車鍵,然后它會(huì)將用戶輸入的值存儲(chǔ)到傳入的參數(shù)中

它主要用于讀取并解析簡(jiǎn)單的基本類型數(shù)據(jù)

func main(){
  var name string
	var age int
	fmt.Print("Enter your name: ")
	fmt.Scanln(&name)
	fmt.Print("Enter your age: ")
	fmt.Scanln(&age)
	fmt.Printf("Hello, %s! You are %d years old.\n", name, age)
}

http

http.Server

  • ListenAndServe:?jiǎn)?dòng)服務(wù),并監(jiān)聽指定的地址和端口,會(huì)阻塞
  • Shutdown:優(yōu)雅地關(guān)閉服務(wù),可以保證正在處理的服務(wù)不會(huì)被中斷
var srv htto.Server
go func(){
  srv.ListenAndServe()
}()
go func(){
  srv.Shutdown()
}()

ServeHTTP

當(dāng)一個(gè)結(jié)構(gòu)體實(shí)現(xiàn)了 ServeHTTP 方法后,那么這個(gè)結(jié)構(gòu)體就實(shí)現(xiàn)了 http.Handler 接口

實(shí)現(xiàn)了 http.Handler 接口的結(jié)構(gòu)體,就可以作為 http.Handle 方法的第二個(gè)參數(shù)

然后調(diào)用 http.ListenAndServe 方法就可以啟動(dòng)一個(gè)服務(wù),會(huì)自動(dòng)調(diào)用 ServeHTTP 方法來處理請(qǐng)求

func main() {
	http.Handle("/ping", &MyHandler{})
	http.ListenAndServe(":8080", nil)
}
type MyHandler struct{}
func (mh MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("pong"))
	default:
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}

將結(jié)構(gòu)體序列化

  • buf := new(bytes.Buffer) 創(chuàng)建了一個(gè)新的 bytes.Buffer 對(duì)象,用于存儲(chǔ)編碼后的 JSON 數(shù)據(jù)
  • enc := json.NewEncoder(buf) 創(chuàng)建了一個(gè)新的 JSON 編碼器 enc,并將其關(guān)聯(lián)到 buf 對(duì)象。這意味著編碼后的 JSON 數(shù)據(jù)將被寫入到 buf
  • err := enc.Encode(r) 使用 JSON 編碼器 enc 將結(jié)構(gòu)體 r 編碼為 JSON 數(shù)據(jù),并將結(jié)果寫入到 buf 中。Encode 方法返回一個(gè)可能的錯(cuò)誤 err
type Registration struct {
	ServiceName string
	ServiceURL  string
}
r := Registration{
  ServiceName: "LogService",
  ServiceURL:  "http://localhost:3000/services",
}
buf := new(bytes.Buffer)
enc := json.NewEncoder(buf)
err := enc.Encode(r)
res, err := http.Post(ServicesURL, "application/json", buf)

使用 http 默認(rèn)請(qǐng)求

  • http.DefaultClient 是標(biāo)準(zhǔn)庫中提供的默認(rèn) HTTP 請(qǐng)求。它已經(jīng)預(yù)先配置好了一些默認(rèn)的設(shè)置,例如超時(shí)時(shí)間、重試機(jī)制等
  • Do(req)http.Client 類型的方法,用于執(zhí)行一個(gè) HTTP 請(qǐng)求并返回響應(yīng)
    • 它接受一個(gè) http.Request 對(duì)象作為參數(shù),表示要發(fā)送的請(qǐng)求
req, _ := http.NewRequest(http.MethodDelete, "http://localhost:3000/services", bytes.NewBuffer([]byte("http://localhost:4000/log")))
req.Header.Add("Content-Type", "text/plain")
res, err := http.DefaultClient.Do(req)

log

log.New

log.New 用于創(chuàng)建一個(gè)新的日志記錄器實(shí)例,用于將日志消息寫入指定的輸出地,并可選擇性地添加前綴字符串

  • 以文件的形式記錄日志,用 log.New 創(chuàng)建一個(gè)新的 log 實(shí)例,然后調(diào)用 log.Printf 方法將日志寫入文件

它接收 io.Writer 類型的參數(shù),os.OpenFile 返回的文件指針類型 *os.File 實(shí)現(xiàn)了 io.Writer 接口,所以可以將文件指針傳入 log.New 方法中

代碼參考如下:

import (
	"fmt"
	stlog "log"
	"os"
)
func main() {
	file, err := os.OpenFile("./logs", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
	if err != nil {
		fmt.Println(err)
	}
	defer file.Close()
	log := stlog.New(file, "[go] -  ", stlog.LstdFlags)
	log.Println("hello world")
}
  • 重寫 log 的 Write 方法,也能實(shí)現(xiàn)將日志寫入文件

在重寫 Write 方法時(shí),需要定義一個(gè)類型別名,然后在類型別名上實(shí)現(xiàn) Write 方法,那么這個(gè)類型別名就能夠傳入 log.New 方法中

代碼參考如下:

import (
	stlog "log"
	"os"
)
type filelog string
func (fl filelog) Write(data []byte) (int, error) {
	file, err := os.OpenFile(string(fl), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
	if err != nil {
		return 0, err
	}
	defer file.Close()
	file.Write(data)
	return len(data), nil
}
func main() {
	log := stlog.New(filelog("./logs"), "[go] -  ", stlog.LstdFlags)
	log.Println("hello world")
}

以上就是用Go語言編寫一個(gè)簡(jiǎn)單的分布式系統(tǒng)的詳細(xì)內(nèi)容,更多關(guān)于Go語言分布式系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go每日一庫之dateparse處理時(shí)間

    Go每日一庫之dateparse處理時(shí)間

    不管什么時(shí)候,處理時(shí)間總是讓人頭疼的一件事情。今天要介紹的dateparse實(shí)現(xiàn)解析日期時(shí)間格式的字符串。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • golang中實(shí)現(xiàn)graphql請(qǐng)求的方法

    golang中實(shí)現(xiàn)graphql請(qǐng)求的方法

    這篇文章主要介紹了如何在golang中實(shí)現(xiàn)graphql請(qǐng)求,在本文中,我們介紹了如何使用gqlgen來構(gòu)建GraphQL服務(wù),需要的朋友可以參考下
    2023-04-04
  • Golang中map數(shù)據(jù)類型的使用方法

    Golang中map數(shù)據(jù)類型的使用方法

    這篇文章主要介紹了Golang中map數(shù)據(jù)類型的使用方法,文章圍繞主題展開詳細(xì)的內(nèi)容戒殺,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-09-09
  • Golang 字符串轉(zhuǎn)time類型實(shí)現(xiàn)

    Golang 字符串轉(zhuǎn)time類型實(shí)現(xiàn)

    本文主要介紹了Golang 字符串轉(zhuǎn)time類型實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Go實(shí)現(xiàn)文件上傳和下載

    Go實(shí)現(xiàn)文件上傳和下載

    這篇文章主要為大家詳細(xì)介紹了Go實(shí)現(xiàn)文件上傳和下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • 詳解如何在Golang中實(shí)現(xiàn)CORS(跨域)

    詳解如何在Golang中實(shí)現(xiàn)CORS(跨域)

    很多時(shí)候,需要允許Web應(yīng)用程序在不同域之間(跨域)實(shí)現(xiàn)共享資源,本文將簡(jiǎn)介跨域、CORS的概念,以及如何在Golang中如何實(shí)現(xiàn)CORS,文中有詳細(xì)的示例代碼,需要的朋友可以參考下
    2023-10-10
  • 關(guān)于go-zero服務(wù)自動(dòng)收集問題分析

    關(guān)于go-zero服務(wù)自動(dòng)收集問題分析

    這篇文章主要介紹了關(guān)于go-zero服務(wù)自動(dòng)收集問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • 詳解go中的引用類型

    詳解go中的引用類型

    這篇文章主要介紹了go中的引用類型,文中給大家提到了值類型和引用類型的區(qū)別,通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Golang 實(shí)現(xiàn)簡(jiǎn)單隨機(jī)負(fù)載均衡

    Golang 實(shí)現(xiàn)簡(jiǎn)單隨機(jī)負(fù)載均衡

    均衡算法又分為 隨機(jī),輪詢,加權(quán)輪詢,哈希,而隨機(jī)負(fù)載均衡算法就是本文的重點(diǎn),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • go語言make初始化的實(shí)現(xiàn)

    go語言make初始化的實(shí)現(xiàn)

    Go語言中的make函數(shù)用于初始化切片、映射和通道,本文就來介紹一下go語言make初始化的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-12-12

最新評(píng)論