微服務網關實戰08-聚合服務請求日誌及斷路

在上一篇中,我們採用resttemplate+ribbon進行後端服務的請求,做數據聚合,但是卻發現自定義的請求並沒有日誌,接下來我們需要做請求日誌的記錄及加入斷路器。

微服務網關實戰08-聚合服務請求日誌及斷路

 

關於日誌,我們採用切面來做

日誌切面類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<Object> requestEntity = new HttpEntity<>("", headers);
        final ResponseEntity<JSONObject> 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-聚合服務請求日誌及斷路

 

調用成功,有日誌出來。

斷路測試:停掉後端服務

微服務網關實戰08-聚合服務請求日誌及斷路

 

返回我們需要的信息,至此聚合服務整合日誌,斷路器完成。

最後,謝謝觀賞,覺得好的話,點個贊,有什麼問題可以留言溝通,麼麼噠。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章