0%

背景

最近刚深度参与了客户现场一个堆的OOM问题的排查,在这儿简单记录一下使用到的工具。

产品为刚发的第一版,功能还在迭代中。

这个现场,是实验局现场,产品运行了1个多月,突然有一天告诉我们程序在能用和不能用之间反复横跳。

开始

我个人先下个结论。

  1. 对于发布市场的产品版本发生OOM,肯定是由于存在某个外因进而触发了内因引起的。
  2. 对于堆的OOM,很可能不是单点问题,而是多点问题,只是在某个时刻由某个单点触发了而已。

问题:

  1. 为什么突然就OOM?而且一天内发生了多次?
  2. 为什么程序直接被系统级的干掉了,连最后的dump都来不及输出?
阅读全文 »

背景

由于最近在查一个OOM问题,所以借机读起了《深入理解Java虚拟机》第三版。简单做个记录。

垃圾收集算法

分代收集理论

大多数垃圾收集器的都应用的理论。

弱分代假说(年轻代):绝大多数朝生夕灭的对象。
强分代假说(老年代):熬过越多次垃圾收集就越难消亡。
跨代引用假说

Partial GC(部分收集):

  • Minor GC/Young GC(年轻代收集)
  • Major GC/Old GC(老年代收集)
  • Mixed GC(混合收集):JDK 11 ,只有G1有,针对年轻代和部分老年代。
    Full GC(整堆收集):整个堆和方法区
阅读全文 »

背景

现场排查OOM,对于GC的一些理解。

杂项记录

https://vladmihalcea.com/improve-statement-caching-efficiency-in-clause-parameter-padding/

http://technodibble.blogspot.com/2015/02/hibernate-in-clause-outofmemory.html

http://xmlandmore.blogspot.com/2014/10/jdk-8-is-tuning-maxnewsize-in-g1-gc.html

heap内存归还给操作系统:G1GC https://openjdk.org/jeps/346

https://www.youtube.com/watch?v=BTIcja5xcK0

https://www.youtube.com/watch?v=IB7oFVYTOJ0

https://gceasy.io/gc-recommendations/important-g1-gc-arguments.jsp
https://github.com/Snailclimb/JavaGuide/blob/83efb36fb56d197f2c4b471084b884c6a4f23e37/docs/books/java.md

https://www.douban.com/doulist/2545443/

https://www.baeldung.com/jvm-parameters
https://blog.csdn.net/myth_g/article/details/119855832
https://docs.oracle.com/en/java/javase/11/gctuning/introduction-garbage-collection-tuning.html#GUID-326EB4CF-8C8C-4267-8355-21AB04F0D304

https://programmer.ink/think/jvm-series-jvm-tuning-jps-jstat-jmap-jhat-jstack-jinfo.html

https://docs.oracle.com/javase/10/jrockit-hotspot/logging.htm#JRHMG121
https://confluence.atlassian.com/confkb/unrecognized-jvm-gc-options-when-using-java-11-1002472841.html

https://dzone.com/articles/understanding-garbage-collection-log

https://sematext.com/blog/java-garbage-collection-tuning/

https://sematext.com/blog/java-garbage-collection-tuning/

https://cloud.tencent.com/developer/article/1811734

https://docs.oracle.com/en/java/javase/11/tools/jstat.html#GUID-5F72A7F9-5D5A-4486-8201-E1D1BA8ACCB5

https://www.javatang.com/archives/2017/10/19/51301886.html

https://morioh.com/p/935f204ccc1a

https://dzone.com/articles/jvm-tuning-using-jcmd

https://sematext.com/blog/java-garbage-collection-logs/

MAT

dump文件分析用的MAT。

https://zhanglvmeng.gitbooks.io/mat-usage/content/kai-shi-shi-yong/yan-shen-yue-du/shi-yong-mat-de-10-ge-jian-yi.html

线程分析

https://geekflare.com/generate-analyze-thread-dumps/

https://blog.fastthread.io/2016/02/22/thread-dump-analysis-pattern-repetitive-strain-injury-rsi/

当应用程序出现性能瓶颈时,大部分线程将开始在有问题的瓶颈区域累积。这些线程将具有相同的堆栈跟踪。因此,每当大量线程表现出相同/重复的堆栈跟踪时,就应该调查这些堆栈跟踪。这可能表示性能问题。

以下是一些这样的场景:

  • 假设您的 SOR 或外部服务正在变慢,那么大量线程将开始等待其响应。在这种情况下,这些线程将显示相同的堆栈跟踪。
  • 假设一个线程获得了一个锁并且它从未释放,那么在同一执行路径中的其他几个线程将进入阻塞状态,显示相同的堆栈跟踪。
  • 如果循环(for 循环、while 循环、do..while 循环)条件未终止,则执行该循环的多个线程将显示相同的堆栈跟踪。
    当出现上述任何一种情况时,应用程序的性能和可用性都会受到质疑。

重点关注:Troubleshooting Tools、Monitoring Tools
https://docs.oracle.com/en/java/javase/11/tools/tools-and-command-reference.html

https://programmer.ink/think/jvm-series-jvm-tuning-jps-jstat-jmap-jhat-jstack-jinfo.html

https://www.hollischuang.com/archives/110

线程状态产生的原因

  • runnable:状态一般为RUNNABLE。

  • in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。

  • waiting for monitor entry:进入区等待,状态为BLOCKED。

  • waiting on condition:等待区等待、被park。

  • sleeping:休眠的线程,调用了Thread.sleep()。

https://jakubstransky.com/2017/12/19/hotspot-jvm-internal-threads/

Tomcat线程模型

NIO: synchronous and non blocking. It can support large concurrency better than traditional bio. This mode is adopted by default after Tomcat 8.0.

NiO

https://developpaper.com/nio-optimization-principle-and-tomcat-thread-model/

Tomcat’s NiO model has more poller rolesAcceptor、PollerandHandler worker thread pool。 Are these three roles very familiar? If poller is replaced by reactor, is it the reactor model. Yes, Tomcat’s NiO model is based onMaster slave reactor modelIt’s just a change of name.

AcceptorThe: accepter thread is specifically responsible for establishing network connections(accept)。 After the new connection is created, instead of directly using the worker thread to process the request, the request is first sent to the poller buffer queue.
Poller: in poller, a selector object is maintained. After poller takes the connection from the buffer queue, it registers in the selector and blocks to wait for read and write ready(Read wait ready, send wait ready)。
Handlers: traverse the selector to find out the ready IO operations in the selector and hand them over to the worker thread for processing(Read memory read, decode, process, encode, send memory write)。

https://www.cnblogs.com/grey-wolf/p/13740845.html

调优
https://tomcat.apache.org/tomcat-9.0-doc/config/http.html
https://www.datadoghq.com/blog/tomcat-architecture-and-performance/

断断续续的在看一本书《代码整洁之道》

记录一下我认为实用的点。

有意义的命名

  • 有意义的名称。
  • 好搜索的名称,比如常量的命名。
  • 可读出来的名称。

可能会说这玩意还用说吗?这是基础的基础,一般情况下的命名我自认为做的挺好,但是看书之后我才发现我一个小毛病,就是习惯于把较长的命名给死命缩短(通常就是改变单词的缩写),感觉不缩短就难受。这样下来就有个问题。下一次再看代码的时候有时候会卡壳,忘了这个缩写是表示啥意思了。我这就是犯了上面的第三点“名称不可读”。

所以命名的前提是首先要能让人看懂,别整虚头巴脑的,一定要描述完整,当然有时候你发现你的命名需要装下好几个单词,得反过来再看看,是不是代码结构存在问题。

函数

一个函数只做一件事,每个函数一个抽象层级(向下规则)。
函数要么做什么事,要么回答什么事,二则不可兼得。

异常

  • 抽离try/catch代码块
  • 使用异常替代错误码

参数

  • 参数能少则少,至多三个,实在超出了三个用对象。
  • 尽量不使用标识参数。比如Boolean isXXX。加了标识参数通常就代表函数最少也做了两件事,是方法变得复杂了起来。
  • 应避免使用输出参数,通常情况下直接修改对象就行,不用再返回。

这几个月,赶项目周末都没得,好不容易休个双休,继续之前曹政老师星球福利课《向上生长》,有想听完整版的课加入星球的可以扫描下方二维码。

我只是随便记录一下某部分印象深的内容。

为什么要向上增长

更好的认识世界,更好的认识自己。

见众生,见天地,见自我。清楚这个世界并行的多重规则。

更好的被世界善待。

所谓的体面和尊严,是需要一定的社会地位和财务基础为保障的。

什么制约了我们的向上生长

嫉妒和自卑

caoz的梦呓有篇文章:自信和自卑,别傻傻分不清楚

这点事我需要注意的,做的不够好:不愿看别人优点,不敢看自己的缺点
真诚的表达对别人优点的称赞,以及真诚的感谢别人对你的帮助
对一些别人背后对自己的不利一轮,如果不是特别严重的,可以适当装傻,所谓难得糊涂,就是这样。

向上的机会从哪儿来

你能做,别人做不来。

这点其实比较难,大多情况下你能做的别人也能做,要有这点认知。

你肯做,别人不肯做。

很多时候,当有个事情抛出来的时候,只要我觉得是我力所能及的时候,不管是否符合自己的切身利益我都会先顶上去,因为我觉得如果leader或者老板抛出来一个事情没人应声,会很尴尬,没错我主要是不想那么尴尬。当然也想着多练练自己。老板也能看见没啥亏不亏的,甚至会有赚。

你看到了,别人看不到。

这点对我就比较玄了,认知、视野都不太够,要着力提升。

针对平时自身面对各种情况作出的决策,事后需要不断反思自己的判断,是不是存在误判的情况,然后复盘寻求认知上的升级。
学一些经济学,学些博弈常识,一切皆交易、一切皆博弈,这样可以解释很多事情,另外共情力、人性洞察,不通价值观的理解都是信息过滤规则库需要填充的重要内容。

重视升级自己的信息过滤和判断规则

你敢做,别人不敢做。

这点要注意,别脑子卡壳误入歧途。对我来说,听过就算。

你熬下来了,别人没熬下来。

有时候机会来自于坚持。

这里要注意,坚持要区别与死扛,比如明知道某件事情做下去就是不会有结果就是个死,那….。

令一点要注意,你觉得你的坚持是对的,这个时候面对诱惑时的处理。

如何留下优秀的印象

履约能力

这点可能是我个人比较拿得出手的职场素质:承落就得兑现。

建立信任是很难的,但是一旦建立必然受益无穷。

靠谱的承诺(课里提到的预期控制,不要过度承诺,不要轻易答应),别啥都承诺,我们团队就有这样的人,很容易人设崩塌。
有效的反馈
如果过程中确实发现完不成,要尽快尽早同步,并寻求补救措施。

积极态度

别抱怨,不散播不积累负能量,遇问题乐观、主动一些。

体现诚意

诚意主要体现在,提前准备,做足功课,以及尽可能的超额交互。

注意:可能有些时候就是发自内心真诚的体现就是诚意,不一定非得怎么做。

真诚的称赞和感谢别人

寻求恰当的反馈与帮助

恰当的寻求反馈和帮助,是巩固社交关系,建立持续友好关系的重要手段。

1.提出高质量有价值的问题。

2.对方的成本是可控的,心里要有数,别装大哥。

3.对别人的价值和回报在哪里,心里也要有数。

曹大说的这句话我觉得很重要:社交关系追求互利,不能奢求等价。

制定成长路线

合理目标

坚持前进比追求速度更重要

自我激励

得给自己一点甜头。

比如我干了一本书就会奖励自己一个星期不看书,加了几天班,就会奖励自己出去消费一把。从我的自我激励来看很明显是过度激励了,得控制。

自我反思

遇到困难和挫折,多想想自己的问题哪儿。比如在作为程序员的我,做好容错也是一种自我反思的结果,很多时候看上去是不是自己的问题,但是如果你做好容错呢?是不是一种优势。

平庸的人找理由,优秀的人找原因。

自律和戒断

这个对我来说最难,我现在就是花挺多时间在娱乐上,在学习上的时间太少。

慢慢来,一个个小目标开始,比如从一天学习1小时变为1个半小时,同时把自我激励拿进来。这样可能对我来说是有效的。

学习是需要有一定的投入,一定的深度思考。自律,自驱,延迟满足。

聚焦,抓大放小,学会减法

做事分主次,抓重点,不需要把每件事都做好,但是要把关键的事做漂亮。

避免一上来就陷入细节,先掌握整体的架构。

做减法,相对立的就是追求完美,工作中我遇到一些个同事就是不太会做减法,总想啥都要啥都行,最终往往拿不到好的结果。做减法个人认为难在,首先你得对你面对的事情有个优先级的认知,比如有些事情看上去很关键但是不紧急,其次得学会抓关键,保底关键内容拿到好的结果,得到正反馈。

学会合作

关于合作的几个建议

  1. 先立规矩,再谈感情。
  2. 撤出机制要讲清。
  3. 合作不是抱大腿,每个人都应该贡献合理的价值。
  4. 做大蛋糕最重要。
  5. 永远都要有信用成本的概念。

正确的花钱

花钱买时间

比如对我来说,打车就是比坐公交好,因为公交通常要花时间找公交站,然后得等公交,然后得挤公交,这些精力和时间,我打车省下来哪怕是多玩会儿也好啊。

时间成本和省钱往往要留意。

花钱买能力

尊重专业的能力,尊重专业服务,关键的地方别省钱。

花钱买信息和知识

比如知识付费。注意贪多嚼不烂,不买就焦虑的想法。我就是前期哐哐哐一顿买,结果看不过来。

买的知识要对你有意义比如能辅助你的决策影响你的工作或者思考方式

花钱买诚意

花费也是表达诚意的一种方式。

花钱买忠诚

个人觉得华为就有这个特质。

花钱买效率

自己做要一个月,给其他人做只要一天,选一下。

莫忘初心

在少数的几次和老板的谈话多,印象最深刻的几句话之一:无论环境如何(公司、同事),希望你能一直保持自己的本色

在成长中肯定会因为各种各样的因素,比如环境、利益等,从而改变自己的一些想法和做事方式,但是切忌要心中一直给最开始的初心、原则留一块地方,这块地方能调整但是不能失去,不然说不定啥时候就变成了你平时最厌烦的那种人。

听友推荐的经济学书籍:

张维迎《博弈与社会》、张捷《霸权博弈》《资源角逐》《定价权》

前言

苹果出第一代M1的时候就想入手来着,不过还是忍了忍。

  • 等一下M1的生态。
  • 不想做第一个吃螃蟹的人,反正也不急。

10月份M1 Pro和M1 Max来了,这回忍不了了,从命名能看出其实等M2是最好的,不过确实不想等了,手里的小米笔记本已经不能满足我了….,这里不得不吐槽下,小米笔记本我就是当了第一个吃螃蟹的人,体验很差(换主板、换屏幕…)。我儿豁,对于消费品真的不想再当吃螃蟹的人了。

选购

准备

因为M1 Pro和M1 Max有很多配置可选,把我整懵逼了,所以想一想还是做些功课再买。
需求先列出来:

  1. 编程,屏幕不能太小
  2. 好看
  3. 有逼格
  4. 不能超过2万

注:其实理智的码农应该选择Linux和x86

另外顺便说一下关于ARM和X86,这里有篇文章我觉得是很客观的:苹果 M1 革了 Intel x86 的命?

功课如下:

  1. M1软件支持列表
  2. 8-core-or-10-core-m1-pro-macbook-pro-14
  3. 16GB vs 32GB RAM M1 Pro MacBook
  4. M1 Pro MacBook - 8 vs 10 CPU Cores
  5. M1 Max性能全解密! 凑齐7台Mac

结果:

方方面面看下来,只能说幸好啊。

大体结论是, 8核cpu和10核cpu,差别不大,没必要上。

16G和32G,贵了小3千块钱,没有特别的必要上,还不如用这个钱加SSD。

M1 Max如果不是资深从业人员没必要上。

本来我想买的是10核cpu,32G内存,1T硬盘。

最终选择了下面的配置:14寸 8CPU + 16G +1T SSD。我个人觉得是比较合适的配置。

最后

最后我还是要说一下,M1系列其实你认真看很多关注度高的评测,基本都是使用视频剪辑、设计等工作台的人员,因为苹果M1就是以自家公司设计工作台的员工作为需求收集的来源之一,所以对视频、设计类软件有这么牛逼的性能当然这也是mac一直来的最大优势之一。

但是咱静下来想一想,你自己的需求到底是什么,会需要在高性能的基础上再加牛逼的性能吗?反正我是不需要,当然还有个原因是我穷。

https://www.redhat.com/zh/topics/api/what-is-a-rest-api

https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/

https://stackoverflow.blog/2021/10/06/best-practices-for-authentication-and-authorization-for-rest-apis/

https://phauer.com/2016/testing-restful-services-java-best-practices/

https://pages.apigee.com/rs/apigee/images/api-design-ebook-2012-03.pdf

https://www.ibm.com/docs/zh/mam/7.6.0?topic=ppdm-put-method

https://www.freecodecamp.org/news/rest-api-best-practices-rest-endpoint-design-examples/
http://algermissen.io/classification_of_http_apis.html