引言

 
数据平台目前通过Hive SQL的方式提供数据分析服务,系统使用多台HiveServer(JDBCServer)接收客户端连接请求,实际使用场景中频频出现HiveServer内存消耗过多导致机器Swap过高,需要重启HiveServer来缓解问题,但在某些任务比较集中的时间段往往会导致大量任务执行失败(我们配备了相应的任务重试机制,但也会带来一定的影响)。
 
在与运维同学的流通过程中,偶然提到是否可能某台HiveServer接收的连接请求过多,执行过程中负担过重引起的(暂不考虑其它可能因素),引出如下思考:
 
(1)目前平台内置两种HiveServer选择算法:随机选择器(通过随机数对HiveServer数目取余)、哈希选择器(通过UUID的哈希值对HiveServer数目取余),目前采用随机选择器;
(2)目前平台两个模块需要与HiveServer频繁交互:作业管理、数据查询,随着业务发展还会有其它逐步衍生其它模块;
 
问题:随机(哈希)选择算法仅仅考虑单个模块内连接的均衡,而且没有考虑HiveServer正在执行的语句条数(表示繁忙程度,粒度比较粗),在这样的场景下确实可能会出现某台HiveServer在特殊时段内负担相对较重。
 
思路
 
当需要与HiveServer建立连接时,应该有一个接口能够给出当前所有HiveServer各自的工作负载情况(根据当前正在执行的SQL语句条数判断),选择工作负载最低的HiveServer进行连接。
 
因为一次连接存在期间,可以执行多条SQL语句,而且多个模块的存在,在每个模块内置入代码是非常不方便的,因此考虑在HiveServer内部实现。
 
实现
 
要给出当前所有HiveServer各自的工作负载情况,就需要有数据源提供当前所有HiveServer各自正在执行哪些SQL语句(条数),因此HiveServer在执行语句之前、之后需要能够给出相应通知,并持久化到数据源,依据该数据源中的实时数据,即可计算工作负载。
 
假设数据源为MySQL,我们至少需要这样的一张表:
 
server HiveServer名称,同一台机器可以开启多个HiveServer实例
hook PRE_EXEC_HOOK、POST_EXEC_HOOK,分别表示语句执行开始之前、执行线束之后
queryId HiveServer内部语句唯一ID
queryStr 具体执行语句,可根据语句复杂度计算工作负载
jobName 平台自己设置,我们仅仅考虑会转化为MR任务的语句,jobName即为MR JobName
preTime 语句执行之前的时间戳
postTime 语句执行之后的时间戳
 
问题:HiveServer如何在执行语句之前、之后发出相应的通知?
 
我们使用Hive Hook机制,需要实出接口ExecuteWithHookContext,核心代码如下:
 
         QueryPlan queryPlan = hookContext.getQueryPlan();

		HiveConf conf = hookContext.getConf();

		String queryId = queryPlan.getQueryId();

		if (StringUtils.isEmpty(queryId)) {
LOGGER.warn("queryId is null or empty, return"); return;
} LOGGER.info("queryId: " + queryId); String queryStr = URLEncoder.encode(queryPlan.getQueryStr(),
CharEncoding.UTF_8); if (StringUtils.isEmpty(queryStr)) {
LOGGER.warn("queryStr is null or empty, return"); return;
} LOGGER.info("queryStr: " + queryStr); String jobName = conf.getVar(HiveConf.ConfVars.HADOOPJOBNAME); LOGGER.info("jobName: " + jobName); if (StringUtils.isEmpty(jobName)) {
LOGGER.warn("jobName is null or empty, return"); return;
} String server = conf.get("hiveserver.execute.hook.server"); if (StringUtils.isEmpty(server)) {
LOGGER.warn("server is null or empty, return"); return;
} LOGGER.info("server: " + server); String rest = conf.get("hiveserver.execute.hook.rest"); LOGGER.info("rest: " + rest); if (StringUtils.isEmpty(rest)) {
LOGGER.warn("rest is null or empty, return"); return;
} Map<String, String> params = new HashMap<String, String>(); params.put("server", server); params.put("hook", hookContext.getHookType().toString()); params.put("queryId", queryId); params.put("queryStr", queryStr); params.put("jobName", jobName); params.put("timestamp", String.valueOf(DatetimeUtil.now())); try {
HttpClientUtil.doPost(rest, params);
} catch (Exception e) {
LOGGER.error("do post error: "
+ ExceptionUtils.getFullStackTrace(e));
}

  

 
可以看出,该Hook同时可以用于PreHook与PostHook,而且为了保持代码的“轻量级”,并没有直接进行数据的持久化,而是通过Rest API交由外部模块处理。
 
此外需要在hive-site.xml文件中进行相应的设置,如下:
 
 
启动HiveServer时,需要指定该实例的名称与具体的Rest API地址,如下:
 
hive --service hiveserver --hiveconf hiveserver.execute.hook.server=localhost:10000 --hiveconf hiveserver.execute.hook.rest=http://localhost:8088/rest/hiveserver/send
 
总结
 
通过以上的机制可以获取到所有(指定)HiveServer当前(时段内)正在执行的语句条数(如果只有PreTime值,而PostTime值为Null,则表示该条语句正在执行),依此可以计算各自的工作负载,从而选取工作负载最小的HiveServer进行连接。
 
后期进一步优化时还可以充分利用JobName,平台每次执行查询任务时均会设置mapred.job.name属性,用以统计一次查询(可以有多条SQL语句)所处理的数据量、消耗的时间等信息,可以利用这些历史数据信息,用于估计当前正在执行的SQL语句的可能消耗时间,进行优化工作负载的计算。

HiveServer连接优化的更多相关文章

  1. mysql优化之连接优化(open-files-limit与table_open_cache)

    MySQL打开的文件描述符限制 Can't open file: '.\test\mytable.frm' (errno: 24) OS error code : Too many open file ...

  2. mysql优化之连接优化

    Posted by Money Talks on 2012/02/23 | 第一篇 序章第二篇 连接优化第三篇 索引优化第四篇 查询优化第五篇 到实战中去 连接优化 连接优化主要指客户端连接数据库以及 ...

  3. MySQL优化二(连接优化和缓存优化)

    body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10 ...

  4. 百度APP移动端网络深度优化实践分享(二):网络连接优化篇

    本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<二>连接优化>,感谢原作者的无私分享. 一.前言 在<百度APP移动端网 ...

  5. 【mysql 优化 5】左连接和右连接优化

    原文地址:8.2.1.8 Left Join and Right Join Optimization mysql以下列方式实现一个A left join B 连接条件: 1,表B设置为依赖于表A和A所 ...

  6. MySQL实验 内连接优化order by+limit 以及添加索引再次改进

    MySQL实验 内连接优化order by+limit 以及添加索引再次改进 在进行子查询优化双参数limit时我萌生了测试更加符合实际生产需要的ORDER BY + LIMIT的想法,或许我们也可以 ...

  7. 网络编程Netty IoT百万长连接优化

    目录 IoT推送系统 IoT是什么 IoT推送系统的设计 心跳检测机制 简述心跳检测 心跳检测机制代码示例 百万长连接优化 连接优化代码示例 TCP连接四元组 配置优化 IoT推送系统 IoT是什么 ...

  8. http连接优化

    http连接的性能优化 并行连接(能够同一时候和多台server建立HTTP连接) 持久连接 管道化连接 复用的连接 并行连接 长处: 并行连接能够在带宽资源充足的情况下同一时候建立多个HTTP连接, ...

  9. 【mysql 优化 4】嵌套连接优化

    原文地址:Nested Join Optimization 与SQL标准相比,table_factor的语法被扩展.后者仅接受table_reference,而不是一对括号内的列表.如果我们将tabl ...

随机推荐

  1. iOS教你轻松打造瀑布流Layout

    前言 : 在写这篇文章之前, 先祝贺自己, 属于我的GitHub终于来了. 这也是我的GitHub的第一份代码, 以下文章的代码均可以在Demo clone或下载. 欢迎大家给予意见. 觉得写得不错的 ...

  2. 通过GitHub Pages建立个人站点(详细步骤)

    1 Git简介 2 为什么使用Github Pages 3 创建Github Pages 3.1 安装git工具. 3.2 两种pages模式 3.3 创建步骤 3.4 常用命令 4 使用Jekyll ...

  3. Android进阶笔记01:Android 网络请求库的比较及实战(一)

    在实际开发中,有的时候需要频繁的网络请求,而网络请求的方式很多,最常见的也就那么几个.本篇文章对常见的网络请求库进行一个总结. 一.使用HttpUrlConnection: 1. HttpUrlCon ...

  4. post 封装Map 发送请求

    package com.j1.weixin.util; import java.io.IOException; import java.util.Map; import java.util.Set; ...

  5. 一道在知乎很火的 Java 题——如何输出 ab【转】

    这是一个源自知乎的话题,原贴链接:一道百度的面试题,有大神会嘛? 虽然我不是大神,但我也点进去看了一下,思考了一会之后有了一些思路,然后去看其它人的答案的时候果然全都已经被各路大神们先想到并贴出来了, ...

  6. dede织梦后台页面及功能修改及精简操作方法

    先让我们来看看都有哪些页面控制着后台的功能和显示.下方为系统默认的后台界面图,为了便于下面的说明我对各个部分进行了一些标示.共A.B.C.D.E五个区域. 常用:A区域[顶部LOGO行]对应文件:/d ...

  7. ASP.NET 5服务

    ASP.NET5已经把web服务从应用程序当中解耦出来了,它支持IIS和IIS Express, 用Kestrel和WebListener自宿主,另外,开发都或者第三方软件提供商都可以自定义开发ASP ...

  8. 新建android系统服务

    一.Android系统服务 Android提供了很多系统服务:如ActivityManger,PowerManger,WindowManger,WifiManger等等. 这些服务都是系统启动开始就一 ...

  9. oracle 添加表分区

    alter table DF_WRITE_FILES_H add partition DF_WRITE_FILES_H96 values less than (201512) tablespace T ...

  10. Linux2.6的所有内核版本

    Index of /pub/linux/kernel/v2.6 Name Last modified Size Parent Directory - incr/ 03-Aug-2011 20:47 - ...