记一次大数据跨区域流量排查及修复

网友投稿 738 2022-09-06

记一次大数据跨区域流量排查及修复

记一次大数据跨区域流量排查及修复

最近公司在降成本,发现了欧州、美国区两个区每天存在 ​​300$​​​ 的跨区流量费用,经过运维同学定位后发现绝大部分流量在 ​​emr​​ 机器上。于是排查就开始了。

前言

首先附上我们的任务调度架构

我们大数据计算使用的是​​AWS​​​ 的​​EMR(Elastic MapReduce)​​​ 集群,由于​​AWS EMR​​​ 天然支持读写​​S3​​​,并且​​S3​​​ 相比较硬盘尤其便宜,所以我们的离线数据都是存储在​​S3​​。即:计算与存储分离的架构。任务调度与开发平台使用的是​​赫拉任务调度​​​,关于为什么选择这款开源调度系统是因为:为了节省费用我们的离线EMR集群只是在任务执行时创建使用,任务执行结束后自动销毁,刚好赫拉任务调度支持动态​​EMR​​​ 的创建并且支持弹性伸缩配置,还可以使用​​SSH​​​ 和直接在​​hadoop​​ 机器上两种方式提交任务。

下面介绍下,为何我们产生了跨区域的外网流量。通过前言的叙述,大家都知道了我们是计算存储分离的架构,我们美国区、欧洲区都是一样的。本来是美国区的任务提交在美国区的 ​​AWS EMR​​​ 集群,存储在美国区的​​S3 bucket​​​,欧洲区的任务提交在欧洲区的 ​​AWS EMR​​​ 集群,存储在欧洲区的​​S3 bucket​​​。但是由于已离职的某位同事为别人建库时,美国库的 ​​location​​​ 建在了欧洲的​​S3 bucket​​​,也就导致了美国的 ​​EMR​​​ 集群计算时读、写使用的数据都来自于欧洲的 ​​S3​​​.跨区域的流量就是这样产生的。最后通过S3提供的数据迁移工具,然后批量修改表的 ​​location​​ 解决掉跨区域的流量,下面附上排查的过程和修复方法。

原因排查

当运维发现我们美国区 ​​EMR​​​ 机器跨区域的流量较大时,运维定位了一台机器给我,顺便问了下欧洲 ​​s3​​​ 的网关地址。 于是我立刻登录上我们的 ​​​EMR​​​ 机器一顿乱操作。。 首先使用 ​​​netstat​​​ 命令加上 ​​-p​​ 参数定位到哪个进程在请求欧洲的网关地址

[root@ip-172-21-31-215 hadoop]# netstat -anop | grep 52.219tcp 54 0 ::ffff:172.21.11.21:40484 ::ffff:52.219.11.21:443 ESTABLISHED 15428/java off (0.00/0/0)

从结果中可以看出,进程 ​​id​​​ 为 ​​15428​​​ 的 ​​java​​​ 进程在与欧洲网关地址通信。继续使用ps命令查看 ​​15428​​是什么任务

[root@ip-172-21-31-215 hadoop]# ps aux | grep 15428yarn 15428 127 3.6 4101284 582660 ? Sl 03:35 2:23 /usr/lib/jvm/java-openjdk/bin/java -server -Xmx2048m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:MaxHeapFreeRatio=70 -XX:+CMSClassUnloadingEnabled -XX:OnOutOfMemoryError=kill -9 %p -Djava.io.tmpdir=/mnt/yarn/usercache/hadoop/appcache/application_1586846714065_1434/container_1586846714065_1434_01_000002/tmp -Dspark.history.ui.port=18080 -Dspark.port.maxRetries=256 -Dspark.driver.port=37217 -Dspark.yarn.app.container.log.dir=/var/log/hadoop-yarn/containers/application_1586846714065_1434/container_1586846714065_1434_01_000002 org.apache.spark.executor.CoarseGrainedExecutorBackend --driver-url spark://CoarseGrainedScheduler@ip-172-21-30-200.eu-central-1.compute.internal:37217 --executor-id 1 --hostname ip-172-21-31-215.eu-central-1.compute.internal --cores 2 --app-id application_1586846714065_1434 --user-class-path file:/mnt/yarn/usercache/hadoop/appcache/application_1586846714065_1434/container_1586846714065_1434_01_000002/__app__.jarroot 18696 0.0 0.0 110520 2196 pts/0 S+ 03:37 0:00 grep --color=auto 15428

原来是 ​​spark​​​ 任务的一个​​container​​​,定位到他的 ​​app id​​​为​​application_1586846714065_1434​​​。然后使用 ​​yarn application -list​​​ 命令查看​​application_1586846714065_1434​​​ 的 ​​name​​

[root@ip-172-21-31-215 hadoop]# yarn application -list | grep application_1586846714065_1434

​​赫拉任务调度​​​提交的 ​​spark sql​​​ 任务都会为其重命名为任务的 ​​id​​​ 便于定位问题。通过上面的结果,我们可以清楚的看到是赫拉为 ​​1082​​​ 的任务在请求跨区域流量。通过在​​赫拉任务调度​​​平台上直接搜索1082就定位到是哪个脚本在执行任务了。最后我发现是算法库的整个库的 ​​location​​​ 建在了欧洲区的 ​​s3​​。

hive> show create database sucx_algorithm;OKCREATE DATABASE `sucx_algorithm`LOCATION 's3://sucx-big-data-eu/bi/sucx_algorithm'Time taken: 0.539 seconds, Fetched: 3 row(s)hive>

找到了原因,剩下就是如何迁移。

迁移数据

迁移涉及到 ​​s3​​​ 数据的迁移和 ​​hive​​​ 元数据的迁移。 首先我要知道默认情况下 ​​​AWS EMR​​​ 的元数据是存储在 ​​GLUE​​​ 的,由于​​GLUE​​​ 没调研到如何查元数据信息,原本是打算直接使用 ​​jdbc​​​ 连接​​hiveserver2​​​ 进行 ​​show create table​​​ 来获取表的 ​​location​​​ 的。刚刚好我们今天要迁移 ​​hive​​​ 元数据 ​​glue​​​ 到 ​​mysql​​​(迁移的方式是:获取所有的建库语句,建表语句,在新的 ​​mysql​​​ 元数据集群上执行建库、建表脚本,然后再​​msck repair table​​​ 修复表即可),所以直接查询元数据库获取所有要迁移表的 ​​location​​ 即可。

准备工作

首先获取要迁移的库的表所有 ​​location​​​ 第一步: 首先从 ​​DBS​​ 中获取库的 ​​DB_ID​​

mysql> select * from DBS where NAME='sucx_algorithm';+-------+------+-----------------------------------------+----------------+------------+------------+| DB_ID | DESC | DB_LOCATION_URI | NAME | OWNER_NAME | OWNER_TYPE |+-------+------+-----------------------------------------+----------------+------------+------------+| 31 | NULL | s3://sucx-big-data-eu/bi/sucx_algorithm | sucx_algorithm | hadoop | USER |+-------+------+-----------------------------------------+----------------+------------+------------+1 row in set (0.00 sec)

第二步: 执行以下 ​​​sql​​​ 查询 ​​sucx_algorithm​​​ 库的所有表名和表对应的LOCATION,并把其结果存到一个文档(可以通过​​mysql -hurl -uuser -Dmetastore -ppass -e "$sql" >location.txt​​来存储)

SELECT TB.TBL_NAME, SDS.LOCATIONFROM ( SELECT TBL_NAME, SD_ID FROM TBLS WHERE DB_ID = 31 ) TBLEFT JOIN SDS ON TB.SD_ID = SDS.SD_ID

第二步产生的文档格式应该是如下:

TBL_NAME

LOCATION

table1

s3://sucx-big-data-eu/bi/sucx_algorithm/ table1

table2

s3://sucx-big-data-eu/bi/sucx_algorithm/ table2

table3

s3://sucx-big-data-eu/bi/sucx_algorithm/ table3

s3数据迁移与对比

​​s3​​​ 的数据要从欧洲区域的 ​​bucket​​​ 迁移到美国区域的 ​​bucket​​​,直接使用​​s3​​​提供的工具即可,由于我这里没有 ​​s3​​ 的操作权限,就不再演示。

关于迁移数据的对比,我是使用的​​hadoop fs -du -s​​​ 命令来检测的,检测大小的路径为准备工作中的 ​​location​​​ 和其切换到美国后的 ​​location​​。

元数据的修改

元数据修改语句为​​alter table tableName set location 's3://sucx-big-data-us/bi/sucx_algorithm/tableName'​​

库location的修改

​​sucx_algorithm​​​ 的库的 ​​location​​​ 无法通过 ​​alter​​​ 语句修改,所以我是直接更新的 ​​DBS​​ 元数据表。

总结

上面的 ​​s3​​ 数据迁移与对比与元数据的修改我使用了一个脚本来生成

//元数据库生成的表名和location的数据 File file = new File("/Users/scx/Desktop/location.txt"); try (BufferedReader br = new BufferedReader(new FileReader(file))) { String line; StringBuilder shells = new StringBuilder("#!/bin/bash\n"); int start = 0; int end = 10000; int index = 0; //是生成alter table的sql文件还是生成对比eu/us的文件大小的脚本 boolean alterSql = false; while ((line = br.readLine()) != null) { if (index >= end) { break; } if (start > index++) { continue; } String[] pair = line.split("\\s"); String tableName = pair[0]; String euLocation = pair[1]; //美国区的location String usLocation = euLocation.replace("s3://sucx-big-data-eu/bi/", "s3://sucx-big-data-us/bi/"); if(alterSql) { shells.append("alter table sucx_algorithm.").append(tableName).append(" set location '").append(usLocation).append("';\n"); } else { shells.append("euSize=$(hadoop fs -du -s ").append(euLocation).append(" | awk '{print $1}')\n"); shells.append("usSize=$(hadoop fs -du -s ").append(usLocation).append(" | awk '{print $1}')\n"); shells.append("echo euSize is $euSize,usSize is $usSize,the index is ").append(index).append("\n"); shells.append("if [ $euSize -ne $usSize ]; then").append("\n"); shells.append(" echo ").append(euLocation).append(" not eq ").append(usLocation).append("\n"); shells.append(" exit 1").append("\n"); shells.append("fi").append("\n"); } } System.out.println(shells.toString()); } catch (IOException e) { e.printStackTrace(); }

对于生成的​​alter sql​​​,我会全部 ​​copy​​​ 到一个 ​​alter.sql​​​ 文件中,然后使用​​hive -f​​​ 命令来修改所有表的​​location​​​。 对于生成的大小对比脚本,由于执行较慢,我会使用定义的 ​​​start​​​ 和 ​​end​​ 变量来进行切分,来提高对比的速度。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:自动生成流水线号(流水号自动生成器)
下一篇:程序员加班有罪吗?
相关文章

 发表评论

暂时没有评论,来抢沙发吧~