resultMap處理欄位和屬性的映射關係 如果欄位名與實體類中的屬性名不一致,該如何處理映射關係? 第一種方法:為查詢的欄位設置別名,和屬性名保持一致 下麵是實體類中的屬性名: private Integer empId; private String empName; private Integ ...
概要
用戶服務基本是每個互聯網產品里必備的一個服務了,因為沒有用戶基本是什麼也幹不了。所以他的重要性不言而喻。本文主要介紹下如何開發一個用戶微服務,以及他的詳細開發流程。
目錄
- Go微服務實戰 - 從0到1搭建一個類Instagram應用(持續更新)
- Go微服務實戰 - 用戶服務(gRPC+Protocol Buffer)
- Go微服務實戰 - 關係服務服務(gRPC+Protocol Buffer)
- Go微服務實戰 - 動態服務(gRPC+Protocol Buffer)
- Go微服務實戰 - 聚合服務(http)
調用流程圖
技術棧
- Go
- Eagle 開發框架
- Redis
- MySQL
- Gorm
- docker
- kubernetes
介面開發
使用proto方式定義,主要包含以下介面
開發步驟
這裡詳細的記錄了開發的步驟,方便參看本項目的同學知道其實現過程。
1、生成proto模板文件
eagle proto add api/user/v1/user.proto
內容如下
syntax = "proto3";
package api.user.v1;
option go_package = "github.com/go-microservice/user-service/api/user/v1;v1";
option java_multiple_files = true;
option java_package = "api.user.v1";
service UserService {
rpc CreateUser (CreateUserRequest) returns (CreateUserReply);
rpc UpdateUser (UpdateUserRequest) returns (UpdateUserReply);
rpc DeleteUser (DeleteUserRequest) returns (DeleteUserReply);
rpc GetUser (GetUserRequest) returns (GetUserReply);
rpc ListUser (ListUser1Request) returns (ListUserReply);
}
message CreateUser1Request {}
message CreateUser1Reply {}
message UpdateUserRequest {}
message UpdateUserReply {}
message DeleteUserRequest {}
message DeleteUserReply {}
message GetUserRequest {}
message GetUserReply {}
message ListUserRequest {}
message ListUserReply {}
2、為proto填充業務方法及欄位定義
vim api/user/v1/user.proto
3、生成pb文件
# 生成所有proto
make grpc
# 或者
# 生成指定proto的pb文件
eagle proto client api/user/v1/user.proto
# Output
ll api/user/v1/
user.pb.go #新增
user.proto
user_grpc.pb.go #新增
會生成兩個文件 api/user/v1/user.pb.go
和 api/user/v1/user.pb.go
4、生成server骨架代碼
# 生成骨架代碼
eagle proto server api/user/v1/user.proto
# 預設會輸出到 internal/service
# 如果需要指定到對應的目錄,可以使用 -t 參數, eg:
# eagle proto server -t internal/logic
# 查看
internal/service/user_svc.go
5、註冊服務到gRPC Server
// internal/server/grpc.go
import (
...
v1 "github.com/go-microservice/user-service/api/user/v1"
...
)
...
// NewGRPCServer creates a gRPC server
func NewGRPCServer(
cfg *app.ServerConfig,
// 新增
svc *service.UserServiceServer,
) *grpc.Server {
grpcServer := grpc.NewServer(
grpc.Network("tcp"),
grpc.Address(cfg.WriteTimeout),
grpc.Timeout(cfg.WriteTimeout),
)
// register biz service
// 新增
v1.RegisterUserServiceServer(grpcServer, svc)
return grpcServer
}
6、在生成的server中編寫業務邏輯
// vim internal/service/user_svc.go
package service
import (
"context"
pb "github.com/go-microservice/moment-service/api/user/v1"
)
var (
_ pb.UserServiceServer = (*UserServiceServer)(nil)
)
type UserServiceServer struct {
pb.UnimplementedUserServiceServer
}
func NewUserServiceServer() *UserServiceServer {
return &UserServiceServer{
}
}
func (s *UserServiceServer) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserReply, error) {
return &pb.CreateUserReply{}, nil
}
func (s *UserServiceServer) UpdateUser(ctx context.Context, req *pb.UpdateUserRequest) (*pb.UpdateUserReply, error) {
return &pb.UpdateUserReply{}, nil
}
func (s *UserServiceServer) DeleteUser(ctx context.Context, req *pb.DeleteUserRequest) (*pb.DeleteUserReply, error) {
return &pb.DeleteUserReply{}, nil
}
func (s *UserServiceServer) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserReply, error) {
return &pb.GetUserReply{}, nil
}
func (s *UserServiceServer) ListUser(ctx context.Context, req *pb.ListUserRequest) (*pb.ListUserReply, error) {
return &pb.ListUserReply{}, nil
}
後面就可以在這裡補充具體的業務邏輯處理了。
7、啟動服務
# 在根目錄下運行
go run main.go
確保運行gRPC server
// main.go
...
eagle.WithServer(
// init gRPC server
gs,
),
...
8、介面調試
調試工具,這裡使用 [grpcurl](https://github.com/fullstorydev/grpcurl)
# 查看服務列表
grpcurl -plaintext localhost:9090 list
# Output
api.user.v1.UserService
grpc.health.v1.Health
grpc.reflection.v1alpha.ServerReflection
# 訪問列表
grpcurl -plaintext -d '{"user_id":2}' localhost:9090 api.user.v1.UserService/ListUser
參數說明
- -d 提交的參數, json格式
- -plaintext 使用純文本連接,跳過TLS
也可以使用以下工具進行本地測試
-
postman: 新版本的postman 也支持gRPC(beta版)調試
-
grpucui: https://github.com/fullstorydev/grpcui
# 開啟UI界面調試視窗 grpcui -plaintext localhost:9090
部署
兩種部署方式
- docker
- k8s (本地部署可以使用minikube)
部署步驟
-
構建docker鏡像
docker build -t user-service:v1.0.0 -f deploy/docker/Dockerfile .
-
打docker tag
docker tag user-service:v1.0.0 qloog/user-service:v1.0.0
-
push tag 到 docker hub
docker push qloog/user-service:v1.0.0
-
部署到k8s
kubectl apply -f deploy/k8s/go-deployment.yaml kubectl apply -f deploy/k8s/go-service.yaml
以上命令都是一步一步執行的,為了方便期間,這裡也提供了一件部署腳本,執行如下
sh deploy/deploy.sh
項目源碼
最終源碼在這裡:https://github.com/go-microservice/user-service
完結
到此,開發、測試、部署已經操作完了,後面會繼續完善鏈路追蹤和監控相關的部分。
感謝閱讀, 祝大家 Happy coding~