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

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
云监控,每月短信1000条
简介: 使用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秒超时。



相关实践学习
基于云监控实现的监控系统
通过阿里云云监控功能给非阿里云主机安装监控插件,从而实现对非阿里云主机的各项指标进行监控和管理,在配置报警规则和报警人的情况下,能对特定的场景做出报警反应通知到报警人的手机上。
相关文章
|
17天前
|
Dubbo Java 应用服务中间件
微服务框架Dubbo环境部署实战
微服务框架Dubbo环境部署的实战指南,涵盖了Dubbo的概述、服务部署、以及Dubbo web管理页面的部署,旨在指导读者如何搭建和使用Dubbo框架。
68 17
微服务框架Dubbo环境部署实战
|
15天前
|
存储 Java Maven
从零到微服务专家:用Micronaut框架轻松构建未来架构
【9月更文挑战第5天】在现代软件开发中,微服务架构因提升应用的可伸缩性和灵活性而广受欢迎。Micronaut 是一个轻量级的 Java 框架,适合构建微服务。本文介绍如何从零开始使用 Micronaut 搭建微服务架构,包括设置开发环境、创建 Maven 项目并添加 Micronaut 依赖,编写主类启动应用,以及添加控制器处理 HTTP 请求。通过示例代码展示如何实现简单的 “Hello, World!” 功能,并介绍如何通过添加更多依赖来扩展应用功能,如数据访问、验证和安全性等。Micronaut 的强大和灵活性使你能够快速构建复杂的微服务系统。
39 5
|
14天前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
43 2
|
15天前
|
Cloud Native 安全 Java
Micronaut对决Spring Boot:谁是微服务领域的王者?揭秘两者优劣,选对框架至关重要!
【9月更文挑战第5天】近年来,微服务架构备受关注,Micronaut和Spring Boot成为热门选择。Micronaut由OCI开发,基于注解的依赖注入,内置多种特性,轻量级且启动迅速;Spring Boot则简化了Spring应用开发,拥有丰富的生态支持。选择框架需考虑项目需求、团队经验、性能要求及社区支持等因素。希望本文能帮助您选择合适的微服务框架,助力您的软件开发项目取得成功!
62 2
|
18天前
|
缓存 安全 Java
如何利用Go语言提升微服务架构的性能
在当今的软件开发中,微服务架构逐渐成为主流选择,它通过将应用程序拆分为多个小服务来提升灵活性和可维护性。然而,如何确保这些微服务高效且稳定地运行是一个关键问题。Go语言,以其高效的并发处理能力和简洁的语法,成为解决这一问题的理想工具。本文将探讨如何通过Go语言优化微服务架构的性能,包括高效的并发编程、内存管理技巧以及如何利用Go生态系统中的工具来提升服务的响应速度和资源利用率。
|
11天前
|
消息中间件 NoSQL Go
PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
【9月更文挑战第7天】在从 PHP 的 ThinkPHP 框架迁移到 Go 的 Gin 框架时,涉及 Redis 延时消息队列的技术实践主要包括:理解延时消息队列概念,其能在特定时间处理消息,适用于定时任务等场景;在 ThinkPHP 中使用 Redis 实现延时队列;在 Gin 中结合 Go 的 Redis 客户端库实现类似功能;Go 具有更高性能和简洁性,适合处理大量消息。迁移过程中需考虑业务需求及系统稳定性。
|
24天前
|
消息中间件 SQL 关系型数据库
go-zero微服务实战系列(十、分布式事务如何实现)
go-zero微服务实战系列(十、分布式事务如何实现)
|
10天前
|
程序员 Go PHP
为什么大部分的 PHP 程序员转不了 Go 语言?
【9月更文挑战第8天】大部分 PHP 程序员难以转向 Go 语言,主要因为:一、编程习惯与思维方式差异,如语法风格和编程范式;二、学习成本高,需掌握新知识体系且面临项目压力;三、职业发展考量,现有技能价值及市场需求不确定性。学习新语言虽有挑战,但对拓宽职业道路至关重要。
40 10
|
Go Apache 应用服务中间件
|
8天前
|
Go API 开发者
深入探讨:使用Go语言构建高性能RESTful API服务
在本文中,我们将探索Go语言在构建高效、可靠的RESTful API服务中的独特优势。通过实际案例分析,我们将展示Go如何通过其并发模型、简洁的语法和内置的http包,成为现代后端服务开发的有力工具。