Livy:Spark REST 服务详解
·
一、Livy 架构与核心概念
1.1 Livy 整体架构
text
Livy 架构组成: ┌─────────────────────────────────────────────────┐ │ Livy Server │ ├─────────────────────────────────────────────────┤ │ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │ │ │ REST API │ │ Session Mgmt│ │ Job Mgmt │ │ │ │ Layer │ │ │ │ │ │ │ └─────────────┘ └─────────────┘ └───────────┘ │ ├─────────────────────────────────────────────────┤ │ ┌─────────────────────────────────────────────┐ │ │ │ Spark Integration │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │ Interactive │ Batch │ │ Spark │ │ │ │ │ │ Sessions │ │ Jobs │ │ Context │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ └─────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────┤ │ ┌─────────────────────────────────────────────┐ │ │ │ Cluster Manager Integration │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │ YARN │ │ Standalone│ │ Kubernetes │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ └─────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────┘
1.2 核心概念解析
1.2.1 Session 类型
java
public enum SessionKind {
SPARK, // 交互式Spark会话
PYSPARK, // 交互式PySpark会话
SPARKR, // 交互式SparkR会话
SQL // 交互式Spark SQL会话
}
1.2.2 Job 执行模式
java
public class JobSubmitRequest {
private String file; // 应用jar包或py文件
private String className; // 主类名
private List<String> args; // 命令行参数
private Map<String, String> conf; // Spark配置
private String driverMemory; // Driver内存
private String executorMemory; // Executor内存
private Integer numExecutors; // Executor数量
}
二、Livy 安装与配置
2.1 环境准备与安装
2.1.1 系统要求
bash
# 依赖检查 java -version # Java 8+ spark-submit --version # Spark 2.0+ curl --version # HTTP客户端 # 下载Livy wget https://archive.apache.org/dist/incubator/livy/0.7.1-incubating/livy-0.7.1-incubating-bin.zip unzip livy-0.7.1-incubating-bin.zip cd livy-0.7.1-incubating
2.1.2 基础配置
properties
# livy.conf 基础配置 livy.server.host = 0.0.0.0 livy.server.port = 8998 livy.spark.master = yarn livy.spark.deploy-mode = cluster # 安全配置 livy.server.auth.type = kerberos livy.server.access.control.enabled = true # 会话管理 livy.server.session.timeout = 2h livy.server.session.max-creation = 10
2.2 高级配置选项
2.2.1 资源管理配置
properties
# 资源队列配置 livy.server.yarn.queue = default livy.server.yarn.app-lookup-timeout = 2m # 动态资源分配 livy.server.dynamic-allocation.enabled = true livy.server.dynamic-allocation.min-executors = 1 livy.server.dynamic-allocation.max-executors = 50 livy.server.dynamic-allocation.executor-idle-timeout = 60s # 内存配置 livy.server.spark.driver.memory = 2g livy.server.spark.executor.memory = 4g livy.server.spark.executor.cores = 2
2.2.2 高可用配置
properties
# ZooKeeper 高可用 livy.server.ha.enabled = true livy.server.zk.connection.string = zk1:2181,zk2:2181,zk3:2181 livy.server.zk.session.timeout = 180s # 状态恢复 livy.server.recovery.state-store = filesystem livy.server.recovery.state-store.url = hdfs:///livy/recovery
三、REST API 详解
3.1 Session 管理 API
3.1.1 创建会话
bash
# 创建Spark会话
curl -X POST -H "Content-Type: application/json" \
-d '{
"kind": "spark",
"name": "my-spark-session",
"conf": {
"spark.executor.memory": "4g",
"spark.executor.cores": "2"
},
"executorMemory": "4g",
"executorCores": 2,
"numExecutors": 5
}' \
http://livy-server:8998/sessions
# 响应示例
{
"id": 0,
"state": "starting",
"kind": "spark",
"log": [],
"appId": null,
"appInfo": {},
"owner": "user1"
}
3.1.2 会话状态管理
bash
# 获取会话列表 curl http://livy-server:8998/sessions # 获取特定会话信息 curl http://livy-server:8998/sessions/0 # 获取会话日志 curl http://livy-server:8998/sessions/0/log # 删除会话 curl -X DELETE http://livy-server:8998/sessions/0
3.2 代码执行 API
3.2.1 执行Spark代码
bash
# 执行Scala代码
curl -X POST -H "Content-Type: application/json" \
-d '{
"code": "val rdd = sc.parallelize(1 to 1000)\nrdd.sum()"
}' \
http://livy-server:8998/sessions/0/statements
# 执行SQL查询
curl -X POST -H "Content-Type: application/json" \
-d '{
"code": "spark.sql(\"SELECT * FROM table WHERE date = '\''2023-01-01'\''\").show()"
}' \
http://livy-server:8998/sessions/0/statements
3.2.2 异步执行与状态查询
bash
# 异步执行代码
response=$(curl -s -X POST -H "Content-Type: application/json" \
-d '{"code": "sc.parallelize(1 to 1000000).count()"}' \
http://livy-server:8998/sessions/0/statements)
statement_id=$(echo $response | jq -r '.id')
# 查询执行状态
curl http://livy-server:8998/sessions/0/statements/$statement_id
# 获取执行结果
curl http://livy-server:8998/sessions/0/statements/$statement_id/result
3.3 Batch Job 管理 API
3.3.1 提交批处理作业
bash
# 提交Spark作业
curl -X POST -H "Content-Type: application/json" \
-d '{
"file": "hdfs:///apps/spark-job.jar",
"className": "com.example.SparkJob",
"args": ["input_path", "output_path"],
"name": "daily-etl-job",
"conf": {
"spark.sql.shuffle.partitions": "200",
"spark.dynamicAllocation.enabled": "true"
},
"driverMemory": "4g",
"executorMemory": "8g",
"numExecutors": 10
}' \
http://livy-server:8998/batches
# 响应示例
{
"id": 1,
"state": "starting",
"appId": null,
"appInfo": {},
"log": [],
"owner": "user1"
}
3.3.2 批处理作业管理
bash
# 获取批处理作业列表 curl http://livy-server:8998/batches # 获取特定作业信息 curl http://livy-server:8998/batches/1 # 获取作业日志 curl http://livy-server:8998/batches/1/log # 删除作业 curl -X DELETE http://livy-server:8998/batches/1
四、多租户与安全配置
4.1 用户认证与授权
4.1.1 Kerberos 集成
properties
# Kerberos 配置 livy.server.auth.type = kerberos livy.server.auth.kerberos.principal = livy/_HOST@EXAMPLE.COM livy.server.auth.kerberos.keytab = /etc/security/keytabs/livy.service.keytab livy.server.auth.kerberos.name.rules = DEFAULT
4.1.2 LDAP 集成
properties
# LDAP 认证配置 livy.server.auth.type = ldap livy.server.auth.ldap.url = ldap://ldap-server:389 livy.server.auth.ldap.baseDN = ou=users,dc=example,dc=com livy.server.auth.ldap.uidAttribute = uid
4.2 资源隔离与配额管理
4.2.1 多租户资源隔离
properties
# 基于用户的资源队列映射 livy.server.user.queue.mapping = \ user1:analytics-queue, \ user2:batch-queue, \ *:default-queue # 用户资源限制 livy.server.user.session.max = 5 livy.server.user.job.max = 10 livy.server.user.memory.max = 16g livy.server.user.cores.max = 20
4.2.2 队列资源限制
properties
# YARN队列资源配置 livy.server.yarn.queue.capacity.analytics = 40 livy.server.yarn.queue.capacity.batch = 30 livy.server.yarn.queue.capacity.interactive = 30 # 队列级别资源限制 livy.server.queue.analytics.max-cores = 100 livy.server.queue.analytics.max-memory = 200g
五、性能优化与监控
5.1 性能调优配置
5.1.1 连接池优化
properties
# HTTP连接池配置 livy.server.http.max-connections = 100 livy.server.http.max-connections-per-route = 20 livy.server.http.connection-timeout = 30s livy.server.http.socket-timeout = 300s # 线程池配置 livy.server.thread-pool.min-size = 10 livy.server.thread-pool.max-size = 100 livy.server.thread-pool.keepalive-time = 60s
5.1.2 会话管理优化
properties
# 会话缓存配置 livy.server.session.cache.enabled = true livy.server.session.cache.size = 1000 livy.server.session.cache.expiry-time = 30m # 心跳检测 livy.server.session.heartbeat.timeout = 10m livy.server.session.heartbeat.interval = 1m
5.2 监控与告警
5.2.1 Prometheus 监控配置
yaml
# prometheus.yml 配置
scrape_configs:
- job_name: 'livy'
metrics_path: '/metrics'
static_configs:
- targets: ['livy-server:8998']
relabel_configs:
- source_labels: [__address__]
target_label: instance
# 关键监控指标
alerting:
groups:
- name: livy-alerts
rules:
- alert: LivySessionOverload
expr: livy_sessions_active > 50
for: 5m
labels:
severity: warning
annotations:
summary: "Livy sessions overload"
5.2.2 健康检查端点
bash
# 健康检查 curl http://livy-server:8998/healthz # 指标端点 curl http://livy-server:8998/metrics # 服务器信息 curl http://livy-server:8998/info
六、客户端集成与示例
6.1 Python 客户端示例
6.1.1 使用 livy-client
python
from livy import LivySession, LivyBatch
# 创建会话
session = LivySession(
host="livy-server",
port=8998,
kind="pyspark",
conf={
"spark.executor.memory": "4g",
"spark.executor.cores": "2"
}
)
# 执行代码
result = session.run("""
df = spark.read.parquet("hdfs:///data/events")
df.groupBy("date").count().show()
""")
print(result.output)
# 关闭会话
session.close()
6.1.2 提交批处理作业
python
from livy import LivyClient
client = LivyClient("http://livy-server:8998")
# 提交批处理作业
batch = client.submit_batch(
file="hdfs:///apps/etl-job.py",
args=["2023-01-01", "hdfs:///output/20230101"],
name="daily-etl",
conf={
"spark.sql.shuffle.partitions": "200",
"spark.dynamicAllocation.enabled": "true"
}
)
# 等待作业完成
batch.wait_for_completion()
# 获取作业状态
print(f"Job state: {batch.state}")
print(f"Application ID: {batch.app_id}")
6.2 Java 客户端示例
6.2.1 使用 Livy Java Client
java
import org.apache.livy.LivyClient;
import org.apache.livy.LivyClientBuilder;
// 创建Livy客户端
LivyClient client = new LivyClientBuilder()
.setURI(new URI("http://livy-server:8998"))
.build();
// 提交Scala代码
String code = "val rdd = sc.parallelize(1 to 1000000)\n" +
"rdd.sum()";
Object result = client.submit(new SparkJob(code)).get();
System.out.println("Result: " + result);
// 提交批处理作业
Map<String, String> conf = new HashMap<>();
conf.put("spark.executor.memory", "4g");
conf.put("spark.executor.cores", "2");
client.submit(new BatchJob()
.setFile("hdfs:///apps/spark-job.jar")
.setClassName("com.example.SparkJob")
.setArgs(Arrays.asList("input", "output"))
.setConf(conf)
).get();
client.stop(true);
七、故障排查与最佳实践
7.1 常见问题排查
7.1.1 日志分析
bash
# 查看Livy服务器日志 tail -f /var/log/livy/livy-server.log # 查看会话日志 curl http://livy-server:8998/sessions/0/log # 查看YARN应用日志 yarn logs -applicationId application_123456789_0001 # 调试模式启动 LIVY_DEBUG=true ./bin/livy-server
7.1.2 性能问题排查
bash
# 监控会话状态
curl http://livy-server:8998/sessions | jq '.sessions[] | {id, state, owner}'
# 检查资源使用
yarn application -list | grep livy
# 网络连接测试
telnet livy-server 8998
7.2 最佳实践指南
7.2.1 会话管理最佳实践
python
# 使用会话池避免频繁创建
class SessionPool:
def __init__(self, max_sessions=10):
self.sessions = []
self.max_sessions = max_sessions
def get_session(self):
if not self.sessions:
return self.create_session()
return self.sessions.pop()
def return_session(self, session):
if len(self.sessions) < self.max_sessions:
self.sessions.append(session)
else:
session.close()
# 使用上下文管理器确保资源释放
@contextmanager
def livy_session():
session = LivySession(...)
try:
yield session
finally:
session.close()
7.2.2 错误处理与重试
python
import requests
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def submit_to_livy(code, session_id):
response = requests.post(
f"http://livy-server:8998/sessions/{session_id}/statements",
json={"code": code},
timeout=30
)
response.raise_for_status()
return response.json()
# 使用示例
try:
result = submit_to_livy("sc.parallelize(1 to 100).count()", 0)
except requests.exceptions.RequestException as e:
print(f"Failed to submit code: {e}")
# 实现重试或fallback逻辑
通过以上详细的配置、API说明和最佳实践,可以充分发挥Livy作为Spark REST服务网关的能力,构建高效、稳定的大数据处理平台。
更多推荐



所有评论(0)