My WordPress Development Toolbox

http://tommcfarlin.com/wordpress-developer-toolbox/

本来是准备找git的客户端,看到这篇文章.不喜欢tower,大爱SoureTree.

browserstack也挺好的,适合做浏览器兼容性测试.

JVM plus Docker: Better together

http://www.javaworld.com/article/2456960/java-app-dev/jvm-plus-docker-better-together.html

docker刚好弥补jvm对资源管理(CPU/IO)的不足.

SharedHashMap vs Redis

http://vanillajava.blogspot.jp/2014/05/sharedhashmap-vs-redis.html

这位哥异常牛掰,java低延迟方面的专家.把性能做到极致啊!!!It was designed to be used in Java in a pause less, garbage free manner.狂赞!!!先留着,有时间了看看源代码.

##高性能服务器架构 http://blog.csdn.net/zhoudaxia/article/details/14223755

这些经验可以参考下:

  • 数据拷贝

    特别是java,很多数据拷贝的代码埋得深,比如StringBuilder扩容,集合扩容等等.java中的数据拷贝除了带来cpu的压力,也会给gc带来压力.

    参考:使用零拷贝提高数据传输效率

  • 上下文切换

    线程越多,上下文切换就会越多.需要合理评估处理模型和系统情况.按照SEDA的方式把一个请求划分为多个阶段,但是多个阶段的独立线程池真的会增加上下文的切换,但这样可能会让系统利用率最高.

  • 内存分配

    采用类似于Buddy memory allocation的策略来减少开销.

  • 锁竞争

    一定要控制好锁的粒度.某些场景用map来存放锁对象,而不要使用一把大锁.

##数据库版本控制工具liquibase http://www.liquibase.org/quickstart.html

今天和勇哥讨论了如何来控制数据库版本.我们想的方案是,数据库里面有张versions表,里面记录当前的版本是多少.然后数据库更新文件存在项目中,并以目录来区分.这样就可以在项目启动时,来对比是否有新版本,是否需要升级.这样可以做到全自动化,需要规范现在的开发同学的行为,更重要的一点是,没有人来做这个事情.

liquibase正好在做这个事情,他也支持sql格式的版本,学习成本相当低.而且有内置的数据库版本和集群场景的检测,给力,先试试.

参考:如何跟踪数据库结构变动

##可伸缩性最佳实践:来自eBay的经验 (http://www.infoq.com/cn/articles/ebay-scalability-best-practices)[http://www.infoq.com/cn/articles/ebay-scalability-best-practices]

手里有本2011年的架构师特刊,翻开看到的第一篇文章.虽然有点老了,但是经验还是值得我们借鉴.

  • 按功能分割

咱们现在的架构体系基本上遵循这条最佳实践.借助于dubbo/cxf实现功能服务化.应用层可以实现水平线性扩展.

  • 水平切分

应用层面的无状态很重要,会话之类的东西可以放在缓存服务器上,尽量让LB来实现水平切分.

数据库层面读写分离/分区/分库/分表.

  • 避免分布式事务

分布式第一定律,不要使用分布式.特别是两阶段提交,对系统的吞吐影响很大.ebuy通过周密调整数据库操作的次序、异步恢复事件,以及数据核对(reconciliation)或者集中决算(settlement batches)来实现最终一致性.

  • 用异步策略解耦程序

组件之间的异步带来的好处是解耦/缓冲压力.组件内的异步能提供跟灵活的资源管理策略(当然带来了上下文切换的开销).我们还需要异步任务管理/确保机制.

  • 将过程转变为异步的流
  • 虚拟化所有层次

虚拟化所有层次我们还做的不够好.硬件资源层面的虚拟化可以通过docker来实现.目前docker最缺少的是资源的管理/发现/注册能力.通用资源服务层面的虚拟化也可以通过注册中心来实现.结合配置管理系统/框架组件化,可以做到对应用的透明.

  • 适当地使用缓存

缓存组件很多,分布式/集中式/进程内,不要选花了眼.同类型的我们只需要一种缓存组件,他必须要能支持丰富的数据结构,如果能提供持久话的能力最好(前提是在down掉的情况下要保证数据的一直.).

##Why Choose Jetty? https://webtide.com/why-choose-jetty/

一直有想法把jetty嵌入到我们的程序中来运行,jetty自身的体系结构优势便于我们去裁剪或者新增功能.

jetty的设计哲学很酷: >Don’t put your application into Jetty, put Jetty into your application.

http proxy

http://rehorn.github.io/livepool/

http://mitmproxy.org/

两个都是好东东.可以看下手机里面在干啥,吐槽下某些粗制滥造的app.也可以用来模拟http请求.

jvm flag

http://stas-blogspot.blogspot.jp/2011/07/most-complete-list-of-xx-options-for.html

最全的jvm flag.

1.场景描述:

某项目使用hibernate,在切换到dubbo后,在构造结果对象时从延迟加载对象中获取数据时,报org.hibernate.LazyInitializationException: could not initialize proxy - no Session

构造结果对象的操作没有在事务环境下执行.

2.原因分析:

cxf不报错是因为在web.xml中配置了org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter,在请求到达web filter后,创建了EntityManager,请求结束后关闭EntityManager.在请求线程处理过程中,都可以拿到EntityManager,所以不会报错(至少可以从ThreadLocal中拿到).

切换为dubbo后,请求不会经过web filter,在事务模版代码中执行业务操作,可以正确的拿到EntityManager,不会报错.但是执行到构造结果对象时,就悲剧了.

3.解决办法:

1.修改模版方法,把构造结果对象部分的代码也放到事务中执行.

2.编写支持dubbo的OpenEntityManagerInViewFilter

可以通过TransactionSynchronizationManager做到如果EntityManagerFactory在线程变量中不存在则创建EntityManager,服务处理结束时,关闭EntityManager.

4.优劣分析

  1. 性能考虑

    open session in veiw模式还是不怎么优雅,事务执行链路太长了,会影响性能.而且对于我们提供的服务接口来说,构造结果对象已经是最后一步了,后面再也不需要延迟加载对象,不需要在filter里面来做此操作.

    web应用有在渲染模版时读取延迟加载对象的场景,这种场景使用还有意义.

  2. 功能角度

    如果遇到应用内的两个dubbo服务调用,dubbo会走injvm协议.此时请求不会经过io栈,但是会执行所有的dubbo filter.

    比如外部请求调用服务A,服务A调用内部服务B.

    外部请求调A时,filter创建EntityManager,然后调用服务B时,filter不创建EntityManager,但是在请求B结束时,filter关闭了EntityManager.在请求A中处理剩下的业务逻辑,如果遇到要操作数据库,就只有哭了.

    为什么web请求就不怕这种filter重入呢?web请求在forward时,你必须把request对象带进去,所以可以在request对象的attribute里面记录是否进过了这个filter.可以参考org.springframework.web.filter.OncePerRequestFilter.但是调用dubbo时,你只需要拿到服务代理对象就ok了,没有办法来知道整个请求链的情况.

5.最后结论

还是修改下我们自己的代码,把构造结果对象部分的代码也放到事务中执行.

vagrant挺火的,用于快速搭建开发环境.官方网站一行大字Development environments made easy.很惹眼.他可以实现可分发的环境搭建.

我们现在要快速搭建开发测试环境的需求很强烈,我们希望使用TA来快速搭建我们的开发测试环境.so,begin…

1.Centos上安装Virtaul Box1

1.1 安装问题unable to find the sources of your current Linux kernel. Specify KERN_DIR=<directory> and run Make again.2

Virtaul Box原因是uname -rls /usr/src/kernels/版本不一致,需要执行yum update,可以把国内的yum镜像用起来,会快点.完了重启下.

参考:

http://rationallyparanoid.com/articles/virtualbox-centos-6.2.html
https://www.centos.org/forums/viewtopic.php?t=5603

2.Centos上安装vagrant3

2.1 static IP on a bridged interface

由于是公用的环境,会有很多个童鞋去访问,所以需要固定ip,并且上面的服务大家也可以自由访问,所以需要桥接网络. 但是官方网站上没有这样的配置,最后在github4上发现了解决方案,测试了N遍,终于对头了:

config.vm.network "public_network", :bridge => "eth0", :ip => "192.168.46.51"

如果是mac上,就用:

config.vm.network "public_network", :bridge => "en0: Wi-Fi (AirPort)", :ip   => "192.168.1.222"

这样也需要注意下,如果要搭建多套环境,最好还是开一个新的网段,别和其他系统的ip冲突了.

如果只是你自己一个人玩,使用host-only吧,很简单.

2.2 ext4 file system inconsistency系统稳定性问题

不知道什么原因,过段时间就启动不了,最后通过ssh tunneling打开Virtaul Box图形化界面才发现了这个ext4 file system inconsistency问题.

错误日志如下:

	There is a known Linux kernel bug which can lead to the corruption of the virtual disk image under these conditions.
	Either enable the host I/O cache permanently in the VM settings or put the disk image and the snapshot folder onto a different file system.
	The host I/O cache will now be enabled for this medium.

这是一个kernel的bug,centos forum上遇到这个问题5,其他的虚拟化vmware也有同样的问题.

如果enable host I/O cache,又会遇到各种问题6.比如data loss,I/O errors,I/O requests time out,Physical memory waste都是童鞋们不能接受的.

只有选择使用不同的文件系统,fdisk -l看下/home还比较大,有上T的空间.

#卸载home分区
umount /dev/mapper/VolGroup-lv_home
#格式化
mkfs.ext3 /dev/mapper/VolGroup-lv_home
#装载home分区
mount /dev/mapper/VolGroup-lv_home /home 最后需要修改 `/etc/fstab`,改变挂载分区为`ext3`,重启后`sudo parted -l`看生效没有.现在可以在`/home`目录启动vagrant.

2.3 guest分配多核反而更慢

如果开启多核(比如设置为20核),又遇到启动很慢的问题7.原因是:

VMs with multiple vCPUs require that all allocated cores be free before processing can begin. This means, if you have a 2 vCPU machine,2 physical cores must be available, and a 4 vCPU requires 4 physical cores

我开启20核,等了半个小时实在等不下去了.

查看cpu个数grep 'physical id' /proc/cpuinfo | sort -u,2个物理cpu.查看每个cpu核心数,grep 'core id' /proc/cpuinfo | sort -u | wc -l,每个cpu6个核心. 按照

One point to note is that if you assign many more vCPUs than you have physical CPUs the system may run slower because the host spends more time scheduling threads than actually running them.

,理论上12个应该是最优的,但是感觉还是不太靠谱,测试某app启动性能:

cpus 启动费时1 启动费时2
1 34664 34291
2 29040 29104
4 26205 26495
6 27207 28566
8 48087 44483

根据上面的测试,给vm配置4 cpus是最优的.卧槽,咱这服务两个物理cpu,每个cpu6 个核心,在加上Hyperthreading,processor都有24个了.如果这台服务器上有多个vm,咱这个测试最优的cpu数还会更少.

3.制作package

3.1 初始化vagrant环境

下载一个官方提供的base box8,用于初始化环境.这里我们选择CentOS 6.4 x86_649. 在前面提到的ext3分区上进行:

 #添加镜像到 Vagrant
 vagrant box add yiji package.box
 #初始化环境
 vagrant init yiji

当前目录会有一个Vagrantfile文件,加上前面测试的东东:

config.vm.network "public_network", :bridge => "eth0", :ip => "192.168.46.51"
config.vm.provider :virtualbox do |vb|
    vb.gui = false
    #设置内存
    vb.customize ["modifyvm", :id, "--memory", "5120"]
    #设置虚拟机ip
    vb.customize ["modifyvm", :id, "--cpus", "4"]
    #设置ioapic,启用多个cpu时,必须设置.如果就一个cpu就不要设置,影响性能
    vb.customize ["modifyvm", :id, "--ioapic", "on"]
    #vb.customize ["modifyvm", :id, "--cpuexecutioncap", "50"]
end

启动虚拟机并ssh登陆:

#启动虚拟机
vagrant up
#ssh登陆
vagrant ssh

3.2 初始化VM环境

ssh登陆后,此时是用vagrant用户登陆的,这个时候神马事情都干不了,切换到root用户

#修改root密码
sudo passwd root
#切换到root账户
su - root 配置路由和dns服务器:

sudo route del default
sudo route add default gw 192.168.46.254
echo "nameserver 192.168.45.10" > /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf 添加定时常用定时任务:

#每12小时时间服务同步
0 */12 * * * rdate -s time.nist.gov
#每天清理日志
0 0 * * * /script/deletelog.sh

关闭防火墙:

chkconfig ip6tables off
chkconfig iptables off 为了集中控制jvm的启动参数,定义java应用依赖环境变量:

export APP_JAVA_OPTS="-Xms256m -Xmx512m" 所有的java应用启动脚本中把`APP_JAVA_OPTS`加在启动参数的最后,它的优先级最高,就很方便的控制所有的jvm进程内存大小了.

上面有些东西可以脚本化的,尽量就脚本化,比如在/etc/rc.d/rc.local增加启动脚本init.sh .其他脚本分为 init_network.sh init_env.sh init_common_app.sh init_app.sh

3.3 安装memcache

安装:

yum install memcached

配置文件:

/etc/sysconfig/memcached 命令:

service memcached start/stop/restart/status

设置开机启动:

chkconfig memcached on 修改`/etc/init.d/memcached`可以修改memcache启动参数

3.4 安装rabbitmq

安装:

yum install rabbitmq
 	#安装webui
 	rabbitmq-plugins enable rabbitmq_management
 	#启用guest账户 访问web ui
 	echo "[{rabbit, [{loopback_users, []}]}]." >/etc/rabbitmq/rabbitmq.config

常用命令:

service rabbitmq-server stop/start/etc.

web ui访问地址,账号密码guest/guest:

http://192.168.46.51:15672/

设置开机启动:

chkconfig rabbitmq-server on

3.5 安装其他软件

jdk/maven/memcache/zookeeper/rabbitmq/dubbo-monitor-simple/dubbo-admin

3.6 服务列表说明

服务 服务端口 web ui 端口
memcache 11211
zookeeper 2181
rabbitmq 5672 15672
dubbo-monitor 7070 7071
dubbo-admin 7073

3.7 制作分发包

vagrant package 上面命令会在当前目录生成一个`package.box`文件,此文件拷贝到其他服务器,就可以快速搭建系统了.

3.8 常用vagrant 命令

#初始化环境,此命令会生成Vagrantfile配置文件,如果当前目录有Vagrantfile,不要执行此命令,直接up吧
vagrant init

#启动虚拟机  
vagrant up

#关闭虚拟机  
vagrant halt

# 重新启动虚拟机,如果Vagrantfile被修改后,执行此命令才能生效.
#但是修改cpu相关参数,此命令也不能重新加载配置,这个时候把虚拟机先停下来,
#通过ssh tunneling在gui界面里调整
vagrant reload 

#SSH至虚拟机
vagrant ssh
  
#查看虚拟机运行状态
vagrant status

# 销毁当前虚拟机
vagrant destroy  

#add box
vagrant box add boxname xxx.box

#remove box

vagrant box remove boxname

#list box
vagrant box list

4.写在最后

virtual box的性能让人担忧,如果部署应用太多需要仔细权衡下,如果只是搭建单机环境,使用vagrant还是很ok的.