微服务实践之分布式定时任务

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 微服务实践之分布式定时任务

承接上篇:上篇文章讲到改造 go-zero 生成的 app module 中的 gateway & RPC 。本篇讲讲如何接入 异步任务 以及 log的使用

Delay Job

日常任务开放中,我们会有很多异步、批量、定时、延迟任务要处理,go-zero中有 go-queue,推荐使用 go-queue 去处理,go-queue 本身也是基于 go-zero 开发的,其本身是有两种模式:

  • dq: 依赖于beanstalkd ,分布式,可存储,延迟、定时设置,关机重启可以重新执行,消息不会丢,使用非常简单,go-queue中使用了redis setnx保证了每个消息只被消费一次,使用场景主要是用来做日常任务使用
  • kq:依赖于 kafka ,这个就不多介绍啦,大名鼎鼎的 kafka ,使用场景主要是做日志用

我们主要说一下dq,kq使用也一样的,只是依赖底层不同,如果没使用过beanstalkd,没接触过beanstalkd的可以先google一下,使用起来还是挺容易的。

我在jobs下使用goctl新建了一个message-job.api服务

info(
 title: //消息任务
 desc: // 消息任务
 author: "Mikael"
 email: "13247629622@163.com"
)
type BatchSendMessageReq {}
type BatchSendMessageResp {}
service message-job-api {
 @handler batchSendMessageHandler // 批量发送短信
 post batchSendMessage(BatchSendMessageReq) returns(BatchSendMessageResp)
}

因为不需要使用路由,所以handler下的routes.go被我删除了,在handler下新建了一个jobRun.go,内容如下:

package handler
import (
 "fishtwo/lib/xgo"
 "fishtwo/app/jobs/message/internal/svc"
)
/**
* @Description 启动job
* @Author Mikael
* @Date 2021/1/18 12:05
* @Version 1.0
**/
func JobRun(serverCtx *svc.ServiceContext)  {
 xgo.Go(func() {
  batchSendMessageHandler(serverCtx)
    //...many job
 })
}

其实xgo.Go就是 go batchSendMessageHandler(serverCtx) ,封装了一下go携程,防止野生goroutine panic

然后修改一下启动文件message-job.go

package main
import (
   "flag"
   "fmt"
   "fishtwo/app/jobs/message/internal/config"
   "fishtwo/app/jobs/message/internal/handler"
   "fishtwo/app/jobs/message/internal/svc"
   "github.com/tal-tech/go-zero/core/conf"
   "github.com/tal-tech/go-zero/rest"
)
var configFile = flag.String("f", "etc/message-job-api.yaml", "the config file")
func main() {
   flag.Parse()
   var c config.Config
   conf.MustLoad(*configFile, &c)
   ctx := svc.NewServiceContext(c)
   server := rest.MustNewServer(c.RestConf)
   defer server.Stop()
   handler.JobRun(ctx)
   fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
   server.Start()
}

主要是handler.RegisterHandlers(server, ctx) 修改为handler.JobRun(ctx)

接下来,我们就可以引入dq了,首先在etc/xxx.yaml下添加dqConf

.....
DqConf:
  Beanstalks:
    - Endpoint: 127.0.0.1:7771
      Tube: tube1
    - Endpoint: 127.0.0.1:7772
      Tube: tube2
  Redis:
    Host: 127.0.0.1:6379
    Type: node

我这里本地用不同端口,模拟开了2个节点,7771、7772

在internal/config/config.go添加配置解析对象

type Config struct {
 ....
 DqConf dq.DqConf
}

修改handler/batchsendmessagehandler.go

package handler
import (
 "context"
 "fishtwo/app/jobs/message/internal/logic"
 "fishtwo/app/jobs/message/internal/svc"
 "github.com/tal-tech/go-zero/core/logx"
)
func batchSendMessageHandler(ctx *svc.ServiceContext){
 rootCxt:= context.Background()
 l := logic.NewBatchSendMessageLogic(context.Background(), ctx)
 err := l.BatchSendMessage()
 if err != nil{
  logx.WithContext(rootCxt).Error("【JOB-ERR】 : %+v ",err)
 }
}

修改logic下batchsendmessagelogic.go,写我们的consumer消费逻辑

package logic
import (
   "context"
   "fishtwo/app/jobs/message/internal/svc"
   "fmt"
   "github.com/tal-tech/go-zero/core/logx"
)
type BatchSendMessageLogic struct {
   logx.Logger
   ctx    context.Context
   svcCtx *svc.ServiceContext
}
func NewBatchSendMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) BatchSendMessageLogic {
   return BatchSendMessageLogic{
    Logger: logx.WithContext(ctx),
    ctx:    ctx,
    svcCtx: svcCtx,
   }
}
func (l *BatchSendMessageLogic) BatchSendMessage() error {
   fmt.Println("job BatchSendMessage start")
   l.svcCtx.Consumer.Consume(func(body []byte) {
    fmt.Printf("job BatchSendMessage %s \n" + string(body))
   })
   fmt.Printf("job BatchSendMessage finish \n")
   return nil
}

这样就大功告成了,启动message-job.go就ok课

go run message-job.go

之后我们就可以在业务代码中向dq添加任务,它就可以自动消费了

producer.Delay 向dq中投递5个延迟任务:

producer := dq.NewProducer([]dq.Beanstalk{
  {
   Endpoint: "localhost:7771",
   Tube:     "tube1",
  },
  {
   Endpoint: "localhost:7772",
   Tube:     "tube2",
  },
 })
 for i := 1000; i < 1005; i++ {
  _, err := producer.Delay([]byte(strconv.Itoa(i)), time.Second * 1)
  if err != nil {
   fmt.Println(err)
  }
 }

producer.At 可以指定某个时间执行,非常好用,感兴趣的朋友自己可以研究下。

错误日志

在前面说到gateway改造时候,如果眼神好的童鞋,在上面的httpresult.go中已经看到了log的身影:

我们在来看下rpc中怎么处理的

是的,我在每个rpc启动的main中加入了grpc拦截器 https://www.yuque.com/tal-tech/go-zero/ttzlo1,那让我们看看grpc拦截器里面做了什么

然后我代码里面使用github/pkg/errors这个包去处理错误的,这个包还是很好用的

所以呢:

我们在 grpc 中打印日志 logx.WithContext(ctx).Errorf("[RPC-SRV-ERR] %+v",err)

api 中打印日志 logx.WithContext(r.Context()).Error("[GATEWAY-SRV-ERR] : %+v ",err)

go-zero 中打印日志,使用logx.WithContext会把trace-id带入,这样一个请求下来,比如

user-api --> user-srv --> message-srv

那如果 messsage-srv 出错,他们三个是同一个 trace-id ,是不是就可以在elk通过输入这个trace-id一次性搜索出来这条请求报错堆栈信息呢?当然你也可以接入 jaeger、zipkin、skywalking 等,这个我暂时还没接入。

框架地址

https://github.com/tal-tech/go-zero

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
8天前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
8天前
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
15天前
|
运维 负载均衡 监控
深入探索微服务架构的核心要素与实践策略
在当今软件开发领域,微服务架构已成为构建灵活、可扩展企业级应用的首选模式。本文旨在剖析微服务架构的设计理念,通过实例阐述其核心组件如服务注册与发现、配置管理、熔断机制等如何协同工作,以提升系统的敏捷性和维护性。同时,探讨了在实践中应对分布式系统复杂性的最佳策略,包括负载均衡、服务监控和日志聚合等关键技术,旨在为后端开发者提供一套完整的微服务实施指南。
32 1
|
7天前
|
运维 Kubernetes 调度
阿里云容器服务 ACK One 分布式云容器企业落地实践
3年前的云栖大会,我们发布分布式云容器平台ACK One,随着3年的发展,很高兴看到ACK One在混合云,分布式云领域帮助到越来越多的客户,今天给大家汇报下ACK One 3年来的发展演进,以及如何帮助客户解决分布式领域多云多集群管理的挑战。
阿里云容器服务 ACK One 分布式云容器企业落地实践
|
3天前
|
Cloud Native 持续交付 微服务
云原生时代的微服务架构实践
【9月更文挑战第30天】随着云计算技术的不断进步,云原生已经成为现代软件开发的重要趋势。本文将通过深入浅出的方式,介绍如何在云原生环境下设计并实施微服务架构,以及如何利用容器化技术和自动化工具来提升服务的可维护性和可扩展性。我们将一起探讨微服务架构的核心原则、优势,以及在云平台中部署和管理微服务的最佳实践。无论你是初学者还是有经验的开发者,这篇文章都将成为你探索云原生和微服务世界的一盏明灯。
|
6天前
|
监控 Cloud Native 持续交付
云原生时代的微服务架构设计原则与实践
【9月更文挑战第27天】本文深入探讨了在云原生环境下,如何高效地实施微服务架构。通过分析微服务的基本概念、设计原则和关键技术,结合实际案例,指导读者理解并应用微服务架构于云计算项目之中。文章旨在为软件开发者和架构师提供一条清晰的路径,以实现更加灵活、可扩展且易于维护的系统。
|
9天前
|
设计模式 Cloud Native API
云原生时代的微服务架构实践
【9月更文挑战第23天】在这篇文章中,我们将深入探讨云原生环境下的微服务架构设计原则、优势以及实施策略。文章不仅涉及理论概念,还结合具体的代码示例,帮助读者理解如何在实际项目中应用微服务架构。通过阅读本文,你将获得构建、部署和管理微服务的实用知识,为你的云原生项目奠定坚实的基础。
|
7天前
|
存储 运维 负载均衡
后端开发中的微服务架构实践与思考
本文旨在探讨后端开发中微服务架构的应用及其带来的优势与挑战。通过分析实际案例,揭示如何有效地实施微服务架构以提高系统的可维护性和扩展性。同时,文章也讨论了在采用微服务过程中需要注意的问题和解决方案。
|
7天前
|
运维 持续交付 API
深入理解并实践微服务架构:从理论到实战
深入理解并实践微服务架构:从理论到实战
28 3
|
11天前
|
消息中间件 缓存 NoSQL
构建高效后端服务:微服务架构的深度实践
本文旨在探讨如何通过采用微服务架构来构建高效的后端服务。我们将深入分析微服务的基本概念、设计原则以及在实际项目中的应用案例,揭示其在提升系统可维护性、扩展性和灵活性方面的优势。同时,本文还将讨论在实施微服务过程中可能遇到的挑战,如服务治理、分布式事务和数据一致性等问题,并分享相应的解决策略和最佳实践。通过阅读本文,读者将能够理解微服务架构的核心价值,并具备将其应用于实际项目的能力。 ##
下一篇
无影云桌面