从安装到GithubAction与Jenkins搭建CICD流水线
早在学习初期查看学习路线的时候, 就看到过CI/CD , 不过开始没有什么开发的经验 , 并不能体会到CI/CD的含义以及作用。
前段时间曾总结过一篇GithubAction与阿里云镜像仓库自动化实现Docker镜像构建与推送的文章 , 通过Github Action以及阿里云的Docker镜像仓库来进行Docker镜像的构建以及推送 , 接着在部署的时候只需要从镜像仓库中拉取镜像然后运行容器即可。
这样做一方面可以降低风险(只需要推送代码到指定分支就可以自动的去构建项目) , 也使得项目部署更加方便 (直接在服务器运行shell即可, 省去了临时去构建doker镜像的讨厌的操作) , 但是还有一点问题就是仍然需要人手动的去构建容器 , 完整的CI/CD流程远非如此
今天在项目开发合并分支的时候, 项目构建的时候突然出现错误(后来发现是server顶不住了) , 不过通过项目组的大佬提前配置好的CI/CD流水线非常方便地来进行项目构建以及发布, 省去了大量的不必要的体力劳动。
计划顺着这个机会,从头来学习CI/CD的知识 , 并且通过GithubAction构建一个完整的CI/CD流水线
之前的GithubAction 配置在 adorabled4/hxBI , 可以先从这个看起, 一步步来理解
What is CI/CD?
CI/CD 是 Continuous Intergration/Continuous Deploy 的简称,翻译过来就是持续集成/持续部署。
其中CD 也会被解释为持续交付(Continuous Delivery)。
简单来说 CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。
仔细看下面这张图
一项技术或者是一种产品的提出(or 发展) , 必然会对应着相应的场景以及一定的需求 , 那么CI/CD也有对应的他需要解决的问题
Was vernünftig ist, das ist wirklich; und was wirklich ist, das ist vernünftig.
----Hegel, Grundlinien der Philosophie des Rechts, Frankfurt am Main 1972, S. 11
CI
大师 Martin Fowler 对持续集成是这 ...
Springboot搭建简易mqtt-server
由于项目开发过程中需要对接物联网设备 , 并且MQTT协议在物联网应用中有着及其广泛的应用, 这里首先简单实现一个demo级别的mqtt-server
核心在于理解MQTT协议的工作方式以及具体的流程。
本文不涉及任何业务代码
完整代码请参考 https://github.com/adorabled4/demo0828 下 com.dhx.dem0828.mqtt
关于MQTT协议
对于后端开发人员来说MQTT协议并不模式, 常用的消息队列如RabbitMQ , ActiveMQ等都支持MQTT协议。
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议
该协议构建于TCP/IP协议上,由IBM在1999年发布。
MQTT最大优点在于,用极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务,作为一种低开销、低带宽占用的即时通讯协议,MQTT协议在物联网应用上有着非常广阔的应用场景。
MQTT协议的主要特点包括
**轻量级:**开销低、报文小,消耗资源更少,即使在有限的能力下也能实现高效的通信。
**可靠:**MQTT 支持多种 QoS 等级、会话感知和持久连接,即使在困难的条件下也能保证消息的可靠传递。
QoS 0(最多一次,At most once):
这是最低的服务质量级别。消息被发布后,不进行确认,也不进行重新传输。发布者发送消息后,不会知道消息是否被成功接收。
消息会尽力传递,但可能会丢失或重复。这种级别适用于对消息的可靠性要求不高的情况。
QoS 1(至少一次,At least once):
在这个级别下,发布者会收到一个消息确认(PUBACK)来确认消息已经被接收,如果没有确认,发布者会尝试重新发送消息。
这个级别保证消息至少传递一次,但可能会导致消息重复。适用于需要确保消息到达,但可以容忍重复的情况。
QoS 2(仅一次,Exactly once):
最高的服务质量级别,确保消息只传递一次且不会重复。它通过使用两个确认(PUBREC 和 PUBCOMP)来实现。
发布者发送消息后会等待完整的确认过程,确保消息不会丢失,也不会重复传递。适用于对消息的可靠性要求非常高的情况,但它会引入一些 ...
一步步实现一个基于Springboot的回调系统
背景
最近在使用微信开放平台的内容审核功能的时候需要接收微信的回调消息来获取审核的结果
原本的审核执行的时序图如下
微信内容审核的接口参数如下 :
请求参数
属性
类型
必填
说明
access_token
string
是
接口调用凭证,该参数为 URL 参数,非 Body 参数。使用access_token或者authorizer_access_token
media_url
string
是
要检测的图片或音频的url,支持图片格式包括jpg, jepg, png, bmp, gif(取首帧),支持的音频格式包括mp3, aac, ac3, wma, flac, vorbis, opus, wav
media_type
number
是
1:音频;2:图片
version
number
是
接口版本号,2.0版本为固定值2
scene
number
是
场景枚举值(1 资料;2 评论;3 论坛;4 社交日志)
openid
string
是
用户的openid(用户需在近两小时访问过小程序)
返回参数
属性
类型
说明
errcode
number
错误码
errmsg
string
错误信息
trace_id
string
唯一请求标识,标记单次请求,用于匹配异步推送结果
异步检测结果推送
异步检测结果在 30 分钟内会推送到你的消息接收服务器。点击查看消息接收服务器配置
返回的 JSON 数据包
属性
类型
说明
ToUserName
string
小程序的username
FromUserName
string
平台推送服务UserName
CreateTime
number
发送时间
MsgType
string
默认为:event
Event
string
默认为:wxa_media_check
appid
string
小程序的appid
trace_id
string
任务id
version
number
可用于区分接口版本
result
object
综合结果
detail
array
详细检测结果
result为综合结果,包含的属性有
属性
类型
说明
suggest
string
建议,有risky ...
lombok的@Data导致StackOverflowError
最近在写代码实现循环依赖问题的时候遇到了一个问题 , 已经解决了循环依赖的问题 , 同时Debug代码也确实按照原本构思的流程走了, 但是在最后执行的时候莫名奇妙出现了栈溢出异常
123BeanA beanA = (BeanA)applicationContext.getBean("beanA");beanA.showB();System.out.println(beanA);
原本还以为在抄代码的时候哪里抄错了 , 导致循环依赖的问题没有解决
不过经过反复的Debug以及手动画流程, 基本可以确定代码逻辑是没有问题的
接着使用了项目作者给出的测试数据 , 并没有出现异常 , 但是在debug到最后准备打印数据的时候 , IDEA的调试器显示出来有一个StackOverflowError
经过反复的问题排查, 最后可以确定问题出在lombok的@Data上
这里先给出代码使用到的类
BeanA
123456789101112131415161718@Datapublic class BeanA { String code; BeanB beanB; public void showB() { System.out.println(beanB + "code : " + code); } public void setCode(String code) { this.code = code; } public void setBeanB(BeanB beanB) { this.beanB = beanB; }}
BeanB
123456789101112131415161718@Datapublic class BeanB { BeanA beanA; String code; public void showA(){ System.out.println(beanA + "code : " + code); } public void setBeanA(BeanA beanA) { this.beanA = beanA; } public void setCode(String code) { ...
GithubAction与阿里云镜像仓库自动化实现Docker镜像构建与推送
使用Docker进行容器化的项目部署已经是非常方便了 , 但是如果线上环境出现了一些小的问题 ,往往需要我们去手动的去修改 , 重新部署, 重复的无意义劳动显然非常令人讨厌。
对于懒人来说自动化的配置显然是最舒服的
谁能理解数据库密码因为数字开头导致线上数据库连接不上 ,
*docker build docker run docker rm docker rmi 敲了一下午晚上闭上眼全是Docker **的痛苦啊???
那么接下来就让我们一起动手去实现 使用GithubAction与阿里云镜像仓库自动化实现Docker镜像构建与推送
创建阿里云镜像仓库
这里使用阿里云的容器镜像服务
然后我们进入控制台, 找到代码源, 选择绑定github(如果使用别的平台那么就选择别的代码源即可)
接着我们创建镜像仓库
创建好了之后页面如下
配置Github Action
准备秘钥
在前面我们在阿里云中配置镜像仓库的时候设置了账户以及密码 , 这里首先需要在Github中设置以供使用
找到 Settings -> Secrets and variables -> Actions -> New repository secret
手动进行添加即可 , 设置成功后可以看到如下内容 (请忽略ID_RSA以及ID_RSA_PUB)
创建工作流
我们的目的是
构建Docker镜像
推送到阿里云仓库
那么可以简单总结工作流的主要工作流程
安装JDK (这里自带了Maven的环境)
通过Maven构建Jar包(如果是gradle项目请注意更改这一步的内容)
登录到阿里云镜像仓库(这里需要使用到前面我们配置的 REGISTRY PASSWORDREGISTRY USERNAME)
构建Docker镜像(通过我们事先准备好的Dockerfile)
推送镜像到阿里云镜像仓库
注意前两个步骤非常重要 , GithubAction的运行环境就是一个非常干净的操作系统(所以环境都需要我们自己手动去配置)
这里使用Dockerfile实际上还有一个大坑
原因也很简单 , 原本的Dockerfile是用来手动进行镜像构建以及项目部署的 , 使用的路径都是自定义的路径 , 但是这里我们使用Github Action , 就需要去通过调试来更改我们的配置(wor ...
Docker部署Springboot+React项目
关于Docker的详细内容以及快速入门, 请参考https://blog.dhx.icu/2022/11/25/springcloud/Springcloud03-Docker/
简单来讲, 将项目部署到 Docker 中可以带来更高效、更稳定、更灵活的部署和管理体验,有助于提高开发和运维效率,同时也增强了应用程序的可扩展性和可维护性。
隔离和独立性: Docker 容器提供了隔离的运行环境,前端和后端可以在各自的容器中独立运行,不会相互影响。这样可以确保应用的稳定性和安全性。
环境一致性: Docker 容器包含了应用所需的所有依赖和运行环境,保证了开发、测试和生产环境之间的一致性,避免了“在我这里是好的”问题。
简化部署: 使用 Docker 部署前后端分离的项目可以更快速、更简单地进行。只需创建 Docker 镜像并在不同环境中运行容器,无需手动安装和配置环境。
易于扩展: Docker 容器可以根据需要进行水平扩展,以适应不断增长的流量。你可以根据负载情况,动态调整容器的数量。
持续集成与持续交付: Docker 可以与持续集成和持续交付(CI/CD)流程无缝集成,帮助自动化构建、测试和部署过程,加速交付新功能。
微服务架构: 将前端和后端分离的项目部署到 Docker 容器中有助于实现微服务架构。每个微服务都可以打包为一个独立的容器,提高模块化和可维护性。
多语言支持: 如果你的项目前后端使用了不同的编程语言,Docker 可以容纳多种语言的应用,不会产生冲突。
资源有效利用: Docker 容器共享主机的操作系统内核,因此可以更高效地使用系统资源,避免资源浪费。
易于迁移: Docker 容器可以在不同的环境中移植,例如从开发环境到测试环境,再到生产环境,无需进行大量的适应性修改。
本文以Springboot项目(后端)以及React项目(前端)为例, 从零到一实现项目部署
准备工作
需要准备好
能够成功编译运行的前后端项目
知道自己的项目运行环境 (比如JDK , MySQL 等)
一台云服务器或虚拟机
一般来讲, 我们的部署顺序是后端->前端。
后端部署
注意事项
一般我们在本地PC开发的过程中,只要项目能跑起来,那么环境基本上是没有问题的。
但是对于线上环境,往往会存在着许多注意不到的地方,对于线上环境,在部署的时候应当主要注意以下的 ...
我的第一次长途骑行
2023年8月2日~8月12日 : 新乡->日照
路程 : 新乡-长垣-东明-菏泽-巨野-济宁-滕州-费县-临沂-日照
Background
故事要从2022年11月长时间的封寝说起。
那个时候由于疫情以及政策的原因,我所在的地区展开了长达数月的封控。从2022年十月中旬一直到2022年十一月底,都封在宿舍里面不能出去,伴随着的是每天有同学半夜被拉走隔离的消息以及逐渐崩溃的精神。
封在宿舍没有事情做,上网课?听课是不可能的,每天都处在发疯的边缘。消遣时间的做法是躺在床上期待下一顿饭会吃什么以及无聊地刷着手机。
大概在十一月的时候,我偶然在bilibili上面刷到了一个视频,是一个大二的学生,假期骑着摩托从学校回家(似乎是从哈尔滨到山东威海)。
看着别人一路上的美丽风光,我怀抱着无比羡慕的内心点进了他的主页,看到了那个让人感觉无比舒适的视频。
***吹着海风,迎着阳光,在绿道上骑行。***这对于饱受封寝摧残的我来说简直如黑暗中的一束光。刹那间我脑海中出现了这样的一个想法:骑着自行车去海边。
大概是下图这样的效果, 原视频由于时间久远已经找不到了。
这个想法对于当时的我可能是不太现实的。由于2022年六月份跑步膝盖处韧带拉伤,我已经恢复了几个月但是还是容易复发。
还好我年轻。
我马上把这个不错的想法分享给了好友, 他也十分赞同我的想法。⭐
BuyBike
随后来到了2023年三月份,此时疫情已经是全面放开了,为了方便出行(其实就是懒得走路),与室友合资800元巨款买了辆电动车。
这个电动车不能说很好,只能说能骑。虽然说质量堪忧,但是对于像我这样的大学生也是十分友好了。
由于我骑这个车总喜欢骑快以及车子的质量问题,好几次差点刹不住车(刹车问题以及轮胎问题)险些撞墙。
偶然间我又想起来去年封寝时候骑车去海边的想法,于是依靠着父母的支持以及我坚定的态度,我买了属于自己的第一辆山地车。
然后对于新手的我并不知道关于骑行的一些要点,只一股脑的骑,后来慢慢的才主动去了解,准备了骑行裤,头盔,手套,眼镜等装备。
Prepare before cycling
真正开始准备这次骑行是在2023年七月底,与好友二人在语雀写文档,买装备,规划路线,做准备工作。
最开始规划的路线
甚至规划好了每天的骑行里程以及目的地。
装备方面的准备也不能落下
为了人身安 ...
Netty网络编程(3)Netty-2[Netty]
粘包&半包
粘包(Packet Concatenation): 粘包指的是发送方发送的多个小数据包在传输过程中被接收方合并成一个大数据包的现象。这种情况下,接收方无法准确地将大数据包拆分成原来的小数据包,导致数据粘连。粘包问题常见于使用面向流的传输协议(如TCP)进行数据传输时,由于TCP协议以字节流的形式传输数据,不保留数据包边界信息。
半包(Incomplete Packet): 半包指的是接收方在读取数据时,并没有完整地接收到一个完整的数据包,而只接收到了部分数据包或者不完整的数据包。这可能发生在接收缓冲区的数据还未达到一个完整数据包的长度时,接收方就开始读取数据,从而造成数据包的不完整。
粘包
server
123456789101112131415161718192021222324252627282930313233343536373839404142434445static final Logger log = LoggerFactory.getLogger(HelloWorldServer.class);void start() { NioEventLoopGroup boss = new NioEventLoopGroup(1); NioEventLoopGroup worker = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.channel(NioServerSocketChannel.class); serverBootstrap.group(boss, worker); serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new Loggi ...
Netty网络编程(2)Netty-1[Netty]
What is Netty
12Netty is an asynchronous event-driven network application frameworkfor rapid development of maintainable high performance protocol servers & clients.
Netty 是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端
hello world - Netty
首先记得导入Netty的依赖
12345<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.84.Final</version></dependency>
server
12345678910111213141516171819202122232425262728293031public class Server { public static void main(String[] args) { // 1.启动器,负责装配netty组件,启动服务器 new ServerBootstrap() // 2.创建 NioEventLoopGroup,可以简单理解为 线程池 + Selector .group(new NioEventLoopGroup()) // 3.选择服务器的 ServerSocketChannel 实现 .channel(NioServerSocketChannel.class) // 4. boss 负责处理连接 , worker(child) 负责处理读写,该方法决定了 child 执行哪些操作 // ChannelInitializer 处理器(仅执行一次) // 它的作用是待客户端SocketChannel建立连接后,执行initChannel以便 ...
传输层[计算机网络]
传输层
概述
传输层协议为运行在不同主机上的应用进程之间提供了逻辑通信
传输层协议只运行于端系统中,也就是说传输层不运行在路由器和交换机中。
主要功能
提供进程与进程之间的通信。
复用和分用(后边会详细解释的)
对收到的报文进行差错检测。
与网络层的关系
在协议栈结构中,传输层运行于网络层之上
传输层协议提供的服务 部分 受制于网络层,如:
如底层网络层协议无法为报文提供时延和带宽保证,那么其上层传输层协议也做不到
但是即使底层网络层协议不可靠,不安全,运行于其上的传输层协议仍然可以做到可靠安全传输
例如IP协议是不可靠不安全的,但是我们通过TCP可以做到可靠的安全传输
寻址和端口
复用:应用层所有的应用进程都可以通过传输层再传输到网络层。
分用:传输层从网络层收到数据后交付指明的应用进程。
逻辑端口/软件端口 : 端口是传输层的SAP,标识主机中的应用进程。
端口号只有本地意义,在因特网中不同计算机的相同端口是没有联系的。
端口号长度为16bit,能表示65536个不同的端口号。
常用的端口号
协议/服务名称
端口号
简介
ftp
20、21
File Transfer Protocol 文件传输协议,20用于连接,21用于传输
ssh
22
Secure Shell 安全外壳协议,专为远程登录会话和其他网络服务提供安全性的协议
http
80
Hyper Text Transfer Protocol 超文本传输协议,用于网页浏览
DNS
53
Domain Name System 域名系统,域名解析
https
443
Hypertext Transfer Protocol Secure 超文本传输安全协议,用于安全浏览网页
www代理服务
8080
Apache Tomcat web server,进行网页浏览
smtp
25
Simple Mail Transfer Protocol 简单邮件传输协议
telnet
23
不安全的文本传送
pop3
110
Post Office Protocol
UDP(User Datagram Protocol)
UDP在IP数据报服务之上添加了复用分用和差错检测的功能。
UDP特点
UDP是无连接的,减少开销和发送 ...