架构解密从分布式到微服务:深入Kubernetes微服务平台
2021-03-17 10:51:16架构师普遍有这样的愿景:在系统中有ServiceA、ServiceB、ServiceC这3种服务,其中ServiceA需要部署3个实例,ServiceB与ServiceC各自需要部署5个实例,希望有一个平台(或工具)自动完成上述13个实例的分布式部署,并且持续监控它们。
深入Kubernetes微服务平台
Kubernetes的概念与功能
架构师普遍有这样的愿景:在系统中有ServiceA、ServiceB、ServiceC这3种服务,其中ServiceA需要部署3个实例,ServiceB与ServiceC各自需要部署5个实例,希望有一个平台(或工具)自动完成上述13个实例的分布式部署,并且持续监控它们。当发现某个 服务器 宕机或者某个服务实例发生故障时,平台能够自我修复,从而确保在任何时间点正在运行的服务实例的数量都符合预期。这样一来,团队只需关注服务开发本身,无须再为基础设施和运维监控的事情头疼了。
在 Kubernetes出现之前,没有一个平台公开声称实现了上面的愿景。Kubernetes是业界第一个将服务这个概念真正提升到第一位的平台。在Kubernetes的世界里,所有概念与组件都是围绕Service运转的。正是这种突破性的设计,使Kubernetes真正解决了多年来困扰我们的分布式系统里的众多难题,让团队有更多的时间去关注与业务需求和业务相关的代码本身,从而在很大程度上提高整个软件团队的工作效率与投入产出比。
Kubernetes里的Service其实就是微服务架构中微服务的概念,它有以下明显特点。
Service既然有了IP地址,就可以顺理成章地采用DNS域名的方式来避免IP地址的变动了。Kubernetes 的 DNS组件自动为每个Service都建立了一个域名与IP的映射表,其中的域名就是Service的Name,IP就是对应的Cluster IP,并且在Kubernetes的每个Pod(类似于Docker’容器)里都设置了DNS Server为 Kubernetes 的 DNS Server,这样一来,微服务架构中的服务发现这个基本问题得以巧妙解决,不但不用复杂的服务发现API供客户端调用,还使所有以TCP/IP方式通信的分布式系统都能方便地迁移到Kubernetes平台上,仅从这个设计来看,Kubernetes就远胜过其他产品。
我们知道,在每个微服务的背后都有多个进程实例来提供服务,在Kubernetes平台上,这些进程实例被封装在Pod中,Pod基本上等同于Docker容器,稍有不同的是,Pod其实是一组密切捆绑在一起并且“同生共死”的 Docker 容器,这组容器共享同一个网络栈与文件系统,相互之间没有隔离,可以直接在进程间通信。最典型的例子是Kubenetes Sky DNS Pod,在这个Pod里有4个Docker ‘容器。
那么,Kubernetes里的 Service 与 Pod 是如何对应的呢?我们怎么知道哪些Pod 为某个Service提供具体的服务?下图给出了答案——“贴标签”。
每个Pod都可以贴一个或多个不同的标签(Label),而每个Service都有一个“标签选择器”(Label Selector),标签选择器确定了要选择拥有哪些标签的对象。下面这段YAML格式的内容定义了一个被称为ku8-redis-master的Service,它的标签选择器的内容为“app: ku8-redis-master”,表明拥有“app= ku8-redis-master”这个标签的Pod都是为它服务的:
下面是 ku8-redis-master这个 Pod 的定义,它的 labels属性的内容刚好匹配Service 的标签选择器的内容:
如果我们需要一个Service在任意时刻都有N个Pod实例来提供服务,并且在其中1个Pod实例发生故障后,及时发现并且自动产生一个新的Pod实例以弥补空缺,那么我们要怎么做呢?答案就是采用 Deployment/RC,它的作用是告诉Kubernetes,拥有某个特定标签的 Pod需要在Kubernetes集群中创建几个副本实例。Deployment/RC的定义包括如下两部分内容。
●目标Pod的副本数量(replicas)。
●目标Pod的创建模板(Template)。
下面这个例子定义了一个RC,目标是确保在集群中任意时刻都有两个 Pod,其标签为“ app:ku8-redis-slave”,对应的容器镜像为redis slave,这两个 Pod 与ku8-redis-master构成了Redis主从集群(一主二从):
至此,上述YAML文件创建了一个一主二从的Redis集群,其中Redis Master被定义为一个微服务,可以被其他Pod或 Service访问,如下图所示。
注意上图在 ku8-reids-slave的容器中有MASTER_ADDR的环境变量,这是Redis Master 的地址,这里填写的是“ku8-redis-master”,它是Redis Master Service 的名称,之前说过:Service的名称就是它的DNS域名,所以Redis Slave容器可以通过这个DNS与Redis Master Service进行通信,以实现Redis 主从同步功能。
Kubernetes 的核心概念就是Service、Pod 及 RC/Deployment。围绕着这三个核心概念,Kubernetes实现了有史以来最强大的基于容器技术的微服务架构平台。比如,在上述Redis集群中,如果我们希望组成一主三从的集群,则只要将控制Redis Slave的 ReplicationController中的replicas改为3,或者用kubectrl scale命令行功能实现扩容即可。命令如下,我们发现,服务的水平扩容变得如此方便:
不仅如此,Kubernetes还实现了水平自动扩容的高级特性——HPA ( Horizontal PodAutoscaling ),其原理是基于Pod 的性能度量参数(CPU utilization和 custom metrics)对RC/Deployment管理的Pod进行自动伸缩。举个例子,假如我们认为上述Redis Slave集群对应的Pod也对外提供查询服务,服务期间Pod的 CPU利用率会不断变化,在这些Pod 的CPU平均利用率超过80%后,就会自动扩容,直到CPU利用率下降到80%以下或者最多达到5个副本位置,而在请求的压力减小后,Pod的副本数减少为1个,用下面的HPA命令即可实现这一目标:
除了很方便地实现微服务的水平扩容功能,Kubernetes还提供了使用简单、功能强大的微服务滚动升级功能(rolling Update),只要一个简单的命令即可快速完成任务。举个例子,假如我们要将上述Redis Slave服务的镜像版本从devopsbq/redis-slave升级为leader/redis-slave,则只要执行下面这条命令即可:
滚动升级的原理如下图所示,Kubernetes在执行滚动升级的过程中,会创建一个新的RC,这个新的RC使用了新的Pod镜像,然后Kubernetes每隔一段时间就将旧RC的replicas数减少一个,导致旧版本的Pod副本数减少一个,然后将新RC的replicas数增加一个,于是多出一个新版本的Pod副本,在升级的过程中 Pod副本数基本保持不变,直到最后所有的副本都变成新的版本,升级才结束。
Kubernetes的组成与原理
Kubernetes集群本身作为一个分布式系统,也采用了经典的Master-Slave架构,如下图所示,集群中有一个节点是Master节点,在其上部署了3个主要的控制程序:API Sever、ControllerManager 及 Scheduler,还部署了Etcd进程,用来持久化存储Kubernetes管理的资源对象(如Service、Pod、RC/Deployment)等。
集群中的其他节点被称为Node节点,属于工人(Worker 节点),它们都由Master 节点领导,主要负责照顾各自节点上分配的Pod副本。下面这张图更加清晰地表明了Kubernetes各个进程之间的交互关系。
从上图可以看到,位于中心地位的进程是API Server,所有其他进程都与它直接交互,其他进程之间并不存在直接的交互关系。那么,APl Server的作用是什么呢?它其实是Kubernetes的数据网关,即所有进入Kubernetes 的数据都是通过这个网关保存到Etcd数据库中的,同时通过API Server将Eted里变化的数据实时发给其他相关的Kubernetes进程。API Server 以REST方式对外提供接口,这些接口基本上分为以下两类。
下面是上图中其他Kubernetes进程的主要功能。
在理解了Kubernetes各个进程的功能后,我们来看看一个RC 从YAML定义到最终被部署成多个Pod 及容器背后所发生的事情。为了很清晰地说明这个复杂的流程,这里给出一张示意图。
首先,在我们通过kubectrl create命令创建一个RC(资源对象)时,kubectrl通过Create RC这个REST接口将数据提交到APl Server,随后API Server将数据写入Etcd里持久保存。与此同时,Controller Manager监听(Watch)所有RC,一旦有RC被写入Etcd中,Controller Manager就得到了通知,它会读取RC的定义,然后比较在RC中所控制的Pod 的实际副本数与期待值的差异,然后采取对应的行动。此刻,Controller Manager 发现在集群中还没有对应的Pod实例,就根据RC里的Pod模板(Template)定义,创建一个Pod并通过API Server保存到Etcd中。类似地,Scheduler进程监听所有 Pod,一旦发现系统产生了一个新生的Pod,就开始执行调度逻辑,为该Pod 安排一个新家(Node),如果一切顺利,该Pod就被安排到某个Node节点上,即Binding to a Node。接下来,Scheduler进程就把这个信息及 Pod状态更新到Etcd里,最后,目标Node节点上的Kubelet监听到有新的Pod被安排到自己这里来了,就按照Pod里的定义,拉取容器的镜像并且创建对应的容器。在容器成功创建后,Kubelet进程再把 Pod的状态更新为Running 并通过API Server更新到 Etcd 中。如果此 Pod还有对应的Service,每个Node上的Kube-proxy进程就会监听所有Service及这些Service对应的Pod实例的变化,一旦发现有变化,就会在所在 Node节点上的 iptables 里增加或者删除对应的NAT转发规则,最终实现了Service的智能负载均衡功能,这一切都是自动完成的,无须人工干预。
那么,如果某个Node’宕机,则会发生什么事情呢?假如某个Node宕机一段时间,则因为在此节点上没有Kubelet进程定时汇报这些Pod 的状态,因此这个Node 上的所有Pod’实例都会被判定为失败状态,此时Controller Manager会将这些Pod删除并产生新的Pod实例,于是这些Pod被调度到其他 Node 上创建出来,系统自动恢复。
本节最后说说Kube-proxy的演变,如下图所示。
Kube-proxy一开始是一个类似于HAProxy的代理服务器,实现了基于软件的负载均衡功能,将Client 发起的请求代理到后端的某个Pod 上,可以将其理解为Kubernetes Service的负载均衡器。Kube-proxy最初的实现机制是操控 iptables规则,将访问Cluster IP 的流量通过NAT方式重定向到本机的Kube-proxy,在这个过程中涉及网络报文从内核态到用户态的多次复制,因此效率不高。Kube-proxy 之后的版本改变了实现方式,在生成 iptables规则时,直接NAT 到目标Pod地址,不再通过Kube-proxy进行转发,因此效率更高、速度更快,采用这种方式比采用客户端负载均衡方式效率稍差一点,但编程简单,而且与具体的通信协议无关,适用范围更广。此时,我们可以认为Kubernetes Service基于 iptables机制来实现路由和负载均衡机制,从此以后,Kube-proxy已不再是一个真正的“proxy””,仅仅是路由规则配置的一个工具类“代理”。
基于iptables 实现的路由和负载均衡机制虽然在性能方面比普通Proxy提升了很多,但也存在自身的固有缺陷,因为每个Service都会产生一定数量的 iptables 规则。在Service数量比较多的情况下,iptables 的规则数量会激增,对iptables的转发效率及对Linux内核的稳定性都造成一定的冲击。因此很多人都在尝试将IPVS(IP虚拟服务器)代替iptables。Kubernetes 从 1.8版本开始,新增了Kube-proxy对IPVS的支持,在1.11版本中正式纳入 GA。与 iptables 不同, IPVS本身就被定位为Linux官方标准中TCP/UDP服务的负载均衡器解决方案,因此非常适合代替iptables来实现 Service的路由和负载均衡。
此外,也有一些机制来代替 Kube-proxy,比如Service Mesh 中的 SideCar 完全代替了Kube-proxy的功能。在 Service 都基于HTTP接口的情况下,我们会有更多的选择方式,比如Ingress、Nginx 等。
基于Kubernetes 的 PaaS平台
PaaS其实是一个重量级但不怎么成功的产品,受限于多语言支持和开发模式的僵硬,但近期又随着容器技术及云计算的发展,重新引发了人们的关注,这是因为容器技术彻底解决了应用打包部署和自动化的难题。基于容器技术重新设计和实现的PaaS平台,既提升了平台的技术含量,又很好地弥补了之前PaaS平台难用、复杂、自动化水平低等缺点。
OpenShift是由 RedHat公司于2011年推出的PaaS云计算平台,在Kubernetes推出之前,OpenShift 就已经演变为两个版本(v1与v2),但在 Kubernetes推出之后,OpenShift的第3个版本v3放弃了自己的容器引擎与容器编排模块,转而全面拥抱Kubernetes。
Kubernetes 拥有如下特性。
国内外已经有很多公司采用了Kubernetes作为它们的PaaS平台的内核,所以本节讲解如何基于Kubernetes 设计和实现一个强大的 PaaS平台。
一个 PaaS平台应该具备如下关键特性。
接下来,我们看看基于Kubernetes 设计和实现的PaaS平台是如何支持上述关键特性的。
如何实现多租户
Kubernetes通过Namespace特性来支持多租户功能。
我们可以创建多个不同的Namespace资源对象,每个租户都有一个Namespace,在不同的Namespace下创建的Pod、Service 与RC等资源对象是无法在另外一个Namespace下看到的,于是形成了逻辑上的多租户隔离特性。但单纯的Namespace隔离并不能阻止不同Namespace下的网络隔离,如果知道其他Namespace中的某个 Pod的IP地址,则我们还是可以发起访问的,如下图所示。
针对多租户的网络隔离问题,Kubernetes增加了Network Policy这一特性,我们简单地将它类比为网络防火墙,通过定义Network Policy资源对象,我们可以控制一个Namespace(租户)下的Pod被哪些Namespace访问。假如我们有两个Namespace,分别为tenant2、tenant3,各自拥有一些Pod,如下图所示。
假如我们需要实现这些网络隔离目标: tenant3里拥有role:db标签的Pod只能被tenant3(本Namespace中)里拥有role:frontend标签的Pod访问,或者被tenent2里的任意Pod访问,则我们可以定义如下图所示的一个Network Policy资源对象,并通过kubectrl工具发布到Kubernetes集群中生效即可。
需要注意的是,Kubernetes Network Policy需要配合特定的CNI网络插件才能真正生效,目前支持Network Policy 的CNI 插件主要有以下几种。
Network Policy目前也才刚刚起步,还有很多问题需要去研究和解决,比如如何定义Service的访问策略?如果Service访问策略与Pod访问策略冲突又该如何解决﹖此外,外部服务的访问策略又该如何定义?总之,在容器领域,相对于计算虚拟化、存储虚拟化来说,网络虚拟化中的很多技术才刚刚起步。
Kubernetes 的 Namespace是从逻辑上隔离不同租户的程序,但多个租户的程序还是可能被调度到同一个物理机(Node)上的,如果我们希望不同租户的应用被调度到不同的Node 上,从而做到物理上的隔离,则可以通过集群分区的方式来实现。具体做法是我们先按照租户将整个集群划分为不同的分区(Partition),如下图所示,对每个分区里的所有 Node 都打上同样的标签,比如租户 a(tanenta)的标签为partition=tenant,租户 b( tanentb)的标签为partition= tenantb,我们在调度Pod 的时候可以使用nodeSelector属性来指定目标Node的标签,比如下面的写法表示Pod需要被调度到租户 a的分区节点上:
Kubernetes 分区与租户可以有多种对应的设计,上面所说的一个分区一个租户的设计是一种典型的设计,也可以将租户分为大客户与普通客户,每个大客户都有一个单独的资源分区,而普通客户可以以N个为一组,共享同一个分区的资源。
PaaS 平台的领域模型设计
我们知道,微服务架构下的一个应用通常是由多个微服务所组成的,而我们的Kubernetes通常会部署多个独立的应用,因此,如果用 Kubernetes建模微服务应用,则我们需要在 PaaS平台的领域模型中设计出 Application这个领域对象,一个Application包括多个微服务,并且最终在发布(部署)时会生成对应的Pod、Deployment 及 Service对象,如下图所示。
如下所示是有更多细节的领域模型图,Kubernetes中的 Node、Namespace分别被建模为k8sNode与TanentNS,分区则被建模为ResPartition对象,每个分区都可以包括1到N个TanentNS,即一个或多个租户(Tanent〉使用。每个租户都包括一些用户账号(User),用来定义和维护本租户的应用(Application)。为了分离权限,可以使用用户组(User Group)的方式,同时可以增加标准的基于角色的权限模型。
上图中的Service领域对象并不是Kubernetes Service,而是包括了Kubernetes Service及相关RC/Deployment的一个“复合结构”。在Service领域对象中只包括了必要的全部属性,在部署应用时会生成对应的Kubernetes Service和RC/Deployment实例。下图给出了Service的定义界面(原型)。
我们在界面上完成对一个Application的定义后,就可以发布应用了。在发布应用的过程中,先要选择某个分区,然后程序调用Kubernetes的 API接口,创建此 Application相关的所有Kubernetes资源对象,然后查询Pod的状态即可判断是否发布成功及失败的具体原因。下面给出了Application从定义到发布的关键模块的设计示意图。
我们知道Kubernetes是基于容器技术的微服务架构平台,每个微服务的二进制文件都被打包成标准的Docker镜像,因此应用的全生命周期管理过程的第一步,就是从源码到Docker镜像的打包,而这个过程很容易实现自动化,我们既可以通过编程方式实现,也可以通过成熟的第三方开源项目实现,这里推荐使用Jenkins。下图是Jenkins实现镜像打包流程的示意图,考虑到Jenkins的强大和用户群广泛,很多PaaS平台都集成了Jenkins 以实现应用的全生命周期管理功能。
PaaS 平台的基础中间件
一个完备的PaaS平台必须集成和提供一些常见的中间件,以方便应用开发和托管运行。首先,第1类重要的基础中间件是 ZooKeeper,ZooKeeper非常容易被部署到Kubernetes集群中,在Kubernetes 的 GitHub上有一个YAML参考文件。ZooKeeper除了给应用使用,也可以作为PaaS平台面向应用提供的“集中配置服务”的基础组成部分,如下图所示。
此外,考虑到很多开源分布式系统都采用了ZooKeeper来管理集群,所以我们也可以部署一个标准命名的ZooKeeper Service,以供这些集群共享使用。
第2类重要的中间件就是缓存中间件了,比如我们之前提到的Redis 及 Memcache,它们也很容易被部署到Kubernetes集群中,作为基础服务提供给第三方应用使用。在Kubernetes的入门案例中有一个GuestBook例子,演示了在PHP页面中访问Redis主从集群的方法,即使是复杂的Codis集群,也可以被成功部署到Kubernetes集群中。此外,RedHat 的J2EE内存缓存中间件Infinispan也有Kubernetes集群部署的案例。
第3类重要的中间件是消息队列中间件,不管是经典的ActiveMQ、RabbitMQ还是新一代的Kafka,这些消息中间件也很容易被部署到Kubernetes集群中提供服务。下图是一个3节点的RabbitMQ集群在Kubernetes平台上的建模示意图。为了组成RabbitMQ集群,我们定义了3个Pod,每个Pod都对应一个Kubernetes Service,从而映射到3个RabbitMQ Server 实例,此外,我们定义了一个单独的Service,名为 ku8-rabbit-mq-server,此 Service对外提供服务,并且对应到上述3个Pod 上,于是每个Pod都有两个标签。
第4类重要的中间件是分布式存储中间件,目前在Kubernetes集群上可以使用Ceph集群提供的块存储服务及GlusterFS提供的分布式文件存储服务,其中 GlusterFS被RedHat的OpenShift平台建议为文件存储的标配存储系统,下面是这种方案的示意图。
在 RedHat的方案中,GlusterFS集群被部署在独立的服务器集群上,这适用于较大的集群规模及对性能和存储要求高的场景。在机器有限的情况下,我们也可以把Kubernetes集群的每个Node节点都当作一个GlusterFS的存储节点,并采用DaemonSet的调度方式将GlusterFS部署到Kubernetes集群上,具体的部署方式在Kubernetes 的 GitHub网站中有详细的说明文档,以Pod方式部署GlusterFS集群也使得GlusterFS 的部署和运维都变得非常简单。
提供全文检索能力的ElasticSearch集群也很容易被部署到Kubernetes中,前面提到的日志集中收集与查询分析的三件套ELK目前基本上全部以Pod的方式部署,以实现Kubernetes集群日志与用户应用日志的统一收集、查询、分析等功能。
在当前热门的大数据领域中,很多系统也都能以容器化方式部署到Kubernetes集群中,比如Hadoop、HBase、Spark 及 Storm等重量级集群。下一节将给出 Storm On Kubernetes 的建模方案,并且将其部署到Kubernetes集群中,最后提交第6章的WordCountTopology 作业并且观察运行结果。
Storm On Kubernetes 实战
通过第6章的学习,我们知道一个 Storm集群是由ZooKeeper、Nimbus (Master)及一些Supervisor (Slave)节点组成的,集群的配置文件默认保存在 conf/storm.yaml中,最关键的配置参数如下。
从上述关键配置信息及Storm集群的工作原理来看,我们首先需要将ZooKeeper建模为Kubernetes Service,以便提供一个固定的域名地址,使得Nimbus 与Supervisor能够访问它。下面是ZooKeeper 的建模过程(为了简单起见,我们只建模一个ZooKeeper节点)。
首先,定义ZooKeeper对应的Service,Service名称为ku8-zookeeper,关联的标签为app=ku8-zookeeper 的Pod:
其次,定义ZooKeeper对应的RC:
接下来,我们需要将Nimbus也建模为Kubernetes Service,因为Storm客户端需要直接访问Nimbus服务以提交拓扑任务,所以在conf/storm.yaml中存在nimbus.sceds参数。由于Nimbus在6627端口上提供了基于Thrift的 RPC服务,因此对Nimbus服务的定义如下:
考虑到在storm.yaml配置文件中有很多参数,所以为了实现任意参数的可配置性,我们可以用Kubernetes的Config Map资源对象来保存storm.yaml,并映射到Nimbus(以及 Supervisor)节点对应的Pod实例上。下面是在本案例中使用的storm.yaml 文件(storm-conf.yaml)的内容:
将上述配置文件创建为对应的ConfigMap ( storm-config),可以执行下面的命令:
然后,storm-config 就可以被任意Pod 以 Volume方式挂载到容器内的任意指定路径上了。接下来,我们可以继续建模 Nimbus服务对应的Pod。在从Docker Hub上搜寻相关 Storm镜像并进行分析后,我们选择了Docker 官方提供的镜像storm:1.0。相对于其他Storm镜像来说,官方维护的这个镜像有以下优点。
采用storm:1.0镜像定义Nimbus Pod的YAML文件如下:
这里我们需要关注两个细节:第1个细节是ConfigMap 的使用方法,首先要把之前定义的ConfigMap ——storm-config映射为Pod的一个Volume,然后在容器中将此Volume挂接到某个具体的路径上;第2个细节是容器的参数 command,上面的command: [ “storm” , “nimbus”]表示此容器启动的是nimus进程。
类似地,我们定义storm-ui服务,这是一个Web管理程序,提供了图形化的Storm管理功能,因为需要在Kubernetes集群之外访问它,所以我们通过NodePort方式映射8080端口到主机上的30010。storm-ui服务的YAML定义文件如下:
最后,我们来建模Supervisor。Supervisor看似不需要被建模为Service,因为Supervisor 不会被主动调用,但实际上Supervisor节点之间会相互发起通信,因此Supervisor节点注册到ZooKeeper 上的地址必须能被相互访问,在 Kubernetes平台上有两种方式解决此问题。
第1种方式,Supervisor节点注册到ZooKeeper上时,不用主机名(Pod名称),而是采用Pod的P地址。
第2种方式,用Headless Service模式,每个Supervisor节点都被建模为一个HeadlessService,并且确保Supervisor节点的容器名称(主机名)与Headless Service的名称一样,此时Supervisor节点注册到ZooKeeper 上的地址就跟Headless Service名称一样了,Supervisor节点之间都能用对方的Headless Service的域名进行通信。
其中,第1种方式需要修改Supervisor的启动脚本和对应的参数才能进行,实现起来比较麻烦,第②种方式无须修改镜像就能实现,所以我们采用了第﹖种方式建模。下面是某个Supervisor节点的Service定义,注意 clusterIP: None的特殊写法:
storm-supervisor 这个节点对应的 Pod定义如下,需要注意Pod 的名称为storm-supervisor,并且command的值为[ “storm”, “supervisor”]:
我们可以定义多个Supervisor 节点,比如在本案例中定义了两个Supervisor节点。在成功部署到Kubernetes集群后,我们通过Storm UI的30010端口进入Storm的管理界面,可以看到如下界面。
下面这个截图验证了两个Supervisor 节点也可以被成功注册在集群中,我们看到每个节点都有4个Slot,这符合我们在storm.yaml中的配置。
至此,Storm集群在Kubernetes 上的建模和部署已经顺利完成了。接下来我们看看如何在Storm集群中提交之前学习过的WordCountTopology作业并且观察它的运行情况。
首先,我们可以去 https:/ljar-download.com/下载编译好的 WordCountTopology 作业的JAR文件storm-starter-topologies-1.0.3.jar,然后通过Storm Client工具将该Topology作业提交到Storm集群中,提交作业的命令如下:
由于在storm:1.0镜像中已经包括了Storm Client 工具,所以最简便的方式是定义一个Pod,然后把下载下来的storm-starter-topologies-1.0.3.jar作为Volume映射到Pod里的/userlib/目录下。将容器的启动命令设置为上述提交作业的命令即可实现,下面是此Pod 的YAML定义:
上述定义有如下关键点。
创建上述 Pod以后,我们查看该Pod 的日志,如果看到下面这段输出,则表明WordCountTopology的拓扑作业已经被成功提交到Storm集群中了。
接下来,我们进入Storm UI去看看作业的执行情况。下图是WordCountTopology的汇总信息,状态为Active,运行了8分钟,占用了3个Worker进程,总共运行了28个Task。
在成功提交到Storm集群后,我们可以进入Supervisor节点(Pod)查看拓扑作业的日志输出,作业的日志输出在目录/log/workers-artifacts下,每个拓扑作业都有一个单独的文件夹存放日志,我们搜索WordCountTopology 的最后一个 Bolt——统计发送Tuple的日志,可以看到如下结果,即每个Word(字)都被统计输出了。
下面这个界面给出了WordCountTopology 的详细信息,分别显示了拓扑里所有Spout的相关信息,例如生成了几个Task、总共发送了多少个Tuple、失败了多少个,以及所有 Bolt 的相关信息,例如处理了多少个 Tuple、处理的延时等统计信息,有助于我们分析Topology 作业的性能瓶颈和改进的可能性。
除了上面的列表信息,Storm UI还提供了展示Stream运行情况的拓扑图,如下图所示,我们看到数据流从spout节点发出,经过 split 节点处理时用了3.13ms,然后抵达count节点,count节点的处理耗时为0.06ms。
Storm 的 Topology 作业一旦运行起来就不会停止,所以你会看到下面界面中的Tuple 的统计数字在不断增加,因为WordCountTopology的 Spout 节点在不断生成Tuple,所以如果我们需要停止作业,则可以单击图中的 Deactvate按钮挂起作业,或者终止作业。
地理小博士论文怎么写?
一、我国防灾减灾科技应用与建设的现状 我国目前已建立起了较为完善、广为覆盖的气象、海洋、地震、水文、森林火灾和病虫害等地面监测和观测网,建立了气象卫星、海洋卫星、陆地卫星系列,并正在建设减灾小卫星星座系统。 在气象监测预报方面,建成了较先进的由地面气象观测站、太空站、各类天气雷达及气象卫星组成的大气探测系统,建立了气象卫星资料接收处理系统、现代化的气象通信系统和中期数值预报业务系统。 全国已形成了由国家、区域、省、地、县五级分工合理、有机结合、逐级指导的基本气象信息加工分析预测体系。 为了监测江河洪水,国家组建了由数目众多的水文站、水位站、雨量站等组成的水文监测网,建立了七大江河地区洪涝灾害易发区警戒水域遥感数据库,将遥感技术在“八五”期间应用于洪灾监测。 大江大河防汛抗旱工程技术有了长足的进步,有些领域已经达到世界先进水平。 另外,利用现代科技积极开展小流域综合治理工作,如农区人工增雨、人工防雹、滴灌工程等,这些技术措施在一定程度上对防灾减灾发生了非常积极的作用。 在地震监测和抗震方面,组建了400多个地震观测台站,“十五”期间进行了数字化改造,由48个国家级数字测震台站组成的国家数字测震台网和由300多个区域数字测震台站组成的20个区域数字测震台网以及若干个流动数字测震台网、数字强震台网构成了中国数字测震系统,建立了大震警报系统和地震前兆观测系统,形成了比较完整的监测预报系统,编制了全国地震烈度区划图和震害预测图,确定了52个城市作为国家重点防震城市,对全国地震烈度6度以上地区的工程建筑,实施综合性震害防御,对城市和大中型工矿企业的新建工程进行了抗震设防,完成了多条铁路干线、主要输油管线和多座骨干电厂、大型炼油厂,一批重点骨干钢铁企业和超大型乙烯工程以及大型水库的抗震加固。 在地质灾害防治方面,加强了对滑坡、泥石流、崩塌以及地面沉降、地面塌陷、地裂等地质灾害的勘查防治工作,采取了包括工程防御体系、生物水保防御体系、管理防护体系,社会管理体系和预测及报警体系在内的综合防御体系,并取得了一定的效果,同时把生态建设与防灾减灾相结合,实施封山育林、退耕还林、退田还湖、退田还草和修建水利工程等一系列措施,极大地防止和减轻了地质灾害的危害和损失。 全国已建立了25片国家级水土流失重点治理区,实施了七大流域水土保持工程,在一万多条水土流失严重的小流域,开展了山水田林综合治理。 先后确立了包括“三北”防护林、长江中上游防护林、沿海防护林、平原农田防护林、淮河太湖流域防护林、珠江流域防护林、辽河流域防护林、黄河中游防护林和太行山绿化工程、防治沙漠化工程的十大林业生态工程。 此外,还发射了“资源一号”、“资源二号”卫星,广泛应用于资源勘查、防灾减灾、地质灾害监测和科学试验等领域。 二、我国防灾减灾科技应用与建设存在的主要问题 1.管理缺乏综合协调 长期以来,我国的灾害管理体制基本是以单一灾种为主、分部门管理的模式,各涉灾管理部门自成系统,各自为战。 由于没有常设的综合管理机构,各灾种之间缺乏统一协调,部门之间缺乏沟通、联动,造成了许多弊端,如缺乏综合系统的法规、技术体系政策与全局的防灾减灾科技发展规划;缺少系统的、连续的防灾减灾思想指导,不利于部门之间协调;缺少综合性的防灾减灾应急处置技术系统;缺少专门为灾害救援的综合型救援专家、技术型队伍;没有形成相对完善的防灾减灾科学技术体系;信息公开和交流渠道不顺畅;资源、信息不能共享;科学决策评估支持系统与财政金融保障制度尚未建立等等,直接影响防灾减灾实效。 2.投入不足 资金渠道单一 全国每年投入到防灾减灾科技研发和应用的经费十分有限,在防灾减灾基础设施建设、科研设备购置、防灾工程建设、防灾减灾基础研究和先进技术推广应用等多方面投入不足。 主要是因为我国防灾减灾科研基本依赖于财政拨款,资金来源渠道单一。 由于防灾减灾科研具有的社会效益远远大于近期经济效益,很难吸引企业资金和社会资金主动投入,造成防灾减灾科技发展和技术推广滞后。 另外,缺少科研成果推广的中间环节与适合防灾减灾工作规律的运行机制,防灾减灾科研成果的转化率低,一些防灾减灾科研成果的推广应用率不足10%,严重影响了全国防灾减灾工作的深入进行,影响了全国防灾减灾工作水平的进一步提高。 3. 科技资源尚待优化配置 我国防灾减灾科技资源主要集中在气象、地震、地质、环保等领域,由于缺乏宏观协调管理及传统的条块分割现状,一方面各领域主要关注本领域的防灾减灾科技发展,研发工作主要局限于解决本领域存在的技术问题,在不同灾种以及防灾减灾的不同环节中,科技资源没有得到合理配置,科技开发与应用水平发展很不平衡,在基础地理信息、救灾设备和队伍建设方面低水平重复建设严重。 另一方面,仪器、设备、资料、数据等都由部门、单位甚至个人所有,不能实现资源共享共用,资源条件不能系统整合形成高效、共享的社会化服务体系,无法形成合力和整体创新优势。 4.防灾减灾科技发展缓慢 一是在不同灾种以及防灾减灾的不同环节中,科技发展与应用水平很不平衡;二是各灾种的应急研究和操作水平差别较大,低水平重复研究较多;三是技术手段和装备落后,监测能力不强,短期预测预报能力还较低;四是缺乏各类灾害的科学评估模型和方法,灾害信息共享应用和评估的技术急需完善;五是对一些重大灾害的认识与防治技术,长期徘徊不前;六是现有科研结合国情实际不够密切,科技整体支撑能力有待提高等。 5. 防灾减灾高水平科技人才匮乏 我国防灾减灾科技人才主要集中在专业管理部门和科研机构中,基层防灾减灾机构普遍缺少技术应用人才,与我国防灾减灾工作重点结合不密切,特别缺乏防灾减灾领域的高层次、高水平的学术技术带头人和工程技术应用人才。 另外,研究经费、待遇等方面条件较差,影响我国防灾减灾科技人才队伍的稳定与发展。 6. 科普宣教力度不够 缺乏统一的防灾减灾科普规划,没有固定的防灾减灾科普教育基地,也缺乏经常性的防灾减灾科普宣传活动,使防灾减灾科普缺乏系统性、连续性,致使我国社会公众防灾减灾知识、防灾减灾意识的科普教育水平较低,全社会对生态环境保护的意识较差,最终影响我三、我国防灾减灾科技支撑的对策建议 1.建立统一综合的防灾减灾组织保障体系 设置统一的具有危机管理性质的防灾减灾综合管理机构,负责对全国防灾减灾工作的大政方针做出决策,逐步实现从部门为主的单一灾种管理体制向政府和部门联动、条块结合的综合应急管理体制转变。 加强科技主管部门与涉灾管理部门的协同,形成跨部门、跨地区、跨学科、多层次、分布式的协同管理职能和机制。 成立集合各灾种、各专业及相关管理部门专家的顾问团体;建立防灾减灾决策的专家咨询系统,为政府防灾减灾决策提供智力支撑。 2. 完善防灾减灾科技进步政策与创新机制 制定科技支撑防灾减灾办法与政策,增加科技投入,在科学研究、技术开发、科技基础设施建设、科技人才培养选拔等方面给予支持;将防灾减灾科普知识纳入国民素质教育体系和工作计划,提高全民防灾减灾意识和能力,在大中小各级学校教育中适当引入防灾减灾课程及读物。 建立高效、合理的防灾减灾科技创新资源配置机制、科技投入机制、成果转化机制、政策激励机制与人才培养机制;加强基础科学和应用科学研究,开展关键技术、共性技术联合攻关;加快科技成果在防灾减灾领域的推广应用。 3. 多渠道增加对防灾减灾的科技投入 将防灾减灾发展所需投入纳入每年科技经费预算,按照一定的使用比例,支持研究开发工作、科技基础设施建设、改善技术装备、参加国际交流等。 并使防灾减灾科技投入的增长幅度不低于科技经费增长的总体水平。 建立社会防灾减灾基金,吸收企业、社会团体、公民及海外人士对防灾减灾的捐赠,按比例将部分基金用于科技投入。 用给予引导资金的方式,促进地方政府增加防灾减灾科技投入,引导技术开发机构与企业投资防灾减灾技术与产品的研发和产业化。 4. 促进防灾减灾科技资源共享平台的建设 借助全国科技基础条件平台的建设,通过制定统一的标准和规范,整合全国各灾害管理部门的分类灾害信息资源,全天候运转监测网;以网络技术为纽带,积极推广应用地理信息系统(GIS)、遥控系统(RS)、全球卫星定位系统(GPS)技术,建设覆盖至全国各乡村的主要灾害实时监测预警系统;充分应用数字化技术及网络技术,综合集成防灾减灾各单位上报的灾情信息,构建包括灾害应急响应、灾害信息分析、灾害救援决策、救援信息反馈等在内的防灾减灾技术及信息资源平台。 5.加强防灾减灾科技能力与科技队伍建设 通过科研体制改革和现代院所制度建设,进行课题制、首席专家负责制和科研经费预算等防灾减灾科技机构科研管理制度建设;鼓励科研与地方防灾减灾需要紧密结合,开展自然灾害综合研究和治理;鼓励科研机构与企业联合研发防灾减灾技术和装备,实现产业化;与管理部门合作,尝试推广先进的防灾减灾技术和管理方法,探索区域防灾减灾综合管理模式;参与重点防灾减灾工程建设、基础设施建设、试验示范区建设。 在培养选拔高层次人才的基础上,大力培训一线工作的防灾减灾技术人员及管理人员,改善基层技术人员的工作生活条件;通过科研项目、激励措施、分配制度、考核选拔等吸引和稳定人才队伍,培育有竞争力的研究群体,加强创新团队建设;培养防灾减灾后备人才,逐步在我国高校中开办防灾减灾专业教育。 6. 加强国内外防灾减灾科技交流与合作 鼓励防灾减灾科研机构、管理部门开展国内外交流合作,获得先进的应用技术及管理经验,追踪最新技术。 在跨国、跨区域的防灾减灾工程建设中,政府应积极协调,为项目实施提供帮助和保障。
asp和jsp有什么区别吗?
总的来讲,JavaSever PagesTM(JSP)和 微软的Active Sever Pages(ASP)在技术方面有许多相似之处。 两者都是为基于WEB应用实现动态交互网页制作提供的技术环境支持。 同等程度上来讲,两者都能够为程序开发人员提供实现应用程序的编制与自带组件设计网页从逻辑上分离的技术。 而且两者都能够替代CGI使网站建设与发展变的较为简单与快捷。 尽管JavaSever Pages 技术和微软的Active Sever Pages在许多方面都有相似的,但仍然存在很多不同之处,其中最本质上的区别在于:两者是来源于不同的技术规范组织,其实现的基础:WEB服务器平台要求不相同。 一、 JSP 技术:开放的技术 JSP和ASP技术明显的不同点:开发人员在对两者各自软件体系设计的深入了解的方式不同。 JSP技术基于平台和服务器的互相独立,输入支持来自广泛的,专门的,各种工具包,服务器的组件和数据库产品开发商所提供。 相比之下,ASP技术主要依赖微软的技术支持。 1、 平台和服务器的独立性 JSP技术依附于一次写入,之后,可以运行在任何具有符合JavaTM语法结构的环境。 取而代之过去依附于单一平台或开发商,JSP技术能够运行在任何WEB服务器上并且支持来自多家开发商提供的各种各样工具包。 由于ASP是基于Activex控件技术提供客户端和服务器端的开发组件,因此ASP技术基本上是局限于微软的操作系统平台之上。 ASP主要工作环境是微软的IIS应用程序结构,又因Activex对象具有平台特性,所以ASP技术不能很容易地实现在跨平台的WEB服务器的工作。 尽管ASP技术通过第三方提供的产品能够得到组件和服务实现跨平台的应用程序,但是Activex对象必须事先放置于所选择的平台中。 2、 开放的开发过程,开放的原代码 SUN应用JAVA社团性过程开发JSP技术。 自从1995年,SUN已经用这种开放过程方法同国际JAVA组织合作开发和修改了JAVA技术与规范。 针对JSP的产品,SUN授权了工具提供商(如Macromedia),结盟公司(如Apache,Netscape),最终用户,协作商及其他。 最近,SUN将最新版本的JSP和JavaTM Servlet(JSP 1.1,JAVA SERVLET 2.2)的原代码发放给Apache,以求JSP与Apache紧密的相互发展。 Apache,SUN和许多其他的公司及个人公开成立一个健壮的咨询机构以便任何公司和个人都能免费取得信息。 (详见:) JSP应用程序界面(API)毫无疑问已经取得成功,并将随JAVA组织不断开放扩大继续完善。 相反,ASP技术仅依靠微软本身的推动,其发展是建立在独占的,封闭的开发过程基础之上。 ASP技术 JSP技术 WEB服务器 微软的IIS或个人WEB服务器 任何WEB服务器包括Apache,Netscape,和IIS 操作系统平台 微软的视窗系统 绝大多数的流行平台,包括solaris操作系统,微软的视窗系统,MAC OS,Linux,及其他UNIX系列平台产品 跨平台访问 需要第三方ASP的引入产品 支持WEB信息机构环境中不同系列的计算机群即保证用户在当前软硬件及人力资源上的投资完全兼容,JSP技术提供灵活,开放选择:可以使用各种各样的工具提供商提供的工具,高度体现工业化标准输入与配置 3、从开发人员的角度来看:ASP和JSP技术都能使开发者实现通过点击网页中的组件制作交互式的,动态的内容和应用程序的WEB站点。 ASP仅支持组件对象模型COM,而JSP技术提供的组件都是基于JavabeansTM技术或JSP标签库。 由此可以看出两者虽有相同之处,但其区别是很明显的。 1) JSP标签可扩充性 尽管ASP和JSP都使用标签与脚本技术来制作动态WEB网页,JSP技术能够使开发者扩展JSP标签得以应用,JSP开发者能定制标签库,所以网页制作者充分利用与XML兼容的标签技术强大的功能,大大减少对脚本语言的依赖。 由于定制标签技术,使网页制作者降低了制作网页和向多个网页扩充关键功能的复杂程度。 2) JSP跨平台的可重用性 JSP的开发人员在开发过程中一直关注可重用性。 JSP组件(企业JavabeansTM,Javabeans,或定制的JSP标签)都是跨平台可重用的。 企业Javabeans组件可以访问传统的数据库,并能以分布式系统模式工作于UNIX和WINDOWS平台。 JSP技术的标签可扩充功能为开发人员提供简便的,与XML兼容的接口即共享网页的打包功能使其完全的工业标准化。 这种基于组件的模式很有效提高应用程序的开发效率,因为这种模式能够使开发人员利用快捷的子组件快速创建模板应用程序,然后再整合一些附加功能以后便可使用。 象这样有效的方法在JSP中无处不在,并可将其打包成一个Javabean或一个工业标准化的Javabean组件。 二、 JAVA的优越性 JSP技术是用JAVA语言作为脚本语言的,而ASP网页使用微软的VBScrip或Jscrip。 JAVA是成熟的,强大的,易扩充的编程语言,远优于基于BASIC的脚本语言。 如:JAVA的可执行性优于VBScript或Jscript语言。 因为它们利用JAVA技术并且都被编译为JAVA Servlets,JSP网页为整个服务器端的JAVA库单元提供了一个接口来服务于HTTP的应用程序。 JAVA使开发人员的工作在其他方面也变的一样容易,简单。 例如,当ASP应用程序在WINDOWS NT系统被怀疑可能会崩溃时,JAVA能有效的防止系统的崩溃。 JAVA语言通过提供防止内存的泄漏的方法,在内存管理方面也能大显身手。 加之,JSP为应用提供了健壮的意外事件处理机制。 1、 易于维护性 基于JSP技术的应用程序比基于ASP的应用程序易于维护和管理。 脚本语言都能很好服务于小的应用程序,但不能适应大型的,复杂的应用程序。 因为,JAVA是结构化的,它比较容易创建和维护庞大的,组件化的应用程序。 JSP突出的组件技术使修改内容而不影响逻辑或修改逻辑而不影响内容变得很容易实现。 企业级的Javabeans结构整合了企业逻辑,例如数据库的访问,安全,事务完整性,及独立性即独立于应用程序。 因为JSP技术是一种开放的,跨平台的结构,因此,WEB服务器,平台,及其他的组件能很容易升级或切换,且不会影响JSP基本的应用程序。 这一特点使JSP能够适用现实世界的各种WEB应用程序不断的变化和发展。 ASP技术 JSP技术 可重用,跨平台组件 没有JAVABEANS 企业级JAVABEANS,定制JSP标签 安全:防范系统崩溃 没有 有 内存泄露保护 没有 有 脚本语言 VBSCRIPT,JSCRIPT JAVA 定制标签 没有 有 2、企业产品的多样性 JAVA2平台即企业版(J2EE)是适用于多企业应用程序的JAVA结构,作为J2EE的部分,JSP网页可访问所有J2EE的组件,包括Javabeans,企业级Javabeans及JAVA Servlets。 JSP网页都能完全编译成为Servlets,所以它们都享有灵活性的特点和为服务器端JAVA应用程序。 J2EE平台内容不仅包括管理复杂的企业应用程序而且包括事务管理技术和Pooling资源管理技术。 JSP网页可以访问标准的J2EE服务,包括: ? JAVA名称和目录界面API ? JDBCTM API(与关联的数据库通讯) ? JavaMailTM(支持基于JAVA邮件和消息应用程序的类) ? JAVATM 消息服务 通过J2EE,JSP网页能够用许多方式同企业系统交互访问。 J2EE支持两种CORBA规范的技术:JAVA IDL和RMI-IIOP。 在企业级JAVABEANS技术支持下,JSP网页通过运用高级的,对象映射的方式访问数据库。 最终,因为JSP技术是基于JAVA的开放性过程的产品,因此它能够广泛支持不同提供商提供的工具,WEB服务器和应用程序的服务,这样能够使用户选择最佳的开发方法,选择最适应他们的应用程序开发的工具包,同时,有效地保护用户在代码和人员培训上的投资。 ASP技术 JSP技术 兼容传统的数据库 可以(COM) 可以(用JDBC API) 集成数据源的能力 能工作在任何符合ODBC规范的数据库 能工作在任何符合ODBC规范的数据库,而且能访问符合JDBC技术规范数据库 组件 COM组件 JAVABEANS,企业级JAVABEANS或扩展的JSP标签 扩展工具支持
要当Java工程师,需要掌握什么技能?
Java工程师需要掌握的技能还是比较多的。 技能傍身才能较好的应对工作,而且不同的Java开发岗位对于面试者的需求也是不一样的。
相关技能可以参考如下:
第一阶段,Java核心基础:
1.深入理解Java面向对象思想
2.掌握开发中常用基础API
3.熟练使用集合框架、IO流、异常
4.能够基于JDK8开发
第二阶段,数据库关键技术
1.掌握最流行关系型数据MySQL常见操作
2.熟练增删改查数据处理
3.掌握Java JDBC、连接池操作
第三阶段,Web网页技术
1.掌握基本的JavaWeb基础知识JSP/Servlet/jQuery等
2.具备基本的B/S结构软件开发能力
3.可以动手开发一个B/S架构的Web项目
第四阶段,开发必备框架&技术
1.掌握SSM框架技术
2.掌握使用Maven进行模块的开发
3.熟悉基本的Linux命令以及Linux服务器的使用
4.掌握高级缓存技术Redis的原理,并熟练使用
第五阶段,互联网高级技术
分布式管理系统、Keepalived+Nginx主备、微服务架构技术、消息中间件技术、MySQL调优、高并发技术、性能优化、内存和GC等
第六阶段,前沿技术&大型企业级项目
edis的原理,并熟练使用
发表评论