什么是缓存击穿以及解决方法

在高并发场景下,如果某一个key被高并发访问,没有被命中,出于对容错性考虑,会尝试去从后端数据库中获取,从而导致了大量请求达到数据库,而当该key对应的数据本身就是空的情况下,这就导致数据库中并发的去执行了很多不必要的查询操作,从而导致巨大冲击和压力。
所以在编写此类缓存的时候要注意潜在的实效缓存的情况,考虑这个缓存的意义和使用的场景,即要考虑考虑命中率的问题。
参考:
http://www.cnblogs.com/dinglang/p/6133501.html
http://www.jianshu.com/p/d96906140199

classloader加载的双亲委托模式[转]

做Java开发,对于ClassLoader的机制是必须要熟悉的基础知识,本文针对Java ClassLoader的机制做一个简要的总结。因为不同的JVM的实现不同,本文所描述的内容均只限于Hotspot Jvm.
本文将会从JDK默认的提供的ClassLoader,双亲委托模型,如何自定义ClassLoader以及Java中打破双亲委托机制的场景四个方面入手去讨论和总结一下。
JDK默认ClassLoader
JDK 默认提供了如下几种ClassLoader

  1. Bootstrp loader
    Bootstrp加载器是用C++语言写的,它是在Java虚拟机启动后初始化的,它主要负责加载%JAVA_HOME%/jre/lib,-Xbootclasspath参数指定的路径以及%JAVA_HOME%/jre/classes中的类。
  2. ExtClassLoader
    Bootstrp loader加载ExtClassLoader,并且将ExtClassLoader的父加载器设置为Bootstrploader.ExtClassLoader是用Java写的,具体来说就是 sun.misc.Launcher$ExtClassLoader,ExtClassLoader主要加载%JAVA_HOME%/jre/lib/ext,此路径下的所有classes目录以及java.ext.dirs系统变量指定的路径中类库。
  3. AppClassLoader
    Bootstrp loader加载完ExtClassLoader后,就会加载AppClassLoader,并且将AppClassLoader的父加载器指定为 ExtClassLoader。AppClassLoader也是用Java写成的,它的实现类是sun.misc.Launcher$AppClassLoader,另外我们知道ClassLoader中有个getSystemClassLoader方法,此方法返回的正是AppclassLoader.AppClassLoader主要负责加载classpath所指定的位置的类或者是jar文档,它也是Java程序默认的类加载器。
    综上所述,它们之间的关系可以通过下图形象的描述:
    双亲委托模型
    Java中ClassLoader的加载采用了双亲委托机制,采用双亲委托机制加载类的时候采用如下的几个步骤:
  4. 当前ClassLoader首先从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。
    每个类加载器都有自己的加载缓存,当一个类被加载了以后就会放入缓存,等下次加载的时候就可以直接返回了。
  5. 当前classLoader的缓存中没有找到被加载的类的时候,委托父类加载器去加载,父类加载器采用同样的策略,首先查看自己的缓存,然后委托父类的父类去加载,一直到bootstrp ClassLoader.
  6. 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入它自己的缓存中,以便下次有加载请求的时候直接返回。
    说到这里大家可能会想,Java为什么要采用这样的委托机制?理解这个问题,我们引入另外一个关于Classloader的概念“命名空间”, 它是指要确定某一个类,需要类的全限定名以及加载此类的ClassLoader来共同确定。也就是说即使两个类的全限定名是相同的,但是因为不同的ClassLoader加载了此类,那么在JVM中它是不同的类。明白了命名空间以后,我们再来看看委托模型。采用了委托模型以后加大了不同的 ClassLoader的交互能力,比如上面说的,我们JDK本生提供的类库,比如hashmap,linkedlist等等,这些类由bootstrp 类加载器加载了以后,无论你程序中有多少个类加载器,那么这些类其实都是可以共享的,这样就避免了不同的类加载器加载了同样名字的不同类以后造成混乱。
    不遵循“双亲委托机制”的场景
    上面说了双亲委托机制主要是为了实现不同的ClassLoader之间加载的类的交互问题,被大家公用的类就交由父加载器去加载,但是Java中确实也存在父类加载器加载的类需要用到子加载器加载的类的情况。下面我们就来说说这种情况的发生。
    Java中有一个SPI(Service Provider Interface)标准,使用了SPI的库,比如JDBC,JNDI等,我们都知道JDBC需要第三方提供的驱动才可以,而驱动的jar包是放在我们应 用程序本身的classpath的,而jdbc 本身的api是jdk提供的一部分,它已经被bootstrp加载了,那第三方厂商提供的实现类怎么加载呢?这里面JAVA引入了线程上下文类加载的概念,线程类加载器默认会从父线程继承,如果没有指定的话,默认就是系统类加载器(AppClassLoader),这样的话当加载第三方驱动的时候,就可 以通过线程的上下文类加载器来加载。
    另外为了实现更灵活的类加载器OSGI以及一些Java appserver也打破了双亲委托机制。

参考:
http://blog.csdn.net/wangyang1354/article/details/49448007
http://www.cnblogs.com/xxbcoder/p/5112632.html
http://blog.csdn.net/zhangzeyuaaa/article/details/42499839

AWS的Cloudfront没有采用GZIP的问题

问题的现象:
例如源站source.ciika.com,加速域名为ciika.com,web服务器为nginx,在直接访问源站的时候,是有gzip的,但是通过CDN之后就没有压缩了,直接原样输出了,所以问题应该出现了cloundfront回源的问题。

问题的原因:
由于cloundfront采用的是http1.0去回源,而http1.0没有携带 Accept-Encoding,这个是在http1.1才有的,所以nginx认为用户无法解压,所以直接把未压缩的内容传输给cdn,然后cdn在原样传输给用户。

解决方案:
修改nginx的配置

gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_types text/css application/x-javascript;
gzip_vary on;

gzip_proxied any,表示无条件的输出gzip内容给用户

参考:
http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_proxied
https://pelanne.com/blog/enabling-gzip-compression-your-nginx-served-cloudfront-content/

wifi吞吐率及信号强度测试

Android设备集成的wifi一般都是由厂商(正基)封装集成WiFi芯片(博通)提供的,通常说的wifi芯片,其实指的是已经封装好的wifi模块,类似AP6330,AP6212等等。Android设备集成wifi芯片后,会在ROM写入wifi芯片的驱动,这个一般是由厂家提供,只需集成。里面有一套参数来控制(非常重要)。现在绝大部分的wifi芯片都支持蓝牙,蓝牙和无线都是由wifi芯片提供的。蓝牙跟wifi会有影响的。(蓝牙无数据传输时,只有心跳包检测,不会有太大影响,一般测试时会关闭蓝牙减少此项干扰)。一般代理厂商在提供wifi模块前会对wifi做一个整体的测试,包括频偏、吞吐率和信号强度等(3M/5M/12M,信道3/7/11),Android设备厂商集成时,也会写相应的驱动,因此Android设备集成后还需要进行一轮整体测试。
222222.png

准备工具:Android设备、笔记本一台、路由器、iperf工具
测试环境:周围路由环境干净(可使用wifi分析仪查看周围路由情况)
测试对象:新产品、新批次wifi模块
测试范围:2.4G近距离,2.4G远距离,5G近距离,5G远距离
测试内容:wifi吞吐率(每个信道)和信号强度
测试步骤:
1.安装 iperf工具:
电脑端: linux:sudo apt-get install iperf 安装即可。(Windows版本没用过。。。。)
Android设备:
1.有root权限:直接将iperf文件拷贝进/system/bin/ ,并赋予权限(755/777)
2.无root权限:直接安装apk文件

2.开启路由器,断开外网(排除干扰,只在局域网内进行),只让电脑和Android设备连接此路由

3.设备上执行命令iperf -s ,开启服务 (ps:有root权限手机直接输入命令即可;无root手机安装apk,进入apk,输入-s,点击start即可开启服务)

4.电脑端输入iperf -c 192.168.1.147 -i 2 -t 20
-c:客户端模式,后接服务器ip
-i:设置带宽报告的时间间隔,单位为秒
-t:设置测试的时长,单位为秒
-p:后接服务端监听的端口
-w:设置tcp窗口大小,一般可以不用设置,默认即可
测试后截图如下:
ffsssssssss.jpg

从上图看出,该设备10s内平均的吞吐速率为90.1Mbits/sec
wifi吞吐率的测试步骤大概就这样。
以太网的吞吐量测试只是比这个多了两根网线,直接使用有线连接,按照上面步骤测试即可。

by同事songqin

HTML5页面在手机上显示1PX的线条

在PC浏览器上看到的1像素的边框,在手机上显示的比较粗,可以通过以下方式解决。
构建1个伪元素, 将它的长宽放大到2倍, 边框宽度设置为1px, 再以transform缩放到50%.

.radius-border{
position: relative;
}
@media screen and (-webkit-min-device-pixel-ratio: 2){
.radius-border:before{
    content: "";
    pointer-events: none; /* 防止点击触发 */
    box-sizing: border-box;
    position: absolute;
    width: 200%;
    height: 200%;
    left: 0;
    top: 0;
    border-radius: 8px;
    border:1px solid #999;
    -webkit-transform(scale(0.5));
    -webkit-transform-origin: 0 0;
    transform(scale(0.5));
    transform-origin: 0 0;
}
}

优点: 其实不止是圆角, 其他的边框也可以这样做出来

缺点: 代码量也很大, 占据了伪元素, 容易引起冲突

摘自:http://www.cnblogs.com/lunarorbitx/p/5287309.html