Dapr Golang HTTP 調用

版本介紹

工程結構

從上圖可知,新建 3 個 Go 啓動項目, cmd 爲啓動項目目錄,其中 client/a/main.go 爲客戶端,用於調用服務。service/http/b、service/http/c 爲服務項目。調用路徑如下圖所示。新建兩個 service 的意義在於展示 http 鏈路調用通過 dapr 如何實現。

internal

response.go 文件,封裝返回數據。數據結構如下:

package internal

import (
	"encoding/json"
	"log"
)

type HttpResult struct {
	Message string
}

func (r *HttpResult) ToBytes() (bytes []byte) {
	var err error
	bytes, err = json.Marshal(r)
	if err != nil {
		log.Fatal("數據轉換失敗")
	}
	return
}

go-service-c

go-service-c 做爲調用鏈路末端,只需要提供監聽端口,以及綁定路由。下面方法通過 s.AddServiceInvocationHandler("/hello", helloHandler) 方法綁定路由和處理方法。以下爲 go-service-c 源碼。

package main

import (
	"context"
	"errors"
	"github.com/Zhang-Byte/dapr-golang/internal"
	"github.com/dapr/go-sdk/service/common"
	daprd "github.com/dapr/go-sdk/service/http"
	"log"
	"net/http"
)

func main() {
	s := daprd.NewService(":9003")
	if err := s.AddServiceInvocationHandler("/hello", helloHandler); err != nil {
		log.Fatalf("error adding invocation handler: %v", err)
	}

	if err := s.Start(); err != nil && err != http.ErrServerClosed {
		log.Fatalf("error listenning: %v", err)
	}
}

func helloHandler(_ context.Context, in *common.InvocationEvent) (out *common.Content, err error) {
	if in == nil {
		err = errors.New("invocation parameter required")
		return
	}
	log.Printf("The go-service-c service method hello has been invoked,recieve message is %v", string(in.Data))
	httpResult := internal.HttpResult{Message: "This message is from Service C."}
	out = &common.Content{
		Data:        httpResult.ToBytes(),
		ContentType: in.ContentType,
		DataTypeURL: in.DataTypeURL,
	}
	return
}

啓動命令:

dapr run --app-id go-service-c \
         --app-protocol http \
         --app-port 9003 \
         --dapr-http-port 3501 \
         --log-level debug \
         --components-path ./config \
         go run ./cmd/service/http/c/main.go

go-service-b

go-service-b 相較於 go-service-c 的代碼來說,添加了初始化客戶端併發送請求的內容。查看代碼 invokeService() 每次都會調用 client(), 在 client() 中方法看上去每次都會新建一個客戶端,查看 dapr 源碼註釋可知 (Note, this default factory function creates Dapr client only once. All subsequent invocations will return the already created instance.) 每次只會返回已經創建好的實例,因此使用完以後不必關閉此客戶端。

package main

import (
	"context"
	"encoding/json"
	"errors"
	"github.com/Zhang-Byte/dapr-golang/internal"
	dapr "github.com/dapr/go-sdk/client"
	"github.com/dapr/go-sdk/service/common"
	"log"
	"net/http"
)
import daprd "github.com/dapr/go-sdk/service/http"

func main() {
	s := daprd.NewService(":9002")
	if err := s.AddServiceInvocationHandler("/hello", helloHandler); err != nil {
		log.Fatalf("error adding invocation handler: %v", err)
	}

	if err := s.Start(); err != nil && err != http.ErrServerClosed {
		log.Fatalf("error listenning: %v", err)
	}
}

func helloHandler(ctx context.Context, in *common.InvocationEvent) (out *common.Content, err error) {
	if in == nil {
		err = errors.New("invocation parameter required")
		return
	}
	log.Printf("The go-service-b service method hello has been invoked,recieve message is %v", string(in.Data))

	msg := invokeService(ctx)
	httpResult := internal.HttpResult{Message: msg}

	out = &common.Content{
		Data:        httpResult.ToBytes(),
		ContentType: in.ContentType,
		DataTypeURL: in.DataTypeURL,
	}
	return
}

func invokeService(ctx context.Context) (msg string) {
	client := client()
	content := &dapr.DataContent{
		ContentType: "text/plain",
		Data:        []byte("This is golang Service B."),
	}
	resp, err := client.InvokeServiceWithContent(ctx, "go-service-c", "hello", content)
	if err != nil {
		panic(err)
	}
	var result internal.HttpResult
	if err := json.Unmarshal(resp, &result); err != nil {
		log.Printf(err.Error())
	}
	msg = result.Message
	return
}

func client() dapr.Client {
	client, err := dapr.NewClient()
	if err != nil {
		panic(err)
	}
	return client
}

啓動命令:

dapr run --app-id go-service-b \
         --app-protocol http \
         --app-port 9002 \
         --dapr-http-port 3500 \
         --log-level debug \
         --components-path ./config \
         go run ./cmd/service/http/b/main.go

go-client-a

最後創建客戶端,客戶端每間隔 5 秒發起一次請求到 go-service-b 。

package main

import (
	"context"
	dapr "github.com/dapr/go-sdk/client"
	"log"
	"time"
)

func main() {
	ctx := context.Background()

	// create the client
	client, err := dapr.NewClient()
	if err != nil {
		panic(err)
	}
	defer client.Close()

	content := &dapr.DataContent{
		ContentType: "text/plain",
		Data:        []byte("This is client A."),
	}
	for {
		resp, err := client.InvokeServiceWithContent(ctx, "go-service-b", "hello", content)
		if err != nil {
			panic(err)
		}
		log.Printf("go-service-b method hello has invoked, response: %s", string(resp))

		time.Sleep(time.Second * 5)
	}

}

啓動命令:

dapr run --app-id go-client-a \
         --components-path ./config \
         --log-level debug \
         go run ./cmd/client/a/main.go

總結

client 啓動後,得到返回值

== APP == 2020/11/06 11:26:41 go-service-b method hello has invoked, response: {"Message":"This message is from Service C."}

go-service-b 打印內容爲:

== APP == 2020/11/06 11:31:51 The go-service-b service has been invoked,recieve message is This is client A.

go-service-c 打印內容爲:

== APP == 2020/11/06 11:33:31 The go-service-c service method hello has been invoked,recieve message is This is golang Service B.

在命令行界面中輸入 dapr dashboard 得到輸出 Dapr Dashboard running on http://localhost:8080,訪問 http://localhost:8080

源碼地址:https://github.com/ZhangX-Byte/dapr-golang

作者:Zhang_Xiang

出處:https://www.cnblogs.com/Zhang-Xiang/p/13936442.html

版權:本作品採用「署名 - 非商業性使用 - 相同方式共享 4.0 國際」許可協議進行許可。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://www.cnblogs.com/Zhang-Xiang/p/13936442.html