云效+mqtt实现本地构建和远程自动发版

之前写过一篇jenkins+mqtt实现本地构建和远程自动发版_jenkins远程调用和本地调用-CSDN博客

由于本地搭建jenkins实在太费机器了,这次改用云效搭建。不过云效并没有直接发送mqtt的方法,需要编写中转接口。

中转接口采用go-gin框架实现,代码如下

main.go

package mainimport ("encoding/json""fmt"mqtt "github.com/eclipse/paho.mqtt.golang""github.com/gin-gonic/gin""os""time"
)func main() {router := gin.Default()router.POST("/publish/notify", func(c *gin.Context) {obj := struct {App  string `json:"app"`Link string `json:"link"`}{}err := c.BindJSON(&obj)if err != nil {fmt.Println(err)} else {fmt.Println(obj)}//把读取到的json透传发送到mqtt服务器Publish(obj.App, obj.Link, "/publish/notify")c.JSON(200, gin.H{"msg": "this is a post msg",})})router.POST("/publish/notifyProd", func(c *gin.Context) {obj := struct {App  string `json:"app"`Link string `json:"link"`}{}err := c.BindJSON(&obj)if err != nil {fmt.Println(err)} else {fmt.Println(obj)}//把读取到的json透传发送到mqtt服务器Publish(obj.App, obj.Link, "/publish/notifyProd")c.JSON(200, gin.H{"msg": "this is a post msg",})})// 默认端口是8080,也可以指定端口 r.Run(":80")router.Run(":80")
}func Publish(app string, link string, topic string) {broker := "tcp://broker.emqx.io:1883"clientId := "go-mqtt-client"opts := mqtt.NewClientOptions().AddBroker(broker).SetClientID(clientId)opts.SetUsername("") // 设置用户名opts.SetPassword("") // 设置密码opts.SetCleanSession(true)opts.SetKeepAlive(2 * time.Second)opts.SetDefaultPublishHandler(f)opts.OnConnect = func(c mqtt.Client) {fmt.Println("Connected")}opts.OnConnectionLost = func(c mqtt.Client, e error) {fmt.Println("Disconnected")}c := mqtt.NewClient(opts)if token := c.Connect(); token.Wait() && token.Error() != nil {panic(token.Error())}// 构建JSON消息message := map[string]string{"app":  app,"link": link,}jsonMessage, err := json.Marshal(message)if err != nil {fmt.Println("Error marshaling JSON:", err)os.Exit(1)}// 发布消息if token := c.Publish(topic, 0, false, jsonMessage); token.Wait() && token.Error() != nil {fmt.Println(token.Error())os.Exit(1)}// 等待一段时间以确保消息被发送time.Sleep(2 * time.Second)c.Disconnect(250)
}
func f(client mqtt.Client, msg mqtt.Message) {fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic())
}

云效调用

在构建制品后选择执行命令

命令内容填写

# input your command here
# 构造 JSON 参数
json_data=$(jq -n --arg app "myapp" --arg link "${artifacts}" '{app: $app, link: $link}')# 打印 JSON 参数(可选)
echo "$json_data"# 发送 HTTP POST 请求
curl -X POST "http://transfer.example.com/publish/notify" \-H "Content-Type: application/json" \-d "$json_data"

将myapp替换成你想改的app名,transfer.example.com改成你部署在公网的中转接口域名或ip

上面用到了${artifacts}参数,需要在云效中添加artifacts=制品名称xxx

之后在部署的服务器上部署发布的客户端

客户端的逻辑跟上一篇文章类似,代码如下

main.go

package mainimport ("bytes""fmt""io/ioutil""log""os""os/exec""os/signal""strings""time""github.com/bitly/go-simplejson"mqtt "github.com/eclipse/paho.mqtt.golang"
)// 全局变量,存储程序启动时的当前工作目录
var baseDir stringvar messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {go handleMessage(client, msg)
}var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) {fmt.Println("Connected")
}var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) {fmt.Printf("Connect lost: %v", err)
}func main() {// 获取程序启动时的当前工作目录var err errorbaseDir, err = os.Getwd()if err != nil {log.Fatalf("获取当前工作目录失败: %v", err)}fmt.Println("程序启动时的当前工作目录:", baseDir)//合建chanc := make(chan os.Signal)//监听指定信号 ctrl+c killsignal.Notify(c, os.Interrupt, os.Kill)//阻塞直到有信号传入fmt.Println("启动")//执行具体方法initmqtt()//阻塞直至有信号传入s := <-cfmt.Println("退出信号", s)
}func initmqtt() {var broker = "broker.emqx.io"var port = 1883opts := mqtt.NewClientOptions()opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port))opts.SetDefaultPublishHandler(messagePubHandler)opts.OnConnect = connectHandleropts.OnConnectionLost = connectLostHandlerclient := mqtt.NewClient(opts)if token := client.Connect(); token.Wait() && token.Error() != nil {panic(token.Error())}sub(client)
}func sub(client mqtt.Client) {topic := "/publish/notify"token := client.Subscribe(topic, 1, nil)token.Wait()fmt.Printf("Subscribed to topic: %s\n", topic)
}// readFile 使用ioutil.ReadFile 直接从文件读取到 []byte中
func readFile(fileName string) string {f, err := ioutil.ReadFile(fileName)if err != nil {log.Printf("读取文件失败:%#v", err)return ""}return string(f)
}// 读取消息的发布模块名和链接
func readIssueModule(issuejson string) (string, string) {buf := bytes.NewBuffer([]byte(issuejson))js, _ := simplejson.NewFromReader(buf)var each_map = make(map[string]interface{})each_map, _ = js.Map()app := each_map["app"].(string)link := each_map["link"].(string)return app, link
}// 根据模块名和模块匹配本地json模块发布
func issueModuleLocalJson(app string, link string, localjson string) {//读本地配置 war包路径 存储命令等fmt.Println(localjson)buf := bytes.NewBuffer([]byte(localjson))js, _ := simplejson.NewFromReader(buf)fmt.Println(js)//获取json字符串中的  数组rows, _ := js.Array()fmt.Println(rows)//遍历rows数组for _, row := range rows {each_map := row.(map[string]interface{})jsonapp := each_map["app"].(string)warpath := each_map["warpath"].(string)warname := each_map["warname"].(string)backpath := each_map["backpath"].(string)stop := each_map["stop"].(string)start := each_map["start"].(string)transfer := each_map["transfer"].(string)unzip := each_map["unzip"].(string)if jsonapp == app {fmt.Println("找到对应模块" + app)// 创建备份目录fmt.Println("创建备份目录" + backpath)exec_shell("mkdir -p " + backpath)// 获取当前时间并格式化timestamp := time.Now().Format("20060102150405")backupDir := fmt.Sprintf("%s/%s/%s", backpath, app, timestamp)// 创建备份子目录fmt.Println("创建备份子目录" + backupDir)err := os.MkdirAll(backupDir, 0755)if err != nil {fmt.Println("创建备份子目录失败:", err)continue}// 改变当前工作目录err = os.Chdir(backupDir)if err != nil {fmt.Println("改变目录失败:", err)continue}pwd, _ := os.Getwd()fmt.Println("当前目录" + pwd)if strings.Contains(link, "&") {link = "'" + link + "'"}fmt.Println("下载文件" + link)exec_shell(transfer + " " + link)fmt.Println("解压文件")exec_shell(unzip)fmt.Println("停止服务")exec_shell(stop)fmt.Println("拷贝文件到对应目录")exec_shell("cp -rf" + " " + warname + " " + warpath)fmt.Println("启动服务")exec_shell(start)fmt.Println("完成本次发布")break}}
}// 阻塞式的执行外部shell命令的函数,等待执行完毕并返回标准输出
func exec_shell(s string) (string, error) {cmd := exec.Command("/bin/bash", "-c", s)var out bytes.Buffercmd.Stdout = &outerr := cmd.Run()checkErr(err)return out.String(), err
}// 错误处理函数
func checkErr(err error) {if err != nil {fmt.Println(err)panic(err)}
}// 处理MQTT消息的函数
func handleMessage(client mqtt.Client, msg mqtt.Message) {fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic())//读取发布配置,备份war包,替换war包,重启tomcat或者dockerissuejson := string(msg.Payload())fmt.Println(issuejson)//读本地配置 war包路径 存储命令等localjson := readFile(baseDir + "/" + "jenkinsmqtt.json")//关于json的配置说明/*app: 应用的名称。warpath: 应用的部署路径。warname: 应用的 WAR 文件名。backpath: 备份路径。stop: 停止应用的命令。start: 启动应用的命令。restart: 重启应用的命令。transfer: 下载应用包的命令。unzip: 解压应用包的命令。*/fmt.Println(localjson)//发布模块解析app, link := readIssueModule(issuejson)fmt.Println(app)fmt.Println(link)//模块发布issueModuleLocalJson(app, link, localjson)
}

jenkinsmqtt.json示例

[{"app": "myapp","warpath": "/data/app/myapp/webapps","warname": "myapp.war","backpath": "/data/app/cibak","stop": "docker stop myapp","start": "docker start myapp","restart": "docker restart myapp","transfer": "wget -O myapp.tgz ","unzip": "tar -zxvf myapp.tgz"}
]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/462641.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

存储器与寄存器

​​​​​​存储器 存储器&#xff08;Memory&#xff09;是计算机中用于存储数据和程序的硬件设备。有了存储器计算机就具有记忆功能。 RAM 随机存取存储器&#xff08;RAM, Random Access Memory&#xff09; 是计算机系统中一种重要的内存类型&#xff0c;主要用于临时存储…

T10打卡—数据增强

​​​​​​​ &#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 1.导入及查看数据 import matplotlib.pyplot as plt plt.rcParams[font.sans-serif][SimHei] plt.rcParams[axes.unicode_minus]False import…

wordpress ripro-v5-8.3开心版主题源码

wordpress 资源下载主题 ripro刚开始出来就风靡很久&#xff0c;这个也是类似子比的一个主题&#xff0c;下载全面&#xff0c;美化包也特别多&#xff0c;此版本为网友投稿开新版本&#xff0c;还是那句话&#xff0c;运营请支持正版授权&#xff0c;提供学习研究而已。 喜欢做…

wps宏代码学习

推荐学习视频&#xff1a;https://space.bilibili.com/363834767/channel/collectiondetail?sid1139008&spm_id_from333.788.0.0 打开宏编辑器和JS代码调试 工具-》开发工具-》WPS宏编辑器 左边是工程区&#xff0c;当打开多个excel时会有多个&#xff0c;要注意不要把…

微信小程序的上拉刷新与下拉刷新

效果图如下&#xff1a; 上拉刷新 与 下拉刷新 代码如下&#xff1a; joked.wxml <scroll-view class"scroll" scroll-y refresher-enabled refresher-default-style"white" bindrefresherrefresh"onRefresh" refresher-triggered&qu…

python之函数总结

函数 对于函数的学习&#xff0c;我整理了网上的一些资料&#xff0c;希望可以帮助到各位&#xff01;&#xff01;&#xff01; 世界级的编程大师Martin Fowler先生曾经说过&#xff1a;“代码有很多种坏味道&#xff0c;重复是最坏的一种&#xff01;”。 为什么使用函数 问题…

Mybatis学习笔记(二)

八、多表联合查询 (一) 多表联合查询概述 在开发过程中单表查询不能满足项目需求分析功能&#xff0c;对于复杂业务来讲&#xff0c;关联的表有几张&#xff0c;甚至几十张并且表与表之间的关系相当复杂。为了能够实业复杂功能业务&#xff0c;就必须进行多表查询&#xff0c…

从0开始的STM32之旅 7 串口通信(I)

现在&#xff0c;我们终于可以做一些有趣的事情了&#xff1a;那就是来一点串口通信了。串口通信在一定程度上可以辅助我们程序的调试&#xff0c;传递信息&#xff0c;以及做其他令人激动的事情。下面我们就来看看如何开始我们的串口通信之旅。 关于数据通信 通信就是在传递…

医院绩效考核管理系统源码,医院如何构建绩效考核体系?

医院绩效考核管理系统作为现代医院管理的重要组成部分&#xff0c;其核心功能旨在提高医院运营效率、优化资源配置、确保医疗服务质量&#xff0c;以及增强医院竞争力。 业务科室绩效考核体系的构建 临床医疗与医技科室绩效考核的设置 临床医疗的绩效考核采用百分制&#xff…

使用DexClassLoader类动态加载插件dex

DexClassLoader类的源码 package dalvik.system;public class DexClassLoader extends BaseDexClassLoader {public DexClassLoader(String dexPath, String optimizedDirectory,String librarySearchPath, ClassLoader parent) {super(dexPath, null, librarySearchPath, par…

国产服务器部署1.获取银河麒麟V10服务器。首先挂gpt数据盘

要做系统国产化&#xff0c;现记录国产化的全过程&#xff1a;银河麒麟V10采用ARM架构&#xff0c;基于Ubuntu 18.04 LTS版本的Linux操作系统。‌‌ #uname -r 看系统是x86还是arm 1.获取银河麒麟V10服务器。首先挂数据盘。 1&#xff09;#lsblk -f vdb为数据盘。需要格式…

Excel:vba实现插入图片

实现的效果&#xff1a; 实现的代码&#xff1a; Sub InsertImageNamesAndPictures()Dim PicPath As StringDim PicName As StringDim PicFullPath As StringDim RowNum As IntegerDim Pic As ObjectDim Name As String 防止表格里面有脏数据Cells.Clear 遍历工作表中的每个图…

性能测试需求分析详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、客户方提出 客户方能提出明确的性能需求&#xff0c;说明对方很重视性能测试&#xff0c;这样的企业一般是金融、电信、银行、医疗器械等&#xff1b;他们一…

机器学习之fetch_olivetti_faces人脸识别--基于Python实现

fetch_olivetti_faces 数据集下载 fetch_olivetti_faceshttps://github.com/jikechao/olivettifaces sklearn.datasets.fetch_olivetti_faces(*, data_homeNone, shuffleFalse, random_state0, download_if_missingTrue, return_X_yFalse, n_retries3, delay1.0)[source] L…

智能离线语音识别不灵敏?如何改善和提升识别率?

前言 有用户反馈离线语音识别不灵敏&#xff0c;跟着笔者一起分析原因吧。笔者知识能力有限&#xff0c;难免会误&#xff0c;还请大家批评指正。 1 影响离线语音识别的因素 笔者分析离线语音识别不灵敏的原因有以下几点 1.1 运行硬件的算力限制 由于离线语音识别在本地MCU…

人工智能在干部选拔任用中的应用研究

干部选拔任用是关系到党和国家事业发展的重要环节。在当今科技飞速发展的时代&#xff0c;人工智能技术的出现为干部选拔任用提供了新的思路和方法。人工智能以其强大的数据处理能力、精准的分析预测能力和高效的决策支持能力&#xff0c;有望在干部选拔任用中发挥重要作用。 …

Grandle 报错_项目无法编译问题解决

文章目录 AndroidStudio 编译遇到的问题Gradle 报错-无法编译需要解决的问题说明AS 与 AGP 版本对应不同平台AS版本及下载地址gradle 无法下载 和 找不到使用腾讯镜像gradle-wrapper.properties 文件找不到 依赖库无法下载&#xff0c;下载速度慢更换阿里镜像仓库阿里仓库镜像下…

C++ 实现俄罗斯方块游戏

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

JS进阶级案例-----时钟

首先呢&#xff0c;是由四张图片构成&#xff0c;使用css摆放好&#xff0c;再使用JS给三个指针绑定获取时间和要旋转的角度&#xff0c;在获取对应的指针元素&#xff0c;给到定时器&#xff0c;实现时钟动态更新。 <!DOCTYPE html> <html lang"en"> &…