【Azkaban优化】防止IP变化导致频繁登录
现状
Azkaban的 session 会根据IP地址判断,如果session的IP发生变化,则会遇到session错误。
如果session正确,而ip不正确,则会如下错误:
{
"error": "session"
}
如果正常写业务逻辑,可能要重新登录。那么分布式场景下,多台服务器请求一台Azkaban-Web-server,
会导致什么?如果没有正确缓存session,则会导致反复重复登录。
原因
直接原因,这里发现IP和Session里面的IP不一致,则返回null。
//azkaban.webapp.servlet.LoginAbstractAzkabanServlet#getSessionFromRequest
private Session getSessionFromSessionId(String sessionId, String remoteIp) {
if (sessionId == null) {
return null;
}
Session session = getApplication().getSessionCache().getSession(sessionId);
// Check if the IP's are equal. If not, we invalidate the sesson.
if (session == null || !remoteIp.equals(session.getIp())) {
return null;
}
return session;
}
在上层逻辑中:
//azkaban.webapp.servlet.LoginAbstractAzkabanServlet#doGet
if (session != null) {
//session正常
} else {
if (hasParam(req, "ajax")) {
HashMap<String, String> retVal = new HashMap<String, String>();
retVal.put("error", "session");
this.writeJSON(resp, retVal);
} else {
handleLogin(req, resp);
}
}
解决方案
有如下三种方案:
- 优化代码,每台机器存储自己的session,不要以Azkaban的IP为key存储Azkaban Session
- 在请求Azkaban的Header中加入
X-Forwarded-For
伪装成反向代理,填入固定的IP。 - 在Azkaban中间加入一层nginx反向代理,配置Azkaban的证书,以及固定上述Header。
proxy_set_header X-Real-IP $remote_addr; # 隐藏客户端时修改为 固定IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 隐藏客户端修改 固定IP
修复效果
Azkaban使用了Guava的缓存,只要24小时以内,访问超过一次,有效期就会延续,因此,理论上业务只要不停止,不需要再登录。
进一步说,如果Redis存储了Session,并且在有效期内、没有过期,那么服务重启也不会影响。