用Jenkins pipeline(流水线)实现SpringBoot Application的docker构建和持续集成(CI)
写在前面
在看了许多CI的内容之后,正好碰上公司尝试把应用容器化以及进行持续集成(之前还是需要手动执行启停脚本),然后我便成了第一个吃螃蟹的人,在一阵折腾之后也勉强算是把整个流程给走通了便在这里记录一下大致的流程和踩到的坑,也是对最近许久不更新的博客增加一些新东西吧.
部署流程
首先描述一下整个部署的流程来理清一下整个逻辑,这里仅仅是给出我自己的暂时的解决方案,由于业务和环境的不同必定没有完全一样的流程,并且这也只是暂时的方案还是有很多可以优化的地方。
1 | 更新代码 ==> 触发Jenkins流水线的构建 ==> Maven打包项目 ==> 制作docker image ==> |
需要注意的是:
- 项目的仓库中包含了Jenkinsfile和部署的脚本(全部交由版本控制)
- 由于线上服务器为阿里ECS并且外网无法访问,所以使用了部署服务器(外网IP)来做跳转和部署
- 因为项目使用了SpringCloud的微服务框架并且使用了NACOS注册中心,所以在服务的优雅下线重启阶段使用了nacos的服务调度API并没有使用SpringCloud自带的端点,当然本质都是通过接口调用告知注册中心下线服务
- 由于线上服务器均没有使用root用户来发布应用所以在这里踩了小坑,暂时的解决方案可能并不完美
Java8函数式编程笔记
chp2.
lambda表达式的几种形式
1 | // () -> 表示没有参数且Runnable接口只有一个run方法 |
Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。
这周搞的一些新东西
话到嘴边又不知道该怎么描述,也算是拾起了很久没用的博客吧,这也算是自己少见的文字输出方式了所以还是来写一写.
之所以会写这周搞的一些新东西这样的博客,主要是这周摸🐟的时光似乎有些多了,也是四处搞了很多新东西和一些之前遗留的事,就来记录一下吧.
敏捷学习仓库合并
在许久之前看了基于GitHub的敏捷学习方法之道与术之后就深受影响然后搞了一个仓库Agile-Learning也坚持搞了一段时间(MySQL文档翻译就是这样促成的),但是过年回来之后惰性发作也就许久没有再去动这个仓库也就闲置了许久,最近打算重新使用之后发现private的仓库不能无偿使用wiki,也就借着public的机会把这个仓库和github.io的仓库给合并了顺便整理了一下吧.
因为写博客的分支是在backup上的,所以对博客访问也没有什么影响,也是方便自己管理,之前没有public敏捷学习的仓库也是因为打算实践一段时间找到自己的使用方式之后再public出来,现在也是想用wiki就用public的方式来督促一下自己吧算是.
阅读:Test-Driven Development By Example
Perface
TDD rules:
- write new code only if you first have a failing automated test.
- eliminate duplication. 消除重复设计
Technical implications:
- design organically: running code providing feedback between decisions.
- write your own test.
- development env must provide rapid response to small change.
- design must be highly cohesive, loosely coupled components(高内聚,低耦合) to make testing easy.
Programing order:
- Red-write a little that doesn’t work.
- Green-make the test work quickly.
- Refactor-eliminate all the duplication created.
InnoDB官方文档--14.7.4 幻影行|14.7.5 InnoDB的死锁
14.7.4 幻影行
所谓的幻读就是同一个事务在不同的时间执行相同的查询产生不同的结果行.例如,如果一个SELECT执行2次,但是第二次返回的行和第一次的不一样,这些行就被称为”幻影行”.
假设在child表的id列上有索引并且你想要对表中id值大于100的所有行进行加锁和读取,为了在之后更新选中列中的数据:1
SELECT * FROM child WHERE id > 100 FOR UPDATE;
查询从id大于100的第一个记录开始扫描.假设表包含90和102.如果扫描范围之内的索引记录没有对插入的间隙加锁,另一个会话可以插入一个id为101的新行到表中.如果你在相同的事务中执行相同的SELECT,你将会在查询结果中看到一个id为101的新行(一个”幻影”).如果我们把这一系列的行视为一个数据项的话,新的幻影数据将违反事务的隔离准则即:在事务期间读取的数据不会发生改变.
为了避免幻读,InnoDB使用了一个叫做next-key锁的算法,它将索引行锁定与间隙锁定相结合.InnoDB以这样的方式执行行级锁定:当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享锁或独占锁.因此,行级锁其实是索引记录锁.此外,索引记录上的next-key锁也会影响索引记录前的间隙.也就是说,next-key锁是索引记录锁加上索引记录锁前间隙锁.如果一个会话在索引记录R上有一个共享或者独占锁,其他会话就不能在索引记录R之前的间隙插入一个新的索引记录了.
当InnoDB扫描索引时,也会对最后一个索引记录后的间隙加锁.在前面的例子中就发生了这种情况:为了避免任何比100大的id插入到表中,InnoDB设置的锁也包括了id为102之后的间隙锁.
你可以使用next-key锁在你的应用中实现唯一性检查:如果你在共享模式下读取你的数据并且你要插入的行中没有重复键,那你就可以安全的插入行数据并且知道在你读取期间设置的next-key锁会组织任何人在同时插入和你重复键的行数据.因此,next-key锁能够使你锁定某些表中不存在的数据.
InnoDB官方文档--14.7.2 InnoDB事务模型|14.7.3 InnoDB中的不同SQL语句设置的锁
14.7.2 InnoDB事务模型
在InnoDB事务模型里,其目标就是把多版本数据库的最佳属性和传统的两段锁相结合.InnoDB在行级进行加锁并且默认情况下将查询作为非锁定的一致性读取来运行,这是Oracle的风格.InnoDB中的锁信息是高效存储的所以不需要升级.通常允许多个用户锁定InnoDB表中的每一行,或行的任何随机子集而不会导致InnoDB内存耗尽.
14.7.2.1 事务隔离级别
事务隔离是数据库处理的基础之一.隔离(Isolation)是ACID中I的缩写;隔离级别是在多个事务同时进行更改和执行查询时对性能和可靠性,一致性和结果的可重复性进行平衡的细微调整的设置.
InnoDB提供SQL:1992标准描述的四种事务隔离级别:READ UNCOMMITTED
,READ COMMITTED
,REPEATABLE READ
和SERIALIZABLE
.InnoDB默认的事务隔离级别是REPEATABLE READ
.
用户可以改变单个会话(session)的隔离级别或使用SET TRANSACTION
语句为连接后面所有的语句设置.为了对所有的连接设置服务器默认的隔离级别,在命令行使用--transaction-isolation
选项或在配置文件中.
InnoDB支持对每个事务隔离级别使用不同的锁策略.你可以对符合ACID规范很重要的关键数据的操作使用默认的REPEATABLE READ
级别来强制执行高一致性.或者你可以使用READ COMMITTED
或READ UNCOMMITTED
放松一致性要求,在例如批量报告等情况下,精确的一致性和可重复结果不如最小化锁的开销那么重要.SERIALIZABLE
比REPEATABLE READ
更严格,且主要用于特殊情况,例如XA事务以及并发和死锁的故障问题排除上.
InnoDB官方文档--14.7 InnoDB锁和事务模型|14.7.1 InnoDB锁
14.7 InnoDB锁和事务模型
为了实现大规模,繁忙或高可靠的数据库应用,从不同的数据库系统移植大量代码或调整MySQL性能,理解InnoDB锁和InnoDB事务模型是很重要的.
这个部分讨论了几个你应该要熟悉的和InnoDB锁和InnoDB事务模型相关的主题.
- 14.7.1 InnoDB锁 描述了InnoDB中使用的锁类型.
- 14.7.2 InnoDB事务模型 描述了事务隔离级别和每个锁的使用策略.同时也讨论了autocommit的使用,一致的无锁读和锁定读取.
- 14.7.3 InnoDB中不同SQL语句设置的锁 讨论了InnoDB中为各种语句设置的特定锁类型.
- 14.7.4 幻想行 描述InnoDB如何使用下一个键锁定来避免幻像行
- 14.7.5 InnoDB中的死锁 提供了一个死锁示例,讨论了死锁检测和回滚,并提供了在InnoDB中最小化和处理死锁的技巧.
InnoDB官方文档--14.6.6 Redo日志|14.6.7 undo日志
14.6.6 Redo日志
redo 日志是一个基于磁盘的数据结构,在崩溃恢复期间用于纠正由不完整事务写入的数据.在正常操作期间,redo日志对更改由SQL语句或低级API调用产生的表数据的请求进行编码.未完成更新数据文件的修改会在以外关闭自动重启的初始化期间和连接接受之前完成.
默认情况下,redo日志在磁盘上由两个名为ib_logfile0和ib_logfile1的文件表示.MySQL以循环方式写入redo日志文件.redo日志中的数据根据受影响的记录进行编码;这些数据统称为redo.通过redo日志的数据传递由不断增加的LSN值表示.
改变InnoDB redo日志文件的数量或大小
为了改变InnoDB redo日志文件的大小或数量,执行下面的步骤:
- 停止MySQL服务并且保证关闭时没有错误.
- 编辑my.cnf改变日志文件配置.修改
innodb_log_file_size
来改变日志文件的大小,修改innodb_log_files_in_group
来增加日志文件的数量. - 再次启动MySQL服务.
InnoDB如果检测到redo日志文件大小和innodb_log_file_size
不一样,会写下日志检查点,关闭和删除旧的日志文件,按照需要的大小创建新的日志文件并且打开新的日志文件(使用).
redo日志刷新的分组提交(Group Commit for Redo Log Flushing)
InnoDB和其他任何符合ACID标准的数据库引擎一样,在提交事务之前刷新事务的redo日志.InnoDB使用组提交功能将多个刷新请求组合在一起来避免每次只提交一个刷新.通过组提交,InnoDB会对日志文件发出一次写入操作来为同时提交的多个用户事务执行提交操作,从而显着提高吞吐量.