






















此项目示例主要是参考Java版Kubernetes微服务示例,在业务需求相同的情况下,搭建一个Golang版本的Kubernetes项目
项目代码:Go微服务架构 Kubernetes
本项目和Java版本的示例类似架构,也是采用的DDD领域驱动设计,故架构图如下:

本项目分别采用了字节的kitex和hertz框架构建的微服务,具体的内容包括:
Kitex框架中序列化的代码生成,具体参考代码生成工具
采用基于Kubernetes的微服务架构,其中的技术组件包括
DockerFile 中的镜像生成,将镜像构建和镜像运行分为了两步:
以gateway模块为例,具体的操作如下:
FROM golang:1.20 as builder
RUN mkdir /app
WORKDIR /app
ENV GO111MODULE=on \
GOPROXY=https://goproxy.cn,direct \
PORT=8888
COPY *.go ./
COPY go.mod go.sum ./
RUN go mod tidy
RUN CGO_ENABLED=0 go build -o bookstore-platform-gateway *.go
###################################################################
## Run container
FROM alpine:latest
RUN apk --no-cache add ca-certificates
RUN mkdir /app
WORKDIR /app
COPY conf/*.toml conf/
COPY --from=builder /app/bookstore-platform-gateway .
EXPOSE $PORT
## Run
CMD [ "./bookstore-platform-gateway" ]
相比于《凤凰架构》中的原工程,这里仅支持 Skaffold 的方式运行。
Skaffold 是根据skaffold.yml中的配置来进行的,开发时 skaffold 通过dev指令来执行这些配置。
kitex 框架中 fastpb 部分对于 google.timestamp 的序列化暂无支持,具体 issue 可以追溯到 https://github.com/cloudwego/kitex/issues/835,这里通过 string 类型兼容了这一处理,具体操作如下:
import "google/protobuf/timestamp.proto";
message Payment {
google.protobuf.Timestamp createTime = 1;
string payId = 2;
double totalPrice = 3;
int64 expires = 4;
string paymentLink = 5;
}
type Payment struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
CreateTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=createTime,proto3" json:"createTime,omitempty"`
PayId string `protobuf:"bytes,2,opt,name=payId,proto3" json:"payId,omitempty"`
TotalPrice float64 `protobuf:"fixed64,3,opt,name=totalPrice,proto3" json:"totalPrice,omitempty"`
Expires int64 `protobuf:"varint,4,opt,name=expires,proto3" json:"expires,omitempty"`
PaymentLink string `protobuf:"bytes,5,opt,name=paymentLink,proto3" json:"paymentLink,omitempty"`
}
func (x *Payment) fastReadField1(buf []byte, _type int8) (offset int, err error) {
value, offset, err := fastpb.ReadString(buf, _type)
if err != nil {
return offset, err
}
timestamp, _ := time.Parse(time.RFC3339Nano, value)
x.CreateTime = ×tamppb.Timestamp{Seconds: timestamp.Unix(), Nanos: int32(timestamp.Nanosecond())}
return offset, nil
}
func (x *Payment) fastWriteField1(buf []byte) (offset int) {
if x.CreateTime == nil {
return offset
}
timestamp := x.GetCreateTime().AsTime()
offset += fastpb.WriteString(buf[offset:], 1, timestamp.Format(time.RFC3339Nano))
return offset
}
func (x *Payment) sizeField1() (n int) {
if x.CreateTime == nil {
return n
}
timestamp := x.GetCreateTime().AsTime()
n += fastpb.SizeString(1, timestamp.Format(time.RFC3339Nano))
return n
}
采用 Kubernetes ConfigMap 定义config.toml 配置文件,在使用 Kubernetes Deployment 构建过程中,将 ConfigMap 映射到 volumes ,并在 volumes 映射到 container 对应的配置文件目录。具体的操作示例如下:
## ConfigMap 定义配置配置文件config.toml
kind: ConfigMap
apiVersion: v1
metadata:
name: gateway
namespace: bookstore-microservices
data:
config.toml: |-
[account.client]
connnum = 1
hostport = ["account:8810"]
[payment.client]
connnum = 1
hostport = ["payment:8812"]
[warehouse.client]
connnum = 1
hostport = ["warehouse:8811"]
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: bookstore-platform-gateway
namespace: bookstore-microservices
labels:
app: gateway
spec:
replicas: 1
selector:
matchLabels:
app: gateway
template:
metadata:
labels:
app: gateway
spec:
serviceAccountName: book-admin
containers:
- name: gateway
image: icyfenix/bookstore-platform-gateway
ports:
- name: http-server
containerPort: 8888
env:
- name: CONFIG_PATH
value: /app/conf/config.toml
## volumes 映射到 container 中的配置文件目录
volumeMounts:
- name: config-volume
mountPath: /app/conf
## 映射 configmap 到 volumes
volumes:
- name: config-volume
configMap:
name: gateway
微服务层面,使用 viper 读取对应的配置文件,具体操作如下:
func NewConfig() (v *viper.Viper) {
v = viper.New()
v.SetDefault(configPathKey, defaultConfigPath)
defaultClientConfig(v)
v.AutomaticEnv()
// 通过ENV获取
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
v.SetTypeByDefaultValue(true)
v.SetConfigFile(v.GetString(configPathKey))
err := v.ReadInConfig()
if err != nil {
klog.CtxErrorf(context.Background(), err.Error())
}
v.WatchConfig()
v.OnConfigChange(func(in fsnotify.Event) {
klog.CtxErrorf(context.Background(), "Config file changed: %s", in.Name)
})
return
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。