vagrant挺火的,用于快速搭建开发环境.官方网站一行大字

1
Development environments made easy.
很惹眼.他可以实现可分发的环境搭建.

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

1.
1
Centos
上安装
1
Virtaul Box
1

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

Virtaul Box原因是

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

参考:

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

2.
1
Centos
上安装
1
vagrant
3

2.1
1
static IP on a bridged interface

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

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

如果是mac上,就用:

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

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

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

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

不知道什么原因,过段时间就启动不了,最后通过

1
ssh tunneling
打开
1
Virtaul Box
图形化界面才发现了这个
1
ext4 file system inconsistency
问题.

错误日志如下:

1
2
3
	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也有同样的问题.

如果

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

只有选择使用不同的文件系统,

1
fdisk -l
看下
1
/home
还比较大,有上T的空间.

1
2
3
4
5
6
#卸载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个数

1
grep 'physical id' /proc/cpuinfo | sort -u
,2个物理cpu.查看每个cpu核心数,
1
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 个核心,在加上

1
Hyperthreading
,
1
processor
都有24个了.如果这台服务器上有多个vm,咱这个测试最优的cpu数还会更少.

3.制作package

3.1 初始化vagrant环境

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

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

当前目录会有一个

1
Vagrantfile
文件,加上前面测试的东东:

1
2
3
4
5
6
7
8
9
10
11
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登陆:

1
2
3
4
#启动虚拟机
vagrant up
#ssh登陆
vagrant ssh

3.2 初始化VM环境

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#修改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

关闭防火墙:

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

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

上面有些东西可以脚本化的,尽量就脚本化,比如在

1
/etc/rc.d/rc.local
增加启动脚本
1
init.sh
.其他脚本分为
1
init_network.sh
1
init_env.sh
1
init_common_app.sh
1
init_app.sh

3.3 安装memcache

安装:

1
yum install memcached

配置文件:

1
2
3
/etc/sysconfig/memcached 命令:

service memcached start/stop/restart/status

设置开机启动:

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

3.4 安装rabbitmq

安装:

1
2
3
4
5
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/

设置开机启动:

1
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 制作分发包

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

3.8 常用vagrant 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#初始化环境,此命令会生成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.写在最后

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

Awesome Sysadmin

https://github.com/kahun/awesome-sysadmin

系统管理员的开源资源,资源暴多,技术选型时参考.

Tengine

http://dmsimard.com/2014/06/21/a-use-case-of-tengine-a-drop-in-replacement-and-fork-of-nginx/

使用tengine来做LB,通过Tengine的

1
unbuffered requests
特性实现了上传性能提升.

不过我自己装tengine启动就遇到了问题.

1
2
3
the configuration file //Users/bohr/software/tengine/conf/nginx.conf syntax is ok
nginx: [emerg] mkdir() "//Users/bohr/software/tengine/logs/access.log" failed (21: Is a directory)
configuration file //Users/bohr/software/tengine/conf/nginx.conf test failed

服务器操作系统应该选择 Debian/Ubuntu 还是 CentOS?

http://www.zhihu.com/question/19599986

生产环境选择操作系统还是要慎重.现在我厂在线上用ubuntu,遇到过几次诡异事件(服务器无缘无故挂了,没有任何日志,时间跳变),看了这篇文章,SA应该会把线上的linux服务器统一了吧.

web-starter-kit

https://github.com/google/web-starter-kit

Web Starter Kit is a starting point for multi-screen web development. It encompasses opinionated recommendations on boilerplate and tooling for building an experience that works great across multiple devices.

微服务:分解应用以实现可部署性和可扩展性

http://www.infoq.com/cn/articles/microservices-intro http://microservices.io/index.html

文章讨论了整体架构和微服务构架的优缺点.对于大型应用而言,微服务架构当然是首选.

API网关模式用于解耦应用客户端和微服务.我们可能没有考虑对不同的客户端提供不同粒度的服务(不同客户端的网络环境不一样).

对于非强一致性数据要求的场景,

1
事件驱动的异步更新
(服务发布事件声明有些数据发生了变化,其他的服务订阅这些事件并更新它们的数据)解耦了事件的生产者和消费者,简化了开发也提升了可用性.某应用,很多配置数据都存在memcache中,一笔业务需要查询缓存>5次,每次都要去查,感觉很不爽.还是使用本地缓存+事件驱动的异步更新来做比较好.

面向GC的Java编程

http://coolshell.cn/articles/11541.html

好文,总结的很不错.

spring boot Initializr

http://start.spring.io/

有了这个,创建spring boot项目就快了.

OOM Killer

很早听说OOM Killer这个东东,感觉很神秘.而且以前分析某次线上故障,我得出的结论是OOM Killer,但是没有找到日志,囧!最近在玩vagrant,用的ubuntu box,虚拟机内存分配512m,某应用配置jvm内存

1
-Xms256M -Xmx512m -XX:PermSize=64m -XX:MaxPermSize=256m
.应用在启动过程中日志刷了一会儿就不动了,
1
command+c
结束后,console报出:

1
2
INFO: Initializing Spring root WebApplicationContext
^C./tomcat.sh: line 6:  7649 Killed                  nohup mvn clean tomcat7:run -Dspring.profiles.active=$env -Dsys.name=$sysname > "$logfile" 2>&1 < /dev/null

找了很久,在

1
/var/log/syslog
发现如下日志:

1
2
May 22 09:47:41 vagrant-ubuntu-saucy-64 kernel: [ 5499.448534] Out of memory: Kill process 7649 (java) score 788 or sacrifice child
May 22 09:47:41 vagrant-ubuntu-saucy-64 kernel: [ 5499.449012] Killed process 7649 (java) total-vm:1460964kB, anon-rss:407220kB, file-rss:0kB

这篇文章解释如何处理oom

vagrant

https://github.com/astaxie/Go-in-Action/blob/master/ebook/zh/01.2.md

http://blog.segmentfault.com/fenbox/1190000000264347

http://docs.vagrantup.com/v2/getting-started/index.html

如果mac环境下虚拟机出现Failed to load VMMR0.r0 (VERR_SUPLIB_WORLD_WRITABLE),执行

1
sudo chmod o-w /Applications
再试试.

构建高可用系统的常用招数

http://bluedavy.me/?p=468

大牛的总结,分享+总结下:

  1. 监控和报警
监控和报警能提前发现问题/缩短故障时间,前提是得能正确的评估监控点.
  1. SPoF(Single Point of Failure)
单点故障也分层次的,不过我们coder一般只关注服务层面.服务尽量做到无状态,只需要做负载就ok了.不能做成无状态的就需要做集群了.实在不行的就做成主备.
  1. 解耦

    后端业务通过消息/事件来解耦(Eventbus也不错),前端页面模块化,互相不影响.

  2. 隔离

    隔离既要防止依赖的系统之间相互影响(防止故障传播),也要防止同一节点上的不同服务相互影响(资源隔离).

    宏观层面,区分服务重要性,如果都能服务化就好做了.不同服务可以选择配置不同个数的服务节点.重要的,访问量大的就多加点节点.这需要监控系统能准确评估服务访问情况.

    微观层面,在服务内部,服务对外提供的能力一般通过线程池大小和请求队列长度来控制.在这里,大不一定就好,多也不定就好.

  3. 容灾

这里谈了几点:超时控制/非关键业务自动降级(用dubbo实现就很方便)/手动降级/自恢复能力(比如druid连接池)/自我保护能力

自己补充点,快速故障恢复能力(日志很重要)/避免人为故障(减少开发人员犯错误的机会)/简单可依赖(能简单做的就绝对不玩花哨)

Uses MySQL to store schema-less data

http://backchannel.org/blog/friendfeed-schemaless-mysql

如何用mysql来存储schema-less的数据,实现很简单.

数据表:

1
2
3
4
5
6
7
8
CREATE TABLE entities (
	added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	id BINARY(16) NOT NULL,
   	 	updated TIMESTAMP NOT NULL,
	body MEDIUMBLOB,
	UNIQUE KEY (id),
	KEY (updated)
) ENGINE=InnoDB;

假如内容是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
	"id": "71f0c4d2291844cca2df6f486e96e37c",
	"user_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
	"feed_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
	"title": "We just launched a new backend system for FriendFeed!",
	"link": "http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c",
	"published": 1235697046,
	"updated": 1235697046,
} 如果要给title建立索引,创建新表

CREATE TABLE index_title (
	title varchar(100) ,
	entity_id BINARY(16) NOT NULL UNIQUE,
   		PRIMARY KEY (user_id, entity_id)
) ENGINE=InnoDB;

查询的时候先从索引表查出entity_id,然后在去entities表查询详细数据.可以存储数据为text,方便数据库直接操作(必要性不是很大,text太占内存了),当然最好还是存储压缩后的二进制数据.不是经常改动的数据,应用层在加上一层cache.

索引可以异步建立,定时任务周期性的去找updated的新数据.

为什么tomcat应用三分钟还关不掉

这种问题一般是因为还有非deamon线程在容器关闭时没有正确的关闭导致的.可以在执行tomcat shutdown脚本后,jstack线程栈,看下还有哪些非deamon线程在执行.

应用使用线程持一定要记得关闭线程池,可以用spring提供的.

1
2
3
4
5
6
7
8
9
<bean id="taskExecutor"
      class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="10"/>
    <property name="keepAliveSeconds" value="200"/>
    <property name="maxPoolSize" value="50"/>
    <property name="queueCapacity" value="1000"/>
    <property name="awaitTerminationSeconds" value="60"/>
    <property name="waitForTasksToCompleteOnShutdown" value="true"/>
</bean> 注意最后面两个参数.

The New RBAC: Resource-Based Access Control

最近看看shiro的相关资料,看到这篇文章.以前也隐隐约约思考过权限控制,也感觉RBAC控制粒度太粗了.作者提到

1
Explicit Access Control
概念,通过资源来解耦角色,控制粒度更细.从权限的分配角度来说,这样使用也更方便,可以把权限分配到某个用户/某个组/某个角色.

当然,我们把资源的权限和角色一一对于,角色有层次关系并且可以继承,RBAC也可以胜任细粒度的权限控制.