JStorm是阿里巴巴出品的强大的企业级流式计算引擎,跟Apache Strom相比,具有使用方便、性能高、生态丰富等优点,是搭建流式计算平台的优秀选择。更多关于JStorm的介绍,请参考官方网站http://www.jstorm.io/
但是,部署JStorm依赖于zookeeper、python、JDK等若干个组件,同时还要配置nimbus、supervisor等角色,部署过程比较长。为了简化这一过程,阿里巴巴JStorm团队和容器服务团队合作推出了Docker版的JStorm,可以实现一键部署
创建集群
首先我们需要创建一个集群用来部署JStorm。阿里云容器服务提供集成界面,可以很方便地创建出一个集群来,流程请参考这个帮助文档。需要注意的是,我们需要至少3台机器。
部署zookeeper
为了达到高可用,我们需要部署3个zookeeper节点。传统的方式部署zookeeper时,需要把所有节点的IP作为配置文件;一旦迁移,需要修改配置并重启所有节点。阿里云容器服务提供类似DNS的容器名解析服务,可以把容器名作为配置项,这样迁移时就不需要修改配置了。其编排模板如下:
zk1:
image: 'mesoscloud/zookeeper:3.4.8-ubuntu'
environment:
- MYID=1
- SERVERS=jstorm_zk1_1,jstorm_zk2_1,jstorm_zk3_1
- constraint:aliyun.node_index==1
restart: 'always'
zk2:
image: 'mesoscloud/zookeeper:3.4.8-ubuntu'
environment:
- MYID=2
- SERVERS=jstorm_zk1_1,jstorm_zk2_1,jstorm_zk3_1
- constraint:aliyun.node_index==2
restart: 'always'
zk3:
image: 'mesoscloud/zookeeper:3.4.8-ubuntu'
environment:
- MYID=3
- SERVERS=jstorm_zk1_1,jstorm_zk2_1,jstorm_zk3_1
- constraint:aliyun.node_index==3
restart: 'always'
其中jstorm_zk1_1、jstorm_zk2_1、jstorm_zk3_1就是容器名,其规则是<应用名>_<服务名>_<容器编号>,所以只要确定了应用名和服务名,容器名就是固定的,可以用来做配置项;而且容器名在容器网络内是可以跨主机解析的。
另外,为了使zookeeper节点分布在不同机器上,我们使用了节点约束constraint:aliyun.node_index==n
,n是指集群中节点的序号,这样该容器只会部署在n号节点上。
部署JStorm
阿里巴巴JStorm团队提供了JStorm的Docker镜像https://dev.aliyun.com/detail.html?srepoId=9448,并且会定期更新最新版本。
JStorm有两个角色,Nimbus和Supervisor。从高可用角度考虑,Nimbus需要部署两个,Supervisor可以根据需要配置数量。
同样的,为了让Nimbus分布在不同的机器上,可以指定应用约束affinity:service!=nimbus
,这样nimbus服务的容器只会部署在没有其他nimbus容器的机器上。
另外,supervisor依赖的nimbus地址,也是用容器名来代替的。
JStorm还提供WebUI,默认在8080端口提供服务。阿里云容器服务提供一个简单的方式将Web服务暴露到外网,只需要配置标签aliyun.routing.port_8080: 'http://nimbus'
。该标签的含义是,将nimbus子域名映射到容器的8080端口。更详细的介绍请参考这篇帮助文档。
其编排模板如下:
nimbus:
image: 'registry.cn-hangzhou.aliyuncs.com/jstorm-docker/jstorm'
environment:
- CHARACTER=nimbus
- ZK_ROOT=/jstorm.docker.root2
- ZK_HOSTS=jstorm_zk1_1,jstorm_zk2_1,jstorm_zk3_1
- CLUSTER_NAME=jstorm.docker.cluster
labels:
aliyun.routing.port_8080: 'http://nimbus'
aliyun.scale: '2'
restart: 'always'
supervisor:
image: 'registry.cn-hangzhou.aliyuncs.com/jstorm-docker/jstorm'
environment:
- CHARACTER=supervisor
- NIMBUS_HOSTS=jstorm_nimbus_1
- ZK_ROOT=/jstorm.docker.root2
- ZK_HOSTS=jstorm_zk1_1,jstorm_zk2_1,jstorm_zk3_1
- CLUSTER_NAME=jstorm.docker.cluster
labels:
aliyun.routing.port_8080: 'http://supervisor'
aliyun.scale: '3'
restart: 'always'
links:
- nimbus
一键部署
我们可以把zookeeper和JStorm放在一个编排文件里,实现一键部署。
在这个编排文件中,我们使用了COMPOSE_PROJECT_NAME这个环境变量。COMPOSE_PROJECT_NAME是默认设置的环境变量,其值为当前应用的名称。
zk1:
image: 'mesoscloud/zookeeper:3.4.8-ubuntu'
environment:
- MYID=1
- SERVERS=${COMPOSE_PROJECT_NAME}_zk1_1,${COMPOSE_PROJECT_NAME}_zk2_1,${COMPOSE_PROJECT_NAME}_zk3_1
- constraint:aliyun.node_index==1
restart: 'always'
zk2:
image: 'mesoscloud/zookeeper:3.4.8-ubuntu'
environment:
- MYID=2
- SERVERS=${COMPOSE_PROJECT_NAME}_zk1_1,${COMPOSE_PROJECT_NAME}_zk2_1,${COMPOSE_PROJECT_NAME}_zk3_1
- constraint:aliyun.node_index==2
restart: 'always'
zk3:
image: 'mesoscloud/zookeeper:3.4.8-ubuntu'
environment:
- MYID=3
- SERVERS=${COMPOSE_PROJECT_NAME}_zk1_1,${COMPOSE_PROJECT_NAME}_zk2_1,${COMPOSE_PROJECT_NAME}_zk3_1
- constraint:aliyun.node_index==3
restart: 'always'
nimbus:
image: 'registry.cn-hangzhou.aliyuncs.com/jstorm-docker/jstorm'
environment:
- CHARACTER=nimbus
- ZK_ROOT=/jstorm.docker.root2
- ZK_HOSTS=${COMPOSE_PROJECT_NAME}_zk1_1,${COMPOSE_PROJECT_NAME}_zk2_1,${COMPOSE_PROJECT_NAME}_zk3_1
- CLUSTER_NAME=jstorm.docker.cluster
labels:
aliyun.routing.port_8080: 'http://nimbus'
aliyun.scale: '2'
restart: 'always'
links:
- zk1
- zk2
- zk3
supervisor:
image: 'registry.cn-hangzhou.aliyuncs.com/jstorm-docker/jstorm'
environment:
- CHARACTER=supervisor
- NIMBUS_HOSTS=jstorm_nimbus_1
- ZK_ROOT=/jstorm.docker.root2
- ZK_HOSTS=${COMPOSE_PROJECT_NAME}_zk1_1,${COMPOSE_PROJECT_NAME}_zk2_1,${COMPOSE_PROJECT_NAME}_zk3_1
- CLUSTER_NAME=jstorm.docker.cluster
labels:
aliyun.routing.port_8080: 'http://supervisor'
aliyun.scale: '3'
restart: 'always'
links:
- nimbus
为了保证zookeeper在JStorm之前部署,我们使用了link功能。link除了让容器之间网络互通,还告诉调度器服务之间的依赖关系,调度器会保证被依赖的服务先启动。
生产部署
通过上面的编排文件,我们从容地实现了一键部署JStorm,但在生产上应用,还需要注意一些细节。
- zookeeper默认把持久化数据保存在/tmp/zookeeper中,生产部署时需要把该数据卷映射到指定的主机目录上
- JStorm的WebUI开放到了公网,生产部署时需要使用内网域名或使用内网SLB
- 我们把zookeeper和JStorm部署在了相同的机器上;生产部署时最好隔离开