diff --git a/2014/12/23/my-new-post/index.html b/2014/12/23/my-new-post/index.html index 598a92d80b..cc69cc4994 100644 --- a/2014/12/23/my-new-post/index.html +++ b/2014/12/23/my-new-post/index.html @@ -428,20 +428,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -466,7 +466,7 @@
- +
diff --git a/2014/12/24/MFC 模态对话框/index.html b/2014/12/24/MFC 模态对话框/index.html index 883e8f52a4..47789d2228 100644 --- a/2014/12/24/MFC 模态对话框/index.html +++ b/2014/12/24/MFC 模态对话框/index.html @@ -307,10 +307,10 @@ @@ -451,20 +451,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -489,7 +489,7 @@
- +
diff --git a/2014/12/30/Clone-Graph-Part-I/index.html b/2014/12/30/Clone-Graph-Part-I/index.html index 8b870502f4..5e7a7660e3 100644 --- a/2014/12/30/Clone-Graph-Part-I/index.html +++ b/2014/12/30/Clone-Graph-Part-I/index.html @@ -300,7 +300,7 @@ @@ -454,20 +454,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -492,7 +492,7 @@
- +
diff --git a/2015/01/04/Path-Sum/index.html b/2015/01/04/Path-Sum/index.html index 66bd732269..fdb99d4a12 100644 --- a/2015/01/04/Path-Sum/index.html +++ b/2015/01/04/Path-Sum/index.html @@ -302,7 +302,7 @@ @@ -457,20 +457,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -495,7 +495,7 @@
- +
diff --git a/2015/01/16/pcre-intro-and-a-simple-package/index.html b/2015/01/16/pcre-intro-and-a-simple-package/index.html index b56a3e5372..d85281c627 100644 --- a/2015/01/16/pcre-intro-and-a-simple-package/index.html +++ b/2015/01/16/pcre-intro-and-a-simple-package/index.html @@ -327,7 +327,7 @@ @@ -469,20 +469,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -507,7 +507,7 @@
- +
diff --git a/2015/03/11/Number-Of-1-Bits/index.html b/2015/03/11/Number-Of-1-Bits/index.html index e86681454a..762f06ff7a 100644 --- a/2015/03/11/Number-Of-1-Bits/index.html +++ b/2015/03/11/Number-Of-1-Bits/index.html @@ -299,7 +299,7 @@ @@ -462,20 +462,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -500,7 +500,7 @@
- +
diff --git a/2016/07/13/swoole-websocket-test/index.html b/2016/07/13/swoole-websocket-test/index.html index 98b0b96968..12539aecb9 100644 --- a/2016/07/13/swoole-websocket-test/index.html +++ b/2016/07/13/swoole-websocket-test/index.html @@ -461,20 +461,20 @@ user3:
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -499,7 +499,7 @@ user3:
- +
diff --git a/2016/08/14/34-Search-for-a-Range/index.html b/2016/08/14/34-Search-for-a-Range/index.html index 0070a4be2a..eb5c8f0249 100644 --- a/2016/08/14/34-Search-for-a-Range/index.html +++ b/2016/08/14/34-Search-for-a-Range/index.html @@ -301,7 +301,7 @@ @@ -455,20 +455,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -493,7 +493,7 @@
- +
diff --git a/2016/08/14/docker-mysql-cluster/index.html b/2016/08/14/docker-mysql-cluster/index.html index 28034d5e0d..ceabfd3297 100644 --- a/2016/08/14/docker-mysql-cluster/index.html +++ b/2016/08/14/docker-mysql-cluster/index.html @@ -304,15 +304,15 @@
@@ -453,20 +453,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -491,7 +491,7 @@
diff --git a/2016/09/29/binary-watch/index.html b/2016/09/29/binary-watch/index.html index aac78082c4..37d84d7159 100644 --- a/2016/09/29/binary-watch/index.html +++ b/2016/09/29/binary-watch/index.html @@ -321,7 +321,7 @@ @@ -463,20 +463,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -501,7 +501,7 @@
diff --git a/2016/10/11/minimum-size-subarray-sum-209/index.html b/2016/10/11/minimum-size-subarray-sum-209/index.html index 9612d1af5c..6f9a2eaa5e 100644 --- a/2016/10/11/minimum-size-subarray-sum-209/index.html +++ b/2016/10/11/minimum-size-subarray-sum-209/index.html @@ -311,7 +311,7 @@ @@ -453,20 +453,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -491,7 +491,7 @@
diff --git a/2016/10/12/summary-ranges-228/index.html b/2016/10/12/summary-ranges-228/index.html index 692e065f5b..5b665bcb01 100644 --- a/2016/10/12/summary-ranges-228/index.html +++ b/2016/10/12/summary-ranges-228/index.html @@ -304,13 +304,13 @@ @@ -452,20 +452,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -490,7 +490,7 @@
diff --git a/2016/11/10/php-abstract-class-and-interface/index.html b/2016/11/10/php-abstract-class-and-interface/index.html index bd7481c327..96359b68de 100644 --- a/2016/11/10/php-abstract-class-and-interface/index.html +++ b/2016/11/10/php-abstract-class-and-interface/index.html @@ -447,20 +447,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -485,7 +485,7 @@
diff --git a/2017/03/28/spark-little-tips/index.html b/2017/03/28/spark-little-tips/index.html index ad5605d1be..c93c594b55 100644 --- a/2017/03/28/spark-little-tips/index.html +++ b/2017/03/28/spark-little-tips/index.html @@ -436,20 +436,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -474,7 +474,7 @@
diff --git a/2017/04/25/rabbitmq-tips/index.html b/2017/04/25/rabbitmq-tips/index.html index c52e8a8eda..6102412b5d 100644 --- a/2017/04/25/rabbitmq-tips/index.html +++ b/2017/04/25/rabbitmq-tips/index.html @@ -448,20 +448,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -486,7 +486,7 @@
diff --git a/2017/05/09/ambari-summary/index.html b/2017/05/09/ambari-summary/index.html index 65c08b0910..264e9a6215 100644 --- a/2017/05/09/ambari-summary/index.html +++ b/2017/05/09/ambari-summary/index.html @@ -440,20 +440,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -478,7 +478,7 @@
diff --git a/2019/06/18/openresty/index.html b/2019/06/18/openresty/index.html index cf35243e47..bae6869d19 100644 --- a/2019/06/18/openresty/index.html +++ b/2019/06/18/openresty/index.html @@ -462,20 +462,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -500,7 +500,7 @@
diff --git a/2019/09/23/AbstractQueuedSynchronizer/index.html b/2019/09/23/AbstractQueuedSynchronizer/index.html index d308a49c20..3d51bdb4f5 100644 --- a/2019/09/23/AbstractQueuedSynchronizer/index.html +++ b/2019/09/23/AbstractQueuedSynchronizer/index.html @@ -437,20 +437,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -475,7 +475,7 @@
diff --git a/2019/12/07/JVM-G1-Part-1/index.html b/2019/12/07/JVM-G1-Part-1/index.html index b26f4b1256..3cab6b0761 100644 --- a/2019/12/07/JVM-G1-Part-1/index.html +++ b/2019/12/07/JVM-G1-Part-1/index.html @@ -332,6 +332,9 @@ +
@@ -472,20 +475,20 @@ @@ -510,7 +513,7 @@ diff --git a/2019/12/10/Redis-Part-1/index.html b/2019/12/10/Redis-Part-1/index.html index 434f741ac7..631a4f618b 100644 --- a/2019/12/10/Redis-Part-1/index.html +++ b/2019/12/10/Redis-Part-1/index.html @@ -465,20 +465,20 @@ @@ -503,7 +503,7 @@ diff --git a/2019/12/18/1Q84读后感/index.html b/2019/12/18/1Q84读后感/index.html index 0da99374df..235c97b143 100644 --- a/2019/12/18/1Q84读后感/index.html +++ b/2019/12/18/1Q84读后感/index.html @@ -443,20 +443,20 @@ @@ -481,7 +481,7 @@ diff --git a/2019/12/21/聊聊Java中的单例模式/index.html b/2019/12/21/聊聊Java中的单例模式/index.html index dd0b2f6e20..1b0854ced0 100644 --- a/2019/12/21/聊聊Java中的单例模式/index.html +++ b/2019/12/21/聊聊Java中的单例模式/index.html @@ -456,20 +456,20 @@ @@ -494,7 +494,7 @@ diff --git a/2019/12/26/redis数据结构介绍/index.html b/2019/12/26/redis数据结构介绍/index.html index 561e4d43c1..1f1121bd5b 100644 --- a/2019/12/26/redis数据结构介绍/index.html +++ b/2019/12/26/redis数据结构介绍/index.html @@ -331,10 +331,10 @@
@@ -463,20 +466,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -501,7 +504,7 @@
diff --git a/2020/05/22/聊聊我刚学会的应用诊断方法/index.html b/2020/05/22/聊聊我刚学会的应用诊断方法/index.html new file mode 100644 index 0000000000..bcb5e035b6 --- /dev/null +++ b/2020/05/22/聊聊我刚学会的应用诊断方法/index.html @@ -0,0 +1,777 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 聊聊我刚学会的应用诊断方法 | Nicksxs's Blog + + + + + + + + + + + + + + + + +
+
+ +
+
+ + +
+ + + +

Nicksxs's Blog

+ +
+

What hurts more, the pain of hard work or the pain of regret?

+
+ + +
+ + + + + + + + + +
+
+ + +
+ + 0% +
+ + + + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ 聊聊我刚学会的应用诊断方法 +

+ + +
+ + + + +
+ + +

因为传说中的出身问题,我以前写的是PHP,在使用 swoole 之前,基本的应用调试手段就是简单粗暴的 var_dump,exit,对于单进程模型的 PHP 也是简单有效,技术栈换成 Java 之后,就变得没那么容易,一方面是需要编译,另一方面是一般都是基于 spring 的项目,如果问题定位比较模糊,那框架层的是很难靠简单的 System.out.println 或者打 log 解决,(PS:我觉得可能我写的东西比较适合从 PHP 这种弱类型语言转到 Java 的小白同学)这个时候一方面因为是 Java,有了非常好用的 idea IDE 的支持,可以各种花式调试,条件断点尤其牛叉,但是又因为有 Spring+Java 的双重原因,有些情况下单步调试可以把手按废掉,这也是我之前一直比较困惑苦逼的点,后来随着慢慢精(jiang)进(you)之后,比如对于一个 oom 的情况,我们可以通过启动参数加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=xx/xx 来配置溢出时的堆dump 日志,获取到这个文件后,我们可以通过像 Memory Analyzer (MAT)[https://www.eclipse.org/mat/] (The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption.)来查看诊断问题所在,之前用到的时候是因为有个死循环一直往链表里塞数据,属于比较简单的,后来一次是由于运维进行应用迁移时按默认的统一配置了堆内存大小,导致内存的确不够用,所以溢出了,
今天想说的其实主要是我们的 thread dump,这也是我最近才真正用的一个方法,可能真的很小白了,用过 ide 的单步调试其实都知道会有一个一层层的玩意,比如函数从 A,调用了 B,再从 B 调用了 C,一直往下(因为是 Java,所以还有很多🤦‍♂️),这个其实也是大部分语言的调用模型,利用了栈这个数据结构,通过这个结构我们可以知道代码的调用链路,由于对于一个 spring 应用,在本身框架代码量非常庞大的情况下,外加如果应用代码也是非常多的时候,有时候通过单步调试真的很难短时间定位到问题,需要非常大的耐心和仔细观察,当然不是说完全不行,举个例子当我的应用经常启动需要非常长的时间,因为本身应用有非常多个 bean,比较难说究竟是 bean 的加载的确很慢还是有什么异常原因,这种时候就可以使用 thread dump 了,具体怎么操作呢

如果在idea 中运行或者调试时,可以直接点击这个照相机一样的按钮,右边就会出现了左边会显示所有的线程,右边会显示线程栈,

+
1
2
3
4
5
6
7
"main@1" prio=5 tid=0x1 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at TreeDistance.treeDist(TreeDistance.java:64)
at TreeDistance.treeDist(TreeDistance.java:65)
at TreeDistance.treeDist(TreeDistance.java:65)
at TreeDistance.treeDist(TreeDistance.java:65)
at TreeDistance.main(TreeDistance.java:45)
+

这就是我们主线程的堆栈信息了,main 表示这个线程名,prio表示优先级,默认是 5,tid 表示线程 id,nid 表示对应的系统线程,后面的runnable 表示目前线程状态,因为是被我打了断点,所以是就许状态,然后下面就是对应的线程栈内容了,在TreeDistance类的 treeDist方法中,对应的文件行数是 64 行。
这里使用 thread dump一般也不会是上面我截图代码里的这种代码量很少的,一般是大型项目,有时候跑着跑着没反应,又不知道跑到哪了,特别是一些刚接触的大项目或者需要定位一个大项目的一个疑难问题,一时没思路时,可以使用这个方法,个人觉得非常有帮助。

+ +
+ + + + + + + + +
+
请我喝杯咖啡
+ + +
+ + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/404.html b/404.html index c86ca27501..63c0aa5b85 100644 --- a/404.html +++ b/404.html @@ -320,20 +320,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -358,7 +358,7 @@
diff --git a/404/index.html b/404/index.html index b1db30cc33..7d976a795f 100644 --- a/404/index.html +++ b/404/index.html @@ -307,20 +307,20 @@
- 50 + 51 posts
- 41 + 44 categories
- 68 + 69 tags
@@ -345,7 +345,7 @@
diff --git a/archives/2014/12/index.html b/archives/2014/12/index.html index a9450207b5..2aa745769e 100644 --- a/archives/2014/12/index.html +++ b/archives/2014/12/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -350,20 +350,20 @@ @@ -388,7 +388,7 @@ diff --git a/archives/2014/index.html b/archives/2014/index.html index 286fa6b0cc..f3a0a4a0f9 100644 --- a/archives/2014/index.html +++ b/archives/2014/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -350,20 +350,20 @@ @@ -388,7 +388,7 @@ diff --git a/archives/2015/01/index.html b/archives/2015/01/index.html index 6897145e87..5888b06141 100644 --- a/archives/2015/01/index.html +++ b/archives/2015/01/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -350,20 +350,20 @@ @@ -388,7 +388,7 @@ diff --git a/archives/2015/03/index.html b/archives/2015/03/index.html index 0942570d45..169ac5c464 100644 --- a/archives/2015/03/index.html +++ b/archives/2015/03/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -350,20 +350,20 @@ @@ -388,7 +388,7 @@ diff --git a/archives/2015/04/index.html b/archives/2015/04/index.html index 30dba79759..a70860b8ce 100644 --- a/archives/2015/04/index.html +++ b/archives/2015/04/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -330,20 +330,20 @@ @@ -368,7 +368,7 @@ diff --git a/archives/2015/06/index.html b/archives/2015/06/index.html index 1ebd0be66f..34f3aa0efc 100644 --- a/archives/2015/06/index.html +++ b/archives/2015/06/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/archives/2015/index.html b/archives/2015/index.html index 40b35062d1..e88252fa1a 100644 --- a/archives/2015/index.html +++ b/archives/2015/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -470,20 +470,20 @@ @@ -508,7 +508,7 @@ diff --git a/archives/2016/07/index.html b/archives/2016/07/index.html index e73a49963b..5c8178144c 100644 --- a/archives/2016/07/index.html +++ b/archives/2016/07/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/archives/2016/08/index.html b/archives/2016/08/index.html index 416df54482..31fca3d540 100644 --- a/archives/2016/08/index.html +++ b/archives/2016/08/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -330,20 +330,20 @@ @@ -368,7 +368,7 @@ diff --git a/archives/2016/09/index.html b/archives/2016/09/index.html index ad1bd4a3f2..0edd35c72f 100644 --- a/archives/2016/09/index.html +++ b/archives/2016/09/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/archives/2016/10/index.html b/archives/2016/10/index.html index 264187bb15..9f5c5e2025 100644 --- a/archives/2016/10/index.html +++ b/archives/2016/10/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -330,20 +330,20 @@ @@ -368,7 +368,7 @@ diff --git a/archives/2016/11/index.html b/archives/2016/11/index.html index 17d3353ec4..fa8dd2aea4 100644 --- a/archives/2016/11/index.html +++ b/archives/2016/11/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/archives/2016/index.html b/archives/2016/index.html index f7859af587..fccb24e3ce 100644 --- a/archives/2016/index.html +++ b/archives/2016/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -430,20 +430,20 @@ @@ -468,7 +468,7 @@ diff --git a/archives/2017/03/index.html b/archives/2017/03/index.html index 3ce0e9c6b9..301ce79eef 100644 --- a/archives/2017/03/index.html +++ b/archives/2017/03/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/archives/2017/04/index.html b/archives/2017/04/index.html index df730fbe2d..cbab517bfb 100644 --- a/archives/2017/04/index.html +++ b/archives/2017/04/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/archives/2017/05/index.html b/archives/2017/05/index.html index b1c75518dd..1012fb31b3 100644 --- a/archives/2017/05/index.html +++ b/archives/2017/05/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/archives/2017/index.html b/archives/2017/index.html index 3e79929ace..b5599e0c33 100644 --- a/archives/2017/index.html +++ b/archives/2017/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -350,20 +350,20 @@ @@ -388,7 +388,7 @@ diff --git a/archives/2019/06/index.html b/archives/2019/06/index.html index 42d6c203aa..d468013512 100644 --- a/archives/2019/06/index.html +++ b/archives/2019/06/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/archives/2019/09/index.html b/archives/2019/09/index.html index c0ef3d5496..47ada35fc9 100644 --- a/archives/2019/09/index.html +++ b/archives/2019/09/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/archives/2019/12/index.html b/archives/2019/12/index.html index f124ab4fd3..ced926363e 100644 --- a/archives/2019/12/index.html +++ b/archives/2019/12/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -390,20 +390,20 @@ @@ -428,7 +428,7 @@ diff --git a/archives/2019/index.html b/archives/2019/index.html index 72695a3b1b..8d96acb308 100644 --- a/archives/2019/index.html +++ b/archives/2019/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -430,20 +430,20 @@ @@ -468,7 +468,7 @@ diff --git a/archives/2020/01/index.html b/archives/2020/01/index.html index faf79d2dc9..87eaf61163 100644 --- a/archives/2020/01/index.html +++ b/archives/2020/01/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -390,20 +390,20 @@ @@ -428,7 +428,7 @@ diff --git a/archives/2020/02/index.html b/archives/2020/02/index.html index f3161fc86c..d3158c0ca9 100644 --- a/archives/2020/02/index.html +++ b/archives/2020/02/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -370,20 +370,20 @@ @@ -408,7 +408,7 @@ diff --git a/archives/2020/03/index.html b/archives/2020/03/index.html index 7326b1c0c0..9779d72491 100644 --- a/archives/2020/03/index.html +++ b/archives/2020/03/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -390,20 +390,20 @@ @@ -428,7 +428,7 @@ diff --git a/archives/2020/04/index.html b/archives/2020/04/index.html index 2aa5aed5fa..7f1127af03 100644 --- a/archives/2020/04/index.html +++ b/archives/2020/04/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -370,20 +370,20 @@ @@ -408,7 +408,7 @@ diff --git a/archives/2020/05/index.html b/archives/2020/05/index.html index 3d561b8759..de83666b2b 100644 --- a/archives/2020/05/index.html +++ b/archives/2020/05/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -216,6 +216,26 @@ 2020
+ +
@@ -350,20 +370,20 @@ @@ -388,7 +408,7 @@ diff --git a/archives/2020/index.html b/archives/2020/index.html index d1365a1ac8..4236d9e90d 100644 --- a/archives/2020/index.html +++ b/archives/2020/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -216,6 +216,26 @@ 2020
+ +
@@ -396,26 +416,6 @@
- -
@@ -493,20 +493,20 @@ @@ -531,7 +531,7 @@ diff --git a/archives/2020/page/2/index.html b/archives/2020/page/2/index.html index ae8f9aba6f..24c9c8a5a0 100644 --- a/archives/2020/page/2/index.html +++ b/archives/2020/page/2/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -216,6 +216,26 @@ 2020
+ +
@@ -396,26 +416,6 @@
- -
@@ -493,20 +493,20 @@ @@ -531,7 +531,7 @@ diff --git a/archives/2020/page/3/index.html b/archives/2020/page/3/index.html index d45bef002d..6ce09468ae 100644 --- a/archives/2020/page/3/index.html +++ b/archives/2020/page/3/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -216,6 +216,26 @@ 2020
+ +
@@ -313,20 +333,20 @@ @@ -351,7 +371,7 @@ diff --git a/archives/index.html b/archives/index.html index 53de5c16bb..729176151f 100644 --- a/archives/index.html +++ b/archives/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -216,6 +216,26 @@ 2020
+ +
@@ -396,26 +416,6 @@
- -
@@ -425,7 +425,7 @@ @@ -493,20 +493,20 @@ @@ -531,7 +531,7 @@ diff --git a/archives/page/2/index.html b/archives/page/2/index.html index 2acdf10d61..d1ac4600b5 100644 --- a/archives/page/2/index.html +++ b/archives/page/2/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -216,6 +216,26 @@ 2020
+ +
@@ -396,26 +416,6 @@
- -
@@ -425,7 +425,7 @@ @@ -493,20 +493,20 @@ @@ -531,7 +531,7 @@ diff --git a/archives/page/3/index.html b/archives/page/3/index.html index 622a7bd7bc..a8eccbe3d4 100644 --- a/archives/page/3/index.html +++ b/archives/page/3/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -216,6 +216,26 @@ 2020
+ +
@@ -402,26 +422,6 @@
- -
@@ -431,7 +431,7 @@ @@ -499,20 +499,20 @@ @@ -537,7 +537,7 @@ diff --git a/archives/page/4/index.html b/archives/page/4/index.html index c54bd57cc2..76e6284cc6 100644 --- a/archives/page/4/index.html +++ b/archives/page/4/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -216,6 +216,26 @@ 2017
+ +
@@ -402,26 +422,6 @@
- -
@@ -431,7 +431,7 @@ @@ -499,20 +499,20 @@ @@ -537,7 +537,7 @@ diff --git a/archives/page/5/index.html b/archives/page/5/index.html index 12eead2234..b845b5c9b0 100644 --- a/archives/page/5/index.html +++ b/archives/page/5/index.html @@ -208,7 +208,7 @@
- OK! 50 posts in total. Keep on posting. + Nice! 51 posts in total. Keep on posting.
@@ -216,6 +216,26 @@ 2015
+ +
@@ -399,26 +419,6 @@
- -
@@ -428,7 +428,7 @@ @@ -496,20 +496,20 @@ @@ -534,7 +534,7 @@ diff --git a/archives/page/6/index.html b/archives/page/6/index.html new file mode 100644 index 0000000000..8cd357c39d --- /dev/null +++ b/archives/page/6/index.html @@ -0,0 +1,596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Archive | Nicksxs's Blog + + + + + + + + + + + + + + + + +
+
+ +
+
+ + +
+ + + +

Nicksxs's Blog

+ +
+

What hurts more, the pain of hard work or the pain of regret?

+
+ + +
+ + + + + + + + + +
+
+ + +
+ + 0% +
+ + + + +
+
+
+ + +
+ + + + + +
+
+
+ + Nice! 51 posts in total. Keep on posting. +
+ + +
+ 2014 +
+ + + + +
+
+ + + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/atom.xml b/atom.xml index b8fbbe4fcf..2127bb12a3 100644 --- a/atom.xml +++ b/atom.xml @@ -6,7 +6,7 @@ - 2020-05-17T15:57:30.000Z + 2020-05-24T13:51:43.115Z https://nicksxs.me/ @@ -16,6 +16,41 @@ Hexo + + 聊聊我刚学会的应用诊断方法 + + https://nicksxs.me/2020/05/22/%E8%81%8A%E8%81%8A%E6%88%91%E5%88%9A%E5%AD%A6%E4%BC%9A%E7%9A%84%E5%BA%94%E7%94%A8%E8%AF%8A%E6%96%AD%E6%96%B9%E6%B3%95/ + 2020-05-22T15:26:50.000Z + 2020-05-24T13:51:43.115Z + + + + + + + + <p>因为传说中的出身问题,我以前写的是PHP,在使用 swoole 之前,基本的应用调试手段就是简单粗暴的 var_dump,exit,对于单进程模型的 PHP 也是简单有效,技术栈换成 Java 之后,就变得没那么容易,一方面是需要编译,另一方面是一般都是基于 spring + + + + + + + + + + + + + + + + + + + + + 聊聊我理解的分布式事务 @@ -79,10 +114,10 @@ - - + + @@ -128,10 +163,10 @@ - - + + @@ -177,10 +212,10 @@ - - + + @@ -731,46 +766,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - redis数据结构介绍三-第三部分 整数集合 - - https://nicksxs.me/2020/01/10/redis%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%BB%8B%E7%BB%8D%E4%B8%89/ - 2020-01-09T16:54:04.000Z - 2020-01-12T13:08:27.005Z - - - - - - - - <p>redis中对于 set 其实有两种处理,对于元素均为整型,并且元素数目较少时,使用 intset 作为底层数据结构,否则使用 dict 作为底层数据结构,先看一下代码先</p> -<figure class="highlight c"><table><tr><td - - - diff --git a/baidu_verify_Gl8jtoDV4z.html b/baidu_verify_Gl8jtoDV4z.html index b7ad5dbe59..a00e8aca6b 100644 --- a/baidu_verify_Gl8jtoDV4z.html +++ b/baidu_verify_Gl8jtoDV4z.html @@ -309,20 +309,20 @@ @@ -347,7 +347,7 @@ diff --git a/baidusitemap.xml b/baidusitemap.xml index 121cdee601..f151dce51f 100644 --- a/baidusitemap.xml +++ b/baidusitemap.xml @@ -1,6 +1,9 @@ + https://nicksxs.me/2020/05/22/%E8%81%8A%E8%81%8A%E6%88%91%E5%88%9A%E5%AD%A6%E4%BC%9A%E7%9A%84%E5%BA%94%E7%94%A8%E8%AF%8A%E6%96%AD%E6%96%B9%E6%B3%95/ + 2020-05-24 + https://nicksxs.me/2020/05/17/%E8%81%8A%E8%81%8A%E6%88%91%E7%90%86%E8%A7%A3%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/ 2020-05-17 @@ -57,27 +60,27 @@ https://nicksxs.me/2020/01/19/redis%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%BB%8B%E7%BB%8D%E5%9B%9B/ 2020-01-18 - - https://nicksxs.me/2019/12/10/Redis-Part-1/ - 2020-01-12 https://nicksxs.me/2015/01/14/Two-Sum/ 2020-01-12 - https://nicksxs.me/2016/11/10/php-abstract-class-and-interface/ + https://nicksxs.me/2019/12/10/Redis-Part-1/ 2020-01-12 https://nicksxs.me/2016/09/29/binary-watch/ 2020-01-12 - https://nicksxs.me/2019/12/26/redis%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%BB%8B%E7%BB%8D/ + https://nicksxs.me/2016/11/10/php-abstract-class-and-interface/ 2020-01-12 - https://nicksxs.me/2015/04/14/Add-Two-Number/ + https://nicksxs.me/2019/12/26/redis%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%BB%8B%E7%BB%8D/ 2020-01-12 https://nicksxs.me/2015/03/13/Reverse-Integer/ 2020-01-12 + + https://nicksxs.me/2015/04/14/Add-Two-Number/ + 2020-01-12 https://nicksxs.me/2014/12/24/MFC%20%E6%A8%A1%E6%80%81%E5%AF%B9%E8%AF%9D%E6%A1%86/ 2020-01-12 @@ -85,10 +88,10 @@ https://nicksxs.me/2016/08/14/docker-mysql-cluster/ 2020-01-12 - https://nicksxs.me/2019/06/18/openresty/ + https://nicksxs.me/2017/05/09/ambari-summary/ 2020-01-12 - https://nicksxs.me/2017/05/09/ambari-summary/ + https://nicksxs.me/2019/06/18/openresty/ 2020-01-12 https://nicksxs.me/2020/01/04/redis%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%BB%8B%E7%BB%8D%E4%BA%8C/ @@ -133,10 +136,10 @@ https://nicksxs.me/2015/03/11/Number-Of-1-Bits/ 2020-01-12 - https://nicksxs.me/2015/04/15/Leetcode-No-3/ + https://nicksxs.me/2019/09/23/AbstractQueuedSynchronizer/ 2020-01-12 - https://nicksxs.me/2019/09/23/AbstractQueuedSynchronizer/ + https://nicksxs.me/2015/04/15/Leetcode-No-3/ 2020-01-12 https://nicksxs.me/2015/01/16/pcre-intro-and-a-simple-package/ diff --git a/categories/C/Mysql/index.html b/categories/C/Mysql/index.html index 4475af85d8..adcbb8d7f3 100644 --- a/categories/C/Mysql/index.html +++ b/categories/C/Mysql/index.html @@ -350,20 +350,20 @@ @@ -388,7 +388,7 @@ diff --git a/categories/C/Redis/index.html b/categories/C/Redis/index.html index f65e862ad6..af4aec6018 100644 --- a/categories/C/Redis/index.html +++ b/categories/C/Redis/index.html @@ -473,20 +473,20 @@ @@ -511,7 +511,7 @@ diff --git a/categories/C/index.html b/categories/C/index.html index d746deb676..09aab7f2d6 100644 --- a/categories/C/index.html +++ b/categories/C/index.html @@ -493,20 +493,20 @@ @@ -531,7 +531,7 @@ diff --git a/categories/C/page/2/index.html b/categories/C/page/2/index.html index ae34c0d5e1..0b3cd9490f 100644 --- a/categories/C/page/2/index.html +++ b/categories/C/page/2/index.html @@ -333,20 +333,20 @@ @@ -371,7 +371,7 @@ diff --git a/categories/Java/Design-Patterns/index.html b/categories/Java/Design-Patterns/index.html index 043c616765..5316a0267e 100644 --- a/categories/Java/Design-Patterns/index.html +++ b/categories/Java/Design-Patterns/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/Java/GC/index.html b/categories/Java/GC/index.html index e2626ad196..b5c3cf797e 100644 --- a/categories/Java/GC/index.html +++ b/categories/Java/GC/index.html @@ -333,20 +333,20 @@ @@ -371,7 +371,7 @@ diff --git a/categories/Java/JVM/index.html b/categories/Java/JVM/index.html index 94dd11af2c..d07c8c3dab 100644 --- a/categories/Java/JVM/index.html +++ b/categories/Java/JVM/index.html @@ -333,20 +333,20 @@ @@ -371,7 +371,7 @@ diff --git a/categories/Java/Maven/index.html b/categories/Java/Maven/index.html index 901775604f..0e197fef7a 100644 --- a/categories/Java/Maven/index.html +++ b/categories/Java/Maven/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/Java/Singleton/index.html b/categories/Java/Singleton/index.html index d3df49ecbd..f26848a9a8 100644 --- a/categories/Java/Singleton/index.html +++ b/categories/Java/Singleton/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/Java/index.html b/categories/Java/index.html index b1e1171565..90e94c42f0 100644 --- a/categories/Java/index.html +++ b/categories/Java/index.html @@ -29,7 +29,7 @@ - + @@ -40,7 +40,7 @@ - + - Category: java | Nicksxs's Blog + Category: Java | Nicksxs's Blog - - - - - - -if (CONFIG.page.isPost) { - if (CONFIG.hostname !== location.hostname) return; - addCount(Counter); - } else if (document.querySelectorAll('.post-title-link').length >= 1) { - showTime(Counter); - } - } - - let api_server = app_id.slice(-9) !== '-MdYXbMMI' ? server_url : `https://${app_id.slice(0, 8).toLowerCase()}.api.lncldglobal.com`; - - if (api_server) { - fetchData(api_server); - } else { - fetch('https://app-router.leancloud.cn/2/route?appId=' + app_id) - .then(response => response.json()) - .then(({ api_server }) => { - fetchData('https://' + api_server); - }); - } - })(); - - - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Category: Thread dump | Nicksxs's Blog + + + + + + + + + + + + + + + + +
+
+ +
+
+ + +
+ + + +

Nicksxs's Blog

+ +
+

What hurts more, the pain of hard work or the pain of regret?

+
+ + +
+ + + + + + + + + +
+
+ + +
+ + 0% +
+ + + + +
+
+
+ + +
+ + + + + +
+
+
+

Thread dump + Category +

+
+ + +
+ 2020 +
+ + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/categories/data-analysis/index.html b/categories/data-analysis/index.html index 5a8294d259..ea8a49753d 100644 --- a/categories/data-analysis/index.html +++ b/categories/data-analysis/index.html @@ -330,20 +330,20 @@ @@ -368,7 +368,7 @@ diff --git a/categories/docker/index.html b/categories/docker/index.html index 1c5ee3138d..4d8983ba81 100644 --- a/categories/docker/index.html +++ b/categories/docker/index.html @@ -29,7 +29,7 @@ - + @@ -40,7 +40,7 @@ - + - Category: Docker | Nicksxs's Blog + Category: docker | Nicksxs's Blog + + + + + + +id.slice(0, 8).toLowerCase()}.api.lncldglobal.com`; + + if (api_server) { + fetchData(api_server); + } else { + fetch('https://app-router.leancloud.cn/2/route?appId=' + app_id) + .then(response => response.json()) + .then(({ api_server }) => { + fetchData('https://' + api_server); + }); + } + })(); + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Category: 工具 | Nicksxs's Blog + + + + + + + + + + + + + + + + +
+
+ +
+
+ + +
+ + + +

Nicksxs's Blog

+ +
+

What hurts more, the pain of hard work or the pain of regret?

+
+ + +
+ + + + + + + + + +
+
+ + +
+ + 0% +
+ + + + +
+
+
+ + +
+ + + + + +
+
+
+

工具 + Category +

+
+ + +
+ 2020 +
+ + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/categories/持续集成/index.html b/categories/持续集成/index.html index 3767b9ae75..29d721af40 100644 --- a/categories/持续集成/index.html +++ b/categories/持续集成/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/生活/index.html b/categories/生活/index.html index 6c7e97f29b..023cc92fe6 100644 --- a/categories/生活/index.html +++ b/categories/生活/index.html @@ -353,20 +353,20 @@ @@ -391,7 +391,7 @@ diff --git a/categories/生活/年终总结/2019/index.html b/categories/生活/年终总结/2019/index.html index b4cc057e3f..affd75e900 100644 --- a/categories/生活/年终总结/2019/index.html +++ b/categories/生活/年终总结/2019/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/生活/年终总结/index.html b/categories/生活/年终总结/index.html index 54268e5afd..2a06e6d8aa 100644 --- a/categories/生活/年终总结/index.html +++ b/categories/生活/年终总结/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/生活/影评/2020/index.html b/categories/生活/影评/2020/index.html index cce028e4f3..17adf3941e 100644 --- a/categories/生活/影评/2020/index.html +++ b/categories/生活/影评/2020/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/生活/影评/index.html b/categories/生活/影评/index.html index 3c0026899b..b18622b21a 100644 --- a/categories/生活/影评/index.html +++ b/categories/生活/影评/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/读后感/index.html b/categories/读后感/index.html index 76ad1429b6..c4df3409ef 100644 --- a/categories/读后感/index.html +++ b/categories/读后感/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/读后感/村上春树/index.html b/categories/读后感/村上春树/index.html index d4f803993b..e9ef0e292e 100644 --- a/categories/读后感/村上春树/index.html +++ b/categories/读后感/村上春树/index.html @@ -310,20 +310,20 @@ @@ -348,7 +348,7 @@ diff --git a/categories/问题排查/index.html b/categories/问题排查/index.html new file mode 100644 index 0000000000..8bbb4ce0a9 --- /dev/null +++ b/categories/问题排查/index.html @@ -0,0 +1,603 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Category: 问题排查 | Nicksxs's Blog + + + + + + + + + + + + + + + + +
+
+ +
+
+ + +
+ + + +

Nicksxs's Blog

+ +
+

What hurts more, the pain of hard work or the pain of regret?

+
+ + +
+ + + + + + + + + +
+
+ + +
+ + 0% +
+ + + + +
+
+
+ + +
+ + + + + +
+
+
+

问题排查 + Category +

+
+ + +
+ 2020 +
+ + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/css/main.css b/css/main.css index 6152c58508..dad54bb2c6 100644 --- a/css/main.css +++ b/css/main.css @@ -1262,7 +1262,7 @@ pre .javascript .function { } .links-of-author a::before, .links-of-author span.exturl::before { - background: #8b7cfe; + background: #0a18b4; border-radius: 50%; content: ' '; display: inline-block; diff --git a/index.html b/index.html index 17bd9e56b7..60001a3736 100644 --- a/index.html +++ b/index.html @@ -203,6 +203,117 @@ +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

因为传说中的出身问题,我以前写的是PHP,在使用 swoole 之前,基本的应用调试手段就是简单粗暴的 var_dump,exit,对于单进程模型的 PHP 也是简单有效,技术栈换成 Java 之后,就变得没那么容易,一方面是需要编译,另一方面是一般都是基于 spring 的项目,如果问题定位比较模糊,那框架层的是很难靠简单的 System.out.println 或者打 log 解决,(PS:我觉得可能我写的东西比较适合从 PHP 这种弱类型语言转到 Java 的小白同学)这个时候一方面因为是 Java,有了非常好用的 idea IDE 的支持,可以各种花式调试,条件断点尤其牛叉,但是又因为有 Spring+Java 的双重原因,有些情况下单步调试可以把手按废掉,这也是我之前一直比较困惑苦逼的点,后来随着慢慢精(jiang)进(you)之后,比如对于一个 oom 的情况,我们可以通过启动参数加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=xx/xx 来配置溢出时的堆dump 日志,获取到这个文件后,我们可以通过像 Memory Analyzer (MAT)[https://www.eclipse.org/mat/] (The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption.)来查看诊断问题所在,之前用到的时候是因为有个死循环一直往链表里塞数据,属于比较简单的,后来一次是由于运维进行应用迁移时按默认的统一配置了堆内存大小,导致内存的确不够用,所以溢出了,
今天想说的其实主要是我们的 thread dump,这也是我最近才真正用的一个方法,可能真的很小白了,用过 ide 的单步调试其实都知道会有一个一层层的玩意,比如函数从 A,调用了 B,再从 B 调用了 C,一直往下(因为是 Java,所以还有很多🤦‍♂️),这个其实也是大部分语言的调用模型,利用了栈这个数据结构,通过这个结构我们可以知道代码的调用链路,由于对于一个 spring 应用,在本身框架代码量非常庞大的情况下,外加如果应用代码也是非常多的时候,有时候通过单步调试真的很难短时间定位到问题,需要非常大的耐心和仔细观察,当然不是说完全不行,举个例子当我的应用经常启动需要非常长的时间,因为本身应用有非常多个 bean,比较难说究竟是 bean 的加载的确很慢还是有什么异常原因,这种时候就可以使用 thread dump 了,具体怎么操作呢

如果在idea 中运行或者调试时,可以直接点击这个照相机一样的按钮,右边就会出现了左边会显示所有的线程,右边会显示线程栈,

+
1
2
3
4
5
6
7
"main@1" prio=5 tid=0x1 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at TreeDistance.treeDist(TreeDistance.java:64)
at TreeDistance.treeDist(TreeDistance.java:65)
at TreeDistance.treeDist(TreeDistance.java:65)
at TreeDistance.treeDist(TreeDistance.java:65)
at TreeDistance.main(TreeDistance.java:45)
+

这就是我们主线程的堆栈信息了,main 表示这个线程名,prio表示优先级,默认是 5,tid 表示线程 id,nid 表示对应的系统线程,后面的runnable 表示目前线程状态,因为是被我打了断点,所以是就许状态,然后下面就是对应的线程栈内容了,在TreeDistance类的 treeDist方法中,对应的文件行数是 64 行。
这里使用 thread dump一般也不会是上面我截图代码里的这种代码量很少的,一般是大型项目,有时候跑着跑着没反应,又不知道跑到哪了,特别是一些刚接触的大项目或者需要定位一个大项目的一个疑难问题,一时没思路时,可以使用这个方法,个人觉得非常有帮助。

+ + +
+ + + + + + +
+
+
+
+ + + + + + +
@@ -365,11 +476,11 @@ , - + , - + , @@ -490,11 +601,11 @@ , - + , - + , @@ -610,11 +721,11 @@ , - + , - + , @@ -1284,122 +1395,10 @@ - - - -
- - - - - -
-

- - -

- - -
- - - - -
- - -

限制下 docker 的 cpu 使用率

这里我们开始玩一点有意思的,我们在容器里装下 vim 和 gcc,然后写这样一段 c 代码

-
1
2
3
4
5
6
7
#include <stdio.h>
int main(void)
{
int i = 0;
for(;;) i++;
return 0;
}
-

就是一个最简单的死循环,然后在容器里跑起来

-
1
2
$ gcc 1.c 
$ ./a.out
-

然后我们来看下系统资源占用(CPU)
Xs562iawhHyMxeO
上图是在容器里的,可以看到 cpu 已经 100%了
然后看看容器外面的
ecqH8XJ4k7rKhzu
可以看到一个核的 cpu 也被占满了,因为是个双核的机器,并且代码是单线程的
然后呢我们要做点啥
因为已经在这个 ubuntu 容器中装了 vim 和 gcc,考虑到国内的网络,所以我们先把这个容器 commit 一下,

-
1
docker commit -a "nick" -m "my ubuntu" f63c5607df06 my_ubuntu:v1
-

然后再运行起来

-
1
docker run -it --cpus=0.1 my_ubuntu:v1 bash
-


我们的代码跟可执行文件都还在,要的就是这个效果,然后再运行一下

结果是这个样子的,有点神奇是不,关键就在于 run 的时候的--cpus=0.1这个参数,它其实就是基于我前一篇说的 cgroup 技术,能将进程之间的cpu,内存等资源进行隔离

-

开始第一个 Dockerfile

上一面为了复用那个我装了 vim 跟 gcc 的容器,我把它提交到了本地,使用了docker commit命令,有点类似于 git 的 commit,但是这个不是个很好的操作方式,需要手动介入,这里更推荐使用 Dockerfile 来构建镜像

-
1
2
3
4
5
6
7
8
From ubuntu:latest
MAINTAINER Nicksxs "nicksxs@hotmail.com"
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean
RUN apt-get update && apt install -y nginx
RUN echo 'Hi, i am in container' \
> /usr/share/nginx/html/index.html
EXPOSE 80
-

先解释下这是在干嘛,首先是这个From ubuntu:latest基于的 ubuntu 的最新版本的镜像,然后第二行是维护人的信息,第三四行么作为墙内人你懂的,把 ubuntu 的源换成阿里云的,不然就有的等了,然后就是装下 nginx,往默认的 nginx 的入口 html 文件里输入一行欢迎语,然后暴露 80 端口
然后我们使用sudo docker build -t="nicksxs/static_web" .命令来基于这个 Dockerfile 构建我们自己的镜像,过程中是这样的


可以看到图中,我的 Dockerfile 是 7 行,里面就执行了 7 步,并且每一步都有一个类似于容器 id 的层 id 出来,这里就是一个比较重要的东西,docker 在构建的时候其实是有这个层的概念,Dockerfile 里的每一行都会往上加一层,这里有还注意下命令后面的.,代表当前目录下会自行去寻找 Dockerfile 进行构建,构建完了之后我们再看下我们的本地镜像

我们自己的镜像出现啦
然后有个问题,如果这个构建中途报了错咋办呢,来试试看,我们把 nginx 改成随便的一个错误名,nginxx(不知道会不会运气好真的有这玩意),再来 build 一把

找不到 nginxx 包,是不是这个镜像就完全不能用呢,当然也不是,因为前面说到了,docker 是基于层去构建的,可以看到前面的 4 个 step 都没报错,那我们基于最后的成功步骤创建下容器看看
也就是sudo docker run -t -i bd26f991b6c8 /bin/bash
答案是可以的,只是没装成功 nginx

还有一点注意到没,前面的几个 step 都有一句 Using cache,说明 docker 在构建镜像的时候是有缓存的,这也更能说明 docker 是基于层去构建镜像,同样的底包,同样的步骤,这些层是可以被复用的,这就是 docker 的构建缓存,当然我们也可以在 build 的时候加上--no-cache去把构建缓存禁用掉。

- - -
- - - - - - -
-
-
-
- - - - @@ -1467,20 +1466,20 @@ @@ -1505,7 +1504,7 @@ diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json index d5e563af33..6a637c54ff 100644 --- a/leancloud_counter_security_urls.json +++ b/leancloud_counter_security_urls.json @@ -1 +1 @@ -[{"title":"2019年终总结","url":"/2020/02/01/2019年终总结/"},{"title":"村上春树《1Q84》读后感","url":"/2019/12/18/1Q84读后感/"},{"title":"34_Search_for_a_Range","url":"/2016/08/14/34-Search-for-a-Range/"},{"title":"AbstractQueuedSynchronizer","url":"/2019/09/23/AbstractQueuedSynchronizer/"},{"title":"add-two-number","url":"/2015/04/14/Add-Two-Number/"},{"title":"Clone Graph Part I","url":"/2014/12/30/Clone-Graph-Part-I/"},{"title":"G1收集器概述","url":"/2020/02/09/G1收集器概述/"},{"title":"Comparator使用小记","url":"/2020/04/05/Comparator使用小记/"},{"title":"leetcode no.3","url":"/2015/04/15/Leetcode-No-3/"},{"title":"MFC 模态对话框","url":"/2014/12/24/MFC 模态对话框/"},{"title":"Number of 1 Bits","url":"/2015/03/11/Number-Of-1-Bits/"},{"title":"Maven实用小技巧","url":"/2020/02/16/Maven实用小技巧/"},{"title":"Path Sum","url":"/2015/01/04/Path-Sum/"},{"title":"Redis_分布式锁","url":"/2019/12/10/Redis-Part-1/"},{"title":"Reverse Bits","url":"/2015/03/11/Reverse-Bits/"},{"title":"Reverse Integer","url":"/2015/03/13/Reverse-Integer/"},{"title":"two sum","url":"/2015/01/14/Two-Sum/"},{"title":"ambari-summary","url":"/2017/05/09/ambari-summary/"},{"title":"docker-mysql-cluster","url":"/2016/08/14/docker-mysql-cluster/"},{"title":"binary-watch","url":"/2016/09/29/binary-watch/"},{"title":"docker比一般多一点的初学者介绍","url":"/2020/03/08/docker比一般多一点的初学者介绍/"},{"title":"docker比一般多一点的初学者介绍三","url":"/2020/03/21/docker比一般多一点的初学者介绍三/"},{"title":"docker比一般多一点的初学者介绍二","url":"/2020/03/15/docker比一般多一点的初学者介绍二/"},{"title":"minimum-size-subarray-sum-209","url":"/2016/10/11/minimum-size-subarray-sum-209/"},{"title":"invert-binary-tree","url":"/2015/06/22/invert-binary-tree/"},{"title":"gogs使用webhook部署react单页应用","url":"/2020/02/22/gogs使用webhook部署react单页应用/"},{"title":"C++ 指针使用中的一个小问题","url":"/2014/12/23/my-new-post/"},{"title":"openresty","url":"/2019/06/18/openresty/"},{"title":"docker使用中发现的echo命令的一个小技巧及其他","url":"/2020/03/29/echo命令的一个小技巧/"},{"title":"pcre-intro-and-a-simple-package","url":"/2015/01/16/pcre-intro-and-a-simple-package/"},{"title":"php-abstract-class-and-interface","url":"/2016/11/10/php-abstract-class-and-interface/"},{"title":"redis数据结构介绍二-第二部分 跳表","url":"/2020/01/04/redis数据结构介绍二/"},{"title":"redis数据结构介绍三-第三部分 整数集合","url":"/2020/01/10/redis数据结构介绍三/"},{"title":"rabbitmq-tips","url":"/2017/04/25/rabbitmq-tips/"},{"title":"redis数据结构介绍五-第五部分 对象","url":"/2020/01/20/redis数据结构介绍五/"},{"title":"redis数据结构介绍四-第四部分 压缩表","url":"/2020/01/19/redis数据结构介绍四/"},{"title":"spark-little-tips","url":"/2017/03/28/spark-little-tips/"},{"title":"summary-ranges-228","url":"/2016/10/12/summary-ranges-228/"},{"title":"swoole-websocket-test","url":"/2016/07/13/swoole-websocket-test/"},{"title":"寄生虫观后感","url":"/2020/03/01/寄生虫观后感/"},{"title":"聊聊 mysql 的 MVCC","url":"/2020/04/26/聊聊-mysql-的-MVCC/"},{"title":"聊聊 mysql 的 MVCC 续篇","url":"/2020/05/02/聊聊-mysql-的-MVCC-续篇/"},{"title":"聊聊Java中的单例模式","url":"/2019/12/21/聊聊Java中的单例模式/"},{"title":"聊聊我理解的分布式事务","url":"/2020/05/17/聊聊我理解的分布式事务/"},{"title":"聊聊 mysql 的 MVCC 续续篇之锁分析","url":"/2020/05/10/聊聊-mysql-的-MVCC-续续篇之加锁分析/"},{"title":"redis数据结构介绍-第一部分 SDS,链表,字典","url":"/2019/12/26/redis数据结构介绍/"},{"title":"redis数据结构介绍六 快表","url":"/2020/01/22/redis数据结构介绍六/"},{"title":"redis系列介绍七-过期策略","url":"/2020/04/12/redis系列介绍七/"},{"title":"JVM源码分析之G1垃圾收集器分析一","url":"/2019/12/07/JVM-G1-Part-1/"},{"title":"redis系列介绍八-淘汰策略","url":"/2020/04/18/redis系列介绍八/"}] \ No newline at end of file +[{"title":"2019年终总结","url":"/2020/02/01/2019年终总结/"},{"title":"34_Search_for_a_Range","url":"/2016/08/14/34-Search-for-a-Range/"},{"title":"AbstractQueuedSynchronizer","url":"/2019/09/23/AbstractQueuedSynchronizer/"},{"title":"add-two-number","url":"/2015/04/14/Add-Two-Number/"},{"title":"Clone Graph Part I","url":"/2014/12/30/Clone-Graph-Part-I/"},{"title":"Comparator使用小记","url":"/2020/04/05/Comparator使用小记/"},{"title":"G1收集器概述","url":"/2020/02/09/G1收集器概述/"},{"title":"村上春树《1Q84》读后感","url":"/2019/12/18/1Q84读后感/"},{"title":"leetcode no.3","url":"/2015/04/15/Leetcode-No-3/"},{"title":"MFC 模态对话框","url":"/2014/12/24/MFC 模态对话框/"},{"title":"Maven实用小技巧","url":"/2020/02/16/Maven实用小技巧/"},{"title":"Path Sum","url":"/2015/01/04/Path-Sum/"},{"title":"Number of 1 Bits","url":"/2015/03/11/Number-Of-1-Bits/"},{"title":"Reverse Bits","url":"/2015/03/11/Reverse-Bits/"},{"title":"Reverse Integer","url":"/2015/03/13/Reverse-Integer/"},{"title":"binary-watch","url":"/2016/09/29/binary-watch/"},{"title":"docker-mysql-cluster","url":"/2016/08/14/docker-mysql-cluster/"},{"title":"docker比一般多一点的初学者介绍","url":"/2020/03/08/docker比一般多一点的初学者介绍/"},{"title":"docker比一般多一点的初学者介绍三","url":"/2020/03/21/docker比一般多一点的初学者介绍三/"},{"title":"docker比一般多一点的初学者介绍二","url":"/2020/03/15/docker比一般多一点的初学者介绍二/"},{"title":"docker使用中发现的echo命令的一个小技巧及其他","url":"/2020/03/29/echo命令的一个小技巧/"},{"title":"gogs使用webhook部署react单页应用","url":"/2020/02/22/gogs使用webhook部署react单页应用/"},{"title":"invert-binary-tree","url":"/2015/06/22/invert-binary-tree/"},{"title":"minimum-size-subarray-sum-209","url":"/2016/10/11/minimum-size-subarray-sum-209/"},{"title":"C++ 指针使用中的一个小问题","url":"/2014/12/23/my-new-post/"},{"title":"openresty","url":"/2019/06/18/openresty/"},{"title":"pcre-intro-and-a-simple-package","url":"/2015/01/16/pcre-intro-and-a-simple-package/"},{"title":"php-abstract-class-and-interface","url":"/2016/11/10/php-abstract-class-and-interface/"},{"title":"rabbitmq-tips","url":"/2017/04/25/rabbitmq-tips/"},{"title":"redis数据结构介绍三-第三部分 整数集合","url":"/2020/01/10/redis数据结构介绍三/"},{"title":"redis数据结构介绍二-第二部分 跳表","url":"/2020/01/04/redis数据结构介绍二/"},{"title":"redis数据结构介绍五-第五部分 对象","url":"/2020/01/20/redis数据结构介绍五/"},{"title":"redis数据结构介绍四-第四部分 压缩表","url":"/2020/01/19/redis数据结构介绍四/"},{"title":"ambari-summary","url":"/2017/05/09/ambari-summary/"},{"title":"Redis_分布式锁","url":"/2019/12/10/Redis-Part-1/"},{"title":"two sum","url":"/2015/01/14/Two-Sum/"},{"title":"spark-little-tips","url":"/2017/03/28/spark-little-tips/"},{"title":"summary-ranges-228","url":"/2016/10/12/summary-ranges-228/"},{"title":"swoole-websocket-test","url":"/2016/07/13/swoole-websocket-test/"},{"title":"聊聊 mysql 的 MVCC 续篇","url":"/2020/05/02/聊聊-mysql-的-MVCC-续篇/"},{"title":"聊聊 mysql 的 MVCC 续续篇之锁分析","url":"/2020/05/10/聊聊-mysql-的-MVCC-续续篇之加锁分析/"},{"title":"寄生虫观后感","url":"/2020/03/01/寄生虫观后感/"},{"title":"聊聊我理解的分布式事务","url":"/2020/05/17/聊聊我理解的分布式事务/"},{"title":"聊聊Java中的单例模式","url":"/2019/12/21/聊聊Java中的单例模式/"},{"title":"聊聊我刚学会的应用诊断方法","url":"/2020/05/22/聊聊我刚学会的应用诊断方法/"},{"title":"聊聊 mysql 的 MVCC","url":"/2020/04/26/聊聊-mysql-的-MVCC/"},{"title":"redis数据结构介绍-第一部分 SDS,链表,字典","url":"/2019/12/26/redis数据结构介绍/"},{"title":"redis数据结构介绍六 快表","url":"/2020/01/22/redis数据结构介绍六/"},{"title":"redis系列介绍七-过期策略","url":"/2020/04/12/redis系列介绍七/"},{"title":"JVM源码分析之G1垃圾收集器分析一","url":"/2019/12/07/JVM-G1-Part-1/"},{"title":"redis系列介绍八-淘汰策略","url":"/2020/04/18/redis系列介绍八/"}] \ No newline at end of file diff --git a/lib/pace/README.html b/lib/pace/README.html index d02cda6fa4..aac0164034 100644 --- a/lib/pace/README.html +++ b/lib/pace/README.html @@ -351,20 +351,20 @@ @@ -389,7 +389,7 @@ diff --git a/page/2/index.html b/page/2/index.html index 6f4d6a4169..f2703659c0 100644 --- a/page/2/index.html +++ b/page/2/index.html @@ -203,6 +203,118 @@ +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

限制下 docker 的 cpu 使用率

这里我们开始玩一点有意思的,我们在容器里装下 vim 和 gcc,然后写这样一段 c 代码

+
1
2
3
4
5
6
7
#include <stdio.h>
int main(void)
{
int i = 0;
for(;;) i++;
return 0;
}
+

就是一个最简单的死循环,然后在容器里跑起来

+
1
2
$ gcc 1.c 
$ ./a.out
+

然后我们来看下系统资源占用(CPU)
Xs562iawhHyMxeO
上图是在容器里的,可以看到 cpu 已经 100%了
然后看看容器外面的
ecqH8XJ4k7rKhzu
可以看到一个核的 cpu 也被占满了,因为是个双核的机器,并且代码是单线程的
然后呢我们要做点啥
因为已经在这个 ubuntu 容器中装了 vim 和 gcc,考虑到国内的网络,所以我们先把这个容器 commit 一下,

+
1
docker commit -a "nick" -m "my ubuntu" f63c5607df06 my_ubuntu:v1
+

然后再运行起来

+
1
docker run -it --cpus=0.1 my_ubuntu:v1 bash
+


我们的代码跟可执行文件都还在,要的就是这个效果,然后再运行一下

结果是这个样子的,有点神奇是不,关键就在于 run 的时候的--cpus=0.1这个参数,它其实就是基于我前一篇说的 cgroup 技术,能将进程之间的cpu,内存等资源进行隔离

+

开始第一个 Dockerfile

上一面为了复用那个我装了 vim 跟 gcc 的容器,我把它提交到了本地,使用了docker commit命令,有点类似于 git 的 commit,但是这个不是个很好的操作方式,需要手动介入,这里更推荐使用 Dockerfile 来构建镜像

+
1
2
3
4
5
6
7
8
From ubuntu:latest
MAINTAINER Nicksxs "nicksxs@hotmail.com"
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean
RUN apt-get update && apt install -y nginx
RUN echo 'Hi, i am in container' \
> /usr/share/nginx/html/index.html
EXPOSE 80
+

先解释下这是在干嘛,首先是这个From ubuntu:latest基于的 ubuntu 的最新版本的镜像,然后第二行是维护人的信息,第三四行么作为墙内人你懂的,把 ubuntu 的源换成阿里云的,不然就有的等了,然后就是装下 nginx,往默认的 nginx 的入口 html 文件里输入一行欢迎语,然后暴露 80 端口
然后我们使用sudo docker build -t="nicksxs/static_web" .命令来基于这个 Dockerfile 构建我们自己的镜像,过程中是这样的


可以看到图中,我的 Dockerfile 是 7 行,里面就执行了 7 步,并且每一步都有一个类似于容器 id 的层 id 出来,这里就是一个比较重要的东西,docker 在构建的时候其实是有这个层的概念,Dockerfile 里的每一行都会往上加一层,这里有还注意下命令后面的.,代表当前目录下会自行去寻找 Dockerfile 进行构建,构建完了之后我们再看下我们的本地镜像

我们自己的镜像出现啦
然后有个问题,如果这个构建中途报了错咋办呢,来试试看,我们把 nginx 改成随便的一个错误名,nginxx(不知道会不会运气好真的有这玩意),再来 build 一把

找不到 nginxx 包,是不是这个镜像就完全不能用呢,当然也不是,因为前面说到了,docker 是基于层去构建的,可以看到前面的 4 个 step 都没报错,那我们基于最后的成功步骤创建下容器看看
也就是sudo docker run -t -i bd26f991b6c8 /bin/bash
答案是可以的,只是没装成功 nginx

还有一点注意到没,前面的几个 step 都有一句 Using cache,说明 docker 在构建镜像的时候是有缓存的,这也更能说明 docker 是基于层去构建镜像,同样的底包,同样的步骤,这些层是可以被复用的,这就是 docker 的构建缓存,当然我们也可以在 build 的时候加上--no-cache去把构建缓存禁用掉。

+ + +
+ + + + + + +
+
+
+
+ + + + + + +
@@ -1272,130 +1384,10 @@ - - - -
- - - - - -
-

- - -

- - -
- - - - -
- - -

redis中对于 set 其实有两种处理,对于元素均为整型,并且元素数目较少时,使用 intset 作为底层数据结构,否则使用 dict 作为底层数据结构,先看一下代码先

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct intset {
// 编码方式
uint32_t encoding;
// 集合包含的元素数量
uint32_t length;
// 保存元素的数组
int8_t contents[];
} intset;

/* Note that these encodings are ordered, so:
* INTSET_ENC_INT16 < INTSET_ENC_INT32 < INTSET_ENC_INT64. */
#define INTSET_ENC_INT16 (sizeof(int16_t))
#define INTSET_ENC_INT32 (sizeof(int32_t))
#define INTSET_ENC_INT64 (sizeof(int64_t))
-

一眼看,为啥整型还需要编码,然后 int8_t 怎么能存下大整形呢,带着这些疑问,我们一步步分析下去,这里的编码其实指的是这个整型集合里存的究竟是多大的整型,16 位,还是 32 位,还是 64 位,结构体下面的宏定义就是表示了 encoding 的可能取值,INTSET_ENC_INT16 表示每个元素用2个字节存储,INTSET_ENC_INT32 表示每个元素用4个字节存储,INTSET_ENC_INT64 表示每个元素用8个字节存储。因此,intset中存储的整数最多只能占用64bit。length 就是正常的表示集合中元素的数量。最奇怪的应该就是这个 contents 了,是个 int8_t 的数组,那放毛线数据啊,最小的都有 16 位,这里我在看代码和《redis 设计与实现》的时候也有点懵逼,后来查了下发现这是个比较取巧的用法,这里我用自己的理解表述一下,先看看 8,16,32,64 的关系,一眼看就知道都是 2 的 N 次,并且呈两倍关系,而且 8 位刚好一个字节,所以呢其实这里的contents 不是个常规意义上的 int8_t 类型的数组,而是个柔性数组。看下 wiki 的定义

-
-

Flexible array members1 were introduced in the C99 standard of the C programming language (in particular, in section §6.7.2.1, item 16, page 103).2 It is a member of a struct, which is an array without a given dimension. It must be the last member of such a struct and it must be accompanied by at least one other member, as in the following example:

-
-
1
2
3
4
struct vectord {
size_t len;
double arr[]; // the flexible array member must be last
};
-

在初始化这个 intset 的时候,这个contents数组是不占用空间的,后面的反正用到了申请,那么这里就有一个问题,给出了三种可能的 encoding 值,他们能随便换吗,显然不行,首先在 intset 中数据的存放是有序的,这个有部分原因是方便二分查找,然后存放数据其实随着数据的大小不同会有一个升级的过程,看下图

新创建的intset只有一个header,总共8个字节。其中encoding = 2, length = 0, 类型都是uint32_t,各占 4 字节,添加15, 5两个元素之后,因为它们是比较小的整数,都能使用2个字节表示,所以encoding不变,值还是2,也就是默认的 INTSET_ENC_INT16,当添加32768的时候,它不再能用2个字节来表示了(2个字节能表达的数据范围是-215~215-1,而32768等于215,超出范围了),因此encoding必须升级到INTSET_ENC_INT32(值为4),即用4个字节表示一个元素。在添加每个元素的过程中,intset始终保持从小到大有序。与ziplist类似,intset也是按小端(little endian)模式存储的(参见维基百科词条Endianness)。比如,在上图中intset添加完所有数据之后,表示encoding字段的4个字节应该解释成0x00000004,而第4个数据应该解释成0x00008000 = 32768

- - -
- - - - - - -
-
-
-
- - - - @@ -1463,20 +1455,20 @@ @@ -1501,7 +1493,7 @@ diff --git a/page/3/index.html b/page/3/index.html index 3075434c2c..a36575fd8d 100644 --- a/page/3/index.html +++ b/page/3/index.html @@ -203,6 +203,126 @@ +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

redis中对于 set 其实有两种处理,对于元素均为整型,并且元素数目较少时,使用 intset 作为底层数据结构,否则使用 dict 作为底层数据结构,先看一下代码先

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct intset {
// 编码方式
uint32_t encoding;
// 集合包含的元素数量
uint32_t length;
// 保存元素的数组
int8_t contents[];
} intset;

/* Note that these encodings are ordered, so:
* INTSET_ENC_INT16 < INTSET_ENC_INT32 < INTSET_ENC_INT64. */
#define INTSET_ENC_INT16 (sizeof(int16_t))
#define INTSET_ENC_INT32 (sizeof(int32_t))
#define INTSET_ENC_INT64 (sizeof(int64_t))
+

一眼看,为啥整型还需要编码,然后 int8_t 怎么能存下大整形呢,带着这些疑问,我们一步步分析下去,这里的编码其实指的是这个整型集合里存的究竟是多大的整型,16 位,还是 32 位,还是 64 位,结构体下面的宏定义就是表示了 encoding 的可能取值,INTSET_ENC_INT16 表示每个元素用2个字节存储,INTSET_ENC_INT32 表示每个元素用4个字节存储,INTSET_ENC_INT64 表示每个元素用8个字节存储。因此,intset中存储的整数最多只能占用64bit。length 就是正常的表示集合中元素的数量。最奇怪的应该就是这个 contents 了,是个 int8_t 的数组,那放毛线数据啊,最小的都有 16 位,这里我在看代码和《redis 设计与实现》的时候也有点懵逼,后来查了下发现这是个比较取巧的用法,这里我用自己的理解表述一下,先看看 8,16,32,64 的关系,一眼看就知道都是 2 的 N 次,并且呈两倍关系,而且 8 位刚好一个字节,所以呢其实这里的contents 不是个常规意义上的 int8_t 类型的数组,而是个柔性数组。看下 wiki 的定义

+
+

Flexible array members1 were introduced in the C99 standard of the C programming language (in particular, in section §6.7.2.1, item 16, page 103).2 It is a member of a struct, which is an array without a given dimension. It must be the last member of such a struct and it must be accompanied by at least one other member, as in the following example:

+
+
1
2
3
4
struct vectord {
size_t len;
double arr[]; // the flexible array member must be last
};
+

在初始化这个 intset 的时候,这个contents数组是不占用空间的,后面的反正用到了申请,那么这里就有一个问题,给出了三种可能的 encoding 值,他们能随便换吗,显然不行,首先在 intset 中数据的存放是有序的,这个有部分原因是方便二分查找,然后存放数据其实随着数据的大小不同会有一个升级的过程,看下图

新创建的intset只有一个header,总共8个字节。其中encoding = 2, length = 0, 类型都是uint32_t,各占 4 字节,添加15, 5两个元素之后,因为它们是比较小的整数,都能使用2个字节表示,所以encoding不变,值还是2,也就是默认的 INTSET_ENC_INT16,当添加32768的时候,它不再能用2个字节来表示了(2个字节能表达的数据范围是-215~215-1,而32768等于215,超出范围了),因此encoding必须升级到INTSET_ENC_INT32(值为4),即用4个字节表示一个元素。在添加每个元素的过程中,intset始终保持从小到大有序。与ziplist类似,intset也是按小端(little endian)模式存储的(参见维基百科词条Endianness)。比如,在上图中intset添加完所有数据之后,表示encoding字段的4个字节应该解释成0x00000004,而第4个数据应该解释成0x00008000 = 32768

+ + +
+ + + + + + +
+
+
+
+ + + + + + +
@@ -1245,115 +1365,10 @@ - - - -
- - - - - -
-

- - -

- - -
- - - - -
- - -

rabbitmq 介绍

接触了一下rabbitmq,原来在选型的时候是在rabbitmq跟kafka之间做选择,网上搜了一下之后发现kafka的优势在于吞吐量,而rabbitmq相对注重可靠性,因为应用在im上,需要保证消息不能丢失所以就暂时选定rabbitmq,
Message Queue的需求由来已久,80年代最早在金融交易中,高盛等公司采用Teknekron公司的产品,当时的Message queuing软件叫做:the information bus(TIB)。 TIB被电信和通讯公司采用,路透社收购了Teknekron公司。之后,IBM开发了MQSeries,微软开发了Microsoft Message Queue(MSMQ)。这些商业MQ供应商的问题是厂商锁定,价格高昂。2001年,Java Message queuing试图解决锁定和交互性的问题,但对应用来说反而更加麻烦了。
RabbitMQ采用Erlang语言开发。Erlang语言由Ericson设计,专门为开发concurrent和distribution系统的一种语言,在电信领域使用广泛。OTP(Open Telecom Platform)作为Erlang语言的一部分,包含了很多基于Erlang开发的中间件/库/工具,如mnesia/SASL,极大方便了Erlang应用的开发。OTP就类似于Python语言中众多的module,用户借助这些module可以很方便的开发应用。
于是2004年,摩根大通和iMatrix开始着手Advanced Message Queuing Protocol (AMQP)开放标准的开发。2006年,AMQP规范发布。2007年,Rabbit技术公司基于AMQP标准开发的RabbitMQ 1.0 发布。所有主要的编程语言均有与代理接口通讯的客户端库。

-

简单的使用经验

通俗的理解

这里介绍下其中的一些概念,connection表示和队列服务器的连接,一般情况下是tcp连接, channel表示通道,可以在一个连接上建立多个通道,这里主要是节省了tcp连接握手的成本,exchange可以理解成一个路由器,将消息推送给对应的队列queue,其实是像一个订阅的模式。

-

集群经验

rabbitmqctl stop这个是关闭rabbitmq,在搭建集群时候先关闭服务,然后使用rabbitmq-server -detached静默启动,这时候使用rabbitmqctl cluster_status查看集群状态,因为还没将节点加入集群,所以只能看到类似

-
1
2
3
4
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
{running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}]
...done.
-

然后就可以把当前节点加入集群,

-
1
2
3
4
5
6
7
rabbit2$ rabbitmqctl stop_app #这个stop_app与stop的区别是前者停的是rabbitmq应用,保留erlang节点,
#后者是停止了rabbitmq和erlang节点
Stopping node rabbit@rabbit2 ...done.
rabbit2$ rabbitmqctl join_cluster rabbit@rabbit1 #这里可以用--ram指定将当前节点作为内存节点加入集群
Clustering node rabbit@rabbit2 with [rabbit@rabbit1] ...done.
rabbit2$ rabbitmqctl start_app
Starting node rabbit@rabbit2 ...done.
-

其他可以参考官方文档

-

一些坑

消息丢失

这里碰到过一个坑,对于使用exchange来做消息路由的,会有一个情况,就是在routing_key没被订阅的时候,会将该条找不到路由对应的queue的消息丢掉What happens if we break our contract and send a message with one or four words, like "orange" or "quick.orange.male.rabbit"? Well, these messages won't match any bindings and will be lost.对应链接,而当使用空的exchange时,会保留消息,当出现消费者的时候就可以将收到之前生产者所推送的消息对应链接,这里就是用了空的exchange。

-

集群搭建

集群搭建的时候有个erlang vm生成的random cookie,这个是用来做集群之间认证的,相同的cookie才能连接,但是如果通过vim打开复制后在其他几点新建文件写入会多一个换行,导致集群建立是报错,所以这里最好使用scp等传输命令直接传输cookie文件,同时要注意下cookie的文件权限。
另外在集群搭建的时候如果更改过hostname,那么要把rabbitmq的数据库删除,否则启动后会马上挂掉

- - -
- - - - - - -
-
-
-
- - - - @@ -1421,20 +1436,20 @@ @@ -1459,7 +1474,7 @@ diff --git a/page/4/index.html b/page/4/index.html index c3480f89d5..7da46d19ab 100644 --- a/page/4/index.html +++ b/page/4/index.html @@ -203,6 +203,111 @@ +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

rabbitmq 介绍

接触了一下rabbitmq,原来在选型的时候是在rabbitmq跟kafka之间做选择,网上搜了一下之后发现kafka的优势在于吞吐量,而rabbitmq相对注重可靠性,因为应用在im上,需要保证消息不能丢失所以就暂时选定rabbitmq,
Message Queue的需求由来已久,80年代最早在金融交易中,高盛等公司采用Teknekron公司的产品,当时的Message queuing软件叫做:the information bus(TIB)。 TIB被电信和通讯公司采用,路透社收购了Teknekron公司。之后,IBM开发了MQSeries,微软开发了Microsoft Message Queue(MSMQ)。这些商业MQ供应商的问题是厂商锁定,价格高昂。2001年,Java Message queuing试图解决锁定和交互性的问题,但对应用来说反而更加麻烦了。
RabbitMQ采用Erlang语言开发。Erlang语言由Ericson设计,专门为开发concurrent和distribution系统的一种语言,在电信领域使用广泛。OTP(Open Telecom Platform)作为Erlang语言的一部分,包含了很多基于Erlang开发的中间件/库/工具,如mnesia/SASL,极大方便了Erlang应用的开发。OTP就类似于Python语言中众多的module,用户借助这些module可以很方便的开发应用。
于是2004年,摩根大通和iMatrix开始着手Advanced Message Queuing Protocol (AMQP)开放标准的开发。2006年,AMQP规范发布。2007年,Rabbit技术公司基于AMQP标准开发的RabbitMQ 1.0 发布。所有主要的编程语言均有与代理接口通讯的客户端库。

+

简单的使用经验

通俗的理解

这里介绍下其中的一些概念,connection表示和队列服务器的连接,一般情况下是tcp连接, channel表示通道,可以在一个连接上建立多个通道,这里主要是节省了tcp连接握手的成本,exchange可以理解成一个路由器,将消息推送给对应的队列queue,其实是像一个订阅的模式。

+

集群经验

rabbitmqctl stop这个是关闭rabbitmq,在搭建集群时候先关闭服务,然后使用rabbitmq-server -detached静默启动,这时候使用rabbitmqctl cluster_status查看集群状态,因为还没将节点加入集群,所以只能看到类似

+
1
2
3
4
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
{running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}]
...done.
+

然后就可以把当前节点加入集群,

+
1
2
3
4
5
6
7
rabbit2$ rabbitmqctl stop_app #这个stop_app与stop的区别是前者停的是rabbitmq应用,保留erlang节点,
#后者是停止了rabbitmq和erlang节点
Stopping node rabbit@rabbit2 ...done.
rabbit2$ rabbitmqctl join_cluster rabbit@rabbit1 #这里可以用--ram指定将当前节点作为内存节点加入集群
Clustering node rabbit@rabbit2 with [rabbit@rabbit1] ...done.
rabbit2$ rabbitmqctl start_app
Starting node rabbit@rabbit2 ...done.
+

其他可以参考官方文档

+

一些坑

消息丢失

这里碰到过一个坑,对于使用exchange来做消息路由的,会有一个情况,就是在routing_key没被订阅的时候,会将该条找不到路由对应的queue的消息丢掉What happens if we break our contract and send a message with one or four words, like "orange" or "quick.orange.male.rabbit"? Well, these messages won't match any bindings and will be lost.对应链接,而当使用空的exchange时,会保留消息,当出现消费者的时候就可以将收到之前生产者所推送的消息对应链接,这里就是用了空的exchange。

+

集群搭建

集群搭建的时候有个erlang vm生成的random cookie,这个是用来做集群之间认证的,相同的cookie才能连接,但是如果通过vim打开复制后在其他几点新建文件写入会多一个换行,导致集群建立是报错,所以这里最好使用scp等传输命令直接传输cookie文件,同时要注意下cookie的文件权限。
另外在集群搭建的时候如果更改过hostname,那么要把rabbitmq的数据库删除,否则启动后会马上挂掉

+ + +
+ + + + + + +
+
+
+
+ + + + + + +
@@ -1137,114 +1242,10 @@ - - - -
- - - - - -
-

- - -

- - -
- - - - -
- - -

*Longest Substring Without Repeating Characters *

- -
- - Read more » - -
- - - -
- - - - - - -
-
-
-
- - - - @@ -1312,20 +1313,20 @@ @@ -1350,7 +1351,7 @@ diff --git a/page/5/index.html b/page/5/index.html index 0cb3e8d783..5994fe79d2 100644 --- a/page/5/index.html +++ b/page/5/index.html @@ -204,7 +204,7 @@
- +