你假笨JVM参数 – 006 ExplicitGCInvokesConcurrent

你假笨的第六次分享: 序号:006 时间:2017-07-31 参数:-XX:ExplicitGCInvokesConcurrent 含义: Enables invoking of concurrent GC by using the System.gc() request. This option is disabled by default and can be enabled only together with the -XX:+UseConcMarkSweepGC option. System.gc()是正常FULL GC,会STW 打开此参数后,在做System.gc()时会做background模式CMS GC,即并行FULL GC,可提高FULL GC效率 注,该参数在允许systemGC且使用CMS GC时有效 举例: -XX:+ExplicitGCInvokesConcurrent 相关参数: -XX:DisableExplicitGC 控制是否允许System.gc(),默认允许 小程序截图: 分享记录:

December 23, 2017 · 1 min · 46 words · Bridge Li

你假笨JVM参数 – 005 CMSScavengeBeforeRemark

你假笨的第五次分享: 序号:005 时间:2017-07-24 参数:-XX:CMSScavengeBeforeRemark 含义: Enable scavenging attempts before the CMS remark step. 开启或关闭在CMS重新标记阶段之前的清除(YGC)尝试 CMS并发标记阶段与用户线程并发进行,此阶段会产生已经被标记了的对象又发生变化的情况,若打开此开关,可在一定程度上降低CMS重新标记阶段对上述“又发生变化”对象的扫描时间,当然,“清除尝试”也会消耗一些时间 注,开启此开关并不会保证在标记阶段前一定会进行清除操作 小程序截图: 分享记录:

December 17, 2017 · 1 min · 18 words · Bridge Li

你假笨JVM参数 – 004 MaxTenuringThreshold

你假笨的第四次分享: 序号:004 时间:2017-07-21 参数:-XX:MaxTenuringThreshold 含义: Sets the maximum tenuring threshold for use in adaptive GC sizing. The largest value is 15. The default value is 15 for the parallel (throughput) collector, and 6 for the CMS collector. 在可自动调整对象晋升老年代年龄阈值的GC中,该参数用于设置上述年龄阈值的最大值 参数值最大为15 Parallel Scavenge中默认值为15,CMS中默认值为6,G1中默认值为15 小程序截图: 分享记录:

December 10, 2017 · 1 min · 43 words · Bridge Li

你假笨JVM参数 – 003 CompileCommand

你假笨的第三次分享: 序号:003 时间:2017-07-19 参数:-XX:CompileCommand 含义: Specifies a command to perform on a method. 该参数用于定制编译需求,比如过滤某个方法不做JIT编译 若未指定方法描述符,则对全部同名方法执行命令操作,具体如何指定见下文[举例] 可使用星号通配符(*)指定类或方法,具体如何使用见下文[举例] 该参数可多次指定,或使用 换行符(\n)分隔参数后的多个命令 解析完该命令后,JIT编译器会读取.hotspot_compiler文件中的命令,该参数也可写在.hotspot_compiler文件中 可使用-XX:CompileCommandFile指定.hotspot_compiler文件为其他文件 用法: -XX:CompileCommand=command,method[,option] 命令: exclude,跳过编译指定的方法 compileonly,只编译指定的方法 inline/dontinline,设置是否内联指定方法 print,打印生成的汇编代码 break,JVM以debug模式运行时,在方法编译开始处设置断点 quiet,不打印在此命令之后、通过-XX:CompileCommand指定的编译选项 log,记录指定方法的编译日志,若未指定,则记录所有方法的编译日志 其他命令,option,help 举例: 设置编译器跳过编译com.jvmpocket.Dummy类test方法的4种写法 -XX:CompileCommand=exclude,com/jvmpocket/Dummy.test -XX:CompileCommand=exclude,com/jvmpocket/Dummy::test -XX:CompileCommand=exclude,com.jvmpocket.Dummy::test -XX:CompileCommand="exclude com/jvmpocket/Dummy test" 设置编译器只跳过编译java.lang.String类int indexOf(String)方法 -XX:CompileCommand=”exclude,java/lang/String.indexOf,(Ljava/lang/String;)I” 设置编译器跳过编译所有类的indexOf方法 -XX:CompileCommand=exclude,*.indexOf 小程序截图: 分享记录:

November 25, 2017 · 1 min · 46 words · Bridge Li

MySQL : The last packet successfully received from the server was XXX milliseconds ago

14年毕业写完论文没事干的时候,自己玩微信公众号开发,当时想做一个自然语言交互,其实就是想试一下lucene,但是当时建索引的时候偶尔会报这个错,一致不知道具体原因,去网上搜索但是天下文章一大抄,你抄我来我抄他,也没找到原因,后来因为工作中也没遇到过,感觉应该是自己当时水平不行就忘了这件事,前几天 fatsjson 和 druid 的作者温少突然在一个群里面说有人通过阿里工单反馈这个问题,他给追踪了一下,找到了原因,原来还是还是有人遇到这个问题,今天记录一下,希望对遇到这个问题的小伙伴有帮助,报错的信息大概就是: Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 20,820,001 milliseconds ago. The last packet sent successfully to the server was 20,820,002 milliseconds ago. is longer than the server configured value of ‘wait_timeout’. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property ‘autoReconnect=true’ to avoid this problem. at sun.reflect.GeneratedConstructorAccessor29.newInstance(Unknown Source) ………… 下面是温少分享的截图 ...

November 11, 2017 · 1 min · 88 words · Bridge Li

你假笨说JVM参数 – 002 StringTableSize

没想到距离第一次整理你假笨的分享已经过去两个多月了,近期会继续整理一系列你假笨关于JVM参数的分享,下面是第二次: 序号:002 时间:2017-07-14 参数:-XX:StringTableSize 含义:Number of buckets in the interned String table String.intern() 被调用时会往 Hashtable 插入一个 String(若该 String 不存在),这里的 Table 就是 StringTable,此参数就是这个 StringTable 的大小,若此参数设置过小,明显的问题就是过多的hash碰撞,造成在查找字符串时比较消耗 CPU 资源 JDK 1.6 起,当冲突次数超过 100 次会自动 rehash,即便如此,若此参数设置过小会导致不断的 rehash,依然会过度消耗 CPU 资源 建议将此参数设置的值稍大一些,以减少 hash 冲突 使用方法:-XX:ReservedCodeCacheSize=__ 小程序截图: 分享记录: 感谢你假笨

November 5, 2017 · 1 min · 42 words · Bridge Li

程序员都应该懂点开源许可协议

最近 Facebook 开源的 React 的开源协议专利条款一事闹得沸沸扬扬,著名的 WordPress、百度等纷纷声明弃用 React,最终 Facebook 听从大众的声音改回了BSD,这就牵涉到一个如何选择开源协议的问题,因为 React 是一个生态,所以这事影响比较大,其实之前有很多关于开源协议用错导致原作者利益受损的事,例如前两个月就有一个被雷军称赞的称为最牛的 00 的 CEO 的公司抄袭别人代码连素材都不修改的案例,所以想到之前曾看到有一个乌克兰程序员 Paul Miller 制作了一张图,一分钟明白你应该选择哪个开源协议,原图如下: 原文地址:http://paulmillr.com/posts/simple-description-of-popular-software-licenses/ 如果英文不好的话(其实我英文更不好,但连猜带蒙也看了个差不多),有热心网友翻译了一个中文版,地址:http://blog.csdn.net/wadefelix/article/details/6384317 多说一点: 记得刚实习的时候,老大强调不准使用任何未经公司批准的任何软件,如果需要必须报备,经相关人员同意后方可使用,当时不明白为什么,其实看看 GPL 协议也就猜到了。另外刚开始玩 GitHub 的时候,以为就随便把代码放上去就完事了,当然代码写的很烂也不会被人使用,但严格意义上来说还是应该选择一个开源协议的,据说 GitHub 目前有相当数量的项目没有添加开源协议,所以为了使开发者养成选择开源许可证的习惯,GitHub 现在在创建新库的表单中添加了一个许可证选项。该选项中提供了一组简化的开源许可证,开发者选择后,Github 会自动在其库的根目录中创建一个 LICENSE 文件。 最后为了维护开源社区的健康发展,同时不致自己的利益受损,大家一定注意选择合适的开源协议。

October 1, 2017 · 1 min · 33 words · Bridge Li

是的,我也开启了全站HTTPS

现在的趋势都在全站HTTPS,据说在Google内部有一个时间表,会把所有未开启HTTPS的网站标注为不安全(目前仅仅会把带密码框的输入页标注为不安全),所以一直想玩玩,去年的时候就看到新浪timyang的博客开启了全站HTTPS,并写了一篇文章如何开启,当时就想玩玩,但感觉还是稍有麻烦,而且当时的博客服务器用的Apache,对Apache配置不熟,想着是自己的小博客就没动,前几天突然看到coolshell网也开启了全站HTTPS,发现现在配置变得很简单了,而且我的博客服务器也由Apache换成了Nginx,所以就玩了玩,确实很方便。 首先声明,无论是timyang还是左耳朵耗子,使用的都是Let’s Encrypt,他是一个公益组织,表示感谢,网址:https://letsencrypt.org/ 下面写一下开启的方法: 首先,打开 https://certbot.eff.org 网页。 在那个机器上图标下面,你需要选择一下你用的 Web 接入软件 和你的 操作系统。比如,我选的,nginx 和 CentOS 6。 然后就会跳转到一个安装教程网页。你就照着做一遍就好了。 例如我选的这个调到安装教程页,出现的命令是: wget https://dl.eff.org/certbot-auto chmod a+x certbot-auto 然后,运行如下命令: ./path/to/certbot-auto –nginx certbot-auto 会自动检查到你的 nginx.conf 下的配置,把你所有的虚拟站点都列出来,然后让你选择需要开启 https 的站点。你就简单的输入列表编号(用空格分开),因为我的就一个所以直接回车就好了(里面有一些需要你填写的东西,连我这英文巨差的人都可以看懂,相信大家都能看的懂),然后,certbot-auto 就帮你下载证书并更新 nginx.conf 了。 但在这个过程中需要注意的一点:记得开启你的 443 端口,我博客用的阿里云,当时没开启直接报错了,开启之后重新执行一下这个命令就好了。 你打开你的 nginx.conf 文件 ,你可以发现你的文件中的 server 配置中可能被做了如下的修改: listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/www.bridgeli.cn/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/www.bridgeli.cn/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot 和 if ($scheme != "https") { return 301 https://$host$request_uri; } # managed by Certbot 另外开启HTTPS之后都建议开启HTTP/2性能更好,但这要求你的Nginx版本要大于 1.9.5 ,开启的方法也无比简单,只需要在 nginx.conf 的 listen 443 ssl; 后面加上 http2 就好了。如下所示: ...

September 3, 2017 · 2 min · 218 words · Bridge Li

你假笨说JVM参数 – 001 ReservedCodeCacheSize

因为之前看过周志明《深入理解Java虚拟机JVM高级特性和最佳实践》,而对JVM的一些东西感兴趣,感觉挺好玩的,前段时间有幸加了阿里寒泉子的微信(现在应该是前阿里了),而加入了一个你假笨建的一个JVM参数交流群,你假笨在里面做过几次分享,看到有小伙伴整理笔记,表示赞同。因为俗话说好记性不如烂笔头,何况自己记性并不怎么好,以下是第一次的分享。另外虽然这些东西平时可能用不到,但当实际出问题的时候不懂这些肯定是束手无策,所以多看看总没有坏处 序号:001 时间:2017-07-13 参数:-XX:ReservedCodeCacheSize 含义:Reserved code cache size (in bytes) – maximum code cache size 用于设置Code Cache大小,JIT编译的代码都放在Code Cache中,若Code Cache空间不足则JIT无法继续编译,并且会去优化,比如编译执行改为解释执行,由此,性能会降低 等价参数:-Xmaxjitcodesize 使用方法:-XX:ReservedCodeCacheSize=__ 小程序截图: 分享记录: 文中小程序截图,是你假笨为了方便大家查询JVM参数而开发的一个小程序,大家可以搜索:JVMPocket添加到自己小程序中,没事的翻翻这些参数也挺好,另外JVMPocket里面有一个签到功能,你假笨会每天设置一个签到的目标人数,达到目标第二天就会在群里面分享一个JVM参数,所以大家可以每天签到,并加到你假笨建的的JVM参数交流群里面,当面听大神的教导。

August 26, 2017 · 1 min · 24 words · Bridge Li

秒杀系统架构优化思路[转载]

看过很多写秒杀的文章,感觉还是58沈剑老师的这篇写的最好最接地气,博客第一百篇文章本想自己写一篇的,最后想想还是转载沈剑老师的这篇好了,因为看完这篇真的很受启发。 原文出处微信公众号:架构师之路,微信号:road5858,链接地址:http://mp.weixin.qq.com/s/5aMN9SqaWa57rYGgtdAF_A 以下是原文: 本文曾在“架构师之路”上发布过,近期支援Qcon-AS大会,在微信群里分享了该话题,故对原文进行重新整理与发布。 一、秒杀业务为什么难做 1)im系统,例如qq或者微博,每个人都读自己的数据(好友列表、群列表、个人信息); 2)微博系统,每个人读你关注的人的数据,一个人读多个人的数据; 3)秒杀系统,库存只有一份,所有人会在集中的时间读和写这些数据,多个人读一个数据。 例如:小米手机每周二的秒杀,可能手机只有1万部,但瞬时进入的流量可能是几百几千万。 又例如:12306抢票,票是有限的,库存一份,瞬时流量非常多,都读相同的库存。读写冲突,锁非常严重,这是秒杀业务难的地方。那我们怎么优化秒杀业务的架构呢? 二、优化方向 优化方向有两个(今天就讲这两个点): (1)将请求尽量拦截在系统上游(不要让锁冲突落到数据库上去)。传统秒杀系统之所以挂,请求都压倒了后端数据层,数据读写锁冲突严重,并发高响应慢,几乎所有请求都超时,流量虽大,下单成功的有效流量甚小。以12306为例,一趟火车其实只有2000张票,200w个人来买,基本没有人能买成功,请求有效率为0。 (2)充分利用缓存,秒杀买票,这是一个典型的读多些少的应用场景,大部分请求是车次查询,票查询,下单和支付才是写请求。一趟火车其实只有2000张票,200w个人来买,最多2000个人下单成功,其他人都是查询库存,写比例只有0.1%,读比例占99.9%,非常适合使用缓存来优化。好,后续讲讲怎么个“将请求尽量拦截在系统上游”法,以及怎么个“缓存”法,讲讲细节。 三、常见秒杀架构 常见的站点架构基本是这样的(绝对不画忽悠类的架构图) (1)浏览器端,最上层,会执行到一些JS代码 (2)站点层,这一层会访问后端数据,拼html页面返回给浏览器 (3)服务层,向上游屏蔽底层数据细节,提供数据访问 (4)数据层,最终的库存是存在这里的,mysql是一个典型(当然还有会缓存) 这个图虽然简单,但能形象的说明大流量高并发的秒杀业务架构,大家要记得这一张图。 后面细细解析各个层级怎么优化。 四、各层次优化细节 第一层,客户端怎么优化(浏览器层,APP层) 问大家一个问题,大家都玩过微信的摇一摇抢红包对吧,每次摇一摇,就会往后端发送请求么?回顾我们下单抢票的场景,点击了“查询”按钮之后,系统那个卡呀,进度条涨的慢呀,作为用户,我会不自觉的再去点击“查询”,对么?继续点,继续点,点点点。。。有用么?平白无故的增加了系统负载,一个用户点5次,80%的请求是这么多出来的,怎么整? (a)产品层面,用户点击“查询”或者“购票”后,按钮置灰,禁止用户重复提交请求; (b)JS层面,限制用户在x秒之内只能提交一次请求; APP层面,可以做类似的事情,虽然你疯狂的在摇微信,其实x秒才向后端发起一次请求。这就是所谓的“将请求尽量拦截在系统上游”,越上游越好,浏览器层,APP层就给拦住,这样就能挡住80%+的请求,这种办法只能拦住普通用户(但99%的用户是普通用户)对于群内的高端程序员是拦不住的。firebug一抓包,http长啥样都知道,js是万万拦不住程序员写for循环,调用http接口的,这部分请求怎么处理? 第二层,站点层面的请求拦截 怎么拦截?怎么防止程序员写for循环调用,有去重依据么?ip?cookie-id?…想复杂了,这类业务都需要登录,用uid即可。在站点层面,对uid进行请求计数和去重,甚至不需要统一存储计数,直接站点层内存存储(这样计数会不准,但最简单)。一个uid,5秒只准透过1个请求,这样又能拦住99%的for循环请求。 5s只透过一个请求,其余的请求怎么办?缓存,页面缓存,同一个uid,限制访问频度,做页面缓存,x秒内到达站点层的请求,均返回同一页面。同一个item的查询,例如车次,做页面缓存,x秒内到达站点层的请求,均返回同一页面。如此限流,既能保证用户有良好的用户体验(没有返回404)又能保证系统的健壮性(利用页面缓存,把请求拦截在站点层了)。 页面缓存不一定要保证所有站点返回一致的页面,直接放在每个站点的内存也是可以的。优点是简单,坏处是http请求落到不同的站点,返回的车票数据可能不一样,这是站点层的请求拦截与缓存优化。 好,这个方式拦住了写for循环发http请求的程序员,有些高端程序员(黑客)控制了10w个肉鸡,手里有10w个uid,同时发请求(先不考虑实名制的问题,小米抢手机不需要实名制),这下怎么办,站点层按照uid限流拦不住了。 第三层 服务层来拦截(反正就是不要让请求落到数据库上去) 服务层怎么拦截?大哥,我是服务层,我清楚的知道小米只有1万部手机,我清楚的知道一列火车只有2000张车票,我透10w个请求去数据库有什么意义呢?没错,请求队列! 对于写请求,做请求队列,每次只透有限的写请求去数据层(下订单,支付这样的写业务) 1w部手机,只透1w个下单请求去db 3k张火车票,只透3k个下单请求去db 如果均成功再放下一批,如果库存不够则队列里的写请求全部返回“已售完”。 对于读请求,怎么优化?cache抗,不管是memcached还是redis,单机抗个每秒10w应该都是没什么问题的。如此限流,只有非常少的写请求,和非常少的读缓存mis的请求会透到数据层去,又有99.9%的请求被拦住了。 当然,还有业务规则上的一些优化。回想12306所做的,分时分段售票,原来统一10点卖票,现在8点,8点半,9点,…每隔半个小时放出一批:将流量摊匀。 其次,数据粒度的优化:你去购票,对于余票查询这个业务,票剩了58张,还是26张,你真的关注么,其实我们只关心有票和无票?流量大的时候,做一个粗粒度的“有票”“无票”缓存即可。 第三,一些业务逻辑的异步:例如下单业务与 支付业务的分离。这些优化都是结合 业务 来的,我之前分享过一个观点“一切脱离业务的架构设计都是耍流氓”架构的优化也要针对业务。 好了,最后是数据库层 浏览器拦截了80%,站点层拦截了99.9%并做了页面缓存,服务层又做了写请求队列与数据缓存,每次透到数据库层的请求都是可控的。db基本就没什么压力了,闲庭信步,单机也能扛得住,还是那句话,库存是有限的,小米的产能有限,透这么多请求来数据库没有意义。 全部透到数据库,100w个下单,0个成功,请求有效率0%。透3k个到数据,全部成功,请求有效率100%。 五、总结 上文应该描述的非常清楚了,没什么总结了,对于秒杀系统,再次重复下我个人经验的两个架构优化思路: (1)尽量将请求拦截在系统上游(越上游越好); (2)读多写少的常用多使用缓存(缓存抗读压力); 浏览器和APP:做限速 站点层:按照uid做限速,做页面缓存 服务层:按照业务做写请求队列控制流量,做数据缓存 数据层:闲庭信步 并且:结合业务做优化 六、Q&A 问题1、按你的架构,其实压力最大的反而是站点层,假设真实有效的请求数有1000万,不太可能限制请求连接数吧,那么这部分的压力怎么处理? 答:每秒钟的并发可能没有1kw,假设有1kw,解决方案2个: (1)站点层是可以通过加机器扩容的,最不济1k台机器来呗。 (2)如果机器不够,抛弃请求,抛弃50%(50%直接返回稍后再试),原则是要保护系统,不能让所有用户都失败。 问题2、“控制了10w个肉鸡,手里有10w个uid,同时发请求” 这个问题怎么解决哈? 答:上面说了,服务层写请求队列控制 ...

August 8, 2017 · 1 min · 95 words · Bridge Li