中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解Spring Cloud網關服務zuul

發布時間:2021-10-15 15:16:25 來源:億速云 閱讀:179 作者:iii 欄目:大數據

本篇內容介紹了“如何理解Spring Cloud網關服務zuul ”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

如何理解Spring Cloud網關服務zuul 可以看到服務端口和注冊中心都在配置文件中配置化

屬性信息

上一篇我們講了如何搭建網關zuul 服務。實現了基本的轉發功能。這篇文章我們要講述zuul過濾器的使用。和三個參數的使用

sensitiveHeaders 屬性關鍵字聲明:Spring Cloud微服務實戰 書中意思為放行字段。而小編在官方文檔查看到是忽略不放行的意思。請注意此處,看過Spring Cloud微服務實戰同學可以用小編實例代碼印證
  • ribbon-isolation-strategy

    • 信號量模式 在該模式下,接收請求和執行下游依賴在同一個線程內完成,不存在線程上下文切換所帶來的性能開銷。默認信號量模式

    • 線程池 在該模式下,用戶請求會被提交到各自的線程池中執行,把執行每個下游服務的線程分離,從而達到資源隔離的作用。當線程池來不及處理并且請求隊列塞滿時,新進來的請求將快速失敗,可以避免依賴問題擴散。

    • 隔離機制 Spring Cloud 默認的隔離機制hystrix 去做限流、熔斷、隔離。一個是基于信號量。一個是基于線程池去完成

  • ignored-services

    • 忽略指定的服務

  • ignored—patterns

    • 忽略指定的url 路徑

  • ignored-headers

    • 忽略指定的header 頭部信息

  • sensitiveHeaders

    • 字段比較敏感,不希望傳遞給下游微服務。 設置空沒有要忽略的敏感字段。全部傳給下游服務

在上面ignored-headers 和 sensitiveHeaders 職責是有重疊的部分。其實他們是有著關系存在的。sensitiveHeaders的內容會最終合并到ignored-headers內。

驗證一下 sensitiveHeaders 字段設置全區忽略 X-ABC

消費者服務 sensitiveHeaders 指定忽略 X-ABC,Authorization

服務提供者轉發不做任何調整 在服務提供者 和 服務消費者 服務上。都創建一個 UrlFilter 攔截器 先設置一下 zuul的yml文件

zuul:
  host:
    # 目標主機的最大連接數,默認值為200
    max-total-connections: 500
    # 每個主機的初始連接數,默認值為20
    max-per-route-connections: 100
  routes:
    discovery-server:
      path: /server/**
      serviceId: cloud-discovery-server
    client-common:
      path: /client/**
      serviceId: cloud-discovery-client
      sensitiveHeaders: X-ABC,X-Foo
  # 所有路由的默認Hystrix隔離模式(ExecutionIsolationStrategy)為SEMAPHORE。如果此隔離模式是首選,則zuul.ribbonIsolationStrategy可以更改為THREAD
  ribbon-isolation-strategy: thread
  # 這個屬性意思,* 忽略未指定的服務列表 有具體服務名稱 忽略指定的服務
  ignored-services: "*"
  # 忽略指定的url 路徑
  ignored—patterns:
  # 忽略指定的header 頭部信息
  ignored-headers: Authorization
  # 字段比較敏感,不希望傳遞給下游微服務。 設置空沒有要忽略的敏感字段。全部傳給下游服務
  sensitive-headers: X-ABC
  ribbon:
    eager-load:
      # 強制加載,不設置會進行懶加載。spring 第一次請求會非常慢
      enabled: true
package com.xian.cloud.filter;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/10/29 13:57
 */
@WebFilter(filterName = "test",urlPatterns = "/*")
@Slf4j
public class UrlFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.warn("UrlFilter init.......");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        Enumeration<String> attributeNames = servletRequest.getAttributeNames();
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        String requestURI = req.getRequestURI();
        String header = req.getHeader("X-Foo");
        String abc = req.getHeader("X-ABC");
        String authorization = req.getHeader("Authorization");
        String tom = req.getParameter("tom");
        String mike = req.getParameter("mike");
        log.warn("過濾器:請求地址"+requestURI);
        log.warn("uuid:{}",header);
        log.warn("abc uuid:{}",abc);
        log.warn("authorization :{}",authorization);
        log.warn("tom :{}",tom);
        log.warn("mike :{}",mike);
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        log.warn(" 過濾器被銷毀");
    }
}

啟動類上添加 @ServletComponentScan 用于掃描 過濾器 @WebFilter注解

package com.xian.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @Author: xlr
 * @Date: Created in 2:44 PM 2019/10/27
 */
@EnableDiscoveryClient
@SpringBootApplication
//新增注解
@ServletComponentScan
public class DiscoveryServerApplication {


    public static void main(String[] args) {
        SpringApplication.run(DiscoveryServerApplication.class, args);
    }
}

使用postman 請求服務 服務端打印日志

2019-10-30 11:10:35.822  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : 過濾器:請求地址/server/hello
2019-10-30 11:10:35.826  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : uuid:x-foo
2019-10-30 11:10:35.826  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : abc uuid:null
2019-10-30 11:10:35.827  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : authorization :null
2019-10-30 11:10:35.827  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : tom :null
2019-10-30 11:10:35.828  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : mike :null
2019-10-30 11:10:35.852  INFO 48882 --- [nio-9012-exec-8] c.x.cloud.controller.DiscoverCotroller   : invoked name = xian age = 20

sensitive-headers、ignored-headers (abc、authorization都在zuul被過濾掉)全局設置生效。

我們再次請求client 服務接口

在看一下 客戶端打印日志

2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : 過濾器:請求地址/client/test
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : uuid:null
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : abc uuid:null
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : authorization :null
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : tom :null
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : mike :null

全局設置,和單個服務定制設置 全部生效。

過濾器

spring cloud Zuul包含了對請求的路由和過濾2個功能。路由功能負責將請求轉發到具體的微服務上,而過濾器負責對請求的處理過程進行干預,是實現權限校驗、服務聚合等功能的基礎。

在實際運行時,路由映射和請求轉發是由幾個不同的過濾器完成的。每一個進入zuul的http請求都會經過一系列的過濾器處理鏈得到請求響應并返回給客戶端。

zuul1.0 對流量的路由分發和過濾倆個功能。路由讓流量分發到內部的微服務集群上。過濾對請求進行修改或者做個性化處理。實現鑒權、安全、監控、日志等。

運行過程中,流量請求會經過一系列的過濾器最終轉發到對應的服務上去。

zuul 路由器主要根絕FilterType類型分為四種類型。一個靜態響應StaticResponseFilter

  • pre 在請求被路由之前調用。對應spring boot 工程Filer 中的 doFilter 方法。

  • route 用于路由到原點,使用http 協議調用。可以理解負責轉發請求到微服務

  • error 錯誤處理,在處理請求發生錯誤時被調用

  • post 用于后路由過濾,在route和error過濾器之后被調用

自定義過濾器

FilterTypeEnum 枚舉類

package com.xian.cloud.enums;

import lombok.Getter;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/10/29 13:01
 */
@Getter
public enum FilterTypeEnum {

    PRE("pre","前置過濾"),
    ROUTE("route","路由請求時被調用"),
    POST("post","后置過濾器"),
    ERROR("error","后置錯誤處理");

    private String type;

    private String desc;

    FilterTypeEnum(String type,String desc){
        this.type = type;
        this.desc = desc;
    }
}

過濾器代碼編寫

package com.xian.cloud.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.xian.cloud.enums.FilterTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/10/29 12:57
 */
@Component
@Slf4j
public class BannedAccessFilter extends ZuulFilter {

    /**
     * 路由器的類型指定
     * @return
     */
    @Override
    public String filterType() {
        return FilterTypeEnum.PRE.getType();
    }

    /**
     * 執行順序 數值越小。執行順序越靠前
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 返回一個boolean值來判斷該過濾器是否要執行。我們可以通過此方法來指定過濾器的有效范圍。
     * @return
     */
    @Override
    public boolean shouldFilter() {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        String requestURI = request.getRequestURI();
        if(StringUtils.isNotBlank(requestURI) && (requestURI.contains("client") ||
            requestURI.contains("server"))){
            return true;
        }
        return false;
    }

    /**
     * 核心業務處理
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletResponse servletResponse = context.getResponse();
        String uuid = UUID.randomUUID().toString();
		//重寫 X-Foo X-ABC值
        context.addZuulRequestHeader("X-Foo", uuid);
        context.addZuulRequestHeader("X-ABC",uuid);
        log.info("X-Foo:{}",uuid);
        return null;
    }
}

run方法是核心業務處理的方法 postman 請求 http://127.0.0.1:9083/server/server/hello?name=1111 攜帶之前設置的header參數 如何理解Spring Cloud網關服務zuul

服務器打印日志

2019-10-30 14:44:44.841  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : 過濾器:請求地址/server/hello
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : uuid:a65b2244-e9a5-456d-968f-eaaba45b6f49
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : abc uuid:null
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : authorization :null
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : tom :null
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : mike :null
2019-10-30 14:44:44.844  INFO 48882 --- [nio-9012-exec-9] c.x.cloud.controller.DiscoverCotroller   : invoked name = 1111 age = 20

可以看到 postman設置的X-Foo 值被 BannedAccessFilter run方法業務覆蓋掉了

攔截的請求對參數的修改操作都是在這里。這里單獨介紹一下 RequestContext 這個類

官方文檔描述

To pass information between filters, Zuul uses a RequestContext. Its data is held in a ThreadLocal specific to
each request. Information about where to route requests, errors and the actual HttpServletRequest and
HttpServletResponse are stored there. The RequestContext extends ConcurrentHashMap, so anything can be
stored in the context. FilterConstants contains the keys that are used by the filters installed by Spring Cloud
Netflix (more on these later).

請求要在過濾器之間傳遞信息,Zuul使用 RequestContext。其數據按照每個請求的ThreadLocal進行。關于路由請求,錯誤以及實際HttpServletRequest和HttpServletResponse的路由信息。RequestContext擴展ConcurrentHashMap,所以任何東西都可以存儲在上下文中。

ThreadLocal保證了請求與請求都是獨立的,相互不影響。擴展ConcurrentHashMap 保證內部過濾器并發操作的安全性。

RequestContext 的特殊性。需要單獨在創建一個過濾器來展示RequestContext 的使用

需要注意點 都在代碼注釋上描述出來了。請根據自己的業務場景定制自己的過濾器。

package com.xian.cloud.filter;

import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import com.xian.cloud.enums.FilterTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/10/29 16:07
 */
@Component
@Slf4j
public class UpdateParamsFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return FilterTypeEnum.PRE.getType();
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {


        // 獲取到request
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        // 獲取請求參數name
        String name = "";
        try {

            // 請求方法
            String method = request.getMethod();
            log.info(String.format("%s >>> %s", method, request.getRequestURL().toString()));
            // 獲取請求的輸入流
            InputStream in = request.getInputStream();
            String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
            // 如果body為空初始化為空json
            if (StringUtils.isBlank(body)) {
                body = "{}";
            }
            log.info("body" + body);
            // 轉化成json
            JSONObject json = JSONObject.parseObject(body);
            // 關鍵步驟,一定要get一下,下面才能取到值requestQueryParams
            if ("GET".equals(method)) {
                request.getParameterMap();
                Map<String, List<String>> requestQueryParams = ctx.getRequestQueryParams();
                if (requestQueryParams == null) {
                    requestQueryParams = new HashMap<>();
                }
                //TODO  寫業務代碼
                List<String> arrayList = new ArrayList<>();
                arrayList.add("hello mike");
                //requestQueryParams.put("mike",arrayList);
                ctx.setRequestQueryParams(requestQueryParams);
            }
            //post和put需重寫HttpServletRequestWrapper
            if ("POST".equals(method) || "PUT".equals(method)) {
                //TODO 在這里修改或者添加內容
                json.put("tom","hello tom");
                String newBody = json.toString();
                final byte[] reqBodyBytes = newBody.getBytes();
                // 重寫上下文的HttpServletRequestWrapper
                ctx.setRequest(new HttpServletRequestWrapper(request) {
                    @Override
                    public ServletInputStream getInputStream() throws IOException {
                        return new ServletInputStreamWrapper(reqBodyBytes);
                    }
                    @Override
                    public int getContentLength() {
                        return reqBodyBytes.length;
                    }
                    @Override
                    public long getContentLengthLong() {
                        return reqBodyBytes.length;
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

“如何理解Spring Cloud網關服務zuul ”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

新泰市| 乌鲁木齐县| 托克托县| 大竹县| 故城县| 于都县| 白玉县| 霍城县| 贵德县| 美姑县| 永仁县| 北碚区| 资兴市| 财经| 象州县| 克山县| 花莲县| 石泉县| 青州市| 班玛县| 孟村| 静海县| 修武县| 肇庆市| 宜君县| 蓝田县| 娄烦县| 疏附县| 城步| 顺义区| 宁强县| 红原县| 遵义县| 麻阳| 疏勒县| 阿克苏市| 吉隆县| 正安县| 阳城县| 汤阴县| 乐亭县|