云溪的 blog
  • Archive
  • Media
  • Search
  • Tags
  • About

go 语言实现轻量级队列事件

最近再开展整合系统的工作,将原有系统中的共用逻辑抽离出来形成一个中台系统,根据业务开展形式的不同,划分出各个子系统。 在开展的过程中,遇到一种情况,在一些场景下子系统需要根据中台系统的一些操作去初始化自身的业务数据。 我们准备用事件( Event ) 的形式来解决这个问题,子系统监听中台系统发布的一些事件,当中台系统进行相关操作时,触发事件通知监听中的子系统。 我们的中台系统 ( main system ) 是用 go 语言开发的,事件的触发是通过队列的形式发送给 event hadle 然后由它去发送事件通知到各个子系统。 在一些其他语言中,队列的消费一般都是启动一个进程来监听处理。而 go 有协程,可以用更轻量的协程来处理队列消费,这样以来有一个直接的好处就是服务启动了,队列的消费者就跟着启动了,不需要单独维护一个进程的启停。 当然要实现上述能力,有几个问题需要解决: 协程消费者如果崩溃了,不能影响主进程的运行 协程异常要能重新拉起一个新的消费者,保证协程消费者能一直运行。 崩溃隔离 消费者有自己的逻辑,在逻辑处理中有可能会出现 panic,我们需要消费者的 panic 限制在协程里,以避免协程崩溃影响主进程。 Go 有 recover 机制,可以让你捕获 panic 并且限制 panic 不在向上蔓延。代码如下: go (func() { defer func() { if err := recover(); err != nil { fmt.Println("捕获到 panic:", err) return } }() err := EventHandle() if err != nil { Logger.Error("event 处理监听失败", err) } })() 消费者协程保活 消费者业务逻辑在协程里,可能在一些场景(panic 或其他不可知情况)下意外退出,我们需要保证能够重新拉起消费者协程,从而保证整个事件逻辑的闭环。 在这里我们用管道实现一个心跳机制,消费之定时发送心跳到主进程,如果超过一段时间没有发送心跳主进程会认为消费之已经出现异常,会重新拉起一个协程消费者。 主进程监听心跳代码如下: func monitorHeartbeat(heartbeat chan bool) { // 设置心跳包的超时时间 timeoutDuration := 3 * time.Second timer := time.NewTimer(timeoutDuration) for { select { case <-heartbeat: // 接收到心跳包,重置定时器 timer.Reset(timeoutDuration) case <-timer.C: // 超时,重新启动协程 fmt.Println("心跳超时,重新启动协程") go startEvent(heartbeat) timer.Reset(timeoutDuration) } } } 协程发送心跳包代码如下: ...

January 31, 2024 · 1 min · 云溪

laravel docker-php 运行环境搭建好了

Laravel 是 PHP 里非常重要的一个框架,对于一个 PHPer 来讲,就算你没有用过 Laravel 也一定听说过它。 同事用 Laravel 开发了一个项目,需要部署一个测试环境,由于服务器的 PHP 环境不满足他项目的要求,所以需要多加一个 PHP 环境。 为了减少对原有系统的影响和更快的安装,我们决定用 Docker 来部署新项目的 PHP 环境。 本以为整个流程会无比的丝滑,但是在推进的过程中遇到了一些问题,也就有了这篇文章记录一下当时的经历,同时也为后续遇到类似问题的同仁提供解决思路。 整个部署方案如下: Dockerfile 很快就编写好了,本地测试能够成功的构建出 Docker Image。到此一切都很顺利,后续只需要把 Dockerfile 上传到服务器在服务器上把镜像构建出来,用 Nginx 解析一下就大功告成了。 当把代码上传到服务器,开始构建 Docker Image 时,问题出现了。在执行 apt update 的时候出现了下面的错误。 The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY 6ED0E7B82643E131 本地构建好好的,怎么上线就出现问题了呢?简单的用搜索引擎搜索了一下,找了几篇带有"亲测"字样的文章进行验证,却都失败了。 后来我想既然这样问问 GPT 吧,看看它有没有什么高见。GPT 告诉我时因为服务器证书问题导致的,这里我就产生了一个疑问,我构建 Dcoker Image 执行 apt update 应该是在 Docker 环境里执行的呀,为什么会跟服务器证书有关系呢? 于是我继续追问,它给出了自己的解释,让我开始质疑自己了。 ...

January 22, 2024 · 1 min · 云溪

如何构建 php-fpm 镜像

在实际的项目部署中,我们有时候会遇到在一个服务器上部署多个 php 环境的情况。遇到这种情况,我们可以在同一物理机上装多个 php-fpm 监听不同端口,Nginx 根据不同的 Vhost 去找不同的 php-fpm 解析。 上述方法虽然可以,但是在项目管理上并不是很友好,比如我需要在某个项目执行 PHP 脚本,那还需要写 /path/php script.php 这样的话就需要每个维护项目的人都十分清楚,哪个项目应该用哪个版本的 PHP 去执行相应的脚本。 其次,如果某天需要把某个项目迁移到其他服务器了,我们还需要在新机器上安装 PHP 环境。 如果用 docker 进行部署,就不会有上面的问题,我们只需要写一次 Dockfile 可以在任何服务器上构建出相同的 php-fpm 环境,从而让迁移更简单,如果需要执行脚本,只需要进入对应的容器,直接执行 php script.php 即可。 php-fpm 官方镜像介绍 在 [php Tags | Docker Hub](https://hub.docker.com/_/php/tags 找到你所需的基础镜像的 tag 扩展安装 Docker PHP 安装有三种方式 Core Extensions: FROM php:8.2-fpm RUN apt-get update && apt-get install -y \ libfreetype-dev \ libjpeg62-turbo-dev \ libpng-dev \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) gd PECL extensions : ...

November 17, 2023 · 2 min · 云溪

Dockerfile 介绍

Dockerfile 是用于构建镜像的脚本文件。在某些情况下,需要在基础镜像上加装一些软件,就需要使用 Dockerfile 来构建出自己所需的镜像。 指令介绍 指定基础镜像 ( FROM ) # 不指定版本则默认拉去 latest FROM nginx # 指定版本 FROM nginx:1.25.3 执行命令 ( RUN ) FROM nginx Run apt-get update \ && apt-get install -y --no-install-recommends git vim libpng-dev libjpeg-dev libfreetype6-dev 声明容器运行时监听的端口号( EXPOSE ) FROM nginx Run apt-get update \ && apt-get install -y --no-install-recommends git vim libpng-dev libjpeg-dev libfreetype6-dev EXPOSE 80 设置工作目录 ( WORKDIR ) FROM nginx Run apt-get update \ && apt-get install -y --no-install-recommends git vim libpng-dev libjpeg-dev libfreetype6-dev EXPOSE 80 WORKDIR /var/www 复制文件到容器目录 ( COPY ) FROM nginx Run apt-get update \ && apt-get install -y --no-install-recommends git vim libpng-dev libjpeg-dev libfreetype6-dev WORKDIR /www COPY . /www EXPOSE 80 入口点 ( ENTRYPOINT ) ENTRYPOINT 和 CMD 两个指令十分相似,都是通过指定容器运行的脚本/命令。具体区别可以查看扩展阅读。 ...

November 17, 2023 · 2 min · 云溪

docker 入门介绍

Docker 可以理解为一个轻量级虚拟机,你可以在一台物理机上,装 N 个系统,每个系统部署不同的服务。 Docker 有几个非常重要的概念:镜像、仓库、容器。 镜像:可以理解为操作系统的系统盘,用于给容器安装系统用的,你也可以基于别人的镜像创建自己的镜像。 仓库:用于存储镜像的仓库 容器:相当于虚拟出来的一台台主机,他有存储、网络、系统等关键要素。你可以在容器里部署任何你想要部署的服务。 镜像操作 你可以创建 ( docker build )、删除 ( docker rmi )、下载 ( docker pull ) 镜像 设置镜像源 Docker 官方镜像仓库,在国内下载比较慢,可以通过国内的镜像源来加速镜像下载。本文介绍 Windows 通过 Docker Desktop 换源,如果你是其他系统,可以自行搜索。 复制下面信息到 Docker Desktop 设置 "registry-mirrors": [ "https://hub-mirror.c.163.com", "https://mirror.baidubce.com" ] 创建镜像 ( docker build ) 前提是要有构建镜像所需的 Dockerfile,关于 Dockerfile 后面会有专门的文章进行讲解。 docker build -t image_name . 下载镜像 ( docker pull ) 这里就会通过仓库下载镜像到本机。 docker pull ubuntu 删除镜像 ( docker rmi ) docker rmi image_name 容器操作 容器操作分为:启动( docker run ),停止 ( docker stop ),删除 ( docker del ),执行 ( exec )、查看日志(docker logs)。 ...

November 17, 2023 · 2 min · 云溪
« Prev  Next  »
© 2025 云溪的 blog