說明
從前面的流程看形耗,我們似乎已經(jīng)差不多把一個(gè)微服務(wù)的開發(fā)流程給實(shí)施了,一遍辙浑,當(dāng)然真正的微服務(wù)開發(fā)中還會(huì)涉及自身業(yè)務(wù)處理激涤,上面只是簡單的一些請(qǐng)求示例的處理,而且復(fù)雜的微服務(wù)的開發(fā)等更多業(yè)務(wù)邏輯處理,而且還缺少對(duì)微服務(wù)的包含微服務(wù)組件網(wǎng)關(guān)倦踢、配置中心送滞、熔斷器以及具體服務(wù)如何融合起來。
基于上述的說明辱挥,我重頭開始梳理一次我的開發(fā)過程犁嗅,也方便自己后續(xù)回頭看看。比較我是一個(gè)小白晤碘,容易忘事褂微!
參考資料
參考:https://github.com/xbox1994/go-micro-example 此示例是micro是V1版本的,我是 改為了我現(xiàn)在使用的V2版本的园爷。
環(huán)境準(zhǔn)備
環(huán)境依賴
- windows 10 + goland
- docker 搭建我們的etcd注冊(cè)中心
- golang 1.14
- protoc宠蚂、protoc-gen-go、protoc-gen-micro
運(yùn)行方式
因?yàn)閮H僅只是開發(fā)階段童社,所以運(yùn)行我們也運(yùn)行在Windows平臺(tái)求厕。直接的go run 即可!
整體架構(gòu)
從圖示流程看扰楼,我們的我們服務(wù)的流程是:
啟動(dòng)我們的服務(wù)呀癣,我們的相關(guān)的服務(wù)都注冊(cè)到服務(wù)注冊(cè)中心,且從Config Service 獲取想的配置信息灭抑。啟動(dòng)好后等待瀏覽器外部請(qǐng)求訪問十艾。
1: 外部瀏覽器請(qǐng)求我們的以 greeter/hello ,進(jìn)入到我們的Micro Api網(wǎng)關(guān)(Api網(wǎng)關(guān)啟動(dòng)后)
2:Micro Api網(wǎng)關(guān)解析請(qǐng)求腾节,并進(jìn)行相關(guān)的身份的驗(yàn)證,驗(yàn)證通過則把解析出來用戶信息寫到header中荤牍,且轉(zhuǎn)向我們的RPC服務(wù)
3:網(wǎng)關(guān)通過驗(yàn)證后案腺,在向我們的GreeterService(srv服務(wù))發(fā)起請(qǐng)求訪問,然后轉(zhuǎn)向我們微服務(wù)內(nèi)部的Greeter.Call方法中,然后處理微服務(wù)內(nèi)部的邏輯康吵,
4:然后我們的GreeterService(srv服務(wù))此時(shí)回向我們的UserService(srv服務(wù))進(jìn)行請(qǐng)求劈榨,嘗試用戶的其他信息,header也轉(zhuǎn)發(fā)過去
6:然后我們的UserService(srv服務(wù))中根據(jù)header中得到的id查詢數(shù)據(jù)庫得到具體的用戶信息并返回
根據(jù)架構(gòu)搭建項(xiàng)目
可選 模塊創(chuàng)建 命令
$ micro new --type srv --alias auth github.com/hb-go/micro/xxxxxx/srv
$ micro new --type api --alias account github.com/hb-go/micro/xxxxxx/api
$ micro new --type web --alias account github.com/hb-go/micro/xxxxxx/web
實(shí)踐步驟
1):使用模板命令創(chuàng)建默認(rèn)兩個(gè)SRV微服務(wù)
D:\code\go\micro-greeter\service>micro new --gopath=false user
D:\code\go\micro-greeter\service>micro new --gopath=false greeter
2):改造我們的user.proto 和 greeter.proto
- 2.1)修改user.proto 源文件:
syntax = "proto3";
package go.micro.service.user;
service User {
rpc Call(Request) returns (Response) {}
rpc Stream(StreamingRequest) returns (stream StreamingResponse) {}
rpc PingPong(stream Ping) returns (stream Pong) {}
}
message Message {
string say = 1;
}
message Request {
string name = 1;
}
message Response {
string msg = 1;
}
message StreamingRequest {
int64 count = 1;
}
message StreamingResponse {
int64 count = 1;
}
message Ping {
int64 stroke = 1;
}
message Pong {
int64 stroke = 1;
}
修改為:
syntax = "proto3";
package go.micro.service.user;
service User {
rpc Login (Request) returns (Response) {}
rpc GetUserInfo (Empty) returns (UserInfo) {}
}
message Empty {
}
message UserInfo {
string id = 1;
string username = 2;
string password = 3;
}
message Token {
string token = 1;
bool valid = 2;
}
message Message {
string say = 1;
}
message Request {
string name = 1;
}
message Response {
string msg = 1;
}
然后生成我們的服務(wù)模板
D:\code\go\micro-greeter\service>cd user
D:\code\go\micro-greeter\service\user>protoc --proto_path=. --micro_out=. --go_out=. proto/user/user.proto
2021/01/27 16:28:46 WARNING: Missing 'go_package' option in "proto/user/user.proto",
please specify it with the full Go package path as
a future release of protoc-gen-go will require this be specified.
See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.
D:\code\go\micro-greeter\service\user>
修改我們的handle下的user,go:
package handler
import (
"context"
log "github.com/micro/go-micro/v2/logger"
user "user/proto/user"
)
type User struct{}
// Call is a single request handler called via client.Call or the generated client code
func (e *User) Call(ctx context.Context, req *user.Request, rsp *user.Response) error {
log.Info("Received User.Call request")
rsp.Msg = "Hello " + req.Name
return nil
}
// Stream is a server side stream handler called via client.Stream or the generated client code
func (e *User) Stream(ctx context.Context, req *user.StreamingRequest, stream user.User_StreamStream) error {
log.Infof("Received User.Stream request with count: %d", req.Count)
for i := 0; i < int(req.Count); i++ {
log.Infof("Responding: %d", i)
if err := stream.Send(&user.StreamingResponse{
Count: int64(i),
}); err != nil {
return err
}
}
return nil
}
// PingPong is a bidirectional stream handler called via client.Stream or the generated client code
func (e *User) PingPong(ctx context.Context, stream user.User_PingPongStream) error {
for {
req, err := stream.Recv()
if err != nil {
return err
}
log.Infof("Got ping %v", req.Stroke)
if err := stream.Send(&user.Pong{Stroke: req.Stroke}); err != nil {
return err
}
}
}
修改為:
PS: 這里可以快速的使用導(dǎo)入實(shí)現(xiàn)方法的形式實(shí)現(xiàn)我們的相關(guān)的對(duì)象的方法:
定義好我們的結(jié)構(gòu)體后晦嵌,選擇它同辣,然后右鍵-
image.png
image.png
image.png
package handler
import (
"context"
"github.com/prometheus/common/log"
user "user/proto/user"
)
type User struct{}
func (u User) Login(ctx context.Context, request *user.Request, response *user.Response) error {
//panic("implement me")
log.Info("Received User.Call request")
response.Msg = "Hello " + request.Name
return nil
}
func (u User) GetUserInfo(ctx context.Context, empty *user.Empty, info *user.UserInfo) error {
panic("implement me")
}
然后氣啟動(dòng)一下我們的用戶服務(wù):
、D:\code\go\micro-greeter\service\user>go run main.go
2021-01-27 16:46:25 file=v2@v2.9.1/service.go:200 level=info Starting [service] go.micro.service.user
2021-01-27 16:46:25 file=grpc/grpc.go:864 level=info Server [grpc] Listening on [::]:57651
2021-01-27 16:46:25 file=grpc/grpc.go:881 level=info Broker [http] Connected to 127.0.0.1:57652
2021-01-27 16:46:25 file=grpc/grpc.go:697 level=info Registry [mdns] Registering node: go.micro.service.user-1985d4f5-d2c6-4b06-a628-27c62b1f1ef6
2021-01-27 16:46:25 file=grpc/grpc.go:730 level=info Subscribing to topic: go.micro.service.user
然后查看我們的服務(wù)信息:
D:\code\go\micro-greeter>micro get service go.micro.service.user
service go.micro.service.user
version latest
ID Address Metadata
go.micro.service.user-1985d4f5-d2c6-4b06-a628-27c62b1f1ef6 192.168.1.213:57651 transport=grpc,broker=http,protocol=grpc,registry=mdns,server=grpc
Endpoint: User.GetUserInfo
Request: {
message_state MessageState {
no_unkeyed_literals NoUnkeyedLiterals
do_not_compare DoNotCompare
do_not_copy DoNotCopy
message_info MessageInfo
}
int32 int32
unknown_fields []uint8
}
Response: {
message_state MessageState {
no_unkeyed_literals NoUnkeyedLiterals
do_not_compare DoNotCompare
do_not_copy DoNotCopy
message_info MessageInfo
}
int32 int32
unknown_fields []uint8
id string
username string
password string
}
Endpoint: User.Login
Request: {
message_state MessageState {
no_unkeyed_literals NoUnkeyedLiterals
do_not_compare DoNotCompare
do_not_copy DoNotCopy
message_info MessageInfo
}
int32 int32
unknown_fields []uint8
name string
}
Response: {
message_state MessageState {
no_unkeyed_literals NoUnkeyedLiterals
do_not_compare DoNotCompare
do_not_copy DoNotCopy
message_info MessageInfo
}
int32 int32
unknown_fields []uint8
msg string
}
Endpoint: User.Handle
Metadata: subscriber=true,topic=go.micro.service.user
Request: {
message_state MessageState {
no_unkeyed_literals NoUnkeyedLiterals
do_not_compare DoNotCompare
do_not_copy DoNotCopy
message_info MessageInfo
}
int32 int32
unknown_fields []uint8
say string
}
Response: {}
D:\code\go\micro-greeter>
同理修改我們的另一個(gè)greeter服務(wù):
syntax = "proto3";
package go.micro.service.greeter;
service Greeter {
rpc Call(Request) returns (Response) {}
}
message Request {
string name = 1;
}
message Response {
string msg = 1;
}
修改greeter服務(wù)的handler:
package handler
import (
"context"
log "github.com/micro/go-micro/v2/logger"
greeter "greeter/proto/greeter"
)
type Greeter struct{}
func (g Greeter) Call(ctx context.Context, req *greeter.Request, rsp *greeter.Response) error {
log.Info("Received Greeter.Call request")
rsp.Msg = "Hello " + req.Name
return nil
}
func (g Greeter) Stream(ctx context.Context, request *greeter.StreamingRequest, stream greeter.Greeter_StreamStream) error {
panic("implement me")
}
func (g Greeter) PingPong(ctx context.Context, stream greeter.Greeter_PingPongStream) error {
panic("implement me")
}
然后啟動(dòng)我們的服務(wù):
D:\code\go\micro-greeter\service\greeter>go run main.go
2021-01-27 17:01:16 file=v2@v2.9.1/service.go:200 level=info Starting [service] go.micro.service.greeter
2021-01-27 17:01:16 file=grpc/grpc.go:864 level=info Server [grpc] Listening on [::]:60294
2021-01-27 17:01:16 file=grpc/grpc.go:697 level=info Registry [mdns] Registering node: go.micro.service.greeter-7dd028b3-dc0b-4442-a370-627674ca440c
查看啟動(dòng)的服務(wù)列表 信息:
D:\code\go\micro-greeter>micro cli
micro> list
go.micro.service.greeter
go.micro.service.user
micro.http.broker
micro>
2):修改我們的注冊(cè)中心惭载。把服務(wù)都注冊(cè)到我們的ECTD上
D:\code\go\micro-greeter\service\greeter>go run main.go --registry=etcd --registry_address=192.168.219.130:2379
D:\code\go\micro-greeter\service\user>go run main.go --registry=etcd --registry_address=192.168.219.130:2379
查看我們的服務(wù)列表:(使用micro cli 進(jìn)行查看)
D:\code\go\micro-greeter>micro --registry etcd --registry_address 192.168.219.130:2379 cli
micro> list
go.micro.service.greeter
go.micro.service.user
micro>