接到一个新的任务。要求系统的实时性比较好,
- 需要在100毫秒内得到返回。
- 需要basic auth验证。
开始就使用了spring security。配置了一个basic auth。并且使用了HandlerInterceptor来记录了服务的执行时间。在调试过后发现,本地和服务器上面运行良好。都在几十毫秒的程度就可以返回。
但是在压力测试的过程中发现了问题,好多都是500毫秒左右。开始怀疑是网络或者是网关的问题。在一步步排除以后发现应该是spring security filter执行的时间不稳定,并且拖累的系统的性能。
后来就手动写了一个basic auth的filter来实现这部分功能。并移除了spring security的依赖。然后发现系统运行的时间变得非常的好。
@Order(1)
@WebFilter(urlPatterns = { "/api/*" })
public class BasicAuthFilter implements Filter {
@Value("${services.username:username}")
private String userName;
@Value("${services.password:password}")
private String password;
final Base64.Decoder decoder = Base64.getDecoder();
private String[] authMethods = { "POST", "GET" };
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest instanceof HttpServletRequest && servletResponse instanceof HttpServletResponse) {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (!needAuth(request.getMethod())) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
response.setCharacterEncoding("UTF-8");
String authorization = request.getHeader("authorization");
if (authorization == null || authorization.equals("")) {
reject(response);
return;
}
String userAndPass = new String(decoder.decode(authorization.split(" ")[1]));
String[] info = userAndPass.split(":");
if (info.length < 2) {
reject(response);
return;
}
String user = info[0];
String pass = info[1];
if (user.equals(userName) && pass.equals(password)) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
reject(response);
}
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
private void reject(HttpServletResponse response) {
response.setStatus(401);
response.setHeader("WWW-authenticate", "Basic realm=\"Please ask the administrator for the username and password.\"");
}
private boolean needAuth(String httpMethod) {
for (String method : authMethods) {
if (StringUtils.equalsAnyIgnoreCase(method, httpMethod)) {
return true;
}
}
return false;
}
}