微服务网关实战08-聚合服务请求日志及断路

在上一篇中,我们采用resttemplate+ribbon进行后端服务的请求,做数据聚合,但是却发现自定义的请求并没有日志,接下来我们需要做请求日志的记录及加入断路器。

微服务网关实战08-聚合服务请求日志及断路_第1张图片

 

关于日志,我们采用切面来做

日志切面类LogAspect:

/**
 * All rights Reserved, Designed By OprCalf
 * Copyright:    Copyright(C) 2016-2020
 * Company       OprCalf Ltd.
*/

package com.platform.gateway.common.aspect;

import java.util.Arrays;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.extern.apachecommons.CommonsLog;

/**@projectName:  platform-gateway
 * @package:      com.platform.gateway.common.aspect
 * @className:    LogAspect.java
 * @description:  日志切面
 * @author:       OprCalf
 * @date:         2019年5月22日
 */
@Component
@Aspect
@CommonsLog
public class LogAspect {

    @Autowired
    private HttpServletRequest request;

    @Pointcut("execution( * com.platform.*.agg..*Controller.*(..))")
    public void logPointCut() {
    }

    @Before("logPointCut()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 记录下请求内容
        log.info("请求地址 : " + request.getRequestURL().toString());
        log.info("请求方法 : " + request.getMethod());
        log.info("类方法 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        log.info("参数 : " + Arrays.toString(joinPoint.getArgs()));

    }

    @AfterReturning(returning = "ret", pointcut = "logPointCut()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容(返回值太复杂时,打印的是物理存储空间的地址)
        log.info("返回值 : " + ret);
    }

    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        final long startTime = System.currentTimeMillis();
        // ob 为方法的返回值
        final Object ob = pjp.proceed();
        log.info("耗时 : " + (System.currentTimeMillis() - startTime));
        return ob;
    }

}

这样子就完成了,待会我们来实验一下,接下来增加断路器,直接在GetRequest类上新增,更改后的代码如下

/**
 * All rights Reserved, Designed By OprCalf
 * Copyright:    Copyright(C) 2016-2020
 * Company       LengYin Ltd.
 */

package com.platform.gateway.common.request;

import javax.annotation.Resource;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.platform.gateway.common.utils.MsgUtils;

/**
 * @projectName:  platform-gateway
 * @package:      com.platform.gateway.common.request
 * @className:    GetRequest.java
 * @description:  Get请求
 * @author:       OprCalf
 * @date:         2020年3月27日
 */
@Service
@SuppressWarnings("deprecation")
public class GetRequest extends Request {

    @Resource(name = "balanceTemplate")
    private RestTemplate balanceTemplate;

    @Resource(name = "singleTemplate")
    private RestTemplate singleTemplate;

    /**
     * 发送请求到服务端,初始化head里面的user为空
     * @author OprCalf
     * @param serviceAdd
     * @param servicePath
     * @param params
     * @return JSONObject
     */
    @HystrixCommand(fallbackMethod = "failNullUserForJson")
    public JSONObject getNullUserForJson(String serviceAdd, String servicePath) {
        final HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        final HttpEntity requestEntity = new HttpEntity<>("", headers);
        final ResponseEntity response = balanceTemplate.exchange(serviceAdd + servicePath, HttpMethod.GET,
                requestEntity,
                JSONObject.class);
        return JSONObject.parseObject(JSONObject.toJSONString(response.getBody(), Request.filter));
    }

    /**
     * 断路器:发送请求到服务端,初始化head里面的user为空
     * @author OprCalf
     * @date 2019年5月22日
     * @return String
     */
    public JSONObject failNullUserForJson(String serviceAdd, String servicePath) {
        return JSON.parseObject(returnError("请求超时,请稍后再试...").toString());
    }

} 
  

Request类更改,代码如下:

/**
 * All rights Reserved, Designed By OprCalf
 * Copyright:    Copyright(C) 2016-2020
 * Company       LengYin Ltd.
 */

package com.platform.gateway.common.request;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.ValueFilter;

import lombok.extern.slf4j.Slf4j;

/**
 * @projectName:  platform-gateway
 * @package:      com.platform.gateway.common.request
 * @className:    Request.java
 * @description:  请求设置
 * @author:       OprCalf
 * @date:         2020年3月27日
 */
@Service
@Slf4j
public class Request {

    @Autowired
    private HttpServletRequest request;

    /**
     * 重写FastJson的值过滤,当为空值的时候返回"",不然转字符串会直接把属性过滤掉
     * @author OprCalf
     */
    public static ValueFilter filter = (obj, s, v) -> {
        if (v == null) {
            return "";
        }
        return v;
    };

    /**
     * 初始化web的请求头信息
     * @author OprCalf
     * @param needUser
     * @return HttpHeaders
     */
    public HttpHeaders initWebHeader() {
        try {
            final String access_token = request.getHeader("access_token");
            final HttpHeaders headers = new HttpHeaders();
            headers.add("access_token", access_token);
            return headers;
        }
        catch (final Exception e) {
            log.error("{}", e.fillInStackTrace());
            return new HttpHeaders();
        }
    }

    /**
     * 返回错误信息
     * @author OprCalf
     * @param result
     * @return JSONObject
     */
    public static JSONObject returnError(Object result) {
        final JSONObject json = new JSONObject();
        final JSONObject data = new JSONObject();
        json.put("respStatus", "01");
        json.put("respDesc", result);
        json.put("data", data);
        return json;
    }

    /**
     * 返回正确的信息
     * @author OprCalf
     * @param successMsg
     * @param data
     * @return String
     */
    public static JSONObject returnSuccess(String successMsg, Object data) {
        final JSONObject json = new JSONObject();
        json.put("respStatus", "00");
        json.put("respDesc", successMsg);
        json.put("data", data);
        return json;
    }

}

完成了,我们开始测试一下

日志测试:直接调用接口

微服务网关实战08-聚合服务请求日志及断路_第2张图片

 

调用成功,有日志出来。

断路测试:停掉后端服务

微服务网关实战08-聚合服务请求日志及断路_第3张图片

 

返回我们需要的信息,至此聚合服务整合日志,断路器完成。

最后,谢谢观赏,觉得好的话,点个赞,有什么问题可以留言沟通,么么哒。

你可能感兴趣的:(微服务网关,网关)