Java springcloud B2B2C o2o多用户商城 springcloud架构-zuul上做日志处理

由于zuul作为api网关,所有的请求都经过这里,所以在网关上,可以做请求相关的日志处理。

我的需求是这样的,需要记录请求的 url,ip地址,参数,请求发生的时间,整个请求的耗时,请求的响应状态,

甚至请求响应的结果等。

很显然,需要实现这样的一个功能,需要写一个ZuulFliter,它应该是在请求发送给客户端之前做处理,并且在

route过滤器路由之后,在默认的情况下,这个过滤器的order应该为500-1000之间。那么如何获取这些我需要的

日志信息呢?找RequestContext,在请求的生命周期里这个对象里,存储了整个请求的所有信息。

了解springcloud架构可以加求求:三五三六二四七二五九
源码来源
现在编码,在代码的注释中,做了详细的说明,代码如下:

@Component
public class LoggerFilter extends ZuulFilter {
   
    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }
    @Override
    public int filterOrder() {
        return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
    }
    @Override
    public boolean shouldFilter() {
        return true;
    }
    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        String method = request.getMethod();//氢气的类型,post get ..
        Map<String, String> params = HttpUtils.getParams(request);
        String paramsStr = params.toString();//请求的参数
        long statrtTime = (long) context.get("startTime");//请求的开始时间
        Throwable throwable = context.getThrowable();//请求的异常,如果有的话
        request.getRequestURI()//请求的uri
        HttpUtils.getIpAddress(request);//请求的iP地址
        context.getResponseStatusCode();//请求的状态
        long duration=System.currentTimeMillis() - statrtTime);//请求耗时
        return null;
    }
}

现在读者也许有疑问,如何得到的statrtTime,即请求开始的时间,其实这需要另外一个过滤器,在网络请求route之前(大部分耗时都在route这一步),在过滤器中,在RequestContext存储一个时间即可,另写一个过滤器,代码如下:

@Component
public class AccessFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return "pre";
    }
    @Override
    public int filterOrder() {
        return 0;
    }
    @Override
    public boolean shouldFilter() {
        return true;
    }
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.set("startTime",System.currentTimeMillis());
        
        return null;
    }
}

可能还有这样的需求,我需要将响应结果,也要存储在log中,在之前已经分析了,在route结束后,将从具体服务获取的

响应流存储在RequestContext中,在SendResponseFilter过滤器写入在HttpServletResponse中,最终返回给客户端。那么我只需要在SendResponseFilter写入响应流之前把响应流写入到 log日志中即可,那么会引发另外一个问题,因为响应流写入到 log后,RequestContext就没有响应流了,在SendResponseFilter就没有流输入到HttpServletResponse中,导致客户端没有任何的返回数据,那么解决的办法是这样的:

InputStream inputStream =RequestContext.getCurrentContext().getResponseDataStream();
InputStream newInputStream= copy(inputStream);
transerferTolog(inputStream);
RequestContext.getCurrentContext().setResponseDataStream(newInputStream);

从RequestContext获取到流之后,首先将流 copy一份,将流转化下字符串,存在日志中,再set到RequestContext中,
这样SendResponseFilter就可以将响应返回给客户端。这样的做法有点影响性能,如果不是字符流,可能需要做更多的处理工作。
在这里插入图片描述
公司最近升级了电子商务系统,将所有电子商务功能全部转为分布式微服务模式
了解springcloud架构可以加求求:三五三六二四七二五九
在这里插入图片描述
源码来源

发布了93 篇原创文章 · 获赞 93 · 访问量 4283

猜你喜欢

转载自blog.csdn.net/weixin_45821812/article/details/104501196
今日推荐