参考博文
https://ewanvalentine.io/microservices-in-golang-part-1/
这个博文是作者微服务系统的第一篇,本学习笔记基于目前的5篇而成
part 1 利用gRPC ,protobuf定义服务
本人在学习过程中没有严格按照博文中放在github目录,而是在主目录中创建一个wdyshippy的目录,目录中文件结构如下
.
├── consignment-cli
│ ├── cli.go
│ ├── consignment-cli
│ ├── consignment.json
│ ├── Dockerfile
│ └── Makefile
└── consignment-service
├── consignment-service
├── Dockerfile
├── main.go
├── Makefile
└── proto
└── consignment
├── consignment.pb.go
└── consignment.proto
4 directories, 11 files
执行的protoc命令
protoc -I. --go_out=plugins=grpc:/home/wdy/wdyshippy/consignment-service proto/consignment/consignment.proto
如果make build时报错
makefile:2: *** 遗漏分隔符
原因是在编写makefile文件时,命令前面应该是tab写为了空格
在这个阶段中,consignment-service的Makefile文件内容如下
build:
protoc -I. --go_out=plugins=grpc:$(GOPATH)/src/github.com/ewanvalentine/shipper/consignment-service \
proto/consignment/consignment.proto
part 2 - Docker and go-micro
创建Dockefiel
$ touch consignment-service/Dockerfile
写入如下内容
FROM alpine:latest
RUN mkdir /app
WORKDIR /app
ADD consignment-service /app/consignment-service
CMD ["./consignment-service"]
原作者提示如果是在linux机子上编译测试时,将alpine改为debian
FROM debian:latest
RUN mkdir /app
WORKDIR /app
ADD consignment-service /app/consignment-service
CMD ["./consignment-service"]
WORKDIR 表示 /app目录作为上下文目录用来装载我们的程序consignment-service
接下来为Makefile文件增加内容用来生成docker image
build:
...
GOOS=linux GOARCH=amd64 go build
docker build -t consignment-service .
除此之外再添加
run:
docker run -p 50051:50051 consignment-service
用来执行consignment-service
docker run -p 后面的参数,第一个端口号是对外的端口,第二个是内部的端口。
Go-micro
使用Go-micro来加入service discovery功能
首先安装
go get -u github.com/micro/protobuf/{proto,protoc-gen-go}
修改makefile文件中protoc的参数,将参数plugins=后面的grpc更改为micro
build:
protoc -I. --go_out=plugins=micro:/home/wdy/wdyshippy/consignment-service proto/consignment/consignment.proto
...
...
代码也要相应修改
import中 要引入 micro “github.com/micro/go-micro”
// consignment-service/main.go
package main
import (
// Import the generated protobuf code
"fmt"
pb "github.com/EwanValentine/shippy/consignment-service/proto/consignment"
micro "github.com/micro/go-micro"
"golang.org/x/net/context"
)
server接口实现时,response的位置改变为输入参数,输出参数只有error
func (s *service) CreateConsignment(ctx context.Context, req *pb.Consignment, res *pb.Response) error {
...
func (s *service) GetConsignments(ctx context.Context, req *pb.GetRequest, res *pb.Response) error {
...
还有就是server的初始化
func main() {
repo := &Repository{}
// Create a new service. Optionally include some options here.
srv := micro.NewService(
// This name must match the package name given in your protobuf definition
micro.Name("go.micro.srv.consignment"),
micro.Version("latest"),
)
// Init will parse the command line flags.
srv.Init()
// Register handler
pb.RegisterShippingServiceHandler(srv.Server(), &service{repo})
// Run the server
if err := srv.Run(); err != nil {
fmt.Println(err)
}
}
最后就是不需要在代码中硬编码端口号,Go-micro通过环境变量或命令行参数来传递。
run:
docker run -p 50051:50051 \
-e MICRO_SERVER_ADDRESS=:50051 \
-e MICRO_REGISTRY=mdns consignment-service
如上,通过 -e MICRO_SERVER_ADDRESS=:50051 指定服务地址,通过-e MICRO_REGISTRY=mdns指定service discovery功能使用mdns。在实际项目中mdns很少使用,大部分使用consul。
除了服务端代码更改外,客户端代码也需要更改
import (
...
"github.com/micro/go-micro/cmd"
microclient "github.com/micro/go-micro/client"
)
func main() {
cmd.Init()
// Create new greeter client
client := pb.NewShippingServiceClient("go.micro.srv.consignment", microclient.DefaultClient)
...
}
通过docker启动consignment-service后,执行客户端程序会连接失败,原因在于server允许在docker中使用的是docker中的dmns,和客户端使用的不是同一个,所以发现不了server,解决方法就是把客户端程序也放入到docker 中,使用同一个dmns。
创建consignment-cli/Makefile文件
build:
GOOS=linux GOARCH=amd64 go build
docker build -t consignment-cli .
run:
docker run -e MICRO_REGISTRY=mdns consignment-cli
Dockerfile文件
FROM alpine:latest
RUN mkdir -p /app
WORKDIR /app
ADD consignment.json /app/consignment.json
ADD consignment-cli /app/consignment-cli
CMD ["./consignment-cli"]
作者最后又提供了一个更加标准的Dockerfile文件,这个文件中包含了consignment-service的开发环境和生存环境
在开发环境中通过引用github.com/golang/dep/cmd/dep 来自动更新包依赖
RUN go get -u github.com/golang/dep/cmd/dep
# Create a dep project, and run `ensure`, which will pull in all
# of the dependencies within this directory.
RUN dep init && dep ensure
完整文件如下
# consignment-service/Dockerfile
# We use the official golang image, which contains all the
# correct build tools and libraries. Notice `as builder`,
# this gives this container a name that we can reference later on.
FROM golang:1.9.0 as builder
# Set our workdir to our current service in t