Prometheus时间序列监控方案

开源项目push 发表了文章 • 0 个评论 • 17 次浏览 • 13 小时前 • 来自相关话题

最近一直在折腾时序类型的数据库,经过一段时间项目应用,觉得十分不错。而Prometheus又是刚刚推出不久的开源方案,中文资料较少,所以打算写一系列应用的实践过程分享一下。
 

Prometheus 是什么?

Prometheus是一套开源的监控&报警&时间序列数据库的组合,起始是由SoundCloud公司开发的。随着发展,越来越多公司和组织接受采用Prometheus,社会也十分活跃,他们便将它独立成开源项目,并且有公司来运作。google SRE的书内也曾提到跟他们BorgMon监控系统相似的实现是Prometheus。现在最常见的Kubernetes容器管理系统中,通常会搭配Prometheus进行监控。

Prometheus 的优点

非常少的外部依赖,安装使用超简单已经有非常多的系统集成 例如:docker HAProxy Nginx JMX等等服务自动化发现直接集成到代码设计思想是按照分布式、微服务架构来实现的
 

Prometheus 的特性

自定义多维度的数据模型非常高效的存储 平均一个采样数据占 ~3.5 bytes左右,320万的时间序列,每30秒采样,保持60天,消耗磁盘大概228G。强大的查询语句轻松实现数据可视化
 
等等, 相对于Graphite这种产品,还是有不少优点的。最让我觉得不错的是非常优秀的写性能和读取性能,它数据结构实现和OpenTSDB是有相似之处,有兴趣可以看看这个文档:解密OpenTSDB的表存储优 。

Prometheus 的系统架构





它的服务过程是这样的 Prometheus daemon 负责定时去目标上抓取 metrics(指标) 数据,每个抓取目标需要暴露一个http服务的接口给它定时抓取。

Prometheus支持通过配置文件、文本文件、zookeeper、Consul、DNS SRV lookup等方式指定抓取目标。
Alertmanager 是独立于Prometheus的一个组件,可以支持Prometheus的查询语句,提供十分灵活的报警方式。
Prometheus支持很多方式的图表可视化,例如十分精美的Grafana,自带的Promdash,以及自身提供的模版引擎等等,还提供HTTP API的查询方式,自定义所需要的输出。

PushGateway这个组件是支持Client主动推送 metrics 到PushGateway,而Prometheus只是定时去Gateway上抓取数据。

如果有使用过statsd的用户,则会觉得这十分相似,只是statsd是直接发送给服务器端,而Prometheus主要还是靠进程主动去抓取。

Prometheus 的数据模型

Prometheus 从根本上所有的存储都是按时间序列去实现的,相同的 metrics(指标名称) 和 label(一个或多个标签) 组成一条时间序列,不同的label表示不同的时间序列。为了支持一些查询,有时还会临时产生一些时间序列存储。
 
metrics name & label 指标名称和标签
每条时间序列是由唯一的 指标名称 和 一组 标签 (key=value)的形式组成。
指标名称 一般是给监测对像起一名字,例如 http_requests_total 这样,它有一些命名规则,可以包字母数字_之类的的。

通常是以应用名称开头_监测对像_数值类型_单位这样, 例如:
push_totaluserlogin_mysql_duration_secondsapp_memory_usage_bytes
 
标签 就是对一条时间序列不同维度的识别了,例如 一个http请求用的是POST还是GET,它的endpoint是什么,这时候就要用标签去标记了, 最终形成的标识便是这样了:http_requests_total{method="POST",endpoint="/api/tracks"}记住,针对http_requests_total这个metrics name 无论是增加标签还是删除标签都会形成一条新的时间序列。
查询语句就可以跟据上面标签的组合来查询聚合结果了。

如果以传统数据库的理解来看这条语句,则可以考虑 http_requests_total是表名,标签是字段,而timestamp是主键,还有一个float64字段是值了。(Prometheus里面所有值都是按float64存储)。

Prometheus 的四种数据类型

Counter:
Counter 用于累计值,例如 记录 请求次数、任务完成数、错误发生次数。一直增加,不会减少。重启进程后,会被重置。
例如:http_response_total{method="GET",endpoint="/api/tracks"} 100
10秒后抓取 http_response_total{method="GET",endpoint="/api/tracks"} 100
Gauge:
Gauge 常规数值,例如 温度变化、内存使用变化。可变大,可变小。重启进程后,会被重置
例如: memory_usage_bytes{host="master-01"} 100 < 抓取值
memory_usage_bytes{host="master-01"} 30
memory_usage_bytes{host="master-01"} 50
memory_usage_bytes{host="master-01"} 80 < 抓取值
Histogram:
Histogram 可以理解为柱状图的意思,常用于跟踪事件发生的规模,例如:请求耗时、响应大小。它特别之处是可以对记录的内容进行分组,提供 count 和 sum 全部值的功能。
例如:{小于10=5次,小于20=1次,小于30=2次},count=7次,sum=7次的求和值



 
Summary:
Summary和Histogram十分相似,常用于跟踪事件发生的规模,例如:请求耗时、响应大小。同样提供 count 和 sum 全部值的功能。例如:count=7次,sum=7次的值求值它提供一个quantiles的功能,可以按%比划分跟踪的结果。例如:quantile取值0.95,表示取采样值里面的95%数据。
 
分享阅读原文:http://www.cnblogs.com/vovlie/p/Prometheus_CONCEPTS.html  查看全部
最近一直在折腾时序类型的数据库,经过一段时间项目应用,觉得十分不错。而Prometheus又是刚刚推出不久的开源方案,中文资料较少,所以打算写一系列应用的实践过程分享一下。
 


Prometheus 是什么?


Prometheus是一套开源的监控&报警&时间序列数据库的组合,起始是由SoundCloud公司开发的。随着发展,越来越多公司和组织接受采用Prometheus,社会也十分活跃,他们便将它独立成开源项目,并且有公司来运作。google SRE的书内也曾提到跟他们BorgMon监控系统相似的实现是Prometheus。现在最常见的Kubernetes容器管理系统中,通常会搭配Prometheus进行监控。


Prometheus 的优点


  • 非常少的外部依赖,安装使用超简单
  • 已经有非常多的系统集成 例如:docker HAProxy Nginx JMX等等
  • 服务自动化发现
  • 直接集成到代码
  • 设计思想是按照分布式、微服务架构来实现的

 


Prometheus 的特性


  • 自定义多维度的数据模型
  • 非常高效的存储 平均一个采样数据占 ~3.5 bytes左右,320万的时间序列,每30秒采样,保持60天,消耗磁盘大概228G。
  • 强大的查询语句
  • 轻松实现数据可视化

 
等等, 相对于Graphite这种产品,还是有不少优点的。最让我觉得不错的是非常优秀的写性能和读取性能,它数据结构实现和OpenTSDB是有相似之处,有兴趣可以看看这个文档:解密OpenTSDB的表存储优 。


Prometheus 的系统架构


prometheus.png

它的服务过程是这样的 Prometheus daemon 负责定时去目标上抓取 metrics(指标) 数据,每个抓取目标需要暴露一个http服务的接口给它定时抓取。

Prometheus支持通过配置文件、文本文件、zookeeper、Consul、DNS SRV lookup等方式指定抓取目标。
Alertmanager 是独立于Prometheus的一个组件,可以支持Prometheus的查询语句,提供十分灵活的报警方式。
Prometheus支持很多方式的图表可视化,例如十分精美的Grafana,自带的Promdash,以及自身提供的模版引擎等等,还提供HTTP API的查询方式,自定义所需要的输出。

PushGateway这个组件是支持Client主动推送 metrics 到PushGateway,而Prometheus只是定时去Gateway上抓取数据。

如果有使用过statsd的用户,则会觉得这十分相似,只是statsd是直接发送给服务器端,而Prometheus主要还是靠进程主动去抓取。


Prometheus 的数据模型


Prometheus 从根本上所有的存储都是按时间序列去实现的,相同的 metrics(指标名称) 和 label(一个或多个标签) 组成一条时间序列,不同的label表示不同的时间序列。为了支持一些查询,有时还会临时产生一些时间序列存储。
 
metrics name & label 指标名称和标签
每条时间序列是由唯一的 指标名称 和 一组 标签 (key=value)的形式组成。
指标名称 一般是给监测对像起一名字,例如 http_requests_total 这样,它有一些命名规则,可以包字母数字_之类的的。

通常是以应用名称开头_监测对像_数值类型_单位这样, 例如:
  1. push_total
  2. userlogin_mysql_duration_seconds
  3. app_memory_usage_bytes

 
标签 就是对一条时间序列不同维度的识别了,例如 一个http请求用的是POST还是GET,它的endpoint是什么,这时候就要用标签去标记了, 最终形成的标识便是这样了:
http_requests_total{method="POST",endpoint="/api/tracks"}
记住,针对http_requests_total这个metrics name 无论是增加标签还是删除标签都会形成一条新的时间序列。
查询语句就可以跟据上面标签的组合来查询聚合结果了。

如果以传统数据库的理解来看这条语句,则可以考虑 http_requests_total是表名,标签是字段,而timestamp是主键,还有一个float64字段是值了。(Prometheus里面所有值都是按float64存储)。


Prometheus 的四种数据类型


Counter:
  • Counter 用于累计值,例如 记录 请求次数、任务完成数、错误发生次数。
  • 一直增加,不会减少。
  • 重启进程后,会被重置。

例如:http_response_total{method="GET",endpoint="/api/tracks"} 100
10秒后抓取 http_response_total{method="GET",endpoint="/api/tracks"} 100

Gauge:
  • Gauge 常规数值,例如 温度变化、内存使用变化。
  • 可变大,可变小。
  • 重启进程后,会被重置

例如: memory_usage_bytes{host="master-01"} 100 < 抓取值
memory_usage_bytes{host="master-01"} 30
memory_usage_bytes{host="master-01"} 50
memory_usage_bytes{host="master-01"} 80 < 抓取值

Histogram:
  • Histogram 可以理解为柱状图的意思,常用于跟踪事件发生的规模,例如:请求耗时、响应大小。它特别之处是可以对记录的内容进行分组,提供 count 和 sum 全部值的功能。

例如:{小于10=5次,小于20=1次,小于30=2次},count=7次,sum=7次的求和值
sum.png

 
Summary:
  • Summary和Histogram十分相似,常用于跟踪事件发生的规模,例如:请求耗时、响应大小。同样提供 count 和 sum 全部值的功能。
  • 例如:count=7次,sum=7次的值求值
  • 它提供一个quantiles的功能,可以按%比划分跟踪的结果。例如:quantile取值0.95,表示取采样值里面的95%数据。

 
分享阅读原文:http://www.cnblogs.com/vovlie/p/Prometheus_CONCEPTS.html 

通过CM启动Hive报错

运维技术koyo 回复了问题 • 2 人关注 • 2 个回复 • 13 次浏览 • 14 小时前 • 来自相关话题

Hive安装配置

大数据/云计算koyo 发表了文章 • 0 个评论 • 14 次浏览 • 15 小时前 • 来自相关话题

相比较于 Apache Hive 而言,Cloudera CDH 将 Hive 拆分为一个个独立的服务,如 hive,metastore,hivesever2等。如果在安装配置之前不能弄清楚各个部分的关系,那么安装过程中出现的各种问题也就不能针对性地解决。因此首先分享一下我个人对于hive,metastore 以及 hiveserve2 之间关系的理解。
 
使用 yum 安装 Cloudera CDH Hive 需要分别安装hive,hive-metastore 和 hive-sever2。其中hive是必须安装的,hive-metastore 和 hive-sever2 则根据要求选择安装。
 
启动 hive 之后出现的 CLI 是查询任务的入口,CLI 提交任务给 DriverDriver 接收到任务后调用 Compiler,Executor,Optimizer 将 SQL 语句转化为可以在 Hadoop 集群上执行的 MapReduce 任务Compiler,Executor 从 metastore 获取所需要的元数据信息hivesever2 作为 hivesever 的改进版本,最主要的变化在于提供了全新的命令行窗口 BeeLine。
 
1、使用 yum 安装 Hive 组件
Hive安装:
 
yum install hive
yum install hive-metastore
yum install hive-server2

2、配置 Hive
创建Hive相关文件的存储路径并更改目录权限
hdfs dfs -mkdir -p /usr/hive/warehouse
hdfs dfs -mkdir -p /usr/hive/tmp
hdfs dfs -mkdir -p /usr/hive/log
hdfs dfs -chmod g+w /usr/hive/warehouse
hdfs dfs -chmod g+w /usr/hive/tmp
hdfs dfs -chmod g+w /usr/hive/log配置环境变量
vim /usr/lib/hive/conf/hive-env.shexport HADOOP_HOME=/usr/lib/hadoop
export HIVE_CONF_DIR=/usr/lib/hive/conf
3、配置 MySQL
Metastore默认使用内嵌的Derby数据库存储元数据信息,同时支持多种数据库可做拓展。官网推荐使用MySQL和PostgreSQL,这里只列出MySQL的具体配置过程,有关PostgreSQL的配置过程可查阅官网。

CentOS 7 默认yum源并未包含mysql,需要首先配置repo源:
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm安装mysql-community-release-el7-5.noarch.rpm包
rpm -ivh mysql-community-release-el7-5.noarch.rpm安装mysql并启动mysql
yum install mysql-server为当前用户分配mysql权限并重启mysql服务
sudo chown -R root:root /var/lib/mysql
service mysqld restart设置root密码
mysql -u rootmysql > use mysql;
mysql > update user set password=password('123456') where user='root';
mysql > exit;创建用于存储元数据的数据库和操作的用户
mysql -uroot -p123456mysql> CREATE DATABASE metastore;
mysql> USE metastore;
mysql> SOURCE /usr/lib/hive/scripts/metastore/upgrade/mysql/hive-schema-0.12.0.mysql.sql;
mysql> CREATE USER 'hive'@'metastore' IDENTIFIED BY '123';
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'hive'@'metastorehost';
mysql> GRANT ALL ON metastore.* TO 'hive'@'metastorehost' IDENTIFIED BY 'hive';
mysql> GRANT ALL ON metastore.* TO 'hive'@'%' IDENTIFIED BY 'hive';
mysql> FLUSH PRIVILEGES;
mysql> ALTER DATABASE metastore CHARACTER SET latin1;
mysql> quit;
4、配置 Hive Metastore
内嵌模式是metastore 的默认模式,使用 Derby 存储元数据信息,但不支持多用户并发对metastore 操作,不建议在实际环境中使用。这里不再赘述。

下面的本地模式和远程模式均需要使用JDBC才能完成metastore和mysql的通信,需要先添加JDBC驱动包。
$ yum install mysql-connector-java
$ ln -s /usr/share/java/mysql-connector-java.jar /usr/lib/hive/lib/mysql-connector-java.jar

所谓的本地模式和远程模式,指的是metastore和hiveserver的位置关系,而和数据库的位置无关,这一点尤为重要。

 
本地模式:
metastore service 和 HiveServer 运行在同一进程,但是数据库运行在独立的进程,也可以将数据库安装在独立的主机上。内嵌的 metastore 服务和数据库通过 JDBC 通信。

配置方式如下:
vim /usr/lib/hive/conf/hive-site.xml添加如下内容
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://mysqlhost/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123</value>
<description>password to use against metastore database</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<!-- base hdfs path -->
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>格式化数据库
cd /usr/lib/hive/bin$ ./schematool --dbType mysql --initSchema
远程模式:
metastore service运行在独立的JVM进程中,通过配置hive.metastore.uris,进而实现HiveServer,Impala 等进程与 metastore 通信。通过配置javax.jdo.option.ConnectionURL,实现 metastore service 和数据库的通信,这点和本地模式是一样的。上述两个配置选项位于$HIVE_HOME/conf/hive-site.xml。

远程模式的主要优点在于管理员不必向每个hive 用户提供数据库的JDBC的登录信息,保证安全性。用户只需要在hive.metastore.uris中添加metastore的Thirft network API(如thrift://192.168.1.1:9083)即可完成所在客户端与服务端的通信,进而获取元数据信息。

所谓客户端,即可以提交查询任务的hive节点;所谓服务端,即为客户端提供metastore service的客户端。这里的客户端分为两类:
1.通过内嵌的metastore服务直接获取元数据
2.通过配置的hive.metastore.uris访问指定的安装hive-metastore的客户端,进而获取元数据,这时被访问的客户端相对于访问的客户端就称为服务端。

 
服务端配置如下,可以注意到这里的配置和本地模式一致。
 
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://mysqlhost/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123</value>
<description>password to use against metastore database</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<!-- base hdfs path -->
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>格式化数据库cd /usr/lib/hive/bin$ ./schematool --dbType mysql --initSchema客户端配置如下:

<!-- thrift://<host_name>:<port> 默认端口是9083 -->
<property>
<name>hive.metastore.uris</name
<value>thrift://metastorehost:9083</value>
<description>Thrift uri for the remote metastore. Used by metastore client to connect to remote metastore.</description>
</property> <!-- hive表的默认存储路径 -->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property> 查看全部
相比较于 Apache Hive 而言,Cloudera CDH 将 Hive 拆分为一个个独立的服务,如 hive,metastore,hivesever2等。如果在安装配置之前不能弄清楚各个部分的关系,那么安装过程中出现的各种问题也就不能针对性地解决。因此首先分享一下我个人对于hive,metastore 以及 hiveserve2 之间关系的理解。
 
使用 yum 安装 Cloudera CDH Hive 需要分别安装hive,hive-metastore 和 hive-sever2。其中hive是必须安装的,hive-metastore 和 hive-sever2 则根据要求选择安装。
 
  • 启动 hive 之后出现的 CLI 是查询任务的入口,CLI 提交任务给 Driver
  • Driver 接收到任务后调用 Compiler,Executor,Optimizer 将 SQL 语句转化为可以在 Hadoop 集群上执行的 MapReduce 任务
  • Compiler,Executor 从 metastore 获取所需要的元数据信息
  • hivesever2 作为 hivesever 的改进版本,最主要的变化在于提供了全新的命令行窗口 BeeLine。

 
1、使用 yum 安装 Hive 组件
Hive安装:
 
yum install hive
yum install hive-metastore
yum install hive-server2

2、配置 Hive
创建Hive相关文件的存储路径并更改目录权限
hdfs dfs -mkdir -p /usr/hive/warehouse
hdfs dfs -mkdir -p /usr/hive/tmp
hdfs dfs -mkdir -p /usr/hive/log
hdfs dfs -chmod g+w /usr/hive/warehouse
hdfs dfs -chmod g+w /usr/hive/tmp
hdfs dfs -chmod g+w /usr/hive/log
配置环境变量
vim /usr/lib/hive/conf/hive-env.sh
export HADOOP_HOME=/usr/lib/hadoop
export HIVE_CONF_DIR=/usr/lib/hive/conf

3、配置 MySQL
Metastore默认使用内嵌的Derby数据库存储元数据信息,同时支持多种数据库可做拓展。官网推荐使用MySQL和PostgreSQL,这里只列出MySQL的具体配置过程,有关PostgreSQL的配置过程可查阅官网。

CentOS 7 默认yum源并未包含mysql,需要首先配置repo源:
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
安装mysql-community-release-el7-5.noarch.rpm包
rpm -ivh mysql-community-release-el7-5.noarch.rpm
安装mysql并启动mysql
yum install mysql-server
为当前用户分配mysql权限并重启mysql服务
sudo chown -R root:root /var/lib/mysql
service mysqld restart
设置root密码
mysql -u root
mysql > use mysql; 
mysql > update user set password=password('123456') where user='root';
mysql > exit;
创建用于存储元数据的数据库和操作的用户
mysql -uroot -p123456
mysql> CREATE DATABASE metastore;
mysql> USE metastore;
mysql> SOURCE /usr/lib/hive/scripts/metastore/upgrade/mysql/hive-schema-0.12.0.mysql.sql;
mysql> CREATE USER 'hive'@'metastore' IDENTIFIED BY '123';
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'hive'@'metastorehost';
mysql> GRANT ALL ON metastore.* TO 'hive'@'metastorehost' IDENTIFIED BY 'hive';
mysql> GRANT ALL ON metastore.* TO 'hive'@'%' IDENTIFIED BY 'hive';
mysql> FLUSH PRIVILEGES;
mysql> ALTER DATABASE metastore CHARACTER SET latin1;
mysql> quit;

4、配置 Hive Metastore
内嵌模式是metastore 的默认模式,使用 Derby 存储元数据信息,但不支持多用户并发对metastore 操作,不建议在实际环境中使用。这里不再赘述。

下面的本地模式和远程模式均需要使用JDBC才能完成metastore和mysql的通信,需要先添加JDBC驱动包。
$ yum install mysql-connector-java
$ ln -s /usr/share/java/mysql-connector-java.jar /usr/lib/hive/lib/mysql-connector-java.jar


所谓的本地模式和远程模式,指的是metastore和hiveserver的位置关系,而和数据库的位置无关,这一点尤为重要。


 
本地模式:
metastore service 和 HiveServer 运行在同一进程,但是数据库运行在独立的进程,也可以将数据库安装在独立的主机上。内嵌的 metastore 服务和数据库通过 JDBC 通信。

配置方式如下:
vim /usr/lib/hive/conf/hive-site.xml
添加如下内容
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://mysqlhost/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123</value>
<description>password to use against metastore database</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<!-- base hdfs path -->
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>
格式化数据库
cd /usr/lib/hive/bin$ ./schematool --dbType mysql --initSchema

远程模式:
metastore service运行在独立的JVM进程中,通过配置hive.metastore.uris,进而实现HiveServer,Impala 等进程与 metastore 通信。通过配置javax.jdo.option.ConnectionURL,实现 metastore service 和数据库的通信,这点和本地模式是一样的。上述两个配置选项位于$HIVE_HOME/conf/hive-site.xml。

远程模式的主要优点在于管理员不必向每个hive 用户提供数据库的JDBC的登录信息,保证安全性。用户只需要在hive.metastore.uris中添加metastore的Thirft network API(如thrift://192.168.1.1:9083)即可完成所在客户端与服务端的通信,进而获取元数据信息。


所谓客户端,即可以提交查询任务的hive节点;所谓服务端,即为客户端提供metastore service的客户端。这里的客户端分为两类:
1.通过内嵌的metastore服务直接获取元数据
2.通过配置的hive.metastore.uris访问指定的安装hive-metastore的客户端,进而获取元数据,这时被访问的客户端相对于访问的客户端就称为服务端。


 
服务端配置如下,可以注意到这里的配置和本地模式一致。
 
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://mysqlhost/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123</value>
<description>password to use against metastore database</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<!-- base hdfs path -->
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>
格式化数据库
cd /usr/lib/hive/bin$ ./schematool --dbType mysql --initSchema
客户端配置如下:

<!-- thrift://<host_name>:<port> 默认端口是9083 --> 
<property>
<name>hive.metastore.uris</name
<value>thrift://metastorehost:9083</value>
<description>Thrift uri for the remote metastore. Used by metastore client to connect to remote metastore.</description>
</property> <!-- hive表的默认存储路径 -->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>

图解Git

回复

运维技术Geek小A 回复了问题 • 1 人关注 • 1 个回复 • 33 次浏览 • 1 天前 • 来自相关话题

Zookeepr参数详解

大数据/云计算Rock 发表了文章 • 0 个评论 • 30 次浏览 • 1 天前 • 来自相关话题

zookeeper的默认配置文件为zookeeper/conf/zoo_sample.cfg,需要将其修改为zoo.cfg。其中各配置项的含义,解释如下:
 
1.tickTime:Client-Server通信心跳时间
tickTime=2000
Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。tickTime以毫秒为单位。2.initLimit:Leader-Follower初始通信时限
initLimit=5
集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量)。3.syncLimit:Leader-Follower同步通信时限
syncLimit=2
集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数(tickTime的数量)。4.dataDir:数据文件目录
dataDir=/data/zookeeper/data
Zookeeper保存数据的目录,默认情况下,Zookeeper将写数据的日志文件也保存在这个目录里。5.clientPort:客户端连接端口
clientPort=2181
客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。6.服务器名称与地址:集群信息(服务器编号,服务器地址,LF通信端口,选举端口)
这个配置项的书写格式比较特殊,规则如下:
server.N=YYY:A:B
server.1=zk1:2888:3888
server.2=zk2:2888:3888
server.3=zk3:2888:38887.ZK为什么设置为奇数个?
zookeeper有这样一个特性:集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的。也就是说如果有2个zookeeper,那么只要有1个死了zookeeper就不能用了,因为1没有过半,所以2个zookeeper的死亡容忍度为0;同理,要是有3个zookeeper,一个死了,还剩下2个正常的,过半了,所以3个zookeeper的容忍度为1;同理你多列举几个:2 -> 0; 3 -> 1; 4 - >1; 5 -> 2; 6 -> 2会发现一个规律,2n和2n-1的容忍度是一样的,都是n-1,所以为了更加高效,何必增加那一个不必要的zookeeper呢。增加处理能力,哈哈。。。 查看全部
zookeeper的默认配置文件为zookeeper/conf/zoo_sample.cfg,需要将其修改为zoo.cfg。其中各配置项的含义,解释如下:
 
1.tickTime:Client-Server通信心跳时间
tickTime=2000
Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。tickTime以毫秒为单位。
2.initLimit:Leader-Follower初始通信时限
initLimit=5
集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量)。
3.syncLimit:Leader-Follower同步通信时限
syncLimit=2 
集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数(tickTime的数量)。
4.dataDir:数据文件目录
dataDir=/data/zookeeper/data
Zookeeper保存数据的目录,默认情况下,Zookeeper将写数据的日志文件也保存在这个目录里。
5.clientPort:客户端连接端口
clientPort=2181
客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
6.服务器名称与地址:集群信息(服务器编号,服务器地址,LF通信端口,选举端口)
这个配置项的书写格式比较特殊,规则如下:
server.N=YYY:A:B
server.1=zk1:2888:3888
server.2=zk2:2888:3888
server.3=zk3:2888:3888
7.ZK为什么设置为奇数个?
zookeeper有这样一个特性:集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的。也就是说如果有2个zookeeper,那么只要有1个死了zookeeper就不能用了,因为1没有过半,所以2个zookeeper的死亡容忍度为0;同理,要是有3个zookeeper,一个死了,还剩下2个正常的,过半了,所以3个zookeeper的容忍度为1;同理你多列举几个:2 -> 0; 3 -> 1; 4 - >1; 5 -> 2; 6 -> 2会发现一个规律,2n和2n-1的容忍度是一样的,都是n-1,所以为了更加高效,何必增加那一个不必要的zookeeper呢。增加处理能力,哈哈。。。

如何列举出git下某个branch下的所有tag名称和注释

运维技术采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 51 次浏览 • 2017-05-17 16:03 • 来自相关话题

MYSQL的不同SQL模式解析

数据库chris 发表了文章 • 0 个评论 • 66 次浏览 • 2017-05-15 23:05 • 来自相关话题

一、Mysql SQL Mode简介

通常来说MySQL服务器能够工作在不同的SQL模式下,并能针对不同的客户端以不同的方式应用这些模式。这样,应用程序就能对服务器操作进行量身定制以满足自己的需求。
 
这类模式定义了MySQL应支持的SQL语法,以及应该在数据上执行何种确认检查。这样,就能在众多不同的环境下、与其他数据库服务器一起更容易地使用MySQL。
 
可以使用" --sql-mode="modes" "选项,通过启动mysqld来设置默认的SQL模式。而从MySQL 4.1开始,也能在启动之后,使用SET [SESSION|GLOBAL] sql_mode='modes'语句,通过设置sql_mode变量更改其模式。
 
通常在linux下安装完mysql后,其默认的sql-mode值是空,在这种情形下mysql执行的是一种不严格的检查,例如日期字段可以插入'0000-00-00 00:00:00'这样的值,还有如果要插入的字段长度超过列定义的长度,那么mysql不会终止操作,而是会自动截断后面的字符继续插入操作,如下例:
mysql> create table t1 (c1 char(3));
mysql> insert into t1 values('abcd');
mysql> select * from t1;
+------+
| c1 |
+------+
| abc |
+------+
1 row in set (0.00 sec)我们发现插入的字符被自动截断了,但是如果我们本意希望如果长度超过限制就报错,那么我们可以设置sql_mode为STRICT_TRANS_TABLES,如下:
mysql> set session sql_mode='STRICT_TRANS_TABLES'这样我们再执行同样的操作,mysql就会告诉我们插入的值太长,操作被终止,如下:
mysql> insert into t1 values('abcd');
ERROR 1406 (22001): Data too long for column 'c1' at row 1
经常使用的sql_mode值:




说明:如果把sql_mode的值设置成后面的两个值(也就是我们说的严格模式),那么当在列中插入或更新不正确的值时,mysql将会给出错误,并且放弃insert/update操作。
 
在我们的一般应用中建议使用这两种模式,而不是使用默认的空或ANSI模式。但是需要注意的问题是,如果数据库运行在严格模式下,并且你的存储引擎不支持事务,那么有数据不一致的风险存在,比如一组sql中有两个dml语句,如果后面的一个出现了问题,但是前面的已经操作成功,那么mysql并不能回滚前面的操作。因此说设置sql_mode需要应用人员权衡各种得失,从而得到一个合适的选择。
 
Sql_mode的值还有很多,这里不再累述,可以参考相关的手册。
 
 

二、SQL Mode与可移植性

如果mysql与其它异构数据库之间有数据移植的需求的话,那么下面的sql_mode的组合设置可以达到相应的效果:




 

三、SQL Mode与数据效验

SQL Mode 还可以实现对数据效验和转移等功能如: 
效验日期数据合法性. 在INSERT或UPDATE过程中,如果被零除(或MOD(X,0)),则产生错误 将‘"'视为识别符引号(‘`'引号字符) 禁用反斜线字符(‘\')做为字符串内的退出字符。启用NO_BACKSLASH_ESCAPES模式,反斜线则成为普通字符。 将||视为字符串连接操作符(+)(同CONCAT()),而不视为OR。 查看全部


一、Mysql SQL Mode简介


通常来说MySQL服务器能够工作在不同的SQL模式下,并能针对不同的客户端以不同的方式应用这些模式。这样,应用程序就能对服务器操作进行量身定制以满足自己的需求。
 
这类模式定义了MySQL应支持的SQL语法,以及应该在数据上执行何种确认检查。这样,就能在众多不同的环境下、与其他数据库服务器一起更容易地使用MySQL。
 
可以使用" --sql-mode="modes" "选项,通过启动mysqld来设置默认的SQL模式。而从MySQL 4.1开始,也能在启动之后,使用SET [SESSION|GLOBAL] sql_mode='modes'语句,通过设置sql_mode变量更改其模式。
 
通常在linux下安装完mysql后,其默认的sql-mode值是空,在这种情形下mysql执行的是一种不严格的检查,例如日期字段可以插入'0000-00-00 00:00:00'这样的值,还有如果要插入的字段长度超过列定义的长度,那么mysql不会终止操作,而是会自动截断后面的字符继续插入操作,如下例:
mysql> create table t1 (c1 char(3));
mysql> insert into t1 values('abcd');
mysql> select * from t1;
+------+
| c1 |
+------+
| abc |
+------+
1 row in set (0.00 sec)
我们发现插入的字符被自动截断了,但是如果我们本意希望如果长度超过限制就报错,那么我们可以设置sql_mode为STRICT_TRANS_TABLES,如下:
mysql> set session sql_mode='STRICT_TRANS_TABLES'
这样我们再执行同样的操作,mysql就会告诉我们插入的值太长,操作被终止,如下:
mysql> insert into t1 values('abcd');
ERROR 1406 (22001): Data too long for column 'c1' at row 1

经常使用的sql_mode值:
sqlmode.png

说明:如果把sql_mode的值设置成后面的两个值(也就是我们说的严格模式),那么当在列中插入或更新不正确的值时,mysql将会给出错误,并且放弃insert/update操作。
 
在我们的一般应用中建议使用这两种模式,而不是使用默认的空或ANSI模式。但是需要注意的问题是,如果数据库运行在严格模式下,并且你的存储引擎不支持事务,那么有数据不一致的风险存在,比如一组sql中有两个dml语句,如果后面的一个出现了问题,但是前面的已经操作成功,那么mysql并不能回滚前面的操作。因此说设置sql_mode需要应用人员权衡各种得失,从而得到一个合适的选择。
 
Sql_mode的值还有很多,这里不再累述,可以参考相关的手册。
 
 


二、SQL Mode与可移植性


如果mysql与其它异构数据库之间有数据移植的需求的话,那么下面的sql_mode的组合设置可以达到相应的效果:
databaseclass.png

 


三、SQL Mode与数据效验


SQL Mode 还可以实现对数据效验和转移等功能如: 
  1. 效验日期数据合法性. 
  2. 在INSERT或UPDATE过程中,如果被零除(或MOD(X,0)),则产生错误 
  3. 将‘"'视为识别符引号(‘`'引号字符) 
  4. 禁用反斜线字符(‘\')做为字符串内的退出字符。启用NO_BACKSLASH_ESCAPES模式,反斜线则成为普通字符。 
  5. 将||视为字符串连接操作符(+)(同CONCAT()),而不视为OR。

​选择云服务器的小窍门有哪些?

大数据/云计算OT学习平台 发表了文章 • 0 个评论 • 57 次浏览 • 2017-05-15 14:59 • 来自相关话题

OTPUB直播活动又双叒叕来喽!
直播主题
老板等等,微软专家找你聊转型!
直播时间
2017年5月16日 14:00-15:00

点击报名>>>
云计算,将云服务器待到了聚光灯下。但选择云服务器是件很困难的事,因为云平台的功能都相差无几。我们货比三家时,建议从细节入手,综合考量,只选对的,不选贵的,选择适配业务需求的云服务器。那么选择云服务器的小窍门有哪些呢?
一、谨记自身需求
云服务器归根到底是为你的业务服务的,因此首先需要明确你对云服务器的需求,比较并评估各种功能,例如虚拟化功能、网络隔离和root权限隔离等。要留意管理和监控处理器、内存、磁盘I/O性能、存储限制等资源管理的功能。确定某个平台能够满足你企业的具体标准之后,再评估成本。
二、网络线路,建议选双线或多线
根据数据中心接入的网络线路,国内云服务器提供电信、联通等单线/双线带宽。建议选择双线。即使你的业务主要面向本地客户群也是如此。因为本地客户的宽带使用状况也不统一,即使中国北方地区也有大量的电信用户。为满足不同网络运营商客户的访问需求,建议选择双线双IP。
三、推荐香港节点
根据部署区域的差异,很多服务商提供国内、香港、韩国、美国等多样化的节点供你选择。国内节点必须备案,美国云服务器连接中国速度慢,因此如果你的业务面向亚太区客户群,个人推荐香港节点。香港节点,一般采用BGP国际多线,支持中国大陆和亚太区极速访问,且大陆南北地区均享高速。更重要的是,香港云服务器免备案,即开即用,你的业务可以最快速度上线,抢占市场先机。如果你的客户群主要分布在北美和欧洲,建议使用美国云服务器。
云服务器
四、云服务器性能测试
选购云服务器前,建议通过性能测试感知云服务器的性能表现(一般很多云服务商都提供测试机型、免费试用、3天无条件退款等,这些都可用于性能测试)。通过对测试IP进行ping、Tracert路由追踪、网站测速工具等可初步把握云服务器的网络连接速度和质量。通过HD Tune等工具测试磁盘性能等。总之,我们需要对云服务器的稳定性、网络稳定性以及软件兼容性等主要方面进行测试,包括云服务器是否宕机、损坏数据恢复能力、是否具备入侵攻击防护、网络延迟和丢包率、软件安装和运行是否正常、软件数据是否兼容等。
以上就是选择云服务器时的小窍门,希望对你有所帮助。最后,我们还要提醒云服务器用户,虽然云服务器拥有多重数据副本、快照备份等机制,但传统的定期本地备份习惯我们也不能丢弃。因为再稳定的云平台也无法保证100%无故障,一旦云平台基础架构出现故障,后果可能是毁灭性的,做好自身网站数据备份并下载到本地保存,是保护我们努力成果的应尽之责,也是防止关键业务数据丢失的最后一道防线。 查看全部
OTPUB直播活动又双叒叕来喽!
直播主题
老板等等,微软专家找你聊转型!
直播时间
2017年5月16日 14:00-15:00

点击报名>>>
云计算,将云服务器待到了聚光灯下。但选择云服务器是件很困难的事,因为云平台的功能都相差无几。我们货比三家时,建议从细节入手,综合考量,只选对的,不选贵的,选择适配业务需求的云服务器。那么选择云服务器的小窍门有哪些呢?
一、谨记自身需求
云服务器归根到底是为你的业务服务的,因此首先需要明确你对云服务器的需求,比较并评估各种功能,例如虚拟化功能、网络隔离和root权限隔离等。要留意管理和监控处理器、内存、磁盘I/O性能、存储限制等资源管理的功能。确定某个平台能够满足你企业的具体标准之后,再评估成本。
二、网络线路,建议选双线或多线
根据数据中心接入的网络线路,国内云服务器提供电信、联通等单线/双线带宽。建议选择双线。即使你的业务主要面向本地客户群也是如此。因为本地客户的宽带使用状况也不统一,即使中国北方地区也有大量的电信用户。为满足不同网络运营商客户的访问需求,建议选择双线双IP。
三、推荐香港节点
根据部署区域的差异,很多服务商提供国内、香港、韩国、美国等多样化的节点供你选择。国内节点必须备案,美国云服务器连接中国速度慢,因此如果你的业务面向亚太区客户群,个人推荐香港节点。香港节点,一般采用BGP国际多线,支持中国大陆和亚太区极速访问,且大陆南北地区均享高速。更重要的是,香港云服务器免备案,即开即用,你的业务可以最快速度上线,抢占市场先机。如果你的客户群主要分布在北美和欧洲,建议使用美国云服务器。
云服务器
四、云服务器性能测试
选购云服务器前,建议通过性能测试感知云服务器的性能表现(一般很多云服务商都提供测试机型、免费试用、3天无条件退款等,这些都可用于性能测试)。通过对测试IP进行ping、Tracert路由追踪、网站测速工具等可初步把握云服务器的网络连接速度和质量。通过HD Tune等工具测试磁盘性能等。总之,我们需要对云服务器的稳定性、网络稳定性以及软件兼容性等主要方面进行测试,包括云服务器是否宕机、损坏数据恢复能力、是否具备入侵攻击防护、网络延迟和丢包率、软件安装和运行是否正常、软件数据是否兼容等。
以上就是选择云服务器时的小窍门,希望对你有所帮助。最后,我们还要提醒云服务器用户,虽然云服务器拥有多重数据副本、快照备份等机制,但传统的定期本地备份习惯我们也不能丢弃。因为再稳定的云平台也无法保证100%无故障,一旦云平台基础架构出现故障,后果可能是毁灭性的,做好自身网站数据备份并下载到本地保存,是保护我们努力成果的应尽之责,也是防止关键业务数据丢失的最后一道防线。

Postfix如何是指支持TLS

运维技术采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 64 次浏览 • 2017-05-12 14:01 • 来自相关话题

华尔街见闻:基于腾讯云容器服务的微服务架构实践

运维技术图灵之歌 发表了文章 • 1 个评论 • 393 次浏览 • 2017-05-09 12:26 • 来自相关话题

简介
华尔街见闻的运营方上海阿牛信息科技有限公司是全球金融信息服务提供商,每天全平台为近200万用户提供资讯、数据、研究等服务。旗舰产品华尔街见闻APP长期位居各应用市场财经资讯类客户端第1位。由于将重大事件、市场的基本面变化和100多种全球资产价格紧密关联,在金融领域具有极高渗透率。首创的7x24快讯模式已经成为在中文世界理解全球市场的最快来源。也因此,该产品有技术架构复杂,需要高并发承载能力等特性。

背景
•老系统日益臃肿
原先的系统是PHP monolithic架构,功能按模块划分,日积月累,最后模块达到60+个,新人接手项目会拿到一整个系统的代码,以及需要整个系统的配置,而他可能只需要专注开发不到1/10的业务。
•伸缩性
我们的主要业务是即时资讯,资讯具有时效性,网站的访问量会呈现锯齿形分布。当遇到特大新闻如英国退欧、美国大选、法国大选等,我们要能弹性地通过增加服务资源,提高服务的容量。
•容错性
我们希望一个低优先级服务出现问题之后,不影响主要服务;一个主要服务能保证更高的可用性,就算出现问题,也要保证优雅降级。
比如在重大事件发生的时候,我们希望文章API保证不会受到影响。
•单体应用
PHP单体应用在生产环境服务的时候,所有业务都跑在一个程序里,增加了系统的脆弱性,一个隐藏的性能问题,能在服务量激增的时候成为压垮骆驼的一根稻草。
•云服务商成本
由于架构落后于需要,我们不得不用硬件弥补性能上的问题,导致云服务器成本不断增加。
•线上运维
由于没有方便的监控和运维工具,导致排查问题的效率低,使得在系统遇到问题的时候排查困难,耗时过长。
•开发新功能
开发新任务的同时,我们需要修复原有系统的性能问题。

PHP monolithic架构图 

每台服务器部署相同的服务端PHP代码,由PHP-fpm解释执行,通过Nginx进行反向代理。
 
华尔街见闻微服务架构设计

因此,在2016年11月至2017年3月,我们采用微服务架构启动重构,尝试解决一部分上述问题,在伸缩性上能以服务为单位进行拓容,同时,这一设计会在某些方面增大我们的开发成本和运维成本。
•错误排查复杂
很显然,以前在单体应用中能直接登录服务器,查看出错日志,现在错误散落在不同的服务中,为我们的错误排查带来了困难。
•日志源增加
如何把服务的日志收集并分析。
•基础设施增加
每个服务有互相独立的MySQL、Redis,公共服务方面需要高可用的服务发现,调用链路分析,日志收集储存设施等。

技术选型

微服务架构图

 每台服务器上均衡地部署服务,LB接受用户的请求,将请求转发到API gateway,API gateway向服务发现查询具体服务的IP和端口,服务执行完业务逻辑后向上返回数据。

服务框架
我们选择golang作为我们的后端开发语言。
•    golang在性能和开发效率上有很好的平衡,语法上很简单,并发编程简单高效,基础库健全。
•    调试工具强大
自带一些pprof包可以profile当前程序的CPU消耗、内存占用、锁状态、channel阻塞等,非常便利我们定位问题。
•    有一些优秀的微服务框架
我们选用go-micro作为开发框架,里面包含几乎所有微服务组件,并且支持非常好的拓展性,通过接口的设计方式,让我们可以拓展一些自己的组件,如服务发现、传输协议等。
•    golang在华尔街见闻已经有过比较多的应用,工程师使用golang开发几乎0学习成本。

服务拆分
拆分的原则是通过服务功能划分,尽量避免双向依赖。我们拆分出了13个服务,包括用户、内容、实时新闻、评论、搜索、商城、支付、三方代理等服务。

服务间通信
服务间使用protobuf协议对数据进行编码,使用UDP作为传输协议。

服务发现
Etcd搭建多节点高可用的服务发现。

服务保护
我们选择Hystrix作为服务保护以及服务降级的方案。
每个服务开发者,需要定义自己服务接口的并发量、超时时间以及fallback方法。

部署方案

我们选择了Kubernetes。 
* Docker Swarm
这是我们最先选择的方案,因为Docker 1.12之后已经将Swarm功能集成到Docker En-gine,能以最少的配置启动Docker集群。经过简化和设计的控制台API,方便地管理集群、调整服务如控制服务的数量、CPU、内存限制等。往集群内加入机器非常简单,只需要运行一条命令即可。使用manager-worker架构,manager作为调度节点,支持高可用。
但遇到了非常致命的问题,比如频繁更新服务的时候会出现服务访问不到,某服务的负载均衡后挂载的服务IP是其它服务的,服务之间的通信有几率出现超时问题,归根结底,还是社区正在不断完善swarm,有很多不稳定的地方,网络方面没有进行优化。
* Kubernetes
这是谷歌主导的服务编排工具,它支持Docker,相比Docker Swarm来说,它的概念更多,分层更细。功能方面多于Docker Swarm,支持一些高级功能如秘钥管理、配置管理、自动拓容等。在生产环境的应用比较广泛,稳定性更高。
* 裸机部署
裸机部署是我们的一个备案,考虑到以上两个方案在当时没有具体线上实施的经验,所以如果Docker Swarm和Kubernetes都没有成功,我们直接裸机部署。
裸机部署的需要解决单机端口冲突,如果一个服务在一个服务器上最多只部署一个,那么可以通过写脚本,并划分服务器角色的方式进行部署,利用ansible可以定义user服务集群、content服务集群、comment服务集群等,通过分发二进制文件的方式让服务启动,这样的方案要考虑到服务更新、服务重启、服务删除等逻辑,同一时间只有部分节点更新,在服务未更新成功的时候流量暂时不能打到正在更新的节点。

准备工作

代码托管
由于之前使用github开发人员的代码提交在有翻墙工具的帮助下速度依然不是很理想,我们自建了Gitlab仓库,自此开发过上了幸福的生活。

容器化
swarm和kubernetes是基于docker快速创建删除服务,通过增加容器为服务拓容,缩减容器为服务缩小规模,所以所有项目必须要构建docker镜像。按项目类型划分,我们遇到3种镜像打包情况。
1.    后端项目
后端服务90%是golang项目,针对golang的镜像,我们采取将golang项目编译成可执行文件,基于最小的alpine镜像打包入docker,这里遇到过一个问题,就是alpine里缺少openssl的证书,无法支持https,我们自定义了新的基础镜像,不仅将证书文件打入镜像,同时为了线上调试方便,增加了tcpdump、strace、bash等工具,在初期调试容器间通信问题时发挥重要的作用。
2.    前端静态文件
见闻的后台以及m站基于Vue,编译后生成的静态文件打入镜像,通过nginx访问。 为了支持HTTP2,我们打入nginx镜像缺少的证书。
3.    服务端渲染
主站PC站基于nodejs、Vue实现服务端渲染,所以不仅需要依赖nodejs,而且需要利用pm2进行nodejs生命周期的管理。为了加速线上镜像构建的速度,我们利用taobao源https://registry.npm.taobao.org进行加速, 并且将一些常见的npm依赖打入了基础镜像,避免每次都需要重新下载,镜像打包从开始的3分钟缩减到1.5分钟。

三类镜像结构
 

持续集成
我们利用Gitlab CI配置了测试、镜像构建、镜像发布、自动部署等流程,后端服务从提交代码到测试分支到测试环境自动部署完成花费1.5分钟,前端服务平均为2.5分钟。

CI任务中的test->build->docker->deploy流程 


云平台的选择
最终,我们选择了腾讯云的容器服务,主要基于以下几点考虑:
•    腾讯云的容器服务是在腾讯云的Iaas上为每个用户构建容器集群,腾讯云提供的微服务架构和持续集成与交付的应用场景基本满足了我们的述求。
•    腾讯云的容器服务是基于Kubernetes实现的,支持完全的kubernetes能力。
•    腾讯云在Kubernetes上实现了他们的存储、负载均衡等产品的插件、复用了腾讯云本身平台的监控、日志等能力。减少了我们接入和开发的成本。

服务在腾讯云的应用
我们将我们的应用重构成微服务的架构,每个微服务部署成腾讯云容器服务上的一个服务,前端接入通过一个负载均衡。后端服务间可互相访问。
服务器安全方面,内部服务器通过VPC进行网络隔离,将网络划分为生产环境、测试环境,在生产环境中又划分backend子网和data子网,设定子网之间的访问规则。
为了禁止内部服务器的外网访问,不给内部服务器分配外网IP,仅通过跳板机访问。

性能对比
利用locust模拟线上请求的比例,利用2台16核的压测机在内网对10台16C32G的机器上的服务进行压测,达到1w/s QPS以上,并且服务的负载并没达到极限,这已经是之前PHP生产环境20+台16C32G服务器能达到的QPS。


线上调用追踪
通过追踪API调用链的流向与耗时,我们可以找出性能的瓶颈。我们通过zipkin实际优化了几种情况:
•    服务调用冗余
当拉取文章列表的时候,我们需要拉取文章对应的作者信息,开始的时候我们使用拉取单个作者信息的方式,后来性能调优阶段,我们将其改为批量拉取作者列表,减少RPC的冗余。
•    服务耗时长
对于有些本身就比较耗时并且对即时性不是那么苛刻的计算服务,我们为了保证服务的响应时间,会适量地加上缓存。

监控与报警
由从外部系统表征到内部日志,我们将监控分为API健康,程序错误报警,以及服务器/容器负载。
排查问题的流程一般有两种情况,一种是用户发现问题,申报问题,开发人员跟进问题;一种是我们的监控优先发现问题,开发人员在用户反馈前跟进并修复。在报警方面,我们通过为监控系统谨慎设置报警阈值,当触发报警时,开发人员会收到邮件。
这里我们在报警的定义上有过思考,即什么样的报警算是有意义的?我们遇到过每天10几条重复的报警,通常开发人员开始时会对报警非常重视,当重复的报警一再出现,渐渐失去了对报警的关注。所以我们有解除一些不必要的报警,并且对剩余一些报警进行调查,甚至有些警报是因为监控工具本身的不准确引起的。

API健康
我们设置默认的时间区间是5分钟
•    统计API五分钟内平均QPS
•    API 98%以内的延迟分布
•    QPS最高的前10的API
•    API的返回码的分布

程序错误报警
后端程序内接入Sentry日志报警系统,golang程序捕获panic日志以及error日志,并发送报警邮件。

服务器/容器负载
通过在服务器上运行telegraf daemon进程,收集服务器metrics并发送给influxdb,使用Grafana作为前端面板,对服务器负载以及容器的平均CPU、内存占用率进行监控。

结束语
本文介绍了华尔街见闻通过重构和服务容器的重新部署,实践微服务架构的情况。经过几个月的开发测试,我们不仅完成了线上服务从PHP到Golang的转型,更在服务的稳定性上经历了考验,支撑了几次重大新闻的高流量。
在开发流程上,搭建了完善的自动化工具,减少了人工操作的重复性和误操作概率。
在运维方面,由于监控系统对系统完整的监控,与Kubernetes健全的上线、下线、回滚、拓容功能配合,能以极快的速度处理线上问题。 查看全部
简介
华尔街见闻的运营方上海阿牛信息科技有限公司是全球金融信息服务提供商,每天全平台为近200万用户提供资讯、数据、研究等服务。旗舰产品华尔街见闻APP长期位居各应用市场财经资讯类客户端第1位。由于将重大事件、市场的基本面变化和100多种全球资产价格紧密关联,在金融领域具有极高渗透率。首创的7x24快讯模式已经成为在中文世界理解全球市场的最快来源。也因此,该产品有技术架构复杂,需要高并发承载能力等特性。

背景
•老系统日益臃肿
原先的系统是PHP monolithic架构,功能按模块划分,日积月累,最后模块达到60+个,新人接手项目会拿到一整个系统的代码,以及需要整个系统的配置,而他可能只需要专注开发不到1/10的业务。
•伸缩性
我们的主要业务是即时资讯,资讯具有时效性,网站的访问量会呈现锯齿形分布。当遇到特大新闻如英国退欧、美国大选、法国大选等,我们要能弹性地通过增加服务资源,提高服务的容量。
•容错性
我们希望一个低优先级服务出现问题之后,不影响主要服务;一个主要服务能保证更高的可用性,就算出现问题,也要保证优雅降级。
比如在重大事件发生的时候,我们希望文章API保证不会受到影响。
•单体应用
PHP单体应用在生产环境服务的时候,所有业务都跑在一个程序里,增加了系统的脆弱性,一个隐藏的性能问题,能在服务量激增的时候成为压垮骆驼的一根稻草。
•云服务商成本
由于架构落后于需要,我们不得不用硬件弥补性能上的问题,导致云服务器成本不断增加。
•线上运维
由于没有方便的监控和运维工具,导致排查问题的效率低,使得在系统遇到问题的时候排查困难,耗时过长。
•开发新功能
开发新任务的同时,我们需要修复原有系统的性能问题。


PHP monolithic架构图 

每台服务器部署相同的服务端PHP代码,由PHP-fpm解释执行,通过Nginx进行反向代理。
 
华尔街见闻微服务架构设计

因此,在2016年11月至2017年3月,我们采用微服务架构启动重构,尝试解决一部分上述问题,在伸缩性上能以服务为单位进行拓容,同时,这一设计会在某些方面增大我们的开发成本和运维成本。
•错误排查复杂
很显然,以前在单体应用中能直接登录服务器,查看出错日志,现在错误散落在不同的服务中,为我们的错误排查带来了困难。
•日志源增加
如何把服务的日志收集并分析。
•基础设施增加
每个服务有互相独立的MySQL、Redis,公共服务方面需要高可用的服务发现,调用链路分析,日志收集储存设施等。


技术选型

微服务架构图

 每台服务器上均衡地部署服务,LB接受用户的请求,将请求转发到API gateway,API gateway向服务发现查询具体服务的IP和端口,服务执行完业务逻辑后向上返回数据。

服务框架
我们选择golang作为我们的后端开发语言。
•    golang在性能和开发效率上有很好的平衡,语法上很简单,并发编程简单高效,基础库健全。
•    调试工具强大
自带一些pprof包可以profile当前程序的CPU消耗、内存占用、锁状态、channel阻塞等,非常便利我们定位问题。
•    有一些优秀的微服务框架
我们选用go-micro作为开发框架,里面包含几乎所有微服务组件,并且支持非常好的拓展性,通过接口的设计方式,让我们可以拓展一些自己的组件,如服务发现、传输协议等。
•    golang在华尔街见闻已经有过比较多的应用,工程师使用golang开发几乎0学习成本。

服务拆分
拆分的原则是通过服务功能划分,尽量避免双向依赖。我们拆分出了13个服务,包括用户、内容、实时新闻、评论、搜索、商城、支付、三方代理等服务。

服务间通信
服务间使用protobuf协议对数据进行编码,使用UDP作为传输协议。

服务发现
Etcd搭建多节点高可用的服务发现。

服务保护
我们选择Hystrix作为服务保护以及服务降级的方案。
每个服务开发者,需要定义自己服务接口的并发量、超时时间以及fallback方法。


部署方案

我们选择了Kubernetes。 
* Docker Swarm
这是我们最先选择的方案,因为Docker 1.12之后已经将Swarm功能集成到Docker En-gine,能以最少的配置启动Docker集群。经过简化和设计的控制台API,方便地管理集群、调整服务如控制服务的数量、CPU、内存限制等。往集群内加入机器非常简单,只需要运行一条命令即可。使用manager-worker架构,manager作为调度节点,支持高可用。
但遇到了非常致命的问题,比如频繁更新服务的时候会出现服务访问不到,某服务的负载均衡后挂载的服务IP是其它服务的,服务之间的通信有几率出现超时问题,归根结底,还是社区正在不断完善swarm,有很多不稳定的地方,网络方面没有进行优化。
* Kubernetes
这是谷歌主导的服务编排工具,它支持Docker,相比Docker Swarm来说,它的概念更多,分层更细。功能方面多于Docker Swarm,支持一些高级功能如秘钥管理、配置管理、自动拓容等。在生产环境的应用比较广泛,稳定性更高。
* 裸机部署
裸机部署是我们的一个备案,考虑到以上两个方案在当时没有具体线上实施的经验,所以如果Docker Swarm和Kubernetes都没有成功,我们直接裸机部署。
裸机部署的需要解决单机端口冲突,如果一个服务在一个服务器上最多只部署一个,那么可以通过写脚本,并划分服务器角色的方式进行部署,利用ansible可以定义user服务集群、content服务集群、comment服务集群等,通过分发二进制文件的方式让服务启动,这样的方案要考虑到服务更新、服务重启、服务删除等逻辑,同一时间只有部分节点更新,在服务未更新成功的时候流量暂时不能打到正在更新的节点。

准备工作

代码托管
由于之前使用github开发人员的代码提交在有翻墙工具的帮助下速度依然不是很理想,我们自建了Gitlab仓库,自此开发过上了幸福的生活。

容器化
swarm和kubernetes是基于docker快速创建删除服务,通过增加容器为服务拓容,缩减容器为服务缩小规模,所以所有项目必须要构建docker镜像。按项目类型划分,我们遇到3种镜像打包情况。
1.    后端项目
后端服务90%是golang项目,针对golang的镜像,我们采取将golang项目编译成可执行文件,基于最小的alpine镜像打包入docker,这里遇到过一个问题,就是alpine里缺少openssl的证书,无法支持https,我们自定义了新的基础镜像,不仅将证书文件打入镜像,同时为了线上调试方便,增加了tcpdump、strace、bash等工具,在初期调试容器间通信问题时发挥重要的作用。
2.    前端静态文件
见闻的后台以及m站基于Vue,编译后生成的静态文件打入镜像,通过nginx访问。 为了支持HTTP2,我们打入nginx镜像缺少的证书。
3.    服务端渲染
主站PC站基于nodejs、Vue实现服务端渲染,所以不仅需要依赖nodejs,而且需要利用pm2进行nodejs生命周期的管理。为了加速线上镜像构建的速度,我们利用taobao源https://registry.npm.taobao.org进行加速, 并且将一些常见的npm依赖打入了基础镜像,避免每次都需要重新下载,镜像打包从开始的3分钟缩减到1.5分钟。

三类镜像结构
 

持续集成
我们利用Gitlab CI配置了测试、镜像构建、镜像发布、自动部署等流程,后端服务从提交代码到测试分支到测试环境自动部署完成花费1.5分钟,前端服务平均为2.5分钟。

CI任务中的test->build->docker->deploy流程 


云平台的选择
最终,我们选择了腾讯云的容器服务,主要基于以下几点考虑:
•    腾讯云的容器服务是在腾讯云的Iaas上为每个用户构建容器集群,腾讯云提供的微服务架构和持续集成与交付的应用场景基本满足了我们的述求。
•    腾讯云的容器服务是基于Kubernetes实现的,支持完全的kubernetes能力。
•    腾讯云在Kubernetes上实现了他们的存储、负载均衡等产品的插件、复用了腾讯云本身平台的监控、日志等能力。减少了我们接入和开发的成本。

服务在腾讯云的应用
我们将我们的应用重构成微服务的架构,每个微服务部署成腾讯云容器服务上的一个服务,前端接入通过一个负载均衡。后端服务间可互相访问。
服务器安全方面,内部服务器通过VPC进行网络隔离,将网络划分为生产环境、测试环境,在生产环境中又划分backend子网和data子网,设定子网之间的访问规则。
为了禁止内部服务器的外网访问,不给内部服务器分配外网IP,仅通过跳板机访问。

性能对比
利用locust模拟线上请求的比例,利用2台16核的压测机在内网对10台16C32G的机器上的服务进行压测,达到1w/s QPS以上,并且服务的负载并没达到极限,这已经是之前PHP生产环境20+台16C32G服务器能达到的QPS。


线上调用追踪
通过追踪API调用链的流向与耗时,我们可以找出性能的瓶颈。我们通过zipkin实际优化了几种情况:
•    服务调用冗余
当拉取文章列表的时候,我们需要拉取文章对应的作者信息,开始的时候我们使用拉取单个作者信息的方式,后来性能调优阶段,我们将其改为批量拉取作者列表,减少RPC的冗余。
•    服务耗时长
对于有些本身就比较耗时并且对即时性不是那么苛刻的计算服务,我们为了保证服务的响应时间,会适量地加上缓存。

监控与报警
由从外部系统表征到内部日志,我们将监控分为API健康,程序错误报警,以及服务器/容器负载。
排查问题的流程一般有两种情况,一种是用户发现问题,申报问题,开发人员跟进问题;一种是我们的监控优先发现问题,开发人员在用户反馈前跟进并修复。在报警方面,我们通过为监控系统谨慎设置报警阈值,当触发报警时,开发人员会收到邮件。
这里我们在报警的定义上有过思考,即什么样的报警算是有意义的?我们遇到过每天10几条重复的报警,通常开发人员开始时会对报警非常重视,当重复的报警一再出现,渐渐失去了对报警的关注。所以我们有解除一些不必要的报警,并且对剩余一些报警进行调查,甚至有些警报是因为监控工具本身的不准确引起的。

API健康
我们设置默认的时间区间是5分钟
•    统计API五分钟内平均QPS
•    API 98%以内的延迟分布
•    QPS最高的前10的API
•    API的返回码的分布

程序错误报警
后端程序内接入Sentry日志报警系统,golang程序捕获panic日志以及error日志,并发送报警邮件。

服务器/容器负载
通过在服务器上运行telegraf daemon进程,收集服务器metrics并发送给influxdb,使用Grafana作为前端面板,对服务器负载以及容器的平均CPU、内存占用率进行监控。

结束语
本文介绍了华尔街见闻通过重构和服务容器的重新部署,实践微服务架构的情况。经过几个月的开发测试,我们不仅完成了线上服务从PHP到Golang的转型,更在服务的稳定性上经历了考验,支撑了几次重大新闻的高流量。
在开发流程上,搭建了完善的自动化工具,减少了人工操作的重复性和误操作概率。
在运维方面,由于监控系统对系统完整的监控,与Kubernetes健全的上线、下线、回滚、拓容功能配合,能以极快的速度处理线上问题。