跳到主要内容

gomicro-2-集成grpc与etcd

一 go micro 示例

1.0 说明

本章的 go micro 示例使用 etcd 为服务发现机制, grpc 为通信协议,并且基于go1.13版本,使用go mod管理包。

项目目录结构:

|-microdemo
|- common 通用文件夹
|- code 项目状态码文件夹
- commonCode.go
|- config 项目通用配置文件夹
- commonConfig.go
|- simple: 简单示例服务文件夹
|- handler 简单示例服务的服务句柄文件夹
|- testHandler
- testHandler.go
|- proto 简单示例服务的grpc协议文件夹
|- testProto
- test.micro.go
- test.pb.go
- test.proto
- main.go 主文件
|- web: web服务文件夹
|- go.mod 项目管理文件

贴士:本项目基于etcd,必须先启动etcd!!!

1.1 创建基础配置

创建一个名为 microdemo 的项目

go mod init microdemo           

commonCode.go:

package code

type res struct {
Code int
Msg string
}

var OK *res
var SERERR *res
var DBERR *res
var INFOERR *res
var FILTERERR *res
var INFONOTFOUND *res

func init() {

// 正确请求
OK = &res{1000, "成功"}

// 数据校验 3
FILTERERR = &res{ 3001, "校验未通过", }

// 资源状态 4
INFONOTFOUND = &res{4001, "资源不存在",}

// 服务器状态 5
SERERR = &res{5001, "服务器错误",}
DBERR = &res{5002, "数据库错误",}

}

commonConfig.go

package config

import "fmt"

var ENV = "TEST"

var EtcdAddr []string = []string{
"127.0.0.1:2379",
"127.0.0.1:2379",
"127.0.0.1:2379",
}

var RedisAddr string = "127.0.0.1"
var RedisPort string = "6379"
var RedisDB string = "0"

var FastDfsAddr string = "127.0.0.1"
var FastDfsPort string = "9090"

var StaticAddr string = "http://" + FastDfsAddr + ":" + FastDfsPort + "/"

func init() {

if ENV == "PROD" {
fmt.Println("执行生产环境配置")
}

}

1.2 创建第一个微服务:simple

simple服务只是一个微服务的简单示例。

生成协议文件:

# simple/proto/simpleProto/simple.proto
syntax = "proto3";

package simpleProto;

service SimpleService {
rpc SimpleFunc(SimpleRequest) returns (SimpleResponse) {}
}

message SimpleRequest {
int32 id = 1;
}

message SimpleResponse {
int32 code = 1;
string msg = 2;
}

# 生成go协议文件
cd simple/proto/simpleProto
protoc simple.proto --proto_path=. --go_out=. --micro_out=.

书写句柄函数:即本服务具体做什么

// simple/handler/simplerHandler/simplerHandler.go
package simpleHandler

import (
"context"
"microdemo/simple/proto/simpleProto"
)

// 简单微服务
type SimpleService struct{}
func (s *SimpleService) SimpleFunc(ctx context.Context, req *simpleProto.SimpleRequest, rsp *simpleProto.SimpleResponse) error {

// 执行业务操作....

// 返回业务数据给web服务
rsp.Code = 1
rsp.Msg = "成功"
return nil
}

main文件:

package main

import (
"github.com/micro/go-micro"
"github.com/micro/go-micro/registry"
"github.com/micro/go-micro/service/grpc"
"github.com/micro/go-micro/util/log"
"github.com/micro/go-plugins/registry/etcdv3"
"microdemo/simple/handler/simpleHandler"
"microdemo/simple/proto/simpleProto"
"microdemo/common/config"
)

func main() {

// 替换micro默认的服务发现框架consul为etcd
reg := etcdv3.NewRegistry(func(op *registry.Options){
op.Addrs = config.EtcdAddr
})

// 创建服务
service := grpc.NewService(
micro.Name("demo.srv.simple"),
micro.Registry(reg),
micro.Version("latest"),
micro.Address(":" + "30066"),
)
service.Init()

// 注册服务句柄
err := simpleProto.RegisterSimpleServiceHandler(service.Server(), new(simpleHandler.SimpleService))
if err != nil {
log.Error("注册句柄错误:", err)
return
}

// 运行服务
if err := service.Run(); err != nil {
log.Error("运行服务错误:", err)
return
}
}

1.3 创建第二个微服务:web

handler句柄文件:

// web/handler/simpleHandler/simpleHandler.go
package simpleHandler

import (
"context"
"encoding/json"
"fmt"
"github.com/julienschmidt/httprouter"
"github.com/micro/go-micro/service/grpc"
"microdemo/simple/proto/simpleProto"
"net/http"
)

// 简单微服务方法
func Simple(w http.ResponseWriter, r *http.Request, p httprouter.Params) {

fmt.Println("参数:", p)

// grpc 服务初始化
service := grpc.NewService()
service.Init()

// 获取服务句柄
simpleClient := simpleProto.NewSimpleService("demo.srv.simple", service.Client())

// 调用服务
rsp, err := simpleClient.SimpleFunc(context.TODO(), &simpleProto.SimpleRequest{})
if err != nil {
fmt.Println("调用服务错误:", err)
http.Error(w, err.Error(), 500)
}

// 创建返回给前端的数据
result := map[string]interface{}{
"code": rsp.Code,
"msg": rsp.Msg,
}
if err := json.NewEncoder(w).Encode(result); err != nil {
http.Error(w, err.Error(), 500)
}
}

main.go

package main

import (
"github.com/julienschmidt/httprouter"
"github.com/micro/go-micro/registry"
"github.com/micro/go-micro/util/log"
"github.com/micro/go-micro/web"
"github.com/micro/go-plugins/registry/etcdv3"
"microdemo/account/config"
"microdemo/web/handler/simpleHandler"
"net/http"
)

func main() {

// 替换micro默认的服务发现框架consul为etcd
reg := etcdv3.NewRegistry(func(op *registry.Options){
op.Addrs = config.EtcdAddr
})

// 创建web服务
service := web.NewService(
web.Name("demo.web.web"),
web.Registry(reg),
web.Version("latest"),
web.Address(":" + "3000"),
)
if err := service.Init(); err != nil {
log.Error("服务初始化错误:", err)
}

// 创建路由
router := httprouter.New()
router.NotFound = http.FileServer(http.Dir("public"))

// 测试路由
router.GET("/simple/:id", simpleHandler.Simple)

service.Handle("/", router)

// 运行服务
if err := service.Run(); err != nil {
log.Error("服务运行错误:", err)
}
}

1.4 服务启动与访问

启动etcd后,启动服务:

# 启动simple服务
cd simple
go run main.go --registry=etcd --registry_address=127.0.0.1:2379

# 启动web服务
cd web
go run main.go --registry=etcd --registry_address=127.0.0.1:2379

访问:

localhost:3000/simple/10001