hello micro!
赶紧完成一个就micro的微服务吧~
micro为我们提供的微服务框架如下
这里面有很多角色,Micro API, Customer API, Customer Service 等等...
其中 Micro API是micro给我们提供的一个工具,是通过RPC调用我们模块的API和做一些负载均衡的作用,实际上Customer API, Customer Service是一组微服务,Customer API 收到 Micro API 转发的请求后,将RESTful转换成protobuf 通过gRPC调用发送给Customer Service做服务处理,然后又将返回protobuf数据转换成RESTful返回给用户。
在微服务架构中 一般称 API为RPC GateWay
GRPC Gateway
此指南帮助我们使用go-micro微服务中的grpc gateway。
grpc-gateway是一个protoc的一个插件。 它基于gRPC服务定义,并且提供一个将RESTful JSON API 转换成gRPC协议的反响代理服务。
我们使用go-grpc 去完成 后台服务, go-grpc 是一个为client/server将go-micro和gRPC结合的一个包裹。
代码案例
1 准备
=====> 我们需要做一些准备工作。
安装 protobuf
我们之前的章节已经安装过了protobuf环境
如果没有安装请尝试以下方法重新安装。
mkdir tmp
cd tmp
git clone https://github.com/google/protobuf
cd protobuf
./autogen.sh
./configure
make
make check
sudo make install
安装 protoc-gen-go 和 protoc-gen-grpc-gateway插件
go get -u github.com/micro/protobuf/protoc-gen-go
go get -u github.com/micro/go-grpc
2 构建hello 微服务
我们先在$GOPATH/src/ 下创建一个我们用来存放我们微服务们的主路径,micro框架的文档中都是用他们现成了,刚接触看起来真的一头雾水,所以我们还是自己重新来吧~~~
cd $GOPATH/src
mkdir micro_services
(1) 创建hello微服务protobuf协议 hello.proto
cd micro_services
mkdir hello
cd hello
mkdir proto
cd proto
touch hello.proto
编辑hello.proto文件
syntax = "proto3";
//包名 建议和 和服务名称一致
package go.micro.srv.hello;
//提供的模块
service Say {
//提供的方法
rpc Hello(Request) returns (Response) {}
}
message Request {
string name = 1;
}
message Response {
string msg = 1;
}
生成pb 文件
protoc --go_out=plugins=micro:. hello.proto
====>
关于 --go_out=plugins=micro 中的
protoc micro插件无法生效的解决方案
有可能我们的环境之前已经安装过了
$GOPATH/src/github.com/golang/protobuf
, 并且在$GOPATH/bin/
中拥有了一个之前的
protoc-gen-go而且跟 github.com/micro/protobuf
解决办法:
将$GOPATH/bin/protoc-gen-go删除,
将$GOPATH/src/github.com/golang/protobuf/删除
重新下载github.com/micro/protobuf
go get -v github.com/micro/protobuf/{proto,protoc-gen-go}
<====
(2) 创建hello微服务 --- srv.go
在microservices/hello/下创建 srv.go文件 相当于处理业务的核心模块。
package main
import (
"log"
"time"
"github.com/micro/go-micro"
hello "micro_services/hello/proto"
"golang.org/x/net/context"
)
type Say struct{}
//实现Hello 方法
func (s *Say) Hello(ctx context.Context, req *hello.Request, rsp *hello.Response) error {
log.Print("Received Say.Hello request")
rsp.Msg = "Hello " + req.Name
return nil
}
func main() {
//创建一个micro service
service := micro.NewService(
//这里是当前服务的名称
micro.Name("go.micro.srv.hello"),
micro.RegisterTTL(time.Second*30),
micro.RegisterInterval(time.Second*10),
)
// optionally setup command line usage
service.Init()
// 将hello protobuf中的服务注册到micro serivice中
hello.RegisterSayHandler(service.Server(), new(Say))
// Run server
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
(3) 创建hello api gateway --- srv.go
package main
import (
"encoding/json"
"log"
"strings"
"github.com/micro/go-micro"
"github.com/micro/go-micro/errors"
api "github.com/micro/micro/api/proto"
hello "micro_services/hello/proto"
"golang.org/x/net/context"
)
type Say struct {
Client hello.SayClient
}
func (s *Say) Hello(ctx context.Context, req *api.Request, rsp *api.Response) error {
log.Print("Received Say.Hello API request....")
//可以从req中得到RESTful 参数等
name, ok := req.Get["name"]
if !ok || len(name.Values) == 0 {
return errors.BadRequest("go.micro.api.hello", "Name cannot be blank")
}
//通过micro封装好的protobuf方法 通过rpc调用远程的Hello方法
//这里是一个 protobuf 的 RPC调用
//response作为返回值 返回值类型当然要参考hello.proto文件
response, err := s.Client.Hello(ctx, &hello.Request{
Name: strings.Join(name.Values, " "),
})
if err != nil {
log.Print("client srv hello error....err = ", err)
return err
}
//给micro API返回200 和message,这里貌似不需要修改
rsp.StatusCode = 200
b, _ := json.Marshal(map[string]string{
"message": response.Msg,
})
rsp.Body = string(b)
return nil
}
func main() {
service := micro.NewService(
//当前api的名称,一般都应该和对应的srv名称一样 ,只不过中的srv变成了api
micro.Name("go.micro.api.hello"),
)
// parse command line flags
service.Init()
service.Server().Handle(
service.Server().NewHandler(
//具体要和哪个微服务通信,这个名称一定要和对应的微服务名称一致
&Say{Client: hello.NewSayClient("go.micro.srv.hello", service.Client())},
),
)
//启动api
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
3 启动micro微服务
(1) 启动服务发现consul
consul agent -dev -enable-script-checks \
-bind=101.200.170.171 \
-config-dir ./consul.d/ \
-client 101.200.170.171
主要用于服务发现,因为micro默认依赖consul进行服务发现,每个基于micro完成的微服务都会向consul注册服务。
(2) 启动micro API
主要是负载均衡和对用户接受RESTful
micro --registry_address "101.200.170.171" \
api \
address "101.200.170.171:8080"
当前API监控 8080端口,所以用户的主入口是8080端口
(3) 启动hello API
进入micro_services/hello/文件下
go run api.go --registry_address "101.200.170.171:8500"
(4) 启动hello srvice
进入micro_services/hello/文件下
go run srv.go --registry_address "101.200.170.171:8500"
4 测试hello 方法
curl测试
curl http://101.200.170.171:8080/hello/say/hello?name=Aceld
结果
{"message":"Hello Aceld"}
浏览器测试
这样我们的Micro 的hello world就跑通了,但是如果再基于他写业务,还得继续研究他的其他接口了。