- 发布于
Go语言微服务开发:构建可扩展的分布式系统
- 作者

- 姓名
- 全能波
- GitHub
- @weicracker
Go语言微服务开发:构建可扩展的分布式系统
Go语言凭借其简洁的语法、高效的性能和内置的并发支持,成为构建微服务的理想选择。本文将详细介绍使用Go开发微服务的完整流程。
微服务架构基础
项目结构和依赖
// go.mod
module microservice-demo
go 1.21
require (
github.com/gin-gonic/gin v1.9.1
github.com/go-kit/kit v0.13.0
github.com/golang/protobuf v1.5.3
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0
github.com/prometheus/client_golang v1.16.0
github.com/spf13/viper v1.16.0
go.mongodb.org/mongo-driver v1.12.1
go.uber.org/zap v1.24.0
google.golang.org/grpc v1.57.0
google.golang.org/protobuf v1.31.0
)
微服务项目结构
microservice-demo/
├── api/
│ ├── proto/
│ │ └── user.proto
│ └── swagger/
├── cmd/
│ ├── user-service/
│ │ └── main.go
│ ├── order-service/
│ │ └── main.go
│ └── api-gateway/
│ └── main.go
├── internal/
│ ├── user/
│ │ ├── domain/
│ │ ├── repository/
│ │ ├── service/
│ │ └── transport/
│ └── order/
│ ├── domain/
│ ├── repository/
│ ├── service/
│ └── transport/
├── pkg/
│ ├── auth/
│ ├── database/
│ ├── logger/
│ └── tracing/
├── deployments/
│ ├── docker/
│ └── kubernetes/
├── scripts/
├── go.mod
└── go.sum
服务定义和接口设计
// api/proto/user.proto
syntax = "proto3";
package user;
option go_package = "microservice-demo/api/proto/user";
import "google/api/annotations.proto";
service UserService {
rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) {
option (google.api.http) = {
post: "/v1/users"
body: "*"
};
}
rpc GetUser(GetUserRequest) returns (GetUserResponse) {
option (google.api.http) = {
get: "/v1/users/{id}"
};
}
rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) {
option (google.api.http) = {
put: "/v1/users/{id}"
body: "*"
};
}
rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse) {
option (google.api.http) = {
delete: "/v1/users/{id}"
};
}
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) {
option (google.api.http) = {
get: "/v1/users"
};
}
}
message User {
string id = 1;
string username = 2;
string email = 3;
string full_name = 4;
string created_at = 5;
string updated_at = 6;
}
message CreateUserRequest {
string username = 1;
string email = 2;
string password = 3;
string full_name = 4;
}
message CreateUserResponse {
User user = 1;
}
message GetUserRequest {
string id = 1;
}
message GetUserResponse {
User user = 1;
}
message UpdateUserRequest {
string id = 1;
string email = 2;
string full_name = 3;
}
message UpdateUserResponse {
User user = 1;
}
message DeleteUserRequest {
string id = 1;
}
message DeleteUserResponse {
bool success = 1;
}
message ListUsersRequest {
int32 page = 1;
int32 page_size = 2;
}
message ListUsersResponse {
repeated User users = 1;
int32 total = 2;
}
领域模型和业务逻辑
// internal/user/domain/user.go
package domain
import (
"time"
"errors"
"regexp"
"golang.org/x/crypto/bcrypt"
)
var (
ErrInvalidUsername = errors.New("invalid username")
ErrInvalidEmail = errors.New("invalid email")
ErrInvalidPassword = errors.New("invalid password")
)
// User 领域模型
type User struct {
ID string `json:"id" bson:"_id,omitempty"`
Username string `json:"username" bson:"username"`
Email string `json:"email" bson:"email"`
Password string `json:"-" bson:"password"`
FullName string `json:"full_name" bson:"full_name"`
CreatedAt time.Time `json:"created_at" bson:"created_at"`
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
}
// NewUser 创建新用户
func NewUser(username, email, password, fullName string) (*User, error) {
// 验证用户名
if !isValidUsername(username) {
return nil, ErrInvalidUsername
}
// 验证邮箱
if !isValidEmail(email) {
return nil, ErrInvalidEmail
}
// 验证密码
if !isValidPassword(password) {
return nil, ErrInvalidPassword
}
// 加密密码
hashedPassword, err := hashPassword(password)
if err != nil {
return nil, err
}
now := time.Now()
return &User{
Username: username,
Email: email,
Password: hashedPassword,
FullName: fullName,
CreatedAt: now,
UpdatedAt: now,
}, nil
}
// UpdateProfile 更新用户资料
func (u *User) UpdateProfile(email, fullName string) error {
if email != "" && email != u.Email {
if !isValidEmail(email) {
return ErrInvalidEmail
}
u.Email = email
}
if fullName != "" {
u.FullName = fullName
}
u.UpdatedAt = time.Now()
return nil
}
// VerifyPassword 验证密码
func (u *User) VerifyPassword(password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
return err == nil
}
// 辅助函数
func isValidUsername(username string) bool {
if len(username) < 3 || len(username) > 30 {
return false
}
pattern := `^[a-zA-Z0-9_]+$`
matched, _ := regexp.MatchString(pattern, username)
return matched
}
func isValidEmail(email string) bool {
pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
matched, _ := regexp.MatchString(pattern, email)
return matched
}
func isValidPassword(password string) bool {
return len(password) >= 8
}
func hashPassword(password string) (string, error) {
hashedBytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hashedBytes), nil
}
数据访问层
// internal/user/repository/mongodb_repository.go
package repository
import (
"context"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"microservice-demo/internal/user/domain"
)
type UserRepository interface {
Create(ctx context.Context, user *domain.User) error
FindByID(ctx context.Context, id string) (*domain.User, error)
FindByUsername(ctx context.Context, username string) (*domain.User, error)
FindByEmail(ctx context.Context, email string) (*domain.User, error)
Update(ctx context.Context, user *domain.User) error
Delete(ctx context.Context, id string) error
List(ctx context.Context, page, pageSize int) ([]*domain.User, int, error)
}
type mongoUserRepository struct {
collection *mongo.Collection
}
func NewMongoUserRepository(db *mongo.Database) UserRepository {
collection := db.Collection("users")
// 创建索引
indexModels := []mongo.IndexModel{
{
Keys: bson.D{{Key: "username", Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{Key: "email", Value: 1}},
Options: options.Index().SetUnique(true),
},
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
_, err := collection.Indexes().CreateMany(ctx, indexModels)
if err != nil {
panic(err)
}
return &mongoUserRepository{
collection: collection,
}
}
func (r *mongoUserRepository) Create(ctx context.Context, user *domain.User) error {
if user.ID == "" {
user.ID = primitive.NewObjectID().Hex()
}
_, err := r.collection.InsertOne(ctx, user)
return err
}
func (r *mongoUserRepository) FindByID(ctx context.Context, id string) (*domain.User, error) {
var user domain.User
err := r.collection.FindOne(ctx, bson.M{"_id": id}).Decode(&user)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
return nil, err
}
return &user, nil
}
func (r *mongoUserRepository) FindByUsername(ctx context.Context, username string) (*domain.User, error) {
var user domain.User
err := r.collection.FindOne(ctx, bson.M{"username": username}).Decode(&user)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
return nil, err
}
return &user, nil
}
func (r *mongoUserRepository) FindByEmail(ctx context.Context, email string) (*domain.User, error) {
var user domain.User
err := r.collection.FindOne(ctx, bson.M{"email": email}).Decode(&user)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
return nil, err
}
return &user, nil
}
func (r *mongoUserRepository) Update(ctx context.Context, user *domain.User) error {
user.UpdatedAt = time.Now()
_, err := r.collection.ReplaceOne(ctx, bson.M{"_id": user.ID}, user)
return err
}
func (r *mongoUserRepository) Delete(ctx context.Context, id string) error {
_, err := r.collection.DeleteOne(ctx, bson.M{"_id": id})
return err
}
func (r *mongoUserRepository) List(ctx context.Context, page, pageSize int) ([]*domain.User, int, error) {
if page < 1 {
page = 1
}
if pageSize < 1 {
pageSize = 10
}
skip := (page - 1) * pageSize
// 查询总数
total, err := r.collection.CountDocuments(ctx, bson.M{})
if err != nil {
return nil, 0, err
}
// 查询用户列表
findOptions := options.Find().
SetSkip(int64(skip)).
SetLimit(int64(pageSize)).
SetSort(bson.D{{Key: "created_at", Value: -1}})
cursor, err := r.collection.Find(ctx, bson.M{}, findOptions)
if err != nil {
return nil, 0, err
}
defer cursor.Close(ctx)
var users []*domain.User
if err := cursor.All(ctx, &users); err != nil {
return nil, 0, err
}
return users, int(total), nil
}
服务层实现
// internal/user/service/service.go
package service
import (
"context"
"errors"
"microservice-demo/internal/user/domain"
"microservice-demo/internal/user/repository"
)
var (
ErrUserNotFound = errors.New("user not found")
ErrUsernameExists = errors.New("username already exists")
ErrEmailExists = errors.New("email already exists")
ErrInvalidCredentials = errors.New("invalid credentials")
)
type UserService interface {
CreateUser(ctx context.Context, username, email, password, fullName string) (*domain.User, error)
GetUser(ctx context.Context, id string) (*domain.User, error)
UpdateUser(ctx context.Context, id, email, fullName string) (*domain.User, error)
DeleteUser(ctx context.Context, id string) error
ListUsers(ctx context.Context, page, pageSize int) ([]*domain.User, int, error)
AuthenticateUser(ctx context.Context, username, password string) (*domain.User, error)
}
type userService struct {
repo repository.UserRepository
}
func NewUserService(repo repository.UserRepository) UserService {
return &userService{
repo: repo,
}
}
func (s *userService) CreateUser(ctx context.Context, username, email, password, fullName string) (*domain.User, error) {
// 检查用户名是否已存在
existingUser, err := s.repo.FindByUsername(ctx, username)
if err != nil {
return nil, err
}
if existingUser != nil {
return nil, ErrUsernameExists
}
// 检查邮箱是否已存在
existingUser, err = s.repo.FindByEmail(ctx, email)
if err != nil {
return nil, err
}
if existingUser != nil {
return nil, ErrEmailExists
}
// 创建新用户
user, err := domain.NewUser(username, email, password, fullName)
if err != nil {
return nil, err
}
// 保存用户
if err := s.repo.Create(ctx, user); err != nil {
return nil, err
}
return user, nil
}
func (s *userService) GetUser(ctx context.Context, id string) (*domain.User, error) {
user, err := s.repo.FindByID(ctx, id)
if err != nil {
return nil, err
}
if user == nil {
return nil, ErrUserNotFound
}
return user, nil
}
func (s *userService) UpdateUser(ctx context.Context, id, email, fullName string) (*domain.User, error) {
user, err := s.repo.FindByID(ctx, id)
if err != nil {
return nil, err
}
if user == nil {
return nil, ErrUserNotFound
}
// 检查邮箱是否已被其他用户使用
if email != "" && email != user.Email {
existingUser, err := s.repo.FindByEmail(ctx, email)
if err != nil {
return nil, err
}
if existingUser != nil && existingUser.ID != id {
return nil, ErrEmailExists
}
}
// 更新用户资料
if err := user.UpdateProfile(email, fullName); err != nil {
return nil, err
}
// 保存更新
if err := s.repo.Update(ctx, user); err != nil {
return nil, err
}
return user, nil
}
func (s *userService) DeleteUser(ctx context.Context, id string) error {
user, err := s.repo.FindByID(ctx, id)
if err != nil {
return err
}
if user == nil {
return ErrUserNotFound
}
return s.repo.Delete(ctx, id)
}
func (s *userService) ListUsers(ctx context.Context, page, pageSize int) ([]*domain.User, int, error) {
return s.repo.List(ctx, page, pageSize)
}
func (s *userService) AuthenticateUser(ctx context.Context, username, password string) (*domain.User, error) {
user, err := s.repo.FindByUsername(ctx, username)
if err != nil {
return nil, err
}
if user == nil {
return nil, ErrInvalidCredentials
}
if !user.VerifyPassword(password) {
return nil, ErrInvalidCredentials
}
return user, nil
}
gRPC传输层实现
// internal/user/transport/grpc_server.go
package transport
import (
"context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "microservice-demo/api/proto/user"
"microservice-demo/internal/user/service"
)
type grpcServer struct {
pb.UnimplementedUserServiceServer
userService service.UserService
}
func NewGRPCServer(userService service.UserService) pb.UserServiceServer {
return &grpcServer{
userService: userService,
}
}
func (s *grpcServer) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserResponse, error) {
user, err := s.userService.CreateUser(ctx, req.Username, req.Email, req.Password, req.FullName)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
return &pb.CreateUserResponse{
User: &pb.User{
Id: user.ID,
Username: user.Username,
Email: user.Email,
FullName: user.FullName,
CreatedAt: user.CreatedAt.Format("2006-01-02T15:04:05Z"),
UpdatedAt: user.UpdatedAt.Format("2006-01-02T15:04:05Z"),
},
}, nil
}
func (s *grpcServer) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) {
user, err := s.userService.GetUser(ctx, req.Id)
if err != nil {
if err == service.ErrUserNotFound {
return nil, status.Error(codes.NotFound, "user not found")
}
return nil, status.Error(codes.Internal, err.Error())
}
return &pb.GetUserResponse{
User: &pb.User{
Id: user.ID,
Username: user.Username,
Email: user.Email,
FullName: user.FullName,
CreatedAt: user.CreatedAt.Format("2006-01-02T15:04:05Z"),
UpdatedAt: user.UpdatedAt.Format("2006-01-02T15:04:05Z"),
},
}, nil
}
func (s *grpcServer) UpdateUser(ctx context.Context, req *pb.UpdateUserRequest) (*pb.UpdateUserResponse, error) {
user, err := s.userService.UpdateUser(ctx, req.Id, req.Email, req.FullName)
if err != nil {
if err == service.ErrUserNotFound {
return nil, status.Error(codes.NotFound, "user not found")
}
return nil, status.Error(codes.Internal, err.Error())
}
return &pb.UpdateUserResponse{
User: &pb.User{
Id: user.ID,
Username: user.Username,
Email: user.Email,
FullName: user.FullName,
CreatedAt: user.CreatedAt.Format("2006-01-02T15:04:05Z"),
UpdatedAt: user.UpdatedAt.Format("2006-01-02T15:04:05Z"),
},
}, nil
}
func (s *grpcServer) DeleteUser(ctx context.Context, req *pb.DeleteUserRequest) (*pb.DeleteUserResponse, error) {
err := s.userService.DeleteUser(ctx, req.Id)
if err != nil {
if err == service.ErrUserNotFound {
return nil, status.Error(codes.NotFound, "user not found")
}
return nil, status.Error(codes.Internal, err.Error())
}
return &pb.DeleteUserResponse{
Success: true,
}, nil
}
func (s *grpcServer) ListUsers(ctx context.Context, req *pb.ListUsersRequest) (*pb.ListUsersResponse, error) {
users, total, err := s.userService.ListUsers(ctx, int(req.Page), int(req.PageSize))
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
pbUsers := make([]*pb.User, len(users))
for i, user := range users {
pbUsers[i] = &pb.User{
Id: user.ID,
Username: user.Username,
Email: user.Email,
FullName: user.FullName,
CreatedAt: user.CreatedAt.Format("2006-01-02T15:04:05Z"),
UpdatedAt: user.UpdatedAt.Format("2006-01-02T15:04:05Z"),
}
}
return &pb.ListUsersResponse{
Users: pbUsers,
Total: int32(total),
}, nil
}
HTTP REST API实现
// internal/user/transport/http_server.go
package transport
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"microservice-demo/internal/user/service"
)
type HTTPServer struct {
userService service.UserService
}
func NewHTTPServer(userService service.UserService) *HTTPServer {
return &HTTPServer{
userService: userService,
}
}
func (h *HTTPServer) RegisterRoutes(router *gin.Engine) {
v1 := router.Group("/api/v1")
{
users := v1.Group("/users")
{
users.POST("", h.CreateUser)
users.GET("/:id", h.GetUser)
users.PUT("/:id", h.UpdateUser)
users.DELETE("/:id", h.DeleteUser)
users.GET("", h.ListUsers)
}
}
}
type CreateUserRequest struct {
Username string `json:"username" binding:"required"`
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required,min=8"`
FullName string `json:"full_name"`
}
func (h *HTTPServer) CreateUser(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user, err := h.userService.CreateUser(c.Request.Context(), req.Username, req.Email, req.Password, req.FullName)
if err != nil {
switch err {
case service.ErrUsernameExists:
c.JSON(http.StatusConflict, gin.H{"error": "username already exists"})
case service.ErrEmailExists:
c.JSON(http.StatusConflict, gin.H{"error": "email already exists"})
default:
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
return
}
c.JSON(http.StatusCreated, gin.H{"user": user})
}
func (h *HTTPServer) GetUser(c *gin.Context) {
id := c.Param("id")
user, err := h.userService.GetUser(c.Request.Context(), id)
if err != nil {
if err == service.ErrUserNotFound {
c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
return
}
c.JSON(http.StatusOK, gin.H{"user": user})
}
type UpdateUserRequest struct {
Email string `json:"email"`
FullName string `json:"full_name"`
}
func (h *HTTPServer) UpdateUser(c *gin.Context) {
id := c.Param("id")
var req UpdateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user, err := h.userService.UpdateUser(c.Request.Context(), id, req.Email, req.FullName)
if err != nil {
switch err {
case service.ErrUserNotFound:
c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
case service.ErrEmailExists:
c.JSON(http.StatusConflict, gin.H{"error": "email already exists"})
default:
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
return
}
c.JSON(http.StatusOK, gin.H{"user": user})
}
func (h *HTTPServer) DeleteUser(c *gin.Context) {
id := c.Param("id")
err := h.userService.DeleteUser(c.Request.Context(), id)
if err != nil {
if err == service.ErrUserNotFound {
c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
return
}
c.JSON(http.StatusOK, gin.H{"message": "user deleted successfully"})
}
func (h *HTTPServer) ListUsers(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
users, total, err := h.userService.ListUsers(c.Request.Context(), page, pageSize)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"users": users,
"total": total,
"page": page,
"page_size": pageSize,
})
}
服务启动和配置
// cmd/user-service/main.go
package main
import (
"context"
"fmt"
"log"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"google.golang.org/grpc"
pb "microservice-demo/api/proto/user"
"microservice-demo/internal/user/repository"
"microservice-demo/internal/user/service"
"microservice-demo/internal/user/transport"
"microservice-demo/pkg/config"
"microservice-demo/pkg/logger"
)
func main() {
// 加载配置
cfg := config.Load()
// 初始化日志
logger := logger.New(cfg.LogLevel)
// 连接数据库
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(cfg.MongoDB.URI))
if err != nil {
log.Fatal("Failed to connect to MongoDB:", err)
}
defer client.Disconnect(context.Background())
db := client.Database(cfg.MongoDB.Database)
// 初始化依赖
userRepo := repository.NewMongoUserRepository(db)
userService := service.NewUserService(userRepo)
// 启动gRPC服务器
go func() {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", cfg.GRPC.Port))
if err != nil {
log.Fatal("Failed to listen for gRPC:", err)
}
grpcServer := grpc.NewServer()
pb.RegisterUserServiceServer(grpcServer, transport.NewGRPCServer(userService))
logger.Info("Starting gRPC server", "port", cfg.GRPC.Port)
if err := grpcServer.Serve(lis); err != nil {
log.Fatal("Failed to serve gRPC:", err)
}
}()
// 启动HTTP服务器
gin.SetMode(gin.ReleaseMode)
router := gin.New()
router.Use(gin.Logger(), gin.Recovery())
httpServer := transport.NewHTTPServer(userService)
httpServer.RegisterRoutes(router)
srv := &http.Server{
Addr: fmt.Sprintf(":%d", cfg.HTTP.Port),
Handler: router,
}
go func() {
logger.Info("Starting HTTP server", "port", cfg.HTTP.Port)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal("Failed to start HTTP server:", err)
}
}()
// 优雅关闭
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
logger.Info("Shutting down servers...")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
logger.Error("HTTP server forced to shutdown", "error", err)
}
logger.Info("Servers stopped")
}
Docker容器化
# deployments/docker/Dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
# 安装依赖
COPY go.mod go.sum ./
RUN go mod download
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o user-service ./cmd/user-service
# 运行阶段
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
# 复制二进制文件
COPY /app/user-service .
# 暴露端口
EXPOSE 8080 9090
# 运行应用
CMD ["./user-service"]
Kubernetes部署配置
# deployments/kubernetes/user-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
labels:
app: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:latest
ports:
- containerPort: 8080
name: http
- containerPort: 9090
name: grpc
env:
- name: MONGODB_URI
valueFrom:
secretKeyRef:
name: user-service-secrets
key: mongodb-uri
- name: LOG_LEVEL
value: "info"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: user-service
labels:
app: user-service
spec:
selector:
app: user-service
ports:
- name: http
port: 80
targetPort: 8080
- name: grpc
port: 9090
targetPort: 9090
type: ClusterIP
---
apiVersion: v1
kind: Secret
metadata:
name: user-service-secrets
type: Opaque
data:
mongodb-uri: bW9uZ29kYjovL3VzZXI6cGFzc3dvcmRAbW9uZ29kYjoyNzAxNy9kYXRhYmFzZQ==
总结
Go语言微服务开发的核心要点:
🎯 架构设计
- 领域驱动设计:清晰的领域模型和业务逻辑
- 微服务拆分:合理的服务边界和职责划分
- API设计:RESTful和gRPC接口设计
- 数据管理:分布式数据存储和一致性
✅ 技术栈
- gRPC和Protocol Buffers
- RESTful API和JSON
- 容器化和Kubernetes
- 服务发现和配置管理
🚀 最佳实践
- 服务间通信模式
- 错误处理和重试策略
- 监控和可观测性
- 安全性和认证授权
💡 性能优化
- 并发处理和资源管理
- 缓存策略和数据库优化
- 负载均衡和自动扩缩容
- 服务网格和流量控制
🔧 部署运维
- Docker容器化
- Kubernetes编排
- CI/CD流水线
- 监控和日志收集
掌握Go微服务开发,构建可扩展的分布式系统!
Go语言的简洁性和高性能特性使其成为构建微服务的理想选择,通过合理的架构设计和最佳实践,可以构建出高效、可靠的分布式系统。