前言
最近較忙,其實准備一篇搞定的
中途有事,只能隔了一天再寫
正文
pb.go
需要注意的是,在本個 demo 中,客戶端與服務端都是 Golang
,所以在客戶端與服務端都公用一個 pb.go
模板文件(如果是不同的語言生成的pb是對應語言),可以將 pb.go
文件放置在雲上由雙方引用,也可以生成兩個副本放在兩端項目中,本次就使用 COPY
兩份的方式
由於 Golang
一個文件夾只有一個 package
,而生成的 pb.go
文件 package
為創建 proto
的名字(示例為 spider
), 所以我們在項目內單獨建立文件夾 spider
將文件放入其中即可正常使用
編寫 server 端
編寫 main.go
文件
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"io/ioutil"
"net"
"net/http"
"server/spider"
)
type server struct{}
const (
// Address 監聽地址
Address string = "localhost:8080"
// Method 通信方法
Method string = "tcp"
)
// 接收client端的請求,函數名需保持一致
// ctx參數必傳
// 參數二為自定義的參數,需從pb文件導入,因此pb文件必須可導入,文件放哪里隨意
// 返回值同參數二,為pb文件的返回結構體指針
func (s *server) GetAddressResponse(ctx context.Context, a *spider.SendAddress) (*spider.GetResponse, error) {
// 邏輯寫在這里
switch a.Method {
case "get", "Get", "GET":
// 演示微服務用,故只寫get示例
status, body, err := get(a.Address)
if err != nil {
return nil, err
}
res := spider.GetResponse{
HttpCode: int32(status),
Response: body,
}
return &res, nil
}
return nil, nil
}
func get(address string) (s int, r string, err error) {
// get請求
resp, err := http.Get(address)
if err != nil {
return
}
defer resp.Body.Close()
s = resp.StatusCode
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
r = string(body)
return
}
func main() {
// 監聽本地端口
listener, err := net.Listen(Method, Address)
if err != nil {
return
}
s := grpc.NewServer() // 創建GRPC
spider.RegisterGoSpiderServer(s, &server{}) // 在GRPC服務端注冊服務
reflection.Register(s) // 在GRPC服務器注冊服務器反射服務
// Serve方法接收監聽的端口,每到一個連接創建一個ServerTransport和server的grroutine
// 這個goroutine讀取GRPC請求,調用已注冊的處理程序進行響應
err = s.Serve(listener)
if err != nil {
return
}
}
編寫 client 端
package main
import (
"client/spider"
"context"
"google.golang.org/grpc"
)
import "fmt"
const (
// Address server端地址
Address string = "localhost:8080"
)
func main() {
// 連接服務器
conn, err := grpc.Dial(Address, grpc.WithInsecure())
if err != nil {
fmt.Println(err)
return
}
defer conn.Close()
// 連接GRPC
c := spider.NewGoSpiderClient(conn)
// 創建要發送的結構體
req := spider.SendAddress{
Address: "http://www.baidu.com",
Method: "get",
}
// 調用server的注冊方法
r, err := c.GetAddressResponse(context.Background(), &req)
if err != nil {
fmt.Println(err)
return
}
// 打印返回值
fmt.Println(r)
}
運行
需要先啟動 server 端監聽端口,再啟動 client 端向端口發送請求
我們運行后可看到結果已經正常返回並打印