最近有反馈这样一个问题:通过note book给livy提交代码片段,无论代码有没有执行完毕,超过1小时后,作业都会被强制kill掉。
这里就需要了解到livy对session的超时管理机制,在livy里面,对于每一次来自客户的的请求,比如发送一个代码片段过来执行,整个过程称为一个session过程。
也就是说livy里面管理的session代表的就是和某一个客户端的链接,和yarn里面的app并不完全一对一的关联,也不和spark context完全一对一的关联,虽然大部分情况下都是一对一
比如极端情况,完全可以在自己的代码里面再造一个作业或者spark context出来。
回到livy的session的管理上来说,session有这样的状态:

def apply(s: String): SessionState = s match {
case "not_started" => NotStarted
case "starting" => Starting
case "recovering" => Recovering
case "idle" => Idle
case "running" => Running
case "busy" => Busy
case "shutting_down" => ShuttingDown
case "error" => Error()
case "dead" => Dead()
case "killed" => Killed()
case "success" => Success()
case _ => throw new IllegalArgumentException(s"Illegal session state: $s")
}

livy会在livy server中维护session的状态机,这个状态和livy在处理timeout的时候,非常有关系,看下livy关于timeout的默认配置:

// How long to check livy session leakage
val YARN_APP_LEAKAGE_CHECK_TIMEOUT = Entry("livy.server.yarn.app-leakage.check-timeout", "600s")
// how often to check livy session leakage
val YARN_APP_LEAKAGE_CHECK_INTERVAL = Entry("livy.server.yarn.app-leakage.check-interval", "60s")

// Whether session timeout should be checked, by default it will be checked, which means inactive
// session will be stopped after "livy.server.session.timeout"
val SESSION_TIMEOUT_CHECK = Entry("livy.server.session.timeout-check", true)

// Whether session timeout check should skip busy sessions, if set to true, then busy sessions
// that have jobs running will never timeout.
val SESSION_TIMEOUT_CHECK_SKIP_BUSY = Entry("livy.server.session.timeout-check.skip-busy", false)

// How long will an inactive session be gc-ed.
val SESSION_TIMEOUT = Entry("livy.server.session.timeout", "1h")

// How long a finished session state will be kept in memory
val SESSION_STATE_RETAIN_TIME = Entry("livy.server.session.state-retain.sec", "600s")

// Max creating session in livyServer
val SESSION_MAX_CREATION = Entry("livy.server.session.max-creation", 100)

里面有几个很有意思的参数,基本上看参数就明白,关于timeout的逻辑,我在这里总结一下就是:

默认每隔1小时,livy会把所有的session都关掉,也就是无论作业有没有结束,超过一小时,session都会被关掉,对于长作业来说,这个行为其实是不合理的。

livy也提供了配置项:livy.server.session.timeout-check 如果为false则永不过期。
livy.server.session.timeout-check.skip-busy 如果为true则在每次超时轮询检查的时候,会跳过正处于busy状态的session,这样可以用在长时作业下,那么就需要搞清楚,什么是busy状态。

当一个代码片段发送过来后,确认session处于running状态:

if (statement.state.get() == StatementState.Running) {
statement.started = System.currentTimeMillis()
statement.output = executeCode(interpreter(tpe), statementId, code)
}

则会开始执行代码:

private def executeCode(interp: Option[Interpreter],
executionCount: Int,
code: String): String = {
changeState(SessionState.Busy)
..........省略其他代码

这里会将状态修改为busy,也就是如果一个session正在有代码片段执行,那么当前session就会标记为busy。

所以如果需要运行大作业,那么建议修改skip busy为true。


扫码手机观看或分享: