over-golang/06-微服务/06-gomicro-2-集成grpc与etcd.md
2021-07-02 18:11:59 +08:00

6.6 KiB
Raw Permalink Blame History

一 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