使用go-zero微服务框架实现云监控后台(二.远程指令下发)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 使用go-zero微服务框架实现云监控后台(二.远程指令下发)

这是逐步实现该方案的第二篇文章。


后台操控指令远程下发的实现


这里记录下如何实现后台命令下发到终端设备上,触发终端上送日志文件,实现运维人员远程可以足不出户,采集设备日志的功能。


实现原理:


终端设备上运行的监控服务会定时10分钟上送一次设备状态。在终端设备请求上送状态时,把后台设置的操作命令响应给它。虽然这样后台的操作指令,只能10分钟后被下发,实时性不够高,然而对采集日志而言,这也不影响什么。


实现方法:


使用redis,封装提供微服务接口,传参数设备号和操控命令字和过期时间。终端设备每10分钟状态上报时,先查询redis缓存是否存在有该设备的控制命令,有则在响应报文中应答给终端。


type CmdSetReq struct {
  Sn     string `json:"sn"`     //设备唯一号
  Cmd    int    `json:"cmd"`    //控制命令字
  Expire int    `json:"expire"` //失效时间(分钟)
}
type CmdSetResp struct {
  Code int    `json:"code"`
  Msg  string `json:"msg"`
}


func (l *CmdSetLogic) CmdSet(in *status.CmdSetReq) (*status.CmdSetResp, error) {
  // todo: add your logic here and delete this line
  err := l.svcCtx.Cache.SetWithExpire(shared.CacheSnPrefix+in.Sn, in.Cmd, 60*time.Duration(in.Expire)*time.Second)
  if err != nil && err == shared.ErrNotFound {
    return &status.CmdSetResp{Code: 1, Msg: "cmd set Cache error"}, nil
  }
  return &status.CmdSetResp{Code: 0, Msg: "ok"}, nil
}


接上篇文章,在monitor项目代码根目录下,创建shared目录,里面放置公共的配置信息,如缓存KEY的前缀和错误码定义信息:


package shared
import "errors"
var ErrNotFound = errors.New("cache not found")
var CacheSnPrefix = "cache::cmd:sn:"


gozero中使用缓存Cache模块。使用方法:


monitor\rpc\status\internal\svc路径下的servicecontext.go中,增加Cache字段,并在NewServiceContext中完成初始化:


package svc
import "monitor/shared"
import "monitor/rpc/status/internal/config"
//手动代码
import "monitor/rpc/status/model"
import "github.com/tal-tech/go-zero/core/stores/sqlx"
import "github.com/tal-tech/go-zero/core/stores/cache"
import "github.com/tal-tech/go-zero/core/syncx"
type ServiceContext struct {
  Config config.Config
  Model  model.TbStatusModel // 手动代码
  Cache  cache.Cache //增加使用redis缓存
}
func NewServiceContext(c config.Config) *ServiceContext {
  //缓存
  ca := cache.New(c.Cache, syncx.NewSharedCalls(), cache.NewStat("cmdset"), shared.ErrNotFound)
  return &ServiceContext{
    Config: c,
    Model:  model.NewTbStatusModel(sqlx.NewMysql(c.DataSource), c.Cache), // 手动代码
    Cache:  ca,
  }
}


在monitor\rpc\status\internal\logic的cmdsetlogic.go中,增加对缓存的设置。


package logic
import (
  "context"
  "monitor/rpc/status/internal/svc"
  "monitor/rpc/status/status"
  "monitor/shared"
  "time"
  "github.com/tal-tech/go-zero/core/logx"
)
type CmdSetLogic struct {
  ctx    context.Context
  svcCtx *svc.ServiceContext
  logx.Logger
}
func NewCmdSetLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CmdSetLogic {
  return &CmdSetLogic{
    ctx:    ctx,
    svcCtx: svcCtx,
    Logger: logx.WithContext(ctx),
  }
}
func (l *CmdSetLogic) CmdSet(in *status.CmdSetReq) (*status.CmdSetResp, error) {
  // todo: add your logic here and delete this line
  err := l.svcCtx.Cache.SetWithExpire(shared.CacheSnPrefix+in.Sn, in.Cmd, 60*time.Duration(in.Expire)*time.Second)
  if err != nil && err == shared.ErrNotFound {
    return &status.CmdSetResp{Code: 1, Msg: "cmd set Cache error"}, nil
  }
  return &status.CmdSetResp{Code: 0, Msg: "ok"}, nil
}


然后在接收到终端上送上来的状态时,先读取一下缓存,看是否有该终端的控制命令。(读redis很快,耗时可忽略)


func (l *StatusUploadLogic) StatusUpload(in *status.StatusUploadReq) (*status.StatusUploadResp, error) {
  // todo: add your logic here and delete this line
  //检查 缓存中是否有值
  var cmd int32 = 0
  err := l.svcCtx.Cache.Get(shared.CacheSnPrefix+in.Sn, &cmd)
  if err != nil && err == shared.ErrNotFound {
    fmt.Println(err)
  } else {
    fmt.Println("GetCache ok:", cmd)
    l.svcCtx.Cache.Del(shared.CacheSnPrefix + in.Sn)
  }
  // 手动代码开始,插入记录到数据库
  t, _ := time.Parse("2006-01-02", in.Ndate)
  _, err = l.model.Insert(model.TbStatus{
    Sn:    sql.NullString{in.Sn, true},
    Posno: sql.NullString{in.Posno, true},
    City:  sql.NullString{in.City, true},
    Tyid:  sql.NullString{in.Tyid, true},
    Ndate: sql.NullTime{t, true},
    Ntime: sql.NullString{in.Ntime, true},
    Cmd:   sql.NullInt64{int64(cmd), true},
  })
  if err != nil {
    return nil, err
  }
  return &status.StatusUploadResp{Code: 0, Msg: "server resp,insert record ok", Cmd: cmd}, nil
}


Over,就这么简单,实现了指令的下发。


注意本机测试时,调整下rest和rpc服务的接口超时时间。默认的网关rest接口超时是3秒,默认rpc服务接口超时时间是2秒。有点儿短,在etc下的yaml文件中调整下即可。


增加timeout:6000的配置改为6秒超时。



相关实践学习
RocketMQ监控/告警一站式搭建应用
RocketMQ监控/告警一站式搭建演示
相关文章
|
1月前
|
运维 监控 Go
Go语言微服务实战与最佳实践
【2月更文挑战第14天】本文将深入探讨使用Go语言进行微服务实战中的最佳实践,包括服务拆分、API设计、并发处理、错误处理、服务治理与监控等方面。通过实际案例和详细步骤,我们将分享如何在Go语言环境中构建高效、稳定、可扩展的微服务系统。
|
6月前
|
负载均衡 中间件 Go
Golang 微服务工具包 Go kit
Golang 微服务工具包 Go kit
43 0
|
6月前
|
SQL 关系型数据库 Go
Go语言微服务框架 - 12.ORM层的自动抽象与自定义方法的扩展
随着接口参数校验功能的完善,我们能快速定位到接口层面的参数问题;而应用服务的分层代码,也可以通过log的trace-id发现常见的业务逻辑问题。 但在最底层与数据库的操作,也就是对GORM的使用,经常会因为我们不了解ORM的一些细节,导致对数据的CRUD失败,或者没有达到预期效果。这时,我们希望能在ORM这一层也有一个通用的解决方案,来加速问题的排查。
45 0
|
8天前
|
Kubernetes Cloud Native Go
《Go 简易速速上手小册》第10章:微服务与云原生应用(2024 最新版)(下)
《Go 简易速速上手小册》第10章:微服务与云原生应用(2024 最新版)
43 0
|
8天前
|
Cloud Native 算法 Go
《Go 简易速速上手小册》第10章:微服务与云原生应用(2024 最新版)(上)
《Go 简易速速上手小册》第10章:微服务与云原生应用(2024 最新版)
32 0
|
4月前
|
Dubbo 应用服务中间件 API
Go语言微服务框架重磅升级:dubbo-go v3.2.0 -alpha 版本预览
随着 Dubbo3 在云原生微服务方向的快速发展,Dubbo 的 go 语言实现迎来了 Dubbo3 版本以来最全面、最大幅度的一次升级,这次升级是全方位的,涉及 API、协议、流量管控、可观测能力等。
|
1月前
|
运维 监控 负载均衡
Go语言中微服务架构设计与原则
【2月更文挑战第14天】本文将深入探讨在Go语言环境下,微服务架构的设计原则和实践。我们将讨论如何根据微服务架构的核心概念,如服务拆分、独立部署、容错处理、服务治理等,来构建一个稳定、可扩展、可维护的Go语言微服务系统。
|
1月前
|
运维 Go 开发者
Go语言基础及其在微服务中的应用
【2月更文挑战第14天】本文旨在探讨Go语言的核心特性及其在构建微服务架构中的实际应用。我们将首先简要介绍Go语言的基本概念与特点,然后详细分析Go语言在构建高性能、高可用微服务中的优势,并通过实例展示如何使用Go语言实现微服务的基础组件和通信机制。
|
6月前
|
Go 微服务
Go 微服务工具包 Go kit 怎么集成 gRPC?
Go 微服务工具包 Go kit 怎么集成 gRPC?
54 0
|
6月前
|
开发框架 Go 微服务
Golang 语言怎么使用 go-micro 和 gin 开发微服务?
Golang 语言怎么使用 go-micro 和 gin 开发微服务?
126 0