登录函数中有一个事务,如下: 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述
事务里面有一个有可能操作比较耗时的过程:
在新增登录日志的时候,获取用户的ip。
具体干了啥不重要,重要的是发了一个http请求,并且是串行的,所以这个请求比较耗时的可能是很大的,并且具备不确定性因素。
TransactionRollbackException
的文档注释为:
This exception indicates that the transaction associated with processing of the request has been rolled back, or marked to roll back. Thus the requested operation either could not be performed or was not performed because further computation on behalf of the transaction would be fruitless
可能的过程为:线程1进入事务、然后进行了一次update操作,获得了一个排他锁,然后被卡在了获取ip的那个地方,即此事务持有着排他锁,然后还长时间不结束(50s+),然后线程2也进入了事务,此时在进行update的时候,需要等待线程1释放排它锁,在50秒过后,仍未获取到锁,此时获取锁时间超过了预设,抛出上述异常。
规避潜在的耗时操作。但是由于此服务没人维护,因此通过本地编译,然后拉包替换相应class文件,再上传到服务器的方式进行修改。
查看获取锁的超时阀值:
输出如下:
1 | +-----------------------------+----------+ |
代码如下:
1 | // --------------------------Controller------------ |
日志输出与项目中出现的错误信息基本一致,如下: 在这里插入图片描述 在这里插入图片描述
在@Transactional
注解中加入timeout后,报错不一样,但是阔以理解为spring框架为我们抛出了异常。如下:
其中对我理解这种现象有很大帮助的资料为这一张图,它让我明白了锁与事务之间的关系。 在这里插入图片描述
参考:
https://segmentfault.com/a/1190000014133576
rebase的主要功能就是改变commit历史,在这篇文章中,场景一是改变未push的commit历史,场景二是在合并分支时,改变当前分支的历史,从而达到简化commit历史的目的,让历史一目了然。对强迫症患者来说简直就是福音。
1.我们来合并最近的 4 次提交纪录,执行:git rebase -i HEAD~4
2.这时候,会自动进入 vi 编辑模式:
1 | s cacc52da add: qrcode |
有几个命令需要注意一下:
1 | p, pick = use commit |
按照如上命令来修改你的提交纪录:
1 | s cacc52da add: qrcode |
3.如果保存的时候,你碰到了这个错误:error: cannot 'squash' without a previous commit
注意不要合并先前提交的东西,也就是已经提交远程分支的纪录。
4.如果你异常退出了 vi 窗口,不要紧张:
git rebase --edit-todo
这时候会一直处在这个编辑的模式里,我们可以回去继续编辑,修改完保存一下:
git rebase --continue
5.查看结果
在这里插入图片描述git log
三次提交合并成了一次,减少了无用的提交信息。
1.我们先从 master
分支切出一个 dev
分支,进行开发:
git1 git2git:(master) git checkout -b feature1
2.这时候,你的同事完成了一次 hotfix
,并合并入了 master
分支,此时 master
已经领先于你的 feature1
分支了:
3.恰巧,我们想要同步 master 分支的改动,首先想到了 merge,执行:
git3git:(feature1) git merge master
图中绿色的点就是我们合并之后的结果,执行:
git:(feature1) git log
就会在记录里发现一些 merge 的信息,但是我们觉得这样污染了 commit 记录,想要保持一份干净的 commit,怎么办呢?这时候,git rebase 就派上用场了。
4.让我们来试试 git rebase ,先回退到同事 hotfix 后合并 master 的步骤: git4
5.使用 rebase
后来看看结果:
git:(feature1) git rebase master
这里补充一点:rebase
做了什么操作呢?
首先,git 会把 git5feature1
分支里面的每个 commit
取消掉;
其次,把上面的操作临时保存成 patch
文件,存在 .git/rebase
目录下;
然后,把 feature1
分支更新到最新的 master
分支;
最后,把上面保存的 patch
文件应用到 feature1
分支上;
从 commit
记录我们可以看出来,feature1
分支是基于 hotfix
合并后的 master
,自然而然的成为了最领先的分支,而且没有 merge
的 commit
记录,是不是感觉很舒服了。
6.在 rebase
的过程中,也许会出现冲突 conflict。在这种情况,git 会停止 rebase
并会让你去解决冲突。在解决完冲突后,用 git add
命令去更新这些内容。
注意,你无需执行 git-commit
,只要执行 continue
git rebase --continue
这样 git 会继续应用余下的 patch 补丁文件。
7.在任何时候,我们都可以用 –abort 参数来终止 rebase 的行动,并且分支会回到 rebase 开始前的状态。
git rebase —abort
只要你的分支上需要 rebase
的所有 commits 历史还没有被 push
过,就可以安全地使用 git-rebase
来操作。
因为push到远程仓库后,你再次提交时,git对比会发现两个仓库的历史不一致。
主要思想是利用redis执行命令时的单线程特性。
1 | /** |
https://leetcode.com/problems/integer-to-roman/
1 | char ONE[5] = {' ', 'I', 'X', 'C', 'M'}; |
https://leetcode.com/problems/roman-to-integer/
1 | int getRomanValue(char ch) { |
nginx指定文件路径有两种方式root和alias,指令的使用方法和作用域:
[root]
语法:root path
默认值:root html
配置段:http、server、location、if
[alias]
语法:alias path
配置段:location
在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上。
root的处理结果是:root路径 + location路径
alias的处理结果是:使用alias路径替换location路径
alias是一个目录别名的定义,root则是最上层目录的定义。
还有一个重要的区别是alias后面必须要用“/”结束,否则会找不到文件的,而root则可有可无。
例:
1 | # 如果一个请求的URI是/t/a.html时,web服务器将会返回服务器上的/www/root/html/t/a.html的文件。 |
搬运工:
文章为: nginx.cn原创,转载请注明本文地址: http://www.nginx.cn/4658.html
一个java -jar服务在被CI启动后,过一段时间,进程就被消失了,不见了。日志没有关于出错的相关信息。对日志中记录的最后一条请求,进行压力测试,但该进程却没有自己消失。个人觉得这个问题很有意思,但是我也明白,找到这其中的原因可能需要很长的时间。
最近公司的其他项目上,又遇到了一个进程老是无缘无故就挂的现象,按照之前的那种场景来排查,并没有发现有那种CI的出现。顿时又陷入了困境之中。不过我还是按部就班的做了三件事:
1 | nohup strace -T -tt -e trace=all -p \`pgrep -f algorithm-work-1.0.0.jar\ ` > trace.\`pgrep -f algorithm-work-1.0.0.jar\`.log &\ |
1 | webapp@ecs-f1c4-0003:/opt/webapp/logs$ cat trace.26077.log |
转机 在这里插入图片描述
发现是被别人用来挖矿了==
详细的情况与下面链接的描述一模一样。本来还有一个进程叫做crond64
,在top中看到占用的CPU非常高,各个核的都占到了90%+。执行的挖矿脚本的目录在~/.ttp
下,打包好了,准备研究研究。
https://askubuntu.com/questions/1115770/crond64-tsm-virus-in-ubuntu
首先想到的是:是不是某一个接口出现了问题,所以根据日志中所记录的最后一条请求,对其进行压力测试。脚本如下:
1 | #!/bin/bash |
结果被认为遭到了ddos攻击,囧! 在这里插入图片描述
该服务进程扛过了这些请求,没有死亡。
因为整个项目通过gitlab管理,而gitlab中有一项叫做CI,可以通过ci脚本来执行一些脚本达到发布、部署最新的服务到相应服务器上。这里面可能会存在问题,比如说,另外一个ci脚本在执行的时候,会把该服务的进程kill掉,只是会有这种可能,因为CI脚本大部分是通过copy的,但是可能性不高,因为所有的CI脚本都能够顺利执行,所以kill掉的肯定是自身服务的进程,不然CI脚本对应的服务可能起不来,但目前所有的CI脚本都能顺利执行完。但是还是去排查一下CI脚本,没毛病。
这个进程消失的原因,可以想到的情况为:jvm崩溃、被操作系统的oom_killer杀掉、被某个脚本杀掉?
由于outofmemory被kill掉的进程,会在/var/log下的某个文件中留下最终的遗迹。但是在整个/var/log下、都没有搜索kill的痕迹,如下: 在这里插入图片描述 在这里插入图片描述
如果没有/var/log/messages这个文件,可以通过设置,将这个log文件开启。
root身份打开 /etc/rsyslog.d/50-default.conf
把注释#去掉
重启后oksudo restart rsyslog
并没有发现这个oom_killer的痕迹
在该服务的启动参数中加入了对崩溃日志的指定:java -jar -Xms512m -Xmx512m -XX:MaxPermSize=126m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/webapp/xxx-server/ -XX:ErrorFile=/opt/webapp/xxx-server/hs_err_pid_%p.log xxx-server.jar
但是在该进程被终结后,并没有发现相应目录下的日志文件。所以这种情况下,同样也没有对其进行内存分析的先决条件、jdk自带的一系列工具并没有发挥出作用的余地。
使用 在这里插入图片描述nohup strace -T -tt -e trace=all -p 21715 > trace.log &
监控该pid的情况,如果是被kill -9
,会出现一个log,大致如下:
通过strace命令的跟踪、最终发现trace.log的内容如下所示: 在这里插入图片描述
出现这个的原因基本上是两个、一个是人为的kill -9、或者就是被系统kill -9。系统杀掉该进程的原因、被逐一排除,结果只剩下人为的因素。关于人为的因素、首先查看命令,并没有相关的kill记录。然后发现开发环境与测试环境的该进程基本上同时挂掉、并且都点了这两个环境的某个CI,然后这两个环境上的该进程都挂掉了,因此基本断定是CI操作杀掉了该进程。
被杀掉的进程名字为:java -jar workorder-server.jar
,通过CI发布&启动的进程名字为:java -jar order-server.jar
。然后在点击order相关的CI时会执行如下操作:
1 | script: |
问题就在 在这里插入图片描述kill -9
上面,pgrep查出来的进程号有两个,所以执行order相关的CI时,顺带也把workorder干掉了。
修改shell语句,让pgrep order-server时,只显示出order-server的进程号即可。
SpringMVC源码探索之RequestBody的工作原理