crow-han(基于go-micro框架的微服务脚手架)-02

2023-05-21  本文已影响0人  玄德公笔记

1. 目录结构

image.png

2. 添加自己的微服务

已获取k8s的node节点列表为例,写一个k8s的微服务接入crow-han中

2.1 配置文件和必要的函数

2.1.1 配置文件

以后放置微服务k8s的main函数、初始化相关代码、配置文件等

2.1.2 连接k8s

internal/conf 目录下创建 connect_k8s.go文件

以下这段是链接k8s的代码。这段代码可以作为微服务k8s的私有代码放在internal/app/k8s中,也可以最为脚手架公用配置放在internal/conf中。考虑到我之后将按照crow-han的风格,在微服务k8s的main函数中初始化k8s链接,为避免以后出现循环调用的可能,这里选择了后者。

ackage conf

import (
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

var K8sClientSet *kubernetes.Clientset

func ConnectK8s() (clientSet *kubernetes.Clientset, err error) {
    configPath := "etc/kube.conf"
    config, err := clientcmd.BuildConfigFromFlags("", configPath)
    if err != nil {
        return nil, err
    }
    clientSet, err = kubernetes.NewForConfig(config)
    if err != nil {
        return nil, err
    }
    return clientSet, nil
}

2.2 k8s服务相关代码

internal/app下添加k8s目录(放置该微服务处理逻辑的一些代码),在下边创建 nodes.go文件(放置node操作相关的代码,我们这里写一个获取nodeList作为示例)。

package service

import (
    "context"
    "crow-han/internal/conf"
    coreV1 "k8s.io/api/core/v1"
    metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func GetNodeList() (nodeList *coreV1.NodeList, err error) {
    nodeList, err = conf.K8sClientSet.CoreV1().Nodes().List(context.TODO(), metaV1.ListOptions{})
    if err != nil {
        return nodeList, err
    }
    return nodeList, nil
}

2.3 proto

2.3.1 创建proto文件

syntax = "proto3";

package k8s;

option go_package = "./proto/k8s;k8s";

service K8s {
  rpc GetNodeList(GetNodeListRequest) returns (GetNodeListResponse) {}
}

message GetNodeListRequest {
}

message GetNodeListResponse {
   string NodeList = 1;
}

GetNodeListResponse这个是微服务返回给gateway的返回值,GetNodeList() 返回是*coreV1.NodeList,通常我们可以转换成proto的格式。但是因为这个node返回值比较复杂,所以这里我返回一个字串(json)然后在gateway再解析回来。

2.3.2 编译proto

 protoc --proto_path=. --micro_out=. --go_out=:. proto/k8s/k8s.proto

2.4 handler

internal/app/k8s目录下创建 /handler目录,下边创建 nodes.go 文件

package handler

import (
    "context"
    "crow-han/internal/app/k8s/service"
    pb "crow-han/proto/k8s"
    "encoding/json"
    "github.com/toolkits/pkg/logger"
)

type Nodes struct{}

func (e *Nodes) GetNodeList(ctx context.Context, req *pb.GetNodeListRequest, rsp *pb.GetNodeListResponse) error {
    logger.Infof("Received K8s.GetNodeList request: %v", req)

    nodeList, err := service.GetNodeList()
    if err != nil {
        logger.Error(err)
        return err
    }

    output, err := json.Marshal(&nodeList)
    if err != nil {
        logger.Error(err)
    }
    rsp.NodeList = string(output)

    return nil
}

2.5 k8s的main函数

在cmd目录下创建k8s目录,目录下创建main.go文件,内容如下

package k8s

import (
    "crow-han/internal/app/k8s/handler"
    "crow-han/internal/cache"
    "crow-han/internal/conf"
    pb "crow-han/proto/k8s"
    "fmt"
    "github.com/go-micro/plugins/v4/registry/consul"
    "github.com/kelseyhightower/envconfig"
    "go-micro.dev/v4/registry"

    "go-micro.dev/v4"
    "go-micro.dev/v4/logger"
)

func init() {
    //初始化变量
    err := envconfig.Process("crow", &conf.MyEnvs)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%+v\n", &conf.MyEnvs)

    //初始化日志
    conf.LoggerInit()
    logger.Info("logger init")
    //mysql初始化
    var tx conf.MyConnect
    tx.ConnectMysql()

    //初始化redis
    //redis初始化
    conf.RedisConnect()
    cache.CheckRides()

    //初始化k8s
    conf.K8sClientSet, err = conf.ConnectK8s()
    if err != nil {
        fmt.Println(err)
    }
}

var (
    service = "k8s"
    version = "latest"
)

func main() {
    // Create service
    srv := micro.NewService()

    consulRegis := consul.NewRegistry(func(options *registry.Options) {
        options.Addrs = []string{
            conf.MyEnvs.ConsulAddr,
        }
    })

    srv.Init(
        micro.Name(service),
        micro.Version(version),
        micro.Registry(consulRegis),
    )

    // Register handler
    if err := pb.RegisterK8SHandler(srv.Server(), new(handler.Nodes)); err != nil {
        logger.Fatal(err)
    }

    if err := srv.Run(); err != nil {
        logger.Fatal(err)
    }
}

3. gateway调用

3.1 调用微服务

internal/app/gate-way/service目录下创建k8s_nodes.go文件,内容如下:

package service

import (
    "context"
    k8sProto "crow-han/proto/k8s"
    "encoding/json"
    "github.com/gin-gonic/gin"
    "github.com/toolkits/pkg/logger"
    coreV1 "k8s.io/api/core/v1"
)

func GetNodeList(c *gin.Context) {

    //调用k8s
    userSrv := k8sProto.NewK8SService("k8s", srv.Client())
    respSr, err := userSrv.GetNodeList(context.Background(), &k8sProto.GetNodeListRequest{})
    logger.Infof("%+v", respSr)
    if err != nil {
        logger.Error(err)
        SetErr(c, 500, err, err.Error())
        return
    }
    //将结果转换为原结构体
    var resp *coreV1.NodeList
    json.Unmarshal([]byte(respSr.NodeList), &resp)
    
    SetOK(c, resp)
}

3.2 router

internal/app/gate-way/service/router.go文件中添加一条路由规则

func ServerRouter() {
    ……
    groupV1 := r.Group("/api/v1")
    {
      ……
      groupV1.GET("/k8s/node/list", user(), GetNodeList) //添加这条路由
    }

说明:需要user验证的加上验证方法 user(),不想验证可以不加。

4. 添加文档 swagger

// GetNodeList 查看node列表
// @Summary 查看node列表
// @Description 查看node列表
// @Tags Node
// @Success 200 {object} response.Response{data=v1.NodeList} "{"requestId": "string","code": 200,"msg": "ok","data": [...]}"
// @Failure 500 {object} response.Response{msg=string} "{"requestId": "string","code": 500,"msg": "string","status": "error","data": null}"
// @Router /api/v1/k8s/node/list [get]
// @Security Bearer
func GetNodeList(c *gin.Context) {
  ……
}

详细方法见另一篇博文《GO语言gin框架实战-03-swagger和接口文档》

cd internal/app/gate-way/service
swag init --parseDependency --parseInternal --parseDepth 2 -g .\router.go

5. 调试

5.1 启动服务

5.2 swagger接口测试

输出结果


image.png image.png

输出如下:


image.png
上一篇下一篇

猜你喜欢

热点阅读