shell交互批量修改主机名

场景 有时候我们有批量修改主机名和同步hosts文件到多台主机的需求,例如新上了一批服务器等,可能主机名称上并不能满足你的命名规则或规范,但如果一台台去更改可能就太慢又无聊,所以shell脚本绝对是你的最佳选择。 需求分析 []ssh公钥拷贝,提供无密...
继续阅读 »


场景


有时候我们有批量修改主机名和同步hosts文件到多台主机的需求,例如新上了一批服务器等,可能主机名称上并不能满足你的命名规则或规范,但如果一台台去更改可能就太慢又无聊,所以shell脚本绝对是你的最佳选择。


需求分析


    []ssh公钥拷贝,提供无密码管理。[/][]批量同步hosts文件到多台主机。[/][]批量修改主机名。[/]


实现


首先编辑一份用于同步到多台主机的hosts文件
# vi /etc/hosts

192.168.0.1 server1
192.168.0.2 server2
192.168.0.3 server3
192.168.0.4 server4
192.168.0.5 server5
192.168.0.6 server6
192.168.0.7 server7
192.168.0.8 server8
192.168.0.9 server9
192.168.0.10 server10
然后编辑shell脚本:
# vi changename.sh

#!/bin/bash
# This is a shell script to change hostname

export PATH=$PATH
export USER=root
export SNAMEPRE=server
export PASSWD=test01 #定义密码
for i in {1..10};
do /usr/bin/expect << EOF [size=16]这里用到了expect完成了确认yes和密码输入交互[/size]
spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $USER@$SNAMEPRE$i
expect {
"(yes/no)?" {send "yes\r";exp_continue}
"password:" {send "$PASSWD\r"}
}
interact
expect eof
EOF
ssh $USER@$SNAMEPRE$i "sed -i s/^HOST.*/HOSTNAME=$SNAMEPRE$i/ /etc/sysconfig/network";
scp /etc/hosts $USER@$SNAMEPRE$i:/etc/hosts;
done;
这里用到了expect完成自动交互确认和密码输入。

Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。Expect的作者Don Libes在1990年 开始编写Expect时对Expect做有如下定义:Expect是一个用来实现自动交互功能的软件套件 (Expect [is a] software suite for automating interactive tools)。使用它系统管理员 的可以创建脚本用来实现对命令或程序提供输入,而这些命令和程序是期望从终端(terminal)得到输入,一般来说这些输入都需要手工输入进行的。
更多Expect信息请查看站点  http://expect.sourceforge.net/
这样一个简单的脚本就帮你完成3件事,拷贝公钥、修改主机名、同步hosts文件。
 
如果使用ansible会更简单! 收起阅读 »

Saltstack高可用架构漫谈

起因 鄙人折腾Salt也已经一年有余了,从最开始Linux运维的基础知识,包括啥叫配置管理都一无所知,事到如今好歹也做了一些事情,虽然没啥功劳,也埋了一些坑,但是总归在自动化方面贡献了一些微薄的力量。 为什么要搞Salt高可用架构呢? 起因是因为公司内部...
继续阅读 »


起因


鄙人折腾Salt也已经一年有余了,从最开始Linux运维的基础知识,包括啥叫配置管理都一无所知,事到如今好歹也做了一些事情,虽然没啥功劳,也埋了一些坑,但是总归在自动化方面贡献了一些微薄的力量。

为什么要搞Salt高可用架构呢? 起因是因为公司内部对于Salt的要求从工具上升到了基础架构组件的层面,要求在响应时间和服务可用性方面有一些更高的要求,简单来说,就是内部的一些重要组件依赖于它来完成一些事情。而Salt原生是默认的单点Master - Minion结构,其Salt-API也是Daemon方式的裸奔运行,我们踩了很多坑,发现实在是痛的不行,鄙人向领导反馈了这一严重隐患,终于也就有了这样的一次折腾。
 
至今,我们研究的成果已经推广到了生产环境,虽然它还是有很多的问题,然而之所以写下这篇博客,实在只是为了聊以纪念一下整个项目团队几个月来的共同努力。


启发


Salt 高可用架构方面的文档和参考案例还是相当稀少的,直到今年(2015)的5月份左右的样子,才看到官方有整理出一篇高可用相关的文档:http://docs.saltstack.com/en/latest/topics/highavailability/index.html
 
而这里面讲的也还是比较宽泛,可以选择的架构以及对应的优缺点信息都比较稀少。好在开源大牛们从来都不缺乏分享的精神,鄙人挖了一下SaltConf15上一些成功的案例分享,最主要的当然是Linkedin的Thomas Jackson大牛的分享,最终通过反复研究,有些收获(期间多亏Kenny的几次指点,真的非常感谢)。
 
MultiSyndic、MultiMaster、Failover Minion、Ext Job Cache
我们这边最后采用的架构采用了MultiSyndic + MultiMaster + Failover Minion这几个salt原生的重要特性,为了不让读者们困惑,这里先首先讲解下这几个特性。


MultiSyndic


MultiSyndic 是 2014.7版本以后才引入的一个重要特性,它使得SYndic架构变得更加灵活,即一台SYndic可以同时被多台MOfM管理(你可以理解为MultiSyndic的MultiMaster),官方文档这方面做的还不是很完善,只是简单的介绍了一下该如何配置,大家可以看看:https://docs.saltstack.com/en/latest/topics/topology/syndic.html
 
具体的源码则是放到了minion.py的这一块,本身原理便是MultiSYndic会去复用一些Syndic的功能,然后做一些转发的处理。
 
MultiSyndic的配置其实有点综合MultiMaster,你需要设置syndic本身的一些配置,包括每台syndic设置syndic_master为一个list mofm,另外Key等文件做共享配置,其次写入一些必要的syndic本身的配置,由于过于细节,这里不再赘述。


Failover Minion(Or MultiMinion)


Failover Minion 则是Salt引入的一个Minion端实现的特性,它允许minion定期的去探测当前master的存活性,一旦发现master不可用,可以在一定时间内做出切换,从而提高整体服务调用的可用性,具体的配置文档也可以参见官方文档,需要注意的是配置MultiMaster 亦或是 MultiMaster PKI都可以使用failover特性,这一点已经由官方强调过,minion配置内容如下:
# multi-master
master:
- 172.16.0.10
- 172.16.0.11
- 172.16.0.12

# 设置为failover minion
master_type: failover

# 设置启动时随机选择一台master
master_shuffle: True

# 探测master是否存活的schedule job
# 即使用salt schedule特性实现的功能
master_alive_interval:


Ext Job Cache


如何分解出master的压力?一方面,可以做负载均衡,将minion分散到不同的Master去管理,另外一方面,跑salt-job的主要需求还是获取job结果,为了减轻查询结果方面的压力,也为了提高整体架构的并发能力,鄙人推荐了引入ext job cache的特性。

实际上,使用ext_job_cache配置搭配合适的returner便可以让salt-master默认将job数据写入到指定的存储,然而这样带来的坏处是一旦你存储的组件挂掉了,比如配的redis returner,redis一旦挂掉,那么job便根本无法下发(因为job下发的时候便会将job load写入到cache,即这次job的执行参数和命中的具体minion数据),为了规避这一个坑,鄙人改造了绿肥同学基于Salt Event系统构建Master端returner这篇博客里讲解的监听event并写入job数据的方案,通过配置额外的服务来实现了ext job cache的写入。


几种高可用架构的选择


OK,至此,我们已经了解了一些基本的Salt原生提供的高可用特性,接下来,鄙人将为您分享我个人认为不同的量级和场景下推荐的Salt高可用架构方案。

备注:这里统一建议一下salt-master的配置性能,我个人之前使用的salt-master是2C6G的低配虚拟机,踩了非常多的坑,包括Auth风暴等等,1k台机器之后使用起来体验也相当糟糕,所以个人建议salt-master配置至少> 8C的计算能力~
 
方案1: Single Master With Warm Backup
适用场景:< 1k Minion的小规模应用
Salt版本限制:印象中至少0.17已经支持了这个特性

问题:我个人也没有在生产具体应用过该架构,但是
SaltConf15上已有这样的用例,应该是完备的一方案~
Salt 原生支持salt-master指向配置成DNS域名,它会通过resolv_dns函数来解析具体的master ip,所以在minion发现与master中断后,它会尝试和master重新连接,而可以通过重新解析DNS来实现Master的切换。
 
方案2:MultiMaster
适用场景: 1k ~ 4k,调用强度集中于小规模机器
鄙人也和几位业内的运维交流了salt的一些心得,应该目前来说,MultiMaster算是最常见的应用架构,它足够的简单,并且Salt原生的支持也相对比较成熟,个人也推荐在中等规模及一般使用的情况下可以使用这样的一个架构来满足需求。
 
方案3:MultiMaster + MultiSYndic + FailoverMinion(linkedin分享的架构#5)
适用场景:并发调用强度相对较高,并且分多套salt各自维护(比如UAT和PROD不是一个团队的人来维护这样一个情况),
对于salt服务的SLA以及性能方面有较高要求的场景,机器数量方面可以通过横向扩展来解决,
一般来说,建议 ~10k 及以上的规模采用此架构方案(并且鄙人尝试配置过官方原生的这个架构,
貌似有很多的坑,我们这边是通过修改了MultiSyndic的部分代码才使得整体架构可用)
话不多说,一图胜千言,实际上,我们内部用的就是linkedin分享的第5套架构,可能有人会问,为啥不用第6套架构呢? 我个人测试过,第6套架构是可行的,但是貌似只能跑两台master互为master\syndic,一旦配成三台便会出现event loop,这个我们内部分析过,应该是一个合理的逻辑,不知道为啥linkedin最终是推荐的这个架构?
salt_arch.png

采用这一架构的话,首先一点,我们可以在MofM这一层架设Salt-API,并设置负载均衡,这样一来的话,能实现API这一层的负载均衡及横向扩展。另外一方面,MultiSyndic这一层,由于每台minion实际一个时刻只由一台SYndic Master管理,因此Syndic Master的压力被分散到了每台机器上,再者,MofM由于可以和所有的SYndic通信,因而上层的Salt-API可以ping通全量的Minion!值得补充的是,我们将syndic的job event额外吐到了统一的redis job cache,这样一来,通过调整salt api的调用方式(从同步改成异步),即可极大的减轻Master的负载,将压力均摊到了redis cache(减少了大量的find_job任务,当然,问题即在于你必须给出一个大致的超时时间,因为问询salt-minion是否完成的逻辑改成了query job cache,所以无法感知minion实际是否真的在执行与否)。

如此一来,即实现了负载均衡 + 高可用 + 可横向扩展的Salt架构方案!Success!


当前架构的利与弊


通过生产环境的线上实际体验,我们也获知了我们当前采取的#5架构的一些具体的利弊所在,不敢私藏,在此分享一二。
利:
这一架构的优势在于高并发的爆发能力和可扩展的负载均衡能力。

首先,我们用nginx + UWSGI将salt-api封装了一层,使得其并发能力和稳定性有了一定的提高。

另外, 这个架构下,上层MofM只负责下发Job并且可以横向扩展,这便实现了强大的API高并发的可能,另外, Syndic每台管理1/n的minion机器,相对的负载被分散到了各台机器上,理论上来说它可以支撑的minion机器规模是足够数量级的。
弊:
诶,这个架构目前的劣势也是相当的明显,成也MultiSyndic,败也MultiSyndic, Syndic的逻辑是处理完结果后会把job数据回吐给MofM,而MofM理论上是可以ping通所有minion的,所以一旦执行类似Salt * test.ping命令的时候,MofM就等于承受了一次短时间的数据流量的冲击,所有Syndic会在短时间内把job result回吐给MofM,1w台minion便是1w条minion job数据,再加上find_job任务,后果不堪设想..

因此,我们如今也在推动整改成异步调用的方式,并且也在思考如何优化这一层的处理,实际上,用户如何使用也是一个很大的哲学。


结语


这篇文章是鄙人今天整理这几个月的感受仓促而成,很多的细节还没有完全的揭露,实际上,生产环境的线上考验仍然不够充分,然而,毕竟还是完成了一个小小的milestone,写出这篇文章,也是为了分享一下个人的踩坑记。Salt的确很坑,有很多的问题, 但是,在决定使用它并将其作为基础架构组件的情况下,抱怨变得毫无意义,如何有方法的具体的去实施,去解决问题才是我们实际需要考虑的事情。

在这几个月的过程中,从最开始的茫然,焦躁,到在Kenny带领下研究架构的方案,再到找上Dingw大哥一起研究和改动MultiSYndic的代码,实在是成长了很多,多亏了几位大哥的帮扶,尤其是Kenny, Dingw,Bshu, JY 几位大哥,在架构和代码二次开发方面出了很多力气,鄙人也算是在几位大哥的carry下算是一起完成了这件事情罢。目前,只是完成了新架构的生产切换,未来可能还会有很多的挑战,鄙人很遗憾后续无法更多的参与,但是很感恩与团队里的同事们一起攻克问题的这几个月的经历。

这个架构是否可以完全适应我们公司内部的使用也有待进一步的考验,也相信我们项目团队会进一步的优化和改善Salt的使用,最终促成一个健壮的Salt基础架构组件服务!!


分享原文作者:jacky
分享原文地址:http://devopstarter.info/saltstack-ha-arch/


收起阅读 »

Linux培训视频大全

兄弟连Linux基础学习视频下载地址:http://pan.baidu.com/s/1c02k6wo 老男孩培训视频大全下载地址:http://pan.baidu.com/s/1o6AJgfS 马哥教育培训视频Linux下载地址:http://pan.ba...
继续阅读 »
兄弟连Linux基础学习视频下载地址:http://pan.baidu.com/s/1c02k6wo
老男孩培训视频大全下载地址:http://pan.baidu.com/s/1o6AJgfS
马哥教育培训视频Linux下载地址:http://pan.baidu.com/s/1hqz0dJA
 
开源技术社区QQ群号:372476089  欢迎加入互相学习
扫码关注微信号:
opsk.jpg
收起阅读 »

所有IT技术相关英文原版书籍

所有IT技术相关英文原版文档官网下载地址:http://www.allitebooks.com/   编程开发所有免费IT技术英文Ebook书籍地址:https://it-ebooks.info/
继续阅读 »
所有IT技术相关英文原版文档官网下载地址:http://www.allitebooks.com/
all_it_ebooks.gif

 
编程开发所有免费IT技术英文Ebook书籍地址:https://it-ebooks.info/
IT_eBooks_Free.gif
收起阅读 »

新增一个hdfs的DataNode节点

场景 在hadoop中的分布式文件系统hdfs中,当存储节点磁盘使用达到预警值是,我们需要新增一个数据存储节点,来存储数据!我这里hdfs的版本是2.2.0!新增方法: []静态添加[/][]动态添加[/] 静态添加 静态新增的方式,就是相当于我们起初...
继续阅读 »


场景


在hadoop中的分布式文件系统hdfs中,当存储节点磁盘使用达到预警值是,我们需要新增一个数据存储节点,来存储数据!我这里hdfs的版本是2.2.0!
新增方法:
    []静态添加[/][]动态添加[/]


静态添加


静态新增的方式,就是相当于我们起初部署hdfs集群规划一样,停止NameNode,新增一个DateNode数据节点,这种方法不适用于线上提供服务的场景,具体操作如下:

1、停止NameNode节点
# cd hdfs_install_dir/sbin/
# ./hadoop-deamon.sh stop namenode

2、修改配置文件slaves文件,并修改/etc/hosts记录把新增的节点对应的ip和hostname追加到各节点
# cd hdfs_install_dir/etc/hadoop/
# echo "new_datanode_hostname" >> ./slaves
# echo "new_datanode_ip new_datanode_hostname" >> /etc/hosts
然后再利用rsync 同步配置文件和hosts文件,到各节点

3、确保Hadoop/HDFS集群的NameNode可以对新节点进行SSH免密码登录。

4、重新启动NameNode节点

5、如果你希望各数据节点磁盘使用量达到一个相对平衡的状态,就是百分比,你还需要执行hadoop balance命令,后面会具体讲到!


动态添加


动态添加,不需要停止启动NameNode节点,具体步骤如下:

1、修改所有hdfs集群机器的配置文件slaves文件,并修改/etc/hosts记录把新增的节点对应的ip和hostname追加到各节点
# cd hdfs_install_dir/etc/hadoop/
# echo "new_datanode_hostname" >> ./slaves
# echo "new_datanode_ip new_datanode_hostname" >> /etc/hosts

如果你使用ansible管理的话,hdfs集群的集群做一个叫hdfs的分组,两条命令搞定:
# ansible hdfs -m shell -a 'echo "new_datanode_hostname" >> hdfs_install_dir/etc/hadoop/slaves'
# ansible hdfs -m shell -a 'echo "new_datanode_ip new_datanode_hostname" >> /etc/hosts'
这样所有的节点slaves文件和host文件都更新了!

2、启动新增的datanode节点
# cd hdfs_install_dir/sbin
# ./hadoop-daemon.sh start datanode

3、查看是否正常加入到集群
web查看方式:http://NameNode_ip:50070/dfsnodelist.jsp?whatNodes=LIVE
命令查看方式:cd hdfs_install_dir/bin/ && ./hadoop dfsadmin -report

4、数据再平衡
添加新节点时,HDFS不会自动重新平衡。然而,HDFS提供了一个手动调用的重新平衡(reblancer)工具。这个工具将整个集群中的数据块分布调整到一个可人工配置的百分比阈值。如果在其他现有的节点上有空间存储问题,再平衡就会根据阀值,然后平衡分布数据。

执行再平衡命令,可选参数-threshold指定了磁盘容量的余量百分比,用来判定一个节点的磁盘利用率是过低还是过高。一个利用不足的数据节点其利用率低于平均利用率−阈值。过度利用的数据节点其利用率高于平均利用率+阈值。该参数设置的越小,整个集群越平衡,但会花费更多的时间进行再平衡操作。默认阈值为10%。平衡执行命令如下:
# cd hdfs_install_dir/sbin/
# ./start-balancer.sh -threshold 5

-threshold参数就是是指定平衡的阈值。
-threshold的默认是10,即每个datanode节点的实际hdfs存储使用量/集群hdfs存储量

具体解释例子如下:
datanode hdfs使用量1000G;
集群总hdfs存储量10T即10000G;
则t值为1000/10000 = 0.1 = 10%
当执行balance的-t参数小于0.1时,集群进行balance;
命令为:start-balancer.sh -threshold 10 ;
Expecting a number in the range of [1.0, 100.0]: 5%
sh $HADOOP_HOME/bin/start-balancer.sh –t 10%
这个命令中-t参数后面跟的是HDFS达到平衡状态的磁盘使用率偏差值。如果机器与机器之间磁盘使用率偏差小于10%,那么我们就认为HDFS集群已经达到了平衡的状态。


标注知识点


1、 balance命令可以在namenode或者datanode上启动,也可以随时利用stop-balance.sh脚本停止平衡! 

2、balance的默认带宽是1M/s。 如果你希望修改平衡数据的带宽大小可以用./hdfs dfsadmin -setBalancerBandwidth 124288000命令指定

3、slave文件是用于重启时使用。集群的start和stop需要读取slave文件。启用datanode时只要在hdfs-site中配置了namenode位置,就可以将信息push给namenode。 这就是为什么slaves文件很重要的原因。
收起阅读 »

rsync增量传输大文件优化案例

前言 rsync用来同步数据非常的好用,特别是增量同步。但是有一种情况如果不增加特定的参数就不是很好用了。比如你要同步多个几十个G的文件,然后网络突然断开了一下,这时候你重新启动增量同步。但是发现等了好久都没有进行数据传输,倒是机器的IO一直居高不下。 ...
继续阅读 »


前言


rsync用来同步数据非常的好用,特别是增量同步。但是有一种情况如果不增加特定的参数就不是很好用了。比如你要同步多个几十个G的文件,然后网络突然断开了一下,这时候你重新启动增量同步。但是发现等了好久都没有进行数据传输,倒是机器的IO一直居高不下。


原因


rsync具体的增量同步算法不太清楚。根据它的表现来看,可能在增量同步已经存在的一个文件时,会校验已传输部分数据是否已源文件一致,校验完成才继续增量同步这个文件剩下的数据。所以如果对一个大文件以这样的算法来增量同步是非常花时间并且占用IO资源的。


方法


集中花了一段时间查看了rsync的文档,发现有一个参数能快速恢复大文件的增量同步,–append。设置–append参数会在增量同步时计算文件大小并直接追加新的数据到文件,这样就省了费IO校验的过程。不过这个参数最好只在源文件和目标文件都不会更改的时候使用比较安全,比如备份的文件。
收起阅读 »

Java调用Hbase API访问接口

HBase是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统(File System)所提供的分布式数据存储一样,H...
继续阅读 »
HBase是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统(File System)所提供的分布式数据存储一样,HBase在Hadoop之上提供了类似于Bigtable的能力。HBase是Apache的Hadoop项目的子项目。HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。另一个不同的是HBase基于列的而不是基于行的模式。
HBase表一般特点:
    []大:一个表可以有上亿行,上百万列[/][]面向列:面向列(族)的存储和权限控制,列(族)独立检索[/][]稀疏:对于为空(null)的列并不占用存储空间,表可以设计非常稀疏[/]

 
Java 调用 Hbase 非关系型数据库,Hbase 中提供了相关的 Java API 访问接口便于使用,下面是本人综合网络总结的通过 Java 操作 HBase 进行创建、修改、删除表以及查询等。具体封装代码如下:
package yoodb.hbase;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.HTablePool;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;

public class HBaseTest {

// 声明静态配置
static Configuration conf = null;
static final HTablePool tablePool;
static {
conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "yoodb");
tablePool = new HTablePool(conf, 15);
}

/*
* 创建表
* @tableName 表名
* @family 列族数组
*/
public static void creatTable(String tableName, String[] family)
throws Exception {
HBaseAdmin admin = new HBaseAdmin(conf);
HTableDescriptor desc = new HTableDescriptor(tableName);
for (int i = 0; i < family.length; i++) {
desc.addFamily(new HColumnDescriptor(family[i]));
}
if (admin.tableExists(tableName)) {
System.out.println("table Exists!");
System.exit(0);
} else {
admin.createTable(desc);
System.out.println("create table Success!");
}
}

/*
* 表添加数据
* @rowKey rowKey
* @tableName 表名
* @column1 第一个列族数组 realname
* @value1 第一个列的值的数组
* @column2 第二个列族数组 address
* @value2 第二个列的值的数组
*/
public static void addTableData(String rowKey, String tableName,String[] column1, String[] value1, String[] column2, String[] value2)
throws IOException {
Put put = new Put(Bytes.toBytes(rowKey));
HTable table = (HTable) tablePool.getTable(tableName);
HColumnDescriptor[] columnFamilies = table.getTableDescriptor()
.getColumnFamilies();

for (int i = 0; i < columnFamilies.length; i++) {
String familyName = columnFamilies[i].getNameAsString();
if (familyName.equals("realname")) {
for (int j = 0; j < column1.length; j++) {
put.add(Bytes.toBytes(familyName),Bytes.toBytes(column1[j]), Bytes.toBytes(value1[j]));
}
}
if (familyName.equals("address")) {
for (int j = 0; j < column2.length; j++) {
put.add(Bytes.toBytes(familyName),Bytes.toBytes(column2[j]), Bytes.toBytes(value2[j]));
}
}
}
table.put(put);
}

/*
* 更新表中的某一列
* @tableName 表名
* @rowKey rowKey
* @familyName 列族名
* @columnName 列名
* @value 更新后的值
*/
public static void updateTable(String tableName, String rowKey,
String familyName, String columnName, String value)
throws IOException {
HTable table = (HTable) tablePool.getTable(tableName);
Put put = new Put(Bytes.toBytes(rowKey));
put.add(Bytes.toBytes(familyName), Bytes.toBytes(columnName),Bytes.toBytes(value));
table.put(put);
System.out.println("update table Success!");
}

/*
* 根据rwokey查询
* @rowKey rowKey
* @tableName 表名
*/
public static Result getResult(String tableName, String rowKey)
throws IOException {
Get get = new Get(Bytes.toBytes(rowKey));
HTable table = (HTable) tablePool.getTable(tableName);
Result result = table.get(get);
for (KeyValue kv : result.list()) {
System.out.println("family==>" + Bytes.toString(kv.getFamily()));
System.out.println("qualifier==>" + Bytes.toString(kv.getQualifier()));
System.out.println("value==>" + Bytes.toString(kv.getValue()));
System.out.println("Timestamp==>" + kv.getTimestamp());
}
return result;
}

/*
* 遍历查询hbase表数组
* @tableName 表名
*/
public static void getResultScann(String tableName) throws IOException {
Scan scan = new Scan();
ResultScanner rs = null;
HTable table = (HTable) tablePool.getTable(tableName);
try {
rs = table.getScanner(scan);
for (Result r : rs) {
for (KeyValue kv : r.list()) {
System.out.println("family==>" + Bytes.toString(kv.getFamily()));
System.out.println("qualifier==>" + Bytes.toString(kv.getQualifier()));
System.out.println("value==>" + Bytes.toString(kv.getValue()));
System.out.println("timestamp==>" + kv.getTimestamp());
}
}
} finally {
rs.close();
}
}

/*
* 查询表中的某单一列
* @tableName 表名
* @rowKey rowKey
*/
public static void getResultByColumn(String tableName, String rowKey,
String familyName, String columnName) throws IOException {
HTable table = (HTable) tablePool.getTable(tableName);
Get get = new Get(Bytes.toBytes(rowKey));
get.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(columnName)); // 获取指定列族以及列中修饰符对应列名
Result result = table.get(get);
for (KeyValue kv : result.list()) {
System.out.println("family==>" + Bytes.toString(kv.getFamily()));
System.out.println("qualifier==>" + Bytes.toString(kv.getQualifier()));
System.out.println("value==>" + Bytes.toString(kv.getValue()));
System.out.println("Timestamp==>" + kv.getTimestamp());
}
}

/*
* 查询某列数据的多个版本
* @tableName 表名
* @rowKey rowKey
* @familyName 列族名
* @columnName 列名
*/
public static void getResultByVersion(String tableName, String rowKey,
String familyName, String columnName) throws IOException {
HTable table = (HTable) tablePool.getTable(tableName);
Get get = new Get(Bytes.toBytes(rowKey));
get.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(columnName));
get.setMaxVersions(5);
Result result = table.get(get);
for (KeyValue kv : result.list()) {
System.out.println("family==>" + Bytes.toString(kv.getFamily()));
System.out.println("qualifier==>" + Bytes.toString(kv.getQualifier()));
System.out.println("value==>" + Bytes.toString(kv.getValue()));
System.out.println("Timestamp==>" + kv.getTimestamp());
}

}

/*
* 删除指定的列
* @tableName 表名
* @rowKey rowKey
* @familyName 列族名
* @columnName 列名
*/
public static void deleteColumn(String tableName, String rowKey,
String falilyName, String columnName) throws IOException {
HTable table = (HTable) tablePool.getTable(tableName);
Delete deleteColumn = new Delete(Bytes.toBytes(rowKey));
deleteColumn.deleteColumns(Bytes.toBytes(falilyName),Bytes.toBytes(columnName));
table.delete(deleteColumn);
System.out.println(falilyName + "==>" + columnName + "is deleted!");
}

/*
* 删除指定的列
* @tableName 表名
* @rowKey rowKey
*/
public static void deleteAllColumn(String tableName, String rowKey) throws IOException {
HTable table = (HTable) tablePool.getTable(tableName);
Delete deleteAll = new Delete(Bytes.toBytes(rowKey));
table.delete(deleteAll);
System.out.println("all columns are deleted!");
}

/*
* 删除表
*
* @tableName 表名
*/
public static void deleteTable(String tableName) throws IOException {
HBaseAdmin admin = new HBaseAdmin(conf);
admin.disableTable(tableName);
admin.deleteTable(tableName);
System.out.println(tableName + " is deleted!");
}
}
Java Hbase main函数测试类,具体代码如下:
package com.yoodb;

public class Test {
public static void main(String[] args) throws Exception {
// 创建表
String tableName = "yoodbblog";
String[] family = { "realname","address" };
HBaseTest.creatTable(tableName,family);
// 为表添加数据
String[] column1 = { "title", "author", "content" };
String[] value1 = {"素文宅","yoodb","www.yoodb.com" };
String[] column2 = { "name", "nickname" };
String[] value2 = { "真实名称", "昵称" };
HBaseTest.addTableData("rowkey1","yoodbblog",column1, value1, column2, value2);
// 删除一列
HBaseTest.deleteColumn("yoodbblog", "rowkey1", "realname", "name");
// 删除所有列
HBaseTest.deleteAllColumn("yoodbblog", "rowkey1");
// 删除表
HBaseTest.deleteTable("yoodbblog");
// 查询
HBaseTest.getResult("yoodbblog", "rowkey1");
// 查询某一列的值
HBaseTest.getResultByColumn("yoodbblog", "rowkey1", "realname", "nickname");
// 修改某一列的值
HBaseTest.updateTable("yoodbblog", "rowkey1", "realname", "nickname","假昵称");
// 遍历表数据查询
HBaseTest.getResultScann("yoodbblog");
// 查询某列的多版本
HBaseTest.getResultByVersion("yoodbblog", "rowkey1", "realname", "name");
}
}
分享原文地址
 
 
  收起阅读 »

云时代,企业网管前途何在

前言: 此文献给那些有上进心,但是目前又处在迷茫中的朋友们!希望对你们有用! 当今中国,每年都有超过1000万的大学毕业生从大学校门走向社会面临就业,根据媒体的报道,每年有将近100万大学生找不到工作。在这个激烈竞争的社会,就业真的有那么难吗?尤其是计算机...
继续阅读 »
前言:


此文献给那些有上进心,但是目前又处在迷茫中的朋友们!希望对你们有用!


当今中国,每年都有超过1000万的大学毕业生从大学校门走向社会面临就业,根据媒体的报道,每年有将近100万大学生找不到工作。在这个激烈竞争的社会,就业真的有那么难吗?尤其是计算机专业毕业的学生,现在北大青鸟,清华万博,乱七八糟的杂牌培训机构遍地开花,如何才能在激烈的竞争中处于不败之地呢?下边我给大家讲讲我的成长道路,希望对你的职业发展有所启发。
2009年7月份,我从北京某不知名大学毕业,毕业的时候,我和大多数的同学一样忙于找工作,每天都要投递大量的简历,结果给我打电话的却少之又少。过了几天,终于等来了电话,是中关村E世界的,当时我应聘的岗位是技术支持工程师,面试的时候,老板和我聊了聊,说他们主要招销售方面的人,就随便问了我一些Windows方面的问题。结果让我回家等通知,等了好久也没有电话。后来又有一家公司给我打电话,我去面试之后,居然是臭名昭著的保险公司(中国平安)。我去面试的时候,那个大姐便开始给我洗脑,说是干保险这个行业是发大财的行业,我说我应聘的是网络工程师,结果被打击了一番。于是我被迫选择在保险公司呆了一个月,这一个月主要是上课,然后考保险人代理证,当时的心态就是,反正先找一个工作干着,不管是什么工作。等到考试的时候,我心里在想,如果考过了,我就认命了,从此就干保险这个行业,如果没有考过,我还是干计算机相关的专业。结果出来的时候,60分及格的成绩我考了58分,果真老天有眼,居然不让我干这个行业。
离开保险公司之后,我就放弃找工作了,每天把自己封闭起来,一心一意地看书,《鸟哥私房菜》,《思科网络技术学院教程 CCNA安全》,《构建高可用集群》,我每天早晨6点就起床看书,做实验,到了9:30,我就坐车去国家图书馆,里边有很多和我专业相关的专业。我连续坚持了一个月,后来通过朋友介绍,我主动去北京工业大学认识了一位老师,和他聊了将近半小时,他建议我考一个行业内的资格证书,然后他私人给我授课,课时是两天,学费是1800,然后考试费是4000多,当时家里给我打的6000块钱,我全部拿出来考试了,以至于后来吃饭都成了问题。因为当时父母的意思就是,你现在已经毕业了,你不能再问家里要钱了。所以每天都只吃一顿饭,当我生存面临问题的时候,我不能坐地等死,而是主动去联系圈子内的同学,朋友帮我找一个能管饭的工作就OK了。就在我去丰台工地工作的第二天,北京工业大学的那个老师给我打电话,说是他手上有一份工作,让我赶紧准备一下去面试,我当天下午就离开工地,去望京那边一家公司面试。面试的时候,是一个和我年龄相仿的人,他也没有问我技术上的问题,毕竟是他老师推荐的人,好意思拒绝嘛?所以第二天就去上班了,我的第一份工作,当时月薪是3500,这和我当时的心理预期值1200相比,还是值得兴奋一下的,当时我的所有同学都在2000以下。后来,我明白了一个道理,只要你想改变,愿意付出代价,你就一定会有回报。给我培训的那个老师拿我的学费,人家心里边自然不会把我放在一边。
工作一年之后,我好不容易工资涨到了4000,但是我开始变得迷茫了,没有刚开始工作时那么卖力了。站在人生的十字路口,我不知道自己的未来到底该走向何方?又一次参加中国交互式设计大赛,我是做现场技术支持的,在场的评委全是全国知名美术学院的教授,一天下来,我们公司作为主办方,给各位教授发红包,里边全是4000块钱,这个价格是在一个项目预算单上看到的,当时心里的落差太大了。我一个月的收入还没有别人一天的收入多,原来这个社会阶级这么明显。那段时间,公司基本上没什么事情,偶尔就是某个人电脑无法上网,新人来了,装装系统,到后来,公司所有的人都认识我了,只要有问题第一个就是想到我,什么插线板不好使,饮水机坏了,厕所堵住了,都会找我,此时我变得有点不耐烦了,原来我真的是一个打杂的,我看上去比谁都忙,但是我的收入比谁都低。
我的青春我做主!我的未来不是梦!哈哈O(∩_∩)O,在心中喊着各种口号,每天爬起来,还是原地踏步走,这样下去肯定会废掉的。与其坐以待毙,不如想个法子提高自己的水平,提高自己的身价。都说人的生命是无价的,但是我想说,每个人的能力是有价的,能力不同,创造的价值也不同。我整天在网上看一些牛人的技术博客,从他们那里学到了很多职业发展的方向。给大家分享一个百度文库《企业网管未来的职业发展》:【http://wenku.baidu.com/view/6f043dd233d4b14e85246888.html】,希望这篇文章对所有刚开始从事IT行业的同学们有一点帮助。
结语:
牛人那么多,需要你努力。在互联网风口漂浮大数据的云时代。你不和云沾点边,都不敢说是互联网公司,不敢说是互联网人。监控有云监控、备份有云备份、主机有云主机、存储有云存储等等!云时代企业网管那该何去何从呢???
收起阅读 »

监控IO脚本

#!/bin/sh /etc/init.d/syslog stop echo 1 > /proc/sys/vm/block_dump sleep 60 dmesg | awk '/(READ|WRITE|dirtied)/ {process[$1]++...
继续阅读 »
#!/bin/sh

/etc/init.d/syslog stop

echo 1 > /proc/sys/vm/block_dump

sleep 60

dmesg | awk '/(READ|WRITE|dirtied)/ {process[$1]++} END {for (x in process) \

print process[x],x}' |sort -nr |awk '{print $2 " " $1}' | \

head -n 10

echo 0 > /proc/sys/vm/block_dump

/etc/init.d/syslog start
收起阅读 »

nginx负载均衡解释

一、特点 1.1 应用情况 Nginx做为一个强大的Web服务器软件,具有高性能、高并发性和低内存占用的特点。此外,其也能够提供强大的反向代理功能。俄罗斯大约有超过20%的虚拟主机采用Nginx作为反向代理服务器,在国内也有腾讯、新浪、网易等多家网站在使用...
继续阅读 »


一、特点


1.1 应用情况
Nginx做为一个强大的Web服务器软件,具有高性能、高并发性和低内存占用的特点。此外,其也能够提供强大的反向代理功能。俄罗斯大约有超过20%的虚拟主机采用Nginx作为反向代理服务器,在国内也有腾讯、新浪、网易等多家网站在使用Nginx作为反向代理服务器。据Netcraft统计,世界上最繁忙的网站中有11.48%使用Nginx作为其服务器或者代理服务器。基于反向代理的功能,Nginx作为负载均衡主要有以下几点理由:
    []高并发连接[/][]内存消耗少[/][]配置文件非常简单[/][]成本低廉[/][]支持Rewrite重写规则[/][]内置的健康检查功能[/][]节省带宽[/][]稳定性高[/]

1.2 架构

nginx_arch.jpg
nginx在启动后,会以daemon的方式在后台运行,后台进程包含一个master进程和多个worker进程。工作进程以非特权用户运行。 master进程主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。worker进程则是处理基本的网络事件。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。开发模型:epoll和kqueue。
    []支持的事件机制:kqueue、epoll、rt signals、/dev/poll 、event ports、select以及poll。[/][]支持的kqueue特性包括EV_CLEAR、EV_DISABLE、NOTE_LOWAT、EV_EOF,可用数据的数量,错误代码.[/][]支持sendfile、sendfile64和sendfilev;文件AIO;DIRECTIO;支持Accept-filters和TCP_DEFER_ACCEP.[/]
1.3 性能Nginx的高并发,官方测试支持5万并发连接。实际生产环境能到2-3万并发连接数。10000个非活跃的HTTP keep-alive 连接仅占用约2.5MB内存。三万并发连接下,10个Nginx进程,消耗内存150M。淘宝tengine团队说测试结果是“24G内存机器上,处理并发请求可达200万”。

二、负载均衡

2.1 协议支持Nginx工作在网络的7层,可以针对http应用本身来做分流策略。支持七层HTTP、HTTPS协议的负载均衡。对四层协议的支持需要第三方插件-yaoweibin的ngx_tcp_proxy_module实现了tcp upstream。https://github.com/yaoweibin/nginx_tcp_proxy_module此外,nginx本身也逐渐在完善对其他协议的支持:
    []Nginx 1.3.13 开发版支持WebSocket代理。[/][]Nginx 1.3.15开发版支持SPDY。[/]
2.2 均衡策略nginx的负载均衡策略可以划分为两大类:内置策略和扩展策略。内置策略包含加权轮询和ip hash,在默认情况下这两种策略会编译进nginx内核,只需在nginx配置中指明参数即可。扩展策略有很多,如fair、通用hash、consistent hash等,默认不编译进nginx内核。 1、加权轮询(weighted round robin)轮询的原理很简单,首先我们介绍一下轮询的基本流程。如下是处理一次请求的流程图:
ngx_wr_process.jpg
图中有两点需要注意,第一,如果可以把加权轮询算法分为先深搜索和先广搜索,那么nginx采用的是先深搜索算法,即将首先将请求都分给高权重的机器,直到该机器的权值降到了比其他机器低,才开始将请求分给下一个高权重的机器;第二,当所有后端机器都down掉时,nginx会立即将所有机器的标志位清成初始状态,以避免造成所有的机器都处在timeout的状态,从而导致整个前端被夯住。 2、ip haship hash是nginx内置的另一个负载均衡的策略,流程和轮询很类似,只是其中的算法和具体的策略有些变化,如下图所示:
ngx_iphash_process.jpg
ip hash算法的核心实现如下:
for(i = 0;i < 3;i++){     hash = (hash * 113 + iphp->addr) % 6271; } p = hash % iphp->rrp.peers->number;
从代码中可以看出,hash值既与ip有关又与后端机器的数量有关。经过测试,上述算法可以连续产生1045个互异的value,这是该算法的硬限制。对此nginx使用了保护机制,当经过20次hash仍然找不到可用的机器时,算法退化成轮询。因此,从本质上说,ip hash算法是一种变相的轮询算法,如果两个ip的初始hash值恰好相同,那么来自这两个ip的请求将永远落在同一台服务器上,这为均衡性埋下了很深的隐患。 3、fairfair策略是扩展策略,默认不被编译进nginx内核。其原理是根据后端服务器的响应时间判断负载情况,从中选出负载最轻的机器进行分流。这种策略具有很强的自适应性,但是实际的网络环境往往不是那么简单,因此要慎用。 4、通用hash、一致性hash这两种也是扩展策略,在具体的实现上有些差别,通用hash比较简单,可以以nginx内置的变量为key进行hash,一致性hash采用了nginx内置的一致性hash环,可以支持memcache。 

2.2 配置示例

1、HTTP
 http {     upstream  www.exmaple.com  {       server   192.168.1.2:80;       server   192.168.1.3:80;     }     server{       listen  80;       server_name  www.example.com;       location / {                proxy_pass        http://www.example.com;                proxy_set_header   Host             $host;                proxy_set_header   X-Real-IP        $remote_addr;                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;       }       location /nginx_status {                stub_status on;                access_log off;                allow 192.168.1.1;#设置为可访问该状态信息的ip                deny all;       }     } }
2、TCP-ngx_tcp_proxy_module
tcp {     upstream cluster {         # simple round-robin         server 192.168.0.1:80;         server 192.168.0.2:80;         check interval=3000 rise=2 fall=5 timeout=1000;         #check interval=3000 rise=2 fall=5 timeout=1000 type=ssl_hello;         #check interval=3000 rise=2 fall=5 timeout=1000 type=http;         #check_http_send "GET / HTTP/1.0\r\n\r\n";         #check_http_expect_alive http_2xx http_3xx;     }     server {         listen 8888;         proxy_pass cluster;     } }
 

三、动态负载均衡

3.1 自身监控内置了对后端服务器的健康检查功能。如果Nginx proxy后端的某台服务器宕机了,会把返回错误的请求重新提交到另一个节点,不会影响前端访问。它没有独立的健康检查模块,而是使用业务请求作为健康检查,这省去了独立健康检查线程,这是好处。坏处是,当业务复杂时,可能出现误判,例如后端响应超时,这可能是后端宕机,也可能是某个业务请求自身出现问题,跟后端无关。3.2 可扩展性Nginx属于典型的微内核设计,其内核非常简洁和优雅,同时具有非常高的可扩展性。如下图所示:
nginx_jg.png
Nginx是纯C语言的实现,其可扩展性在于其模块化的设计。目前,Nginx已经有很多的第三方模块,大大扩展了自身的功能。nginx_lua_module可以将Lua语言嵌入到Nginx配置中,从而利用Lua极大增强了Nginx本身的编程能力,甚至可以不用配合其它脚本语言(如PHP或Python等),只靠Nginx本身就可以实现复杂业务的处理。3.3 配置修改nginx的配置架构如下图所示:
nginx_gx.png
Nginx支持热部署,几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。能够在不间断服务的情况下,对软件版本进行进行升级。Nginx的配置文件非常简单,风格跟程序一样通俗易懂,能够支持perl语法。使用nginx –s reload可以在运行时加载配置文件,便于运行时扩容/减容。重新加载配置时,master进程发送命令给当前正在运行的worker进程worker进程接到命令后会在处理完当前任务后退出。同时,master进程会启动新的worker进程来接管工作。

四、优势和劣势

4.1 优势[list=1][]可以很好地进行http 的头处理[/][]对http协议以及https的良好支持[/][]有足够的第三方插件供使用[/][]支持热部署,更改后端是平滑的[/]4.2 劣势[list=1][]缺少对session的支持[/][]对四层tcp的支持不够好[/][]post请求写文件系统,造成500 error[/][]缺乏主动的后端服务器健康监测[/][]默认的监控界面统计信息不全[/]

五、Tengine

5.1 特性[list=1][]继承Nginx-1.2.9的所有特性,100%兼容Nginx的配置;[/][]动态模块加载(DSO)支持。加入一个模块不再需要重新编译整个Tengine;[/][]输入过滤器机制支持。通过使用这种机制Web应用防火墙的编写更为方便;[/][]动态脚本语言Lua支持。扩展功能非常高效简单;[/][]支持管道(pipe)和syslog(本地和远端)形式的日志以及日志抽样;[/][]组合多个CSS、JavaScript文件的访问请求变成一个请求;[/][]更加强大的负载均衡能力,包括一致性hash模块、会话保持模块,还可以对后端的服务器进行主动健康检查,根据服务器状态自动上线下线;[/][]自动根据CPU数目设置进程个数和绑定CPU亲缘性;[/][]监控系统的负载和资源占用从而对系统进行保护;[/][]显示对运维人员更友好的出错信息,便于定位出错机器;[/][]更强大的防攻击(访问速度限制)模块;[/][]更方便的命令行参数,如列出编译的模块列表、支持的指令等;[/][]可以根据访问文件类型设置过期时间;[/]5.2 负载均衡负载均衡方面,Tengine主要有以下几个特点,基本上弥补了 nginx在负载均衡方面的欠缺:[list=1][]支持一致性Hash模块[/][]会话保持模块[/][]对后端服务器的主动健康检查。[/][]增加了请求体不缓存到磁盘的机制[/]
收起阅读 »