5.5 微服务基础
gRPC 基础
protobuf
// proto/user.proto
syntax = "proto3";
package user;
option go_package = "example.com/user";
service UserService {
rpc GetUser(GetUserRequest) returns (User);
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
rpc CreateUser(CreateUserRequest) returns (User);
}
message User {
int32 id = 1;
string name = 2;
string email = 3;
}
message GetUserRequest {
int32 id = 1;
}
message ListUsersRequest {
int32 page = 1;
int32 page_size = 2;
}
message ListUsersResponse {
repeated User users = 1;
int32 total = 2;
}go
// 生成代码
// protoc --go_out=. --go_opt=paths=source_relative \
// --go-grpc_out=. --go-grpc_opt=paths=source_relative \
// user.proto
// gRPC 服务器
type UserService struct {
pb.UnimplementedUserService
}
func (s *UserService) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.User, error) {
return &pb.User{Id: req.Id, Name: "Alice"}, nil
}
lis, _ := net.Listen("tcp", ":50051")
server := grpc.NewServer()
pb.RegisterUserService(server, &UserService{})
server.Serve(lis)
// gRPC 客户端
conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure())
client := pb.NewUserServiceClient(conn)
resp, _ := client.GetUser(context.Background(), &pb.GetUserRequest{Id: 1})Protocol Buffers
protobuf
// 标量类型
// double, float, int32, int64, uint32, uint64
// sint32, sint64, fixed32, fixed64, sfixed32, sfixed64
// bool, string, bytes
// 字段规则
optional // 可有可无
repeated // 数组
oneof // 多选一
// 枚举
enum Status {
STATUS_UNKNOWN = 0;
STATUS_ACTIVE = 1;
}
// Map
map<string, int32> scores = 1;
// 嵌套消息
message Address {
string street = 1;
string city = 2;
}
message Person {
string name = 1;
Address address = 2;
}服务发现
go
// etcd 服务发现
import "github.com/etcd-io/etcd/client/v3"
// 服务注册
func RegisterService(etcdClient *clientv3.Client, serviceName, serviceAddr string) {
key := fmt.Sprintf("/services/%s/%s", serviceName, serviceAddr)
etcdClient.Put(context.Background(), key, serviceAddr)
}
// 服务发现
func DiscoverService(etcdClient *clientv3.Client, serviceName string) ([]string, error) {
resp, _ := etcdClient.Get(context.Background(),
fmt.Sprintf("/services/%s/", serviceName),
clientv3.WithPrefix())
var addrs []string
for _, kv := range resp.Kvs {
addrs = append(addrs, string(kv.Value))
}
return addrs, nil
}负载均衡
go
// gRPC 负载均衡
conn, _ := grpc.Dial(
"etcd:///myservice",
grpc.WithInsecure(),
grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`),
)
// 客户端负载均衡策略:
// 1. 随机
// 2. 轮询
// 3. 加权
// 4. 最少连接