国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Gateway全局異常處理及請求響應監(jiān)控

這篇具有很好參考價值的文章主要介紹了Gateway全局異常處理及請求響應監(jiān)控。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

我們在上一篇文章基于壓測進行Feign調(diào)優(yōu)完成的服務間調(diào)用的性能調(diào)優(yōu),此時我們也關注到一個問題,如果我們統(tǒng)一從網(wǎng)關調(diào)用服務,但是網(wǎng)關因為某些原因報錯或者沒有找到服務怎么辦呢?

如下所示,筆者通過網(wǎng)關調(diào)用account服務,但是account服務還沒起來。此時請求還沒有到達account就報錯了,這就意味著我們服務中編寫的@RestControllerAdvice對網(wǎng)關沒有任何作用。

curl 127.0.0.1:8090/account/getByCode/zsy

響應結果如下,可以看到響應結果如下所示,要知道現(xiàn)如今的開發(fā)模式為前后端分離模式,前后端交互完全是基于協(xié)商好的格式,如果網(wǎng)關響應格式與我們規(guī)定的格式完全不一致,前端就需要特殊處理,這使得代碼不僅會變得丑陋,對于后續(xù)的功能擴展的交互復雜度也會增加,而gateway默認響應錯誤如下:

{
    "timestamp":"2023-02-09T15:22:20.278+0000",
    "path":"/account/getByCode/zsy",
    "status":500,
    "error":"Internal Server Error",
    "message":"Connection refused: no further information: /192.168.43.73:9000"
}

gateway 如何處理后端微服務返回的json,微服務,微服務,gateway

網(wǎng)關異常默認處理

所以我們必須了解一下是什么原因導致網(wǎng)關報錯會響應這個值。

我們在gateway源碼中找到ErrorWebFluxAutoConfiguration這個自動裝配類,可以看到下面這段代碼,我們從中得知網(wǎng)關報錯時默認使用DefaultErrorWebExceptionHandler 來返回結果,所以我們不妨看看這個類做了那些事情。

@Bean
	@ConditionalOnMissingBean(value = ErrorWebExceptionHandler.class, search = SearchStrategy.CURRENT)
	@Order(-1)
	public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
	//網(wǎng)關默認異常處理的handler
		DefaultErrorWebExceptionHandler exceptionHandler = new DefaultErrorWebExceptionHandler(errorAttributes,
				this.resourceProperties, this.serverProperties.getError(), this.applicationContext);
		exceptionHandler.setViewResolvers(this.viewResolvers);
		exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
		exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
		return exceptionHandler;
	}

我們不妨基于debug了解一下這個類,當我們服務沒有注冊到nacos,并通過網(wǎng)關調(diào)用報錯時,代碼就會走到下方,route 方法第一個參數(shù)是RequestPredicate謂詞,而后者則是謂詞的處理,進行renderErrorViewandRoute同理將報錯的請求通過renderErrorResponse返回錯誤結果

@Override
//route 方法第一個參數(shù)是RequestPredicate謂詞,而后者則是謂詞的處理,進行renderErrorView,然后通過然后通過andRoute將報錯的請求通過renderErrorResponse返回錯誤結果
	protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
		return route(acceptsTextHtml(), this::renderErrorView).andRoute(all(), this::renderErrorResponse);
	}

我們不妨看看renderErrorResponse,可以看到一行getErrorAttributes,一旦步入我們就可以看到上文請求錯誤的結果格式

protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
		boolean includeStackTrace = isIncludeStackTrace(request, MediaType.ALL);
		Map<String, Object> error = getErrorAttributes(request, includeStackTrace);
		return ServerResponse.status(getHttpStatus(error)).contentType(MediaType.APPLICATION_JSON_UTF8)
				.body(BodyInserters.fromObject(error));
	}

getErrorAttributes源碼,可以看到組裝的key值就是我們調(diào)試時響應的參數(shù):

@Override
	public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
		Map<String, Object> errorAttributes = new LinkedHashMap<>();
		errorAttributes.put("timestamp", new Date());
		errorAttributes.put("path", request.path());
		Throwable error = getError(request);
		HttpStatus errorStatus = determineHttpStatus(error);
		errorAttributes.put("status", errorStatus.value());
		errorAttributes.put("error", errorStatus.getReasonPhrase());
		errorAttributes.put("message", determineMessage(error));
		handleException(errorAttributes, determineException(error), includeStackTrace);
		return errorAttributes;
	}

自定義異常處理

了解的默認錯誤處理,我們就可以改造,返回一個和普通服務一樣的格式給前端告知網(wǎng)關報錯。從上文我們可知網(wǎng)關默認錯誤處理時DefaultErrorWebExceptionHandler,通過類圖我們可以發(fā)現(xiàn)它繼承了一個ErrorWebExceptionHandler,所以我們也可以繼承這個類重寫一個Handler。

gateway 如何處理后端微服務返回的json,微服務,微服務,gateway

以筆者的代碼如下,可以看到筆者使用Order注解強制獲得最高異常處理優(yōu)先級,然后使用bufferFactory.wrap方法傳遞自定義錯誤格式返回給前端。



@Slf4j
@Order(-1)
@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GlobalErrorWebExceptionHandler implements ErrorWebExceptionHandler {

    private final ObjectMapper objectMapper;

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();
        if (response.isCommitted()) {
            return Mono.error(ex);
        }

        // 設置返回值類型為json
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

        //設置返回編碼
        if (ex instanceof ResponseStatusException) {
            response.setStatusCode(((ResponseStatusException) ex).getStatus());
        }

        return response.writeWith(Mono.fromSupplier(() -> {
            DataBufferFactory bufferFactory = response.bufferFactory();
            try {
                //writeValueAsBytes 組裝錯誤響應結果
                return bufferFactory.wrap(objectMapper.writeValueAsBytes(ResultData.fail(500, "網(wǎng)關捕獲到異常:" + ex.getMessage())));
            } catch (JsonProcessingException e) {
                log.error("Error writing response", ex);
                return bufferFactory.wrap(new byte[0]);
            }
        }));
    }
}

最終返回的結果如下所示,可以看到結果和一般的服務調(diào)用報錯格式一模一樣,這樣一來前端就無需為了網(wǎng)關報錯加一個特殊處理的邏輯了

curl 127.0.0.1:8090/account/getByCode/zsy

輸出結果

{
    "status":500,
    "message":"網(wǎng)關捕獲到異常:503 SERVICE_UNAVAILABLE \"Unable to find instance for account-service\"",
    "data":null,
    "success":false,
    "timestamp":1675959617386
}

請求響應日志監(jiān)控

對于微服務架構來說,監(jiān)控是很重要的,在高并發(fā)場景情況下,很多問題我們都可以在網(wǎng)關請求響應中定位到,所以我們希望能有這么一種方式將用戶日常請求響應的日志信息記錄下來,便于日常運維和性能監(jiān)控。

查閱了網(wǎng)上的資料發(fā)現(xiàn),基于MongoDB進行網(wǎng)關請求響應數(shù)據(jù)采集是一種不錯的方案,所以筆者本篇文章整理一下筆者如何基于網(wǎng)關過濾器結合MongoDB完成請求日志采集。

本篇文章可能會涉及MongoDB相關的知識,不了解的讀者可以參考筆者的這篇文章:

MongoDB快速入門

gateway整合MongoDB采集日志步驟

  1. 添加MongoDB依賴并完成MongoDB配置:

首先在gateway中添加MongoDB依賴,需要注意的是,筆者后續(xù)的過濾器某些代碼段會用到hutool的工具類,所以這里也添加了hutool的依賴。

 <!--mongodb依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>



        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>

然后我們在gateway的配置中添加MongoDB的連接參數(shù)配置:

# mongodb的ip地址
spring.data.mongodb.host=ip
# mongodb端口號
spring.data.mongodb.port=27017
# mongodb數(shù)據(jù)庫名稱
spring.data.mongodb.database=accesslog
# 用戶名
spring.data.mongodb.username=xxxx
# 密碼
spring.data.mongodb.password=xxx
  1. 編寫MongoDB保存邏輯:

我們希望保存網(wǎng)關響應的內(nèi)容到mongodb中,所以我們要把我們需要的內(nèi)容封裝成一個對象,如下GatewayLog

@Data
public class GatewayLog {
    /**
     * 請求相對路徑
     */
    private String requestPath;
    /**
     *請求方法 :get post
     */
    private String requestMethod;
    /**
     *請求協(xié)議:http rpc
     */
    private String schema;
    /**
     *請求體內(nèi)容
     */
    private String requestBody;
    /**
     *響應內(nèi)容
     */
    private String responseBody;
    /**
     *ip地址
     */
    private String ip;
    /**
     * 請求時間
     */
    private String requestTime;
    /**
     *響應時間
     */
    private String responseTime;
    /**
     *執(zhí)行時間 單位:毫秒
     */
    private Long executeTime;

}

完成對象定義后,我們就可以編寫service層接口和實現(xiàn)類的邏輯了:

public interface AccessLogService {

    /**
     * 保存AccessLog
     * @param gatewayLog 請求響應日志
     * @return 響應日志
     */
    GatewayLog saveAccessLog(GatewayLog gatewayLog);

}

實現(xiàn)類代碼如下,可以看到筆者完全基于mongoTemplatesave方法將日志數(shù)據(jù)存到gatewayLog表中。

@Service
public class AccessLogServiceImpl implements AccessLogService {

    @Autowired
    private MongoTemplate mongoTemplate;

	//collection名稱
    private final String collectionName="gatewayLog" ;

    @Override
    public GatewayLog saveAccessLog(GatewayLog gatewayLog) {
        GatewayLog result = mongoTemplate.save(gatewayLog, collectionName);
        return result;
    }
}
  1. 基于gateway過濾器完成請求相應日志采集,代碼比較長,首先是CachedBodyOutputMessage,由于筆者用的是Spring boot 2.x版本,沒有CachedBodyOutputMessage 這個類,所以筆者從網(wǎng)上找了一份。讀者可以根據(jù)注釋進行復制修改即可。
public class CachedBodyOutputMessage implements ReactiveHttpOutputMessage {
    private final DataBufferFactory bufferFactory;
    private final HttpHeaders httpHeaders;
    private Flux<DataBuffer> body = Flux.error(new IllegalStateException("The body is not set. Did handling complete with success? Is a custom \"writeHandler\" configured?"));
    private Function<Flux<DataBuffer>, Mono<Void>> writeHandler = this.initDefaultWriteHandler();

    public CachedBodyOutputMessage(ServerWebExchange exchange, HttpHeaders httpHeaders) {
        this.bufferFactory = exchange.getResponse().bufferFactory();
        this.httpHeaders = httpHeaders;
    }

    public void beforeCommit(Supplier<? extends Mono<Void>> action) {
    }

    public boolean isCommitted() {
        return false;
    }

    public HttpHeaders getHeaders() {
        return this.httpHeaders;
    }

    private Function<Flux<DataBuffer>, Mono<Void>> initDefaultWriteHandler() {
        return (body) -> {
            this.body = body.cache();
            return this.body.then();
        };
    }

    public DataBufferFactory bufferFactory() {
        return this.bufferFactory;
    }

    public Flux<DataBuffer> getBody() {
        return this.body;
    }

    public void setWriteHandler(Function<Flux<DataBuffer>, Mono<Void>> writeHandler) {
        Assert.notNull(writeHandler, "'writeHandler' is required");
        this.writeHandler = writeHandler;
    }

    public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
        return Mono.defer(() -> {
            return (Mono)this.writeHandler.apply(Flux.from(body));
        });
    }

    public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
        return this.writeWith(Flux.from(body).flatMap((p) -> {
            return p;
        }));
    }

    public Mono<Void> setComplete() {
        return this.writeWith(Flux.empty());
    }
}

過濾器代碼如下,筆者將核心內(nèi)容都已注釋了,讀者可以基于此代碼進行修改


@Slf4j
@Component
public class AccessLogGlobalFilter implements GlobalFilter, Ordered {
    private final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();

    //todo 存在線程安全問題,后續(xù)需要優(yōu)化掉
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    @Autowired
    private AccessLogService accessLogService;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        GatewayLog gatewayLog = new GatewayLog();

        ServerHttpRequest request = exchange.getRequest();
        //獲取請求的ip,url,method,body
        String requestPath = request.getPath().pathWithinApplication().value();
        String clientIp = request.getRemoteAddress().getHostString();
        String scheme = request.getURI().getScheme();
        String method = request.getMethodValue();
        
        //數(shù)據(jù)記錄到gatwayLog中
        gatewayLog.setSchema(scheme);
        gatewayLog.setRequestMethod(method);
        gatewayLog.setRequestPath(requestPath);
        gatewayLog.setRequestTime(simpleDateFormat.format(new Date().getTime()));
        gatewayLog.setIp(clientIp);

        MediaType contentType = request.getHeaders().getContentType();
        if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType) || MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) {
            return writeBodyLog(exchange, chain, gatewayLog);
        } else {
            //寫入日志信息到mongoDb
            return writeBasicLog(exchange, chain, gatewayLog);
        }
    }

    private Mono<Void> writeBasicLog(ServerWebExchange exchange, GatewayFilterChain chain, GatewayLog accessLog) {
        StringBuilder builder = new StringBuilder();
        MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
        for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
            builder.append(entry.getKey()).append("=").append(StringUtils.join(entry.getValue(), ","));
        }
        //記錄響應內(nèi)容
        accessLog.setRequestBody(builder.toString());

        //   獲取響應體
        ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange, accessLog);
        return chain.filter(exchange.mutate().response(decoratedResponse).build())
                .then(Mono.fromRunnable(() -> {
                    //打印日志
                    writeAccessLog(accessLog);
                }));
    }


    /**
     * 解決request body 只能讀取一次問題
     *
     * @param exchange
     * @param chain
     * @param gatewayLog
     * @return
     */
    private Mono writeBodyLog(ServerWebExchange exchange, GatewayFilterChain chain, GatewayLog gatewayLog) {
        ServerRequest serverRequest = ServerRequest.create(exchange, messageReaders);
        Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
                .flatMap(body -> {
                    gatewayLog.setRequestBody(body);
                    return Mono.just(body);
                });

        // 通過 BodyInsert 插入 body(支持修改body), 避免 request body 只能獲取一次
        BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
        HttpHeaders headers = new HttpHeaders();
        headers.putAll(exchange.getRequest().getHeaders());

        headers.remove(HttpHeaders.CONTENT_LENGTH);
        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);

        return bodyInserter.insert(outputMessage, new BodyInserterContext())
                .then(Mono.defer(() -> {
                    // 重新封裝請求
                    ServerHttpRequest decoratedRequest = requestDecorate(exchange, headers, outputMessage);

                    // 記錄響應日志
                    ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange, gatewayLog);

                    // 記錄普通的
                    return chain.filter(exchange.mutate().request(decoratedRequest).response(decoratedResponse).build())
                            .then(Mono.fromRunnable(() -> {
                                // 打印日志
                                writeAccessLog(gatewayLog);
                            }));
                }));
    }


    /**
     * 打印日志并將日志內(nèi)容寫入mongodb
     *
     * @param gatewayLog
     */
    private void writeAccessLog(GatewayLog gatewayLog) {
        log.info("寫入網(wǎng)關日志,日志內(nèi)容:" + JSON.toJSONString(gatewayLog));
        accessLogService.saveAccessLog(gatewayLog);
    }

    /**
     * 請求裝飾器,重新計算 headers
     *
     * @param exchange
     * @param headers
     * @param outputMessage
     * @return
     */
    private ServerHttpRequestDecorator requestDecorate(ServerWebExchange exchange, HttpHeaders headers,
                                                       CachedBodyOutputMessage outputMessage) {
        return new ServerHttpRequestDecorator(exchange.getRequest()) {
            @Override
            public HttpHeaders getHeaders() {
                long contentLength = headers.getContentLength();
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.putAll(super.getHeaders());
                if (contentLength > 0) {
                    httpHeaders.setContentLength(contentLength);
                } else {
                    httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                }
                return httpHeaders;
            }

            @Override
            public Flux<DataBuffer> getBody() {
                return outputMessage.getBody();
            }
        };
    }

    /**
     * 記錄響應日志
     *
     * @param exchange
     * @param gatewayLog
     * @return
     */
    private ServerHttpResponseDecorator recordResponseLog(ServerWebExchange exchange, GatewayLog gatewayLog) {
        ServerHttpResponse response = exchange.getResponse();
        DataBufferFactory bufferFactory = response.bufferFactory();

        return new ServerHttpResponseDecorator(response) {
            @SneakyThrows
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    String responseTime = simpleDateFormat.format(new Date().getTime());
                    gatewayLog.setResponseTime(responseTime);
                    // 計算執(zhí)行時間
                    long executeTime = (simpleDateFormat.parse(responseTime).getTime() - simpleDateFormat.parse(gatewayLog.getRequestTime()).getTime());
                    gatewayLog.setExecuteTime(executeTime);

                    // 獲取響應類型,如果是 json 就打印
                    String originalResponseContentType = exchange.getAttribute(ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);

                    if (ObjectUtils.equals(this.getStatusCode(), HttpStatus.OK)
                            && StringUtils.isNotBlank(originalResponseContentType)
                            && originalResponseContentType.contains("application/json")) {

                        Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {

                            // 合并多個流集合,解決返回體分段傳輸
                            DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                            DataBuffer join = dataBufferFactory.join(dataBuffers);
                            byte[] content = new byte[join.readableByteCount()];
                            join.read(content);

                            // 釋放掉內(nèi)存
                            DataBufferUtils.release(join);
                            String responseResult = new String(content, StandardCharsets.UTF_8);
                            gatewayLog.setResponseBody(responseResult);

                            return bufferFactory.wrap(content);
                        }));
                    }
                }
                return super.writeWith(body);
            }
        };
    }

    /**
     * 調(diào)小優(yōu)先級使得該過濾器最先執(zhí)行
     * @return
     */
    @Override
    public int getOrder() {
        return -100;
    }
}

  1. 測試

以筆者項目為例,通過網(wǎng)關調(diào)用order服務:

curl 127.0.0.1:8090/order/getByCode/zsy

可以看到響應成功了,接下來我們就確認一下mongoDb中是否有存儲網(wǎng)關請求響應信息


{"status":100,"message":"操作成功","data":{"id":1,"accountCode":"zsy","accountName":"zsy","amount":10000.00},"success":true,"timestamp":1676439102837}

通過數(shù)據(jù)庫連接工具查詢,可以看到網(wǎng)關請求響應日志也成功存儲到MongoDB中。

gateway 如何處理后端微服務返回的json,微服務,微服務,gateway

參考文獻

SpringCloud Alibaba微服務實戰(zhàn)二十四 - SpringCloud Gateway的全局異常處理

軟件開發(fā)設計中的上游與下游

SpringCloud Alibaba實戰(zhàn)二十九 | SpringCloud Gateway 請求響應日志

MongoDB 數(shù)據(jù)查詢操作

實戰(zhàn) | MongoDB的安裝配置

spring cloud gateway中實現(xiàn)請求、響應參數(shù)日志打印文章來源地址http://www.zghlxwxcb.cn/news/detail-759363.html

到了這里,關于Gateway全局異常處理及請求響應監(jiān)控的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • SpringCloud GateWay通過過濾器GatewayFilter修改請求或響應內(nèi)容

    Spring Cloud Gateway在有些場景中需要獲取request body內(nèi)容進行參數(shù)校驗或參數(shù)修改,我們通過在GatewayFilter中獲取請求內(nèi)容來獲取和修改請求體,下面我們就基于ServerWebExchange來實現(xiàn): ServerWebExchange命名為服務網(wǎng)絡交換器,存放著重要的請求-響應屬性、請求實例和響應實例等等,有

    2024年02月16日
    瀏覽(21)
  • SpringCloud Gateway 整合RSA對請求參數(shù)解密、響應結果加密【SpringCloud系列10】

    SpringCloud Gateway 整合RSA對請求參數(shù)解密、響應結果加密【SpringCloud系列10】

    本文章實現(xiàn)的是 網(wǎng)關中的 參數(shù)解密、響應數(shù)據(jù)體加密功能。 1 集成 commons-codec commons-codec 是Apache開源組織提供的用于摘要運算、編碼解碼的包。常見的編碼解碼工具Base64、MD5、Hex、SHA1、DES等。 本項目中集成RSA 非對稱算法,RSAUtils 工具類 然后創(chuàng)建一個測試類,生成一組公鑰

    2024年02月06日
    瀏覽(21)
  • 記一次線上bug排查-----SpringCloud Gateway組件 請求頭accept-encoding導致響應結果亂碼

    記一次線上bug排查-----SpringCloud Gateway組件 請求頭accept-encoding導致響應結果亂碼

    ? ? ? ?基于公司的業(yè)務需求,在SpringCloud Gateway組件的基礎上,寫了一個轉發(fā)服務,測試開發(fā)階段運行正常,并實現(xiàn)初步使用。但三個月后,PostMan請求接口,返回異常,經(jīng)排查,從日志中獲取到轉發(fā)響應的結果為亂碼: ? ? ?? 跟蹤日志: 轉發(fā)到目標接口,響應結果已亂碼

    2024年02月04日
    瀏覽(22)
  • Gateway網(wǎng)關 全局過濾器

    Gateway網(wǎng)關 全局過濾器

    一、全局過濾器 全局過濾器GlobalFilter 全局過濾器的作用也是處理一切進入網(wǎng)關的請求和微服務響應,與GatewayFilter的作用一樣。 區(qū)別在于GatewayFilter通過配置定義,處理邏輯是固定的。 需求:定義全局過濾器,攔截請求,判斷請求的參數(shù)是否滿足下面條件: 參數(shù)中是否有au

    2024年02月07日
    瀏覽(23)
  • GateWay自定義網(wǎng)關全局攔截

    在com.xxxxa.gateway.filter包下創(chuàng)建 是在網(wǎng)關下面操作: 網(wǎng)關的包里創(chuàng)建: 定義方式是非常簡單,只需實現(xiàn) GlobalFilter 接口 —————————————————————————————————————————————— 在filter中編寫自定義邏輯,可以實現(xiàn)下列功能: 登

    2024年02月10日
    瀏覽(17)
  • Spring Cloud GateWay 全局過濾器

    這是一個自定義的 Spring Cloud Gateway 全局過濾器(Global Filter)。在 Spring Cloud Gateway 中,全局過濾器可以在請求被路由到目標服務之前或之后執(zhí)行一些操作。這個過濾器實現(xiàn)了 GlobalFilter 接口和 Ordered 接口,這兩個接口的作用如下: GlobalFilter 接口: 這是一個 Spring Cloud Gateway 提

    2024年02月11日
    瀏覽(20)
  • Gateway自定義過濾器——全局過濾器

    Gateway自定義過濾器——全局過濾器

    首先,我們要知道全局過濾器其實是特殊路由過濾器(特殊的GatewayFilter),會有條件地作用于所有路由。 為什么要自定義全局過濾器?就好比是看大門的保安大叔,平時主要是做好進出大門外來人員登記即可,但是因為新冠疫情,現(xiàn)在還需要給外來人員測量體溫等等。而已有的

    2024年02月16日
    瀏覽(23)
  • 基于Spring-cloud-gateway實現(xiàn)全局日志記錄

    基于Spring-cloud-gateway實現(xiàn)全局日志記錄

    最近項目在線上運行出現(xiàn)了一些難以復現(xiàn)的bug需要定位相應api的日志,通過nginx提供的api請求日志難以實現(xiàn),于是在gateway通過全局過濾器記錄api請求日志。 接受到用戶請求后,經(jīng)過全局過濾器,檢驗是否開啟相應的日志配置及相應的黑白名單配置 在gateway前置處理如記錄當前

    2024年02月11日
    瀏覽(39)
  • 【深入解析spring cloud gateway】05 gateway請求轉發(fā)實驗

    三個工程: eureka-server eureka-client gateway 實驗目的:通過網(wǎng)關訪問對應的微服務:eureka-client。gateway和eureka-client注冊到eureka-server上 eureka-server略 eureka-client application.yml 提供一個接口 pom.xml application.yml 定義一個filter用于去掉路徑中的/gateway 自定義一個GlobalFilter,用于去掉路徑

    2024年02月10日
    瀏覽(19)
  • Spring Cloud Gateway GlobalFilter(全局過濾器)詳解(官方原版)

    GlobalFilter接口具有與GatewayFilter相同的簽名。這些是有條件地應用于所有路由的特殊過濾器。 當請求與路由匹配時,過濾web處理程序會將GlobalFilter的所有實例和GatewayFilter的所有路由特定實例添加到過濾器鏈中。這個組合過濾器鏈由org.springframework.core.Ordered接口排序,您可以通

    2024年02月09日
    瀏覽(16)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包