spring-cloud-zuul及其應(yīng)用

概述

網(wǎng)關(guān)為我們管理api接口提供的主要功能

  • 管理api接口
  • 適配協(xié)議
  • 安全認(rèn)證
  • 轉(zhuǎn)發(fā)路由
  • 限制流量
  • 監(jiān)控日志
  • 防止爬蟲(chóng)
  • 灰度發(fā)布
  • 服務(wù)聚合

不建議使用zuul1作為線(xiàn)上網(wǎng)關(guān)使用,大家可以使用zuul2或者是spring-cloud-gateway作為微服務(wù)的網(wǎng)關(guān)

假如你使用zuul2作為網(wǎng)關(guān)的話(huà),zuul1可以學(xué)習(xí)使用,其實(shí)基本功能類(lèi)似,只是在底層改為netty去轉(zhuǎn)發(fā)http請(qǐng)求

zuul1提供的功能

zuul的核心功能是過(guò)濾器,通過(guò)過(guò)濾器實(shí)現(xiàn)

  • 動(dòng)態(tài)路由
  • 請(qǐng)求監(jiān)控
  • 認(rèn)證鑒權(quán)
  • 壓力測(cè)試
  • 灰度發(fā)布

坑一

  • 注意zuul1和springboot的版本適配問(wèn)題(zuul后面已經(jīng)被spring-cloud干掉了,不在支持集成使用)
<dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>

基礎(chǔ)的重定向,從path重定向到url

spring.application.name=zuul-gateway-static
server.port=9011
server.address=127.0.0.1

debug=true

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=ALWAYS

zuul.routes.test1.path=/abc/**
zuul.routes.test1.url=http://www.example.com/

zuul.routes.localpath.path=/a/**
zuul.routes.localpath.url=forward:/a

zuul.routes.userinfo.path=/user/**
zuul.routes.userinfo.service-id=zuul-user
zuul.routes.userinfo.stripPrefix=false
zuul.routes.userinfo.sensitive-headers=true
zuul.routes.userinfo.customSensitiveHeaders=true

zuul.retryable=true
ribbon.okhttp.enabled=true


eureka.instance.ip-address=127.0.0.1
eureka.client.serviceUrl.defaultZone=http://tom:123456@localhost:9010/eureka/
eureka.instance.preferIpAddress=true
eureka.instance.instance-id=${spring.application.name}:${server.address}:${server.port}
eureka.client.healthcheck.enabled=true
eureka.instance.lease-expiration-duration-in-seconds=20
eureka.instance.lease-renewal-interval-in-seconds=15

logging.config=classpath:logback.xml

查看所有routers的配置

  1. 訪(fǎng)問(wèn)服務(wù):
  2. http://localhost:9011/abc/123
  3. 基礎(chǔ)的匹配
zuul.routes.test1.path=/abc/**
zuul.routes.test1.url=http://www.example.com/
  1. 本地跳轉(zhuǎn)zuul.routes.localpath.path=/a/**
    zuul.routes.localpath.url=forward:/a
  2. 使用eureka的匹配
  3. http://localhost:9011/user/1234
zuul.routes.userinfo.path=/user/**
zuul.routes.userinfo.service-id=zuul-user
zuul.routes.userinfo.stripPrefix=false
zuul.routes.userinfo.sensitive-headers=true
zuul.routes.userinfo.customSensitiveHeaders=true
  1. 自定義過(guò)濾器
  2. pre 請(qǐng)求被路由之前調(diào)用
  3. route 請(qǐng)求路由時(shí)調(diào)用
  4. post 在route和error過(guò)濾器之后調(diào)用
  5. error 在請(qǐng)求發(fā)生錯(cuò)誤時(shí)調(diào)用

代碼路徑:

https://github.com/beckbikang/spring-cloud/tree/main/kzuul

實(shí)現(xiàn)動(dòng)態(tài)路由的網(wǎng)關(guān)才是真正可用的網(wǎng)關(guān)

  1. 先上代碼,基于redis存儲(chǔ)了配置信息
  2. 繼承SimpleRouteLocator類(lèi)和實(shí)現(xiàn)了RefreshableRouteLocator接口

最最核心的代碼了,如果需要實(shí)現(xiàn)動(dòng)態(tài)路由,可以基于這個(gè)去改造了

package cn.beckbi.route;

import cn.beckbi.route.entity.ZuulEntity;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.*;


/**
 * @program: spring-cloud
 * @description:
 * @author: bikang
 * @create: 2022-08-14 13:04
 */
public class DynamicRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {

    private static final String ZUUL_EKY = "LOCAL_ZUUL_RULES_REDIS_KEY";

    private ZuulProperties zuulProperties;

    public static String getRouteKey() {
        return ZUUL_EKY;
    }

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    public DynamicRouteLocator(String servletPath, ZuulProperties properties) {
        super(servletPath, properties);
        this.zuulProperties = properties;
    }

    @Override
    public void refresh() {
        doRefresh();
    }

    @Override
    protected Map<String, ZuulProperties.ZuulRoute> locateRoutes() {
        Map<String, ZuulProperties.ZuulRoute> routesMap = new LinkedHashMap(20);

        zuulProperties.getRoutes().clear();

        routesMap.putAll(super.locateRoutes());

        routesMap.putAll(locateRoutesFromRedis());

        zuulProperties.getRoutes().putAll(routesMap);

        return routesMap;
    }

    private Map<? extends String, ? extends ZuulProperties.ZuulRoute> locateRoutesFromRedis() {
        LinkedHashMap routesMap = new LinkedHashMap();

        String routeData = stringRedisTemplate.opsForValue().get(ZUUL_EKY);
        List<ZuulEntity> zuulEntityList = JSONObject.parseObject(routeData, new TypeReference<List<ZuulEntity>>(){});

        for (ZuulEntity zuulEntity: zuulEntityList){
            routesMap.put(zuulEntity.getPath(),new ZuulProperties.ZuulRoute(
                    zuulEntity.getId(),
                    zuulEntity.getPath(),
                    zuulEntity.getServiceId(),
                    zuulEntity.getUrl(),
                    zuulEntity.isStripPrefix(),
                    zuulEntity.getRetryable(),
                    new LinkedHashSet(1)));
        }
        return routesMap;
    }

    @Override
    public Collection<String> getIgnoredPaths() {
        return super.getIgnoredPaths();
    }

    @Override
    public List<Route> getRoutes() {
        return super.getRoutes();
    }

    @Override
    public Route getMatchingRoute(String path) {
        return super.getMatchingRoute(path);
    }
}

刷新路由

直接轉(zhuǎn)發(fā)

基于eureka的路由

具體代碼可以看這個(gè):

https://github.com/beckbikang/spring-cloud/tree/main/kzuul

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容