控制Elasticsearch分片和副本的分配
ES集群中索引可能由多个分片构成,并且每个分片可以拥有多个副本。通过将一个单独的索引分为多个分片,我们可以处理不能在一个单一的服务器上面运行的大型索引,简单的说就是索引的大小过大,导致效率问题。不能运行的原因可能是内存也可能是存储。由于每个分片可以有多个副本,通过将副本分配到多个服务器,可以提高查询的负载能力。
为了进行分片和副本的操作,ES需要确定将这些分片和副本放到集群节点的哪个位置,就是需要确定把每个分片和副本分配到哪台服务器/节点上。
生产情景:
1、指定节点的参数
如上图所示,我们将ES集群划分为两个"空间"。当然你也可以叫做区域,随便命名。我们将左边的三台ES节点服务器放置到zone_one的空间上面,将右边的三台ES节点服务器放到zone_two的空间上。
配置
为了做到我们需要的效果,我们需要将如下属性配置到左边三台ES集群节点服务器的elasticsearch.yml配置文件中
索引创建
当所有节点配置文件属性配置完成后,我们就可以根据空间名称,我们就可以创建索引放到指定的空间。
首先我们运行如下命令,来创建man索引:
同样对woman索引我们做类似操作:
最后我们需要将katoey索引放置到上面所有的ES集群节点上面,配置设置命令如下:
2、分配时排除节点
跟我们上面操作为索引指定放置节点位置一样,我们也可以在索引分配的时候排除某些节点。参照之前的例子,我们新建一个people索引,但是不希望people索引放置到zone_one的ES集群节点服务器上,我们可以运行如下命令操作:
使用IP地址进行分配配置
除了在节点的配置中添加一些特殊的属性参数外,我们还可以使用IP地址来指定你将分片和副本分配或者不分配到哪些节点上面。为了做到这点,我们应该使用_ip属性,把zone换成_ip就好了。例如我们希望lucky索引分配到IP地址为10.0.1.110和10.0.1.119的节点上,我们可以运行如下命令设置:
除了索引层面指定分配活着排除分配之外(上面我们所做的都是这两种情况),我们还可以指定集群中所有索引的分配。例如,我们希望将所有的新索引分配到IP地址为10.0.1.112和10.0.1.114的节点上,我们可以运行如下命令设置:
除了指定分片和副本的分配,我们还可以对一个索引指定每个节点上的最大分片数量。例如我们希望ops索引在每个节点上只有一个分片,我们可以运行如下命令:
接下来我们介绍一下节点间手动移动分片和副本。可以使用ElasticSearch提供的_cluster/reroute REST端点进行控制,能够进行下面操作:
移动分片
假设我们有两个节点:es_node_one和es_node_two,ElasticSearch在es_node_one节点上分配了ops索引的两个分片,我们现在希望将第二个分片移动到es_node_two节点上。可以如下操作实现:
取消分配
如果希望取消一个正在进行的分配过程,我们通过运行cancel命令来指定我们希望取消分配的索引、节点以及分片,如下所示:
分配分片
除了取消和移动分片和副本之外,我们还可以将一个未分配的分片分配到一个指定的节点上。假设ops索引上有一个编号为0的分片尚未分配,并且我们希望ElasticSearch将其分配到es_node_two上,可以运行如下命令操作:
我们可以在一次HTTP请求中包含多个命令,例如:
为了进行分片和副本的操作,ES需要确定将这些分片和副本放到集群节点的哪个位置,就是需要确定把每个分片和副本分配到哪台服务器/节点上。
一、显式控制分配
生产情景:
比如生产环境有三个索引分别为 man、woman、katoey
希望达到的效果:
man索引放置在一些集群节点上
woman索引又单独放置到集群的另外一些集群节点上
katoey索引希望放置在所有放置man索引和woman索引的集群节点上
这么做是因为katoey索引比其他两个索引小很多,因此我们可以将它和其他两个索引一起分配。
但是基于ES默认算法的处理方法,我们不能确定分片和副本的存放位置,但是ES允许我们对其做相应的控制!
1、指定节点的参数
如上图所示,我们将ES集群划分为两个"空间"。当然你也可以叫做区域,随便命名。我们将左边的三台ES节点服务器放置到zone_one的空间上面,将右边的三台ES节点服务器放到zone_two的空间上。
配置
为了做到我们需要的效果,我们需要将如下属性配置到左边三台ES集群节点服务器的elasticsearch.yml配置文件中
node.zone: zone_one将如下属性配置到右边的三台ES集群节点服务器elasticsearch.yml配置文件中
node.zone: zone_two
索引创建
当所有节点配置文件属性配置完成后,我们就可以根据空间名称,我们就可以创建索引放到指定的空间。
首先我们运行如下命令,来创建man索引:
# curl -XPOST "http://ESnode:9200/man'第一条命令是创建man索引;第二条命令是发送到_settings REST端点,用来指定这个索引的其他配置信息。我们将index.routing.allocation.include.zone属性设置为zone_one值,就是我们所希望的把man索引放置到node.zone属性值为zone_one的ES集群节点服务器上。
# curl -XPUT "http://ESnode:9200/man/_settings' -d '{
"index.routing.allocation.include.zone" : "zone_one"
}'
同样对woman索引我们做类似操作:
# curl -XPOST "http://ESnode:9200/woman'不同的是,这次指定woman索引放置在node.zone属性值为zone_two的ES集群节点服务器上
# curl -XPUT "http://ESnode:9200/woman/_settings' -d '{
"index.routing.allocation.include.zone" : "zone_two"
}'
最后我们需要将katoey索引放置到上面所有的ES集群节点上面,配置设置命令如下:
# curl -XPOST "http://ESnode:9200/katoey"
# curl -XPUT "http://ESnode:9200/katoey/_settings" -d '{
"index.routing.allocation.include.zone" : "zone_one,zone_two"
}'
2、分配时排除节点
跟我们上面操作为索引指定放置节点位置一样,我们也可以在索引分配的时候排除某些节点。参照之前的例子,我们新建一个people索引,但是不希望people索引放置到zone_one的ES集群节点服务器上,我们可以运行如下命令操作:
# curl -XPOST "http://EScode:9200/people"请注意,在这里我们使用的是index.routing.allocation.exclude.zone属性而不是index.routing.allocation.include.zone属性。
# curl -XPUT "http://EScode:9200/people/_settings" -d '{
"index.routing.allocation.exclude.zone" : "zone_one"
}'
使用IP地址进行分配配置
除了在节点的配置中添加一些特殊的属性参数外,我们还可以使用IP地址来指定你将分片和副本分配或者不分配到哪些节点上面。为了做到这点,我们应该使用_ip属性,把zone换成_ip就好了。例如我们希望lucky索引分配到IP地址为10.0.1.110和10.0.1.119的节点上,我们可以运行如下命令设置:
# curl -XPOST "http://ESnode:9200/lucky"
# curl -XPUT "http://ESnode:9200/lucky/_settings" -d '{
"index.routing.allocation.include._ip" "10.0.1.110,10.0.1.119"
}'
二、集群范围内分配
除了索引层面指定分配活着排除分配之外(上面我们所做的都是这两种情况),我们还可以指定集群中所有索引的分配。例如,我们希望将所有的新索引分配到IP地址为10.0.1.112和10.0.1.114的节点上,我们可以运行如下命令设置:
# curl -XPUT "http://ESnode:9200/_cluster/settings" -d '{集群级别的控制后续还会分享transient和persistent属性介绍
"transient" : {
"cluster.routing.allocation.include._ip" "10.0.1.112,10.0.1.114"
}
}'
三、每个节点上分片和副本数量的控制
除了指定分片和副本的分配,我们还可以对一个索引指定每个节点上的最大分片数量。例如我们希望ops索引在每个节点上只有一个分片,我们可以运行如下命令:
# curl -XPUT "http://ESnode:9200/ops/_settings" -d '{这个属性也可以直接配置到elasticsearch.ym配置文件中,或者使用上面命令在活动索引上更新。如果配置不当,导致主分片无法分配的话,集群就会处于red状态。
"index.routing.allocation.total_shards_per_node" : 1
}'
四、手动移动分片和副本
接下来我们介绍一下节点间手动移动分片和副本。可以使用ElasticSearch提供的_cluster/reroute REST端点进行控制,能够进行下面操作:
- []将一个分片从一个节点移动到另外一个节点[/][]取消对分片的分配[/][]强制对分片进行分配[/]
移动分片
假设我们有两个节点:es_node_one和es_node_two,ElasticSearch在es_node_one节点上分配了ops索引的两个分片,我们现在希望将第二个分片移动到es_node_two节点上。可以如下操作实现:
# curl -XPOST "http://ESnode:9200/_cluster/reroute" -d '{我们通过move命令的index属性指定移动哪个索引,通过shard属性指定移动哪个分片,最终通过from_node属性指定我们从哪个节点上移动分片,通过to_node属性指定我们希望将分片移动到哪个节点。
"commands" : [ {
"move" : {
"index" : "ops",
"shard" : 1,
"from_node" : "es_node_one",
"to_node" : "es_node_two"
}
}]
}'
取消分配
如果希望取消一个正在进行的分配过程,我们通过运行cancel命令来指定我们希望取消分配的索引、节点以及分片,如下所示:
# curl -XPOST "http://ESnode:9200/_cluster/reroute" -d '{运行上面的命令将会取消es_node_one节上ops索引的第0个分片的分配
"commands" : [ {
"cancel" : {
"index" : "ops",
"shard" : 0,
"node" : "es_node_one"
}
} ]
}'
分配分片
除了取消和移动分片和副本之外,我们还可以将一个未分配的分片分配到一个指定的节点上。假设ops索引上有一个编号为0的分片尚未分配,并且我们希望ElasticSearch将其分配到es_node_two上,可以运行如下命令操作:
# curl -XPOST "http://ESnode:9200/_cluster/reroute' -d '{一次HTTP请求包含多个命令
"commands" : [ {
"allocate" : {
"index" : "ops",
"shard" : 0,
"node" : "es_node_two"
}
} ]
}'
我们可以在一次HTTP请求中包含多个命令,例如:
# curl -XPOST "http://ESnode:9200/_cluster/reroute" -d '{收起阅读 »
"commands" : [
{"move" : {"index" : "ops", "shard" : 1, "from_node" : "es_node_one", "to_node" : "es_node_two"}},
{"cancel" : {"index" : "ops", "shard" : 0, "node" : "es_node_one"}}
]
}'
最棒的60个DevOps开源工具
你喜欢免费的东西吗?获得开发者社区支持的自动化,开源的工具是大家梦寐以求的。这里列举了 60+ 款最棒的开源工具,可以帮助你很好的实行 DevOps。
大图点这里
开发工具
版本控制&协作开发
版本控制系统 Git
Git 是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。
开源中国 Git 代码托管平台:http://git.oschina.net/
代码托管平台 GitLab
GitLab 是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。开源中国代码托管平台 git.oschina.net 就是基于 GitLab 项目搭建。
代码评审工具 Gerrit
Gerrit 是一个免费、开放源代码的代码审查软件,使用网页界面。利用网页浏览器,同一个团队的软件程序员,可以相互审阅彼此修改后的程序代码,决定是否能够提交,退回或者继续修改。它使用 Git 作为底层版本控制系统。
版本控制系统 Mercurial
Mercurial 是一种轻量级分布式版本控制系统,采用 Python 语言实现,易于学习和使用,扩展性强。
版本控制系统 Subversion
Subversion 是一个版本控制系统,相对于的RCS、CVS,采用了分支管理系统,它的设计目标就是取代CVS。互联网上免费的版本控制服务多基于Subversion。
版本控制系统 Bazaar
Bazaar 是一个分布式的版本控制系统,它发布在 GPL 许可协议之下,并可用于 Windows、GNU/Linux、UNIX 以及 Mac OS 系统。
自动化构建和测试
Apache Ant
Apache Ant是一个将软件编译、测试、部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发。
Maven
Maven 除了以程序构建能力为特色之外,还提供 Ant 所缺少的高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目,而使用 Ant 则需要十几行。事实上,由于 Maven 的面向项目的方法,许多 Apache Jakarta 项目现在使用 Maven,而且公司项目采用 Maven 的比例在持续增长。开源中国的 Maven 库 http://maven.oschina.net
Selenium
Selenium (SeleniumHQ) 是 thoughtworks公司的一个集成测试的强大工具。
PyUnit
Python单元测试框架(The Python unit testing framework),简称为PyUnit, 是Kent Beck和Erich Gamma这两位聪明的家伙所设计的 JUnit 的Python版本。
QUnit
QUnit 是 jQuery 的单元测试框架。
JMeter
JMeter 是 Apache 组织的开放源代码项目,它是功能和性能测试的工具,100% 的用 java 实现。
Gradle
Gradle 就是可以使用 Groovy 来书写构建脚本的构建系统,支持依赖管理和多项目,类似 Maven,但比之简单轻便。
PHPUnit
PHPUnit 是一个轻量级的PHP测试框架。它是在PHP5下面对JUnit3系列版本的完整移植,是xUnit测试框架家族的一员(它们都基于模式先锋Kent Beck的设计)。
持续集成&交付
Jenkins
Jenkins 的前身是 Hudson 是一个可扩展的持续集成引擎。
Capistrano
Capistrano 是一个用来并行的在多台机器上执行相同命令的工具,使用用来安装一整批机器。它最初是被开发用来发布 Rails 应用的。
BuildBot
BuildBot 是一个系统 的自动化编译/测试周期最需要的软件,以验证代码的变化。通过自动重建和测试每次发生了变化的东西,在建设迅速查明之前,减少不必要的失败。
Fabric
fabric8 是开源 Java Containers(JVMs) 深度管理集成平台。有了 fabric8 可以非常方便的从 UI 和 UX 一致的中央位置进行自动操作,配置和管理。fabric8 同时提供一些非功能性需求,比如配置管理,服务发现故障转移,集中化监控,自动化等等。
Tinderbox
Travis CI
Travis CI 是一个基于云的持续集成项目, 目前已经支持大部分主流语言了,比如:C,PHP,Ruby,Python, Nodejs等等。
Continuum
Apache Continuum 是最新的 CI 服务器之一,也是值得关注的一个新进入者。基于 Web 的界面使得配置项目很容易。而且,还不需要安装 Web 服务器,因为 Continuum 内置了 Jetty Web 服务器。并且,Continuum 可以作为 Windows 服务运行,还在应用程序的某些部分嵌入了上下文敏感的文档,从而提供了很多帮助。
LuntBuild
LuntBuild 是一个强大自动构建的工具。通过一个简洁的web接口就可以很容易地进行系统的持续构建。
CruiseControl
CruiseControl 是一个针对持续构建程序(项目持续集成)的框架,它包括一个email通知的插件,Ant和各种各样的CVS工具。CruiseControl提供了一个Web接口, 可随时查看当前的编译状况和历史状况
Integrity
Integrity 是 Ruby 开发的持续集成服务器。
Gump
Gump 是 Apache 的整合工具。它以 Python 写成、完全支持 Apache Ant、Apache Maven 等等软件组建工具。
Go
Go 是 Google 开发的一种编译型,并发型,并具有垃圾回收功能的编程语言。
部署工具
容器平台
Docker配置管理
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
Rocket
Rocket (也叫 rkt)是 CoreOS 推出的一款容器引擎,和 Docker 类似,帮助开发者打包应用和依赖包到可移植容器中,简化搭环境等部署工作。
Ubuntu(LXC)
LXD 是 ubuntu 基于 LXC 技术的重构,容器天然支持非特权和分布式。LXD 与 Docker 的思路不同,Docker 是 PAAS,LXD 是 IAAS。LXC 项目由一个 Linux 内核补丁和一些 userspace 工具组成。这些 userspace 工具使用由补丁增加的内核新特性,提供一套简化的工具来维护容器。
Chef微服务平台
Chef 是一个系统集成框架,为整个架构提供配置管理功能
Puppet
Puppet,您可以集中管理每一个重要方面,您的系统使用的是跨平台的规范语言,管理所有的单独的元素通常聚集在不同的文件,如用户, CRON作业,和主机一起显然离散元素,如包装,服务和文件。
CFengine
Cfengine(配置引擎)是一种 UNIX 管理工具,其目的是使简单的管理的任务自动化,使困难的任务变得较容易。Cfengine 适用于管理各种环境,从一台主机到上万台主机的机群均可使用。
Bash
bash 是大多数Linux系统以及Mac OS X v10.4默认的shell,它能运行于大多数Unix风格的操作系统之上,甚至被移植到了Microsoft Windows上的Cygwin系统中,以实现windows的POSIX虚拟接口。此外,它也被DJGPP项目移植到了MS-DOS上。
Rudder
Rudder 已改名为Flannel,为每个使用 Kubernetes 的机器提供一个子网。也就是说 Kubernetes 集群中的每个主机都有自己一个完整的子网,例如机器 A 和 B 可以有 10.0.1.0/24 和 10.0.2.0/24 子网。
Powershell
RunDeck
RunDeck 是用 Java/Grails 写的开源工具,帮助用户在数据中心或者云环境中自动化各种操作和流程。通过命令行或者web界面,用户可以对任意数量的服务器进行操作,大大降低了对服务器自动化的门槛。
Saltstack
Saltstack 可以看做是func的增强版+Puppet的弱化版。使用Python编写。非常好用,快速可以基于EPEL部署。Salt 是一个开源的工具用来管理你的基础架构,可轻松管理成千上万台服务器。
Ansible
Ansible 提供一种最简单的方式用于发布、管理和编排计算机系统的工具,你可在数分钟内搞定。Ansible 是一个模型驱动的配置管理器,支持多节点发布、远程任务执行。默认使用 SSH 进行远程连接。无需在被管理节点上安装附加软件,可使用各种编程语言进行扩展。
OpenShift服务开通
OpenShift 是由红帽推出的一款面向开源开发人员开放的平台即服务(PaaS)。 OpenShift通过为开发人员提供在语言、框架和云上的更多的选择,使开发人员可以构建、测试、运行和管理他们的应用。
Cloud Foundry
Cloud Foundry 是VMware于2011年4月12日推出的业界第一个开源PaaS云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发 人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。
Kubernetes
Kubernetes 是来自 Google 云平台的开源容器集群管理系统。基于 Docker 构建一个容器的调度服务。该系统可以自动在一个容器集群中选择一个工作容器供使用。其核心概念是 Container Pod。
Mesosphere
Apache Mesos 是一个集群管理器,提供了有效的、跨分布式应用或框架的资源隔离和共享,可以运行Hadoop、MPI、Hypertable、Spark。
Puppet
Puppet,您可以集中管理每一个重要方面,您的系统使用的是跨平台的规范语言,管理所有的单独的元素通常聚集在不同的文件,如用户, CRON作业,和主机一起显然离散元素,如包装,服务和文件。
Razor
Docker Swarm
Docker Swarm 是一个Dockerized化的分布式应用程序的本地集群,它是在Machine所提供的功能的基础上优化主机资源的利用率和容错服务。具体来 说,Docker Swarm支持用户创建可运行Docker Daemon的主机资源池,然后在资源池中运行Docker容器。Docker Swarm可以管理工作负载并维护集群状态。
Vagrant
Vagrant 是一个基于 Ruby 的工具,用于创建和部署虚拟化开发环境。它使用 Oracle 的开源 VirtualBox 虚拟化系统,使用 Chef 创建自动化虚拟环境。
Powershell
OpenStack Heat
维护
日志记录
Logstash
Logstash 是一个应用程序日志、事件的传输、处理、管理和搜索的平台。你可以用它来统一对应用程序日志进行收集管理,提供 Web 接口用于查询和统计。
CollectD
collectd 是一个守护(daemon)进程,用来收集系统性能和提供各种存储方式来存储不同值的机制。比如以RRD 文件形式。
StatsD
StatsD 是一个简单的网络守护进程,基于 Node.js 平台,通过 UDP 或者 TCP 方式侦听各种统计信息,包括计数器和定时器,并发送聚合信息到后端服务,例如 Graphite
监控,警告&分析
Nagios以上,如果有其他补充可以在评论中跟大家分享哦!
Nagios 是一个监视系统运行状态和网络信息的监视系统。Nagios能监视所指定的本地或远程主机以及服务,同时提供异常通知功能等。
Ganglia
Ganglia 是一个跨平台可扩展的,高 性能计算系统下的分布式监控系统,如集群和网格。它是基于分层设计,它使用广泛的技术,如XML数据代表,便携数据传输,RRDtool用于数据存储和可视化。
Sensu
Sensu 是开源的监控框架。主要特性:高度可组合;提供一个监控代理,一个事件处理器和文档 APIs;为云而设计;Sensu 的现代化架构允许监控大规模的动态基础设施,能够通过复杂的公共网络监控几千个全球分布式的机器和服务;热情的社区。
zabbix
zabbix 是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。
ICINGA
ICINGA 项目是 由Michael Luebben、HendrikB?cker和JoergLinge等人发起的,他们都是现有的Nagios项目社区委员会的成员,他们承诺,新的开源项 目将完全兼容以前的Nagios应用程序及扩展功能。
Graphite
Graphite 是一个用于采集网站实时信息并进行统计的开源项目,可用于采集多种网站服务运行状态信息。Graphite服务平均每分钟有4800次更新操作。
Kibana
Kibana 是一个为 Logstash 和 ElasticSearch 提供的日志分析的 Web 接口。可使用它对日志进行高效的搜索、可视化、分析等各种操作。
原文地址:https://elasticbox.com/blog/devops-open-source-tools/ 收起阅读 »
Netstat命令详解
简介
Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等。
输出信息含义
执行netstat后,其输出结果为
一个是Active Internet connections,称为有源TCP连接,其中"Recv-Q"和"Send-Q"指%0A的是接收队列和发送队列。这些数字一般都应该是0。如果不是则表示软件包正在队列中堆积。这种情况只能在非常少的情况见到。
另一个是Active UNIX domain sockets,称为有源Unix域套接口(和网络套接字一样,但是只能用于本机通信,性能可以提高一倍)。
Proto显示连接使用的协议,RefCnt表示连接到本套接口上的进程号,Types显示套接口的类型,State显示套接口当前的状态,Path表示连接到套接口的其它进程使用的路径名。
常见参数
列出所有端口 netstat -a
只显示监听端口 netstat -l
显示所有端口的统计信息 netstat -s
netstat -p 可以与其它开关一起使用,就可以添加 “PID/进程名称” 到 netstat 输出中,这样 debugging 的时候可以很方便的发现特定端口运行的程序。
当你不想让主机,端口和用户名显示,使用 netstat -n。将会使用数字代替那些名称。
同样可以加速输出,因为不用进行比对查询。
netstat 将每隔一秒输出网络信息。
并不是所有的进程都能找到,没有权限的会不显示,使用 root 权限查看所有的信息。
查看连接某服务端口最多的的IP地址
http://www.ipcpu.com/2011/07/netstat-linux/ 收起阅读 »
Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等。
输出信息含义
执行netstat后,其输出结果为
Active Internet connections (w/o servers)从整体上看,netstat的输出结果可以分为两个部分:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 2 210.34.6.89:telnet 210.34.6.96:2873 ESTABLISHED
tcp 296 0 210.34.6.89:1165 210.34.6.84:netbios-ssn ESTABLISHED
tcp 0 0 localhost.localdom:9001 localhost.localdom:1162 ESTABLISHED
tcp 0 0 localhost.localdom:1162 localhost.localdom:9001 ESTABLISHED
tcp 0 80 210.34.6.89:1161 210.34.6.10:netbios-ssn CLOSE
Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags Type State I-Node Path
unix 1 [ ] STREAM CONNECTED 16178 @000000dd
unix 1 [ ] STREAM CONNECTED 16176 @000000dc
unix 9 [ ] DGRAM 5292 /dev/log
unix 1 [ ] STREAM CONNECTED 16182 @000000df
一个是Active Internet connections,称为有源TCP连接,其中"Recv-Q"和"Send-Q"指%0A的是接收队列和发送队列。这些数字一般都应该是0。如果不是则表示软件包正在队列中堆积。这种情况只能在非常少的情况见到。
另一个是Active UNIX domain sockets,称为有源Unix域套接口(和网络套接字一样,但是只能用于本机通信,性能可以提高一倍)。
Proto显示连接使用的协议,RefCnt表示连接到本套接口上的进程号,Types显示套接口的类型,State显示套接口当前的状态,Path表示连接到套接口的其它进程使用的路径名。
常见参数
-a (all)显示所有选项,默认不显示LISTEN相关实用命令实例
-t (tcp)仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化成数字。
-l 仅列出有在 Listen (监听) 的服務状态
-p 显示建立相关链接的程序名
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计
-c 每隔一个固定时间,执行该netstat命令。
提示:LISTEN和LISTENING的状态只有用-a或者-l才能看到
1. 列出所有端口 (包括监听和未监听的)
列出所有端口 netstat -a
# netstat -a | more列出所有 tcp 端口 netstat -at
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 localhost:30037 [i]:[/i] LISTEN
udp 0 0 [i]:bootpc [/i]:*
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 6135 /tmp/.X11-unix/X0
unix 2 [ ACC ] STREAM LISTENING 5140 /var/run/acpid.socket
# netstat -at列出所有 udp 端口 netstat -au
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 localhost:30037 [i]:[/i] LISTEN
tcp 0 0 localhost:ipp [i]:[/i] LISTEN
tcp 0 0 [i]:smtp [/i]:* LISTEN
tcp6 0 0 localhost:ipp [::]:* LISTEN
# netstat -au
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
udp 0 0 [i]:bootpc [/i]:*
udp 0 0 [i]:49119 [/i]:*
udp 0 0 [i]:mdns [/i]:*
- 列出所有处于监听状态的 Sockets
只显示监听端口 netstat -l
# netstat -l只列出所有监听 tcp 端口 netstat -lt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 localhost:ipp [i]:[/i] LISTEN
tcp6 0 0 localhost:ipp [::]:* LISTEN
udp 0 0 *:49119
# netstat -lt只列出所有监听 udp 端口 netstat -lu
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 localhost:30037 [i]:[/i] LISTEN
tcp 0 0 [i]:smtp [/i]:* LISTEN
tcp6 0 0 localhost:ipp [::]:* LISTEN
# netstat -lu只列出所有监听 UNIX 端口 netstat -lx
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
udp 0 0 [i]:49119 [/i]:*
udp 0 0 [i]:mdns [/i]:*
# netstat -lx
Active UNIX domain sockets (only servers)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 6294 private/maildrop
unix 2 [ ACC ] STREAM LISTENING 6203 public/cleanup
unix 2 [ ACC ] STREAM LISTENING 6302 private/ifmail
unix 2 [ ACC ] STREAM LISTENING 6306 private/bsmtp
- 显示每个协议的统计信息
显示所有端口的统计信息 netstat -s
# netstat -s显示 TCP 或 UDP 端口的统计信息 netstat -st 或 -su
Ip:
total packets received
with invalid addresses
forwarded
incoming packets discarded
incoming packets delivered
requests sent out
Icmp:
ICMP messages received
input ICMP message failed.
Tcp:
active connections openings
failed connection attempts
connection resets received
Udp:
packets received
packets to unknown port received.
.....
# netstat -st
# netstat -su
- 在 netstat 输出中显示 PID 和进程名称 netstat -p
netstat -p 可以与其它开关一起使用,就可以添加 “PID/进程名称” 到 netstat 输出中,这样 debugging 的时候可以很方便的发现特定端口运行的程序。
# netstat -pt
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 1 0 ramesh-laptop.loc:47212 192.168.185.75:www CLOSE_WAIT 2109/firefox
tcp 0 0 ramesh-laptop.loc:52750 lax:www ESTABLISHED 2109/firefox
- 在 netstat 输出中不显示主机,端口和用户名 (host, port or user)
当你不想让主机,端口和用户名显示,使用 netstat -n。将会使用数字代替那些名称。
同样可以加速输出,因为不用进行比对查询。
# netstat -an如果只是不想让这三个名称中的一个被显示,使用以下命令
# netsat -a --numeric-ports
# netsat -a --numeric-hosts
# netsat -a --numeric-users
- 持续输出 netstat 信息
netstat 将每隔一秒输出网络信息。
# netstat -c
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 ramesh-laptop.loc:36130 101-101-181-225.ama:www ESTABLISHED
tcp 1 1 ramesh-laptop.loc:52564 101.11.169.230:www CLOSING
tcp 0 0 ramesh-laptop.loc:43758 server-101-101-43-2:www ESTABLISHED
tcp 1 1 ramesh-laptop.loc:42367 101.101.34.101:www CLOSING
^C
- 显示系统不支持的地址族 (Address Families)
netstat --verbose在输出的末尾,会有如下的信息
netstat: no support for `AF IPX' on this system.
netstat: no support for `AF AX25' on this system.
netstat: no support for `AF X25' on this system.
netstat: no support for `AF NETROM' on this system.
- 显示核心路由信息 netstat -r
# netstat -r注意: 使用 netstat -rn 显示数字格式,不查询主机名称。
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
192.168.1.0 * 255.255.255.0 U 0 0 0 eth2
link-local * 255.255.0.0 U 0 0 0 eth2
default 192.168.1.1 0.0.0.0 UG 0 0 0 eth2
- 找出程序运行的端口
并不是所有的进程都能找到,没有权限的会不显示,使用 root 权限查看所有的信息。
# netstat -ap | grep ssh找出运行在指定端口的进程
tcp 1 0 dev-db:ssh 101.174.100.22:39213 CLOSE_WAIT -
tcp 1 0 dev-db:ssh 101.174.100.22:57643 CLOSE_WAIT -
# netstat -an | grep ':80'
- 显示网络接口列表
查看连接某服务端口最多的的IP地址
wss8848@ubuntu:~$ netstat -nat | grep "192.168.1.15:22" |awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -nr|head -20TCP各种状态列表
221.136.168.36
154.74.45.242
78.173.31.236
62.183.207.98
192.168.1.14
182.48.111.215
124.193.219.34
119.145.41.2
114.255.41.30
75.102.11.99
wss8848@ubuntu:~$ netstat -nat |awk '{print $6}'先把状态全都取出来,然后使用uniq -c统计,之后再进行排序。
established)
Foreign
LISTEN
TIME_WAIT
ESTABLISHED
TIME_WAIT
SYN_SENT
wss8848@ubuntu:~$ netstat -nat |awk '{print $6}'|sort|uniq -c最后的命令如下:
ESTABLISHED
FIN_WAIT1
Foreign
LAST_ACK
LISTEN
SYN_SENT
TIME_WAIT
established)
netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn分析access.log获得访问前10位的ip地址
awk '{print $1}' access.log |sort|uniq -c|sort -nr|head -10参考资料:http://blog.maxiang.net/10-netstat-command-examples/139/
http://www.ipcpu.com/2011/07/netstat-linux/ 收起阅读 »
Nginx开启HTTP/2
具体操作步骤:
在.conf文件中添加如下:
- []安装oneinstack一键包配置生产环境(步骤略)[/][]获取Nginx原有编辑配置[/][]编译及安装HTTP/2[/][]配置HTTP/2[/]
cd oneinstack/src配置HTTP/2
tar xzf nginx-1.9.4.tar.gz
cd nginx-1.9.4
# /usr/local/nginx/sbin/nginx -V #查看nginx已经编译参数 千万要去除--with-http_spdy_module,与HTTP/2有冲突!
wget http://nginx.org/patches/http2/patch.http2.txt
patch -p1 --dry-run < patch.http2.txt
patch -p1 < patch.http2.txt
make clean
./configure --prefix=/usr/local/nginx --user=www --group=www \
--with-http_stub_status_module \
--with-http_v2_module \
--with-http_ssl_module \
--with-ipv6 \
--with-http_gzip_static_module \
--with-http_realip_module \
--with-http_flv_module \
在.conf文件中添加如下:
server {重启Nginx(service nginx restart)网站就成功开启HTTP/2了。 收起阅读 »
listen 443 ssl http2 default_server;
ssl_certificate server.crt;
ssl_certificate_key server.key;
...
}
HDFS高可用方案之QJM
喜欢一个人,可以为TA做任何事,得到不接受却依然心甘情愿鞍前马后,苦苦等候那一线希望。对,这就是备胎,挂在汽车背后,可能一辈子也用不到的那个圆圈状的玩意儿,大部分情况下,它都会默默地挂在那里,等待几千分之一的机会,有个倒霉的轮子兄弟出事了,于是它就能派上用场了……(摘自豆瓣)
在Hadoop的分布式文件系统HDFS中,NameNode用来保存文件系统的元数据(包含目录结构/数据块位置等),如果NameNode上的数据丢失,HDFS上对应的文件数据就无法找回来了。Hadoop在2.0.0之前的版本,使用SecondaryNameNode备份NameNode的数据,但SecondaryNameNode无法转成NameNode,如果NameNode挂了,整个HDFS就会挂掉,无法实现真正的failover。这篇博文总结了5种Hadoop HA(High Available,高可用)方案,Hadoop2之后官方引入了QJM(Quorum Journal Manager)和NFS用于NameNode的备份和切换。本方将介绍的是QJM方案,它使用第二个NameNode实时同步当前NameNode的数据,相比于SecondaryNameNode,他可以随时切换成为真正的NameNode(一个可转正的高级备胎)。
先看看没有HA的HDFS的系统架构(用draw.io画的,尼马这么好的网站也被墙了):
然后有HA方案的系统架构:
以下的实验基于4个节点的Hadoop集群。其中每个节点的运行的进程列表如下:
实验环境中,所有节点的运行环境基本相同:
手动方式
上面的NameNode默认以standby的状态启动,这时因为没有active的NameNode,所以是不能在HDFS读写文件,需要将其中的一个转成active状态。比如将nn1(对应前面的配置)转成Active:
转成standby的命令是:
bin/hdfs haadmin -transitionToStandby nn1
自动切换
在当前NameNode不能使用时自动切换到第二个NameNode上,需要借助于ZooKeeper[url=ZK]/url。
ZK的安装过程和Hadoop差不多,就是下载文件、修改配置、复制到所有机器、启动。具体步骤在这里。
配置文件conf/zoo.conf:
然后要在hdfs-site.xml上添加配置:
测试
在当前NameNode运行jps看NameNode的进程ID,然后kill掉。通过Web页面( http://hdx:50070 ),可以看到standby的NameNode几乎在kill的同时转成active了。
转载地址:原文地址 收起阅读 »
在Hadoop的分布式文件系统HDFS中,NameNode用来保存文件系统的元数据(包含目录结构/数据块位置等),如果NameNode上的数据丢失,HDFS上对应的文件数据就无法找回来了。Hadoop在2.0.0之前的版本,使用SecondaryNameNode备份NameNode的数据,但SecondaryNameNode无法转成NameNode,如果NameNode挂了,整个HDFS就会挂掉,无法实现真正的failover。这篇博文总结了5种Hadoop HA(High Available,高可用)方案,Hadoop2之后官方引入了QJM(Quorum Journal Manager)和NFS用于NameNode的备份和切换。本方将介绍的是QJM方案,它使用第二个NameNode实时同步当前NameNode的数据,相比于SecondaryNameNode,他可以随时切换成为真正的NameNode(一个可转正的高级备胎)。
先看看没有HA的HDFS的系统架构(用draw.io画的,尼马这么好的网站也被墙了):
然后有HA方案的系统架构:
以下的实验基于4个节点的Hadoop集群。其中每个节点的运行的进程列表如下:
实验环境中,所有节点的运行环境基本相同:
- []Ubuntu14.04 X64[/][]4G内存[/][]OpenJDK-1.7.0[/][]100Mbps以太网[/]
严格按照单节点搭建和集群搭建两个步骤,系统建起来完全没压力。我遇到的问题是刚开始在配置文件(salves和core-site.xml等文件)中使用的是ip地址而非主机名,然后在log文件里看到各种无法连接。解决方案是修改主机名并在hosts文件里建立映射关系。[list=1]
安装Hadoop系统
hostname {new_hostname} # 修改主机名,只有当前Session有效sudo vi /etc/hostname # 永久修改主机名的方法另外,对于64位的系统,最好重新编译源码。
hdfs-site.xml文件:[list=1]
修改配置文件
dfs.namenode.name.dir /data/hadoop/namenode dfs.datanode.data.dir /data/hadoop/datanode dfs.replication 2 dfs.nameservices mycluster dfs.ha.namenodes.mycluster nn1,nn2 dfs.namenode.rpc-address.mycluster.nn1 hd1:8020 dfs.namenode.rpc-address.mycluster.nn2 hd3:8020 dfs.namenode.http-address.mycluster.nn1 hd1:50070 dfs.namenode.http-address.mycluster.nn2 hd3:50070 dfs.namenode.shared.edits.dir qjournal://hd1:8485;hd2:8485;hd4:8485/mycluster dfs.client.failover.proxy.provider.mycluster org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider dfs.ha.fencing.methods sshfence dfs.ha.fencing.ssh.private-key-files /home/hduser/.ssh/id_rsa dfs.journalnode.edits.dir /data/hadoop/journalnode
- []其中nameservices是集群的命名空间,即使有多个集群,可以共用配置文件,但是要注意某些配置项的顺序。[/][]dfs.ha.namenodes.mycluster中的mycluster是可以任取的,但是要和dfs.nameservices对应。[/][]dfs.namenode.rpc-address.mycluster.nn1参考上一条。[/][]dfs.namenode.shared.edits.dir值的格式是"qjournal://host1:port1;host2:port2;host3:port3/journalId",用来指定对应的JN节点,journalId建议使用和nameservices相同的名称。[/][]dfs.client.failover.proxy.provider.mycluster指定激活NameNode的Java类,目前Hadoop内置的只有上面那个。[/][]dfs.ha.fencing.methods是来用来隔离失效的NameNode的方法,有sshfence和Shell两种方式。sshfence需要配置dfs.ha.fencing.ssh.private-key-files私钥文件,以便交互的过程不需要输入密码。[/][]dfs.journalnode.edits.dir是JN保存数据的文件。[/]
fs.defaultFS hdfs://mycluster
- []注意mycluster要和dhfs-site.xml中的dfs.nameservices对应。fs.defaultFS不用端口号。[/]
改好配置文件好,就要将配置文件同步到所有的机器上了。可以用rsync将文件同步到多台机器上。rsync是一个增量同步工具,需要先安装。下面的rsync.sh的功能是将当前目录的所有文件发送到文件或参数对应的机器上。[list=1]
部署
$ cat rsync.sh #! /bin/bashdir=`pwd`pdir=`dirname $dir`send(){ echo "Sending to $2:$1" rsync -avez -e ssh $1 $2:$3}mul_send(){ while read host do send $dir $host $pdir done < $1}[ -f $1 ] && mul_send $1 || send $dir $1 $pdir
将rsync.sh放在etc/hadoop目录下,进入目录运行chmod +x rsync.sh./rsync.sh slaves# or ./rsync.sh hostname发送完文件之后,就是启动系统。步骤如下: 启动JNs.在所有JournalNode上运行
sbin/hadoop-daemon.sh --script hdfs start journalnode启动NameNode. 在原NameNode上运行
bin/hadoop --script hdfs start namenode # NameNode需要已经format。[url=使用上面的rsync.sh文件]/code[/url]将原NameNode(nn1)上的数据复制到第二个NameNode(nn2)。然后在nn2上运行:[code]bin/hdfs namenode -bootstrapStandby启动其他节点在NameNode上运行
sbin/start-dfs.sh
[list=1]
切换NameNode
手动方式
上面的NameNode默认以standby的状态启动,这时因为没有active的NameNode,所以是不能在HDFS读写文件,需要将其中的一个转成active状态。比如将nn1(对应前面的配置)转成Active:
bin/hdfs haadmin -transitionToActive nn1然后在NameNode的web页面上部的括号里的standby变成active。
转成standby的命令是:
bin/hdfs haadmin -transitionToStandby nn1
自动切换
在当前NameNode不能使用时自动切换到第二个NameNode上,需要借助于ZooKeeper[url=ZK]/url。
ZK的安装过程和Hadoop差不多,就是下载文件、修改配置、复制到所有机器、启动。具体步骤在这里。
配置文件conf/zoo.conf:
tickTime=2000hd2,hd3,hd4是主机名,至少需要三台,这个在一台机挂了整个系统还能用,ZK的数量一般是奇数,为什么为奇数可以参考这里。
dataDir=/data/hadoop/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=hd2:2888:3888
server.2=hd3:2888:3888
server.3=hd4:2888:3888
然后要在hdfs-site.xml上添加配置:
然后就是在NameNode的机器上初始化NameNode在ZK的状态了:
dfs.ha.automatic-failover.enabled
true
ha.zookeeper.quorum
hd2:2181,hd3:2181,hd4:2181
bin/hdfs zkfc -formatZK重启HDFS或手动启动DFSZKFailoverController(ZKFC):
sbin/stop-dfs.sh # 重启hdfs在该HA方案中,每一个NameNode都有一个对应的ZKFC。ZKFC会随NameNode启动。
sbin/start-dfs.sh
sbin/hadoop-daemon.sh start zkfc # 启动ZKFC
测试
在当前NameNode运行jps看NameNode的进程ID,然后kill掉。通过Web页面( http://hdx:50070 ),可以看到standby的NameNode几乎在kill的同时转成active了。
转载地址:原文地址 收起阅读 »
Apache无法解析PHP代码问题分析
源码安装Apache 和PHP, Apache的版本是httpd-2.2.12.tar.gz,PHP的版本是php-5.3.6.tar.gz
Apache编译参数如下:
安装完成后配置Apache,写个php的info页面test.php:
在Apache中的配置文件httpd.conf中添加AddType application/x-httpd-php .php,重启APACHE,还是出现同样的错误。
而且Apache的配置文件已经加载了PHP的模块LoadModule php5_module modules/libphp5.so。最后发现是由于Apache的配置文件缺少如下的配置:
收起阅读 »
Apache编译参数如下:
./configure --prefix=/usr/local/apache2 --disable-authn-file --disable-authn-default --disable-authz-groupfile --disable-authz-user --disable-authz-default --disable-auth-basic --disable-include --enable-so --with-mpm=preforkPHP编译参数如下:
./configure --prefix=/usr/local/php5.3.6 --with-apxs2=/usr/local/apache2/bin/apxs --enable-mbstring --with-curl --with-openssl --with-zlib --enable-sockets --enable-ftp --with-mysql --with-openssl --with-gd --with-png-dir --with-jpeg-dir --with-freetype-dir --enable-sockets --enable-pcntl --with-mhash --with-mcrypt --enable-bcmath --with-gettext --enable-zip --with-pdo-mysql安装完PHP后将安装源文件中的 cp php.ini-dist /usr/local/php5.3.6/lib/php.ini
安装完成后配置Apache,写个php的info页面test.php:
phpinfo();然后用浏览器访问test.php,页面出现的是test.php文件中的内容,并不是php的info信息。
?>
在Apache中的配置文件httpd.conf中添加AddType application/x-httpd-php .php,重启APACHE,还是出现同样的错误。
而且Apache的配置文件已经加载了PHP的模块LoadModule php5_module modules/libphp5.so。最后发现是由于Apache的配置文件缺少如下的配置:
AddType application/x-httpd-php .php然后重启Apache,代码可以正常解析了!
AddType application/x-httpd-php .php .phtml .php3
AddType application/x-httpd-php-source .phps
收起阅读 »
Python编写HDFS Datanode监控进程并自动恢复
因为hadoop集群中datanode是大量存在的,那么多机器,什么事都可能发生,最通常的大概就是进程挂掉了。所以为了省事,参考别人的代码写了这个监控进程的daemon。当然,稍加修改就可以用来监控别的必须常驻的进程。只需start,不用后面跟&或者前面加nohup。
其实很多人都对进程挂掉很头疼,没事半夜得爬起来上服务器启动进程是一件非常痛苦的事情。
每2秒监测一次进程,发现进程消失就重启进程。主要原理是fork出子进程,然后将子进程挂起,并退出父进程。其程序本身作为被监控进程的外壳程序存在。
转载原文地址:原文地址 收起阅读 »
其实很多人都对进程挂掉很头疼,没事半夜得爬起来上服务器启动进程是一件非常痛苦的事情。
每2秒监测一次进程,发现进程消失就重启进程。主要原理是fork出子进程,然后将子进程挂起,并退出父进程。其程序本身作为被监控进程的外壳程序存在。
#!/usr/bin/env python实际使用中还是比较好用的,把该程序加入到启动文件中,重启服务器,服务器重启后会自动启动其所监控的进程。用到的都是python的基本模块,不会存在依赖缺失问题。
import sys, os, time, atexit, string
from signal import SIGTERM
class Daemon:
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
#需要获取调试信息,改为stdin='/dev/stdin', stdout='/dev/stdout', stderr='/dev/stderr',以root身份运行。
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
def _daemonize(self):
try:
pid = os.fork()
if pid > 0:
#退出主进程
sys.exit(0)
except OSError, e:
sys.stderr.write('fork #1 failed: %d (%s)\n' % (e.errno, e.strerror))
sys.exit(1)
os.chdir("/")
os.setsid()
os.umask(0)
#创建子进程
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
sys.stderr.write('fork #2 failed: %d (%s)\n' % (e.errno, e.strerror))
sys.exit(1)
#重定向文件描述符
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
#创建processid文件
atexit.register(self.delpid)
pid = str(os.getpid())
file(self.pidfile,'w+').write('%s\n' % pid)
def delpid(self):
os.remove(self.pidfile)
def start(self):
#检查pid文件是否存在以探测是否存在进程
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if pid:
message = 'pidfile %s already exist. Daemon already running?\n'
sys.stderr.write(message % self.pidfile)
sys.exit(1)
#启动监控
self._daemonize()
self._run()
def stop(self):
#从pid文件中获取pid
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if not pid:
message = 'pidfile %s does not exist. Daemon not running?\n'
sys.stderr.write(message % self.pidfile)
return #重启不报错
#杀进程
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
os.system('/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh stop datanode')
os.system('/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh stop tasktracker')
except OSError, err:
err = str(err)
if err.find('No such process') > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
def restart(self):
self.stop()
self.start()
def _run(self):
while True:
datanode = os.popen('ps -fe | grep "java" | grep "datanode" | grep -v "grep" | wc -l').read().strip()
tasktracker = os.popen('ps -fe | grep "java" | grep "tasktracker" | grep -v "grep" | wc -l').read().strip()
#选出进程中含有java且含有datanode|tasktracker且不含有grep,计算出现行数。修改上面的进程监控语句以适应其他应用需求
if datanode == '0':
os.system('/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh start datanode')
#修改这里的启动命令
if tasktracker == '0':
os.system('/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh start tasktracker')
#修改这里的启动命令
time.sleep(2)
#修改这里的停留时间
if __name__ == '__main__':
daemon = Daemon('/tmp/watch_process.pid')
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()
elif 'restart' == sys.argv[1]:
daemon.restart()
else:
print 'Unknown command'
sys.exit(2)
sys.exit(0)
else:
print 'usage: %s start|stop|restart' % sys.argv[0]
sys.exit(2)
#/bin/sh
while true;
do
count=`ps -fe | grep "java" | grep "datanode" | grep -v "grep"`
if [ "$?" != "0" ]; then
/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh start datanode
fi
sleep 2
done
#/bin/sh其实作用是一样的,只是一个前台,一个后台。一个利用bash,一个利用python。
while true;
do
count=`ps -fe | grep "java" | grep "tasktracker" | grep -v "grep"`
if [ "$?" != "0" ]; then
/opt/modules/hadoop/hadoop-0.20.203.0/bin/hadoop-daemon.sh start tasktracker
fi
sleep 2
done
转载原文地址:原文地址 收起阅读 »
HDFS中Datanode存在大量没有删除的Block磁盘被占满案例分析
最近发现hdfs中,有的datanode节点,磁盘发生告警,然后分析了一下。
然后上网搜索了一下为什么,分析如下:
查看对应datanode的数据目录,发现确实有很多的数据块(量非常大,都超过了实际hdfs中的数据块总量)
这时候,猜测应该是有很多需要被删除的数据块没有被删除。猜测可能是NameNode和DataNode之间的通讯出现异常导致。于是查看NameNode和DataNode日志,发现并没有任何异常信息,只是发现NameNode定时对其中的三台机器发出了删除指令
按照网上的方法,通过dfsadmin证实了,确实是有大量的block在等待删除
没有办法,只好从源码着手。在FSNameSystem.java文件里面找到了最终问题的所在:
也就是说每次只处理
8*32% = 3(这就解释了为啥每次只删除三台数据节点上的数据块。)
再查看节点选择部分:
所以只要这三个节点有数据需要删除,就不会删除到其他节点
这时候,发现这个问题是调整的时候,修改了一个配置项(dfs.replication.interval,默认是3秒,我修改成了30秒)导致的,当时修改的初衷是防止过早出现数据块复制。但是修改这个配置项以后,数据块副本数检查的间隔拉长了,导致30秒内,有几台机器一直有数据块需要删除,从而无法删除其他节点上的数据块,最终导致磁盘空间无法释放。因为INVALIDATE_WORK_PCT_PER_ITERATION是系统写死的,所以只能通过把dfs.replication.interval改回来,暂时解决这个问题。
收起阅读 »
然后上网搜索了一下为什么,分析如下:
查看对应datanode的数据目录,发现确实有很多的数据块(量非常大,都超过了实际hdfs中的数据块总量)
这时候,猜测应该是有很多需要被删除的数据块没有被删除。猜测可能是NameNode和DataNode之间的通讯出现异常导致。于是查看NameNode和DataNode日志,发现并没有任何异常信息,只是发现NameNode定时对其中的三台机器发出了删除指令
BLOCK[i] ask 192.168.200.8:50010 to delete blk_7080908721303033545_7530145 BLOCK[/i] ask 192.168.200.9:50010 to delete blk_-6550808355677895247_7465333 BLOCK* ask 192.168.200.7:50010 to delete blk_2415291932316966347_7460687
按照网上的方法,通过dfsadmin证实了,确实是有大量的block在等待删除
hadoop dfsadmin -metasave meta.txt然后到logs目录下查看meta.txt文件结果如下:
Metasave: Blocks 572428 waiting deletion from 8 datanodes.显示有几十万的block等待删除
没有办法,只好从源码着手。在FSNameSystem.java文件里面找到了最终问题的所在:
public int computeDatanodeWork() throws IOException {computeInvalidateWork就是用于计算这次需要删除的数据块。但是并不是每次都把所有的节点都处理一遍,而是每次只处理nodesToProcess个节点,而这个数量决定于datanode的总数(heartbeats.size,我这儿是8)和一个系数(INVALIDATE_WORK_PCT_PER_ITERATION,写死的32)。
int workFound = 0;
int blocksToProcess = 0;
int nodesToProcess = 0;
// blocks should not be replicated or removed if safe mode is on
if (isInSafeMode())
return workFound;
synchronized(heartbeats) {
blocksToProcess = (int)(heartbeats.size()
* ReplicationMonitor.REPLICATION_WORK_MULTIPLIER_PER_ITERATION);
nodesToProcess = (int)Math.ceil((double)heartbeats.size()
* ReplicationMonitor.INVALIDATE_WORK_PCT_PER_ITERATION / 100);
}
workFound = computeReplicationWork(blocksToProcess);
// Update FSNamesystemMetrics counters
synchronized (this) {
pendingReplicationBlocksCount = pendingReplications.size();
underReplicatedBlocksCount = neededReplications.size();
scheduledReplicationBlocksCount = workFound;
corruptReplicaBlocksCount = corruptReplicas.size();
}
workFound += computeInvalidateWork(nodesToProcess);
return workFound;
}
也就是说每次只处理
8*32% = 3(这就解释了为啥每次只删除三台数据节点上的数据块。)
再查看节点选择部分:
……发现是通过iterator遍历的,然后悲剧的发现recentInvalidateSets用的是TreeMap,也就是说是有序的……
private Map> recentInvalidateSets =
new TreeMap>();
……
String firstNodeId = recentInvalidateSets.keySet().iterator().next();
……
所以只要这三个节点有数据需要删除,就不会删除到其他节点
这时候,发现这个问题是调整的时候,修改了一个配置项(dfs.replication.interval,默认是3秒,我修改成了30秒)导致的,当时修改的初衷是防止过早出现数据块复制。但是修改这个配置项以后,数据块副本数检查的间隔拉长了,导致30秒内,有几台机器一直有数据块需要删除,从而无法删除其他节点上的数据块,最终导致磁盘空间无法释放。因为INVALIDATE_WORK_PCT_PER_ITERATION是系统写死的,所以只能通过把dfs.replication.interval改回来,暂时解决这个问题。
收起阅读 »