大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

Spring Cloud微服務(wù)實(shí)踐

Spring Cloud API網(wǎng)關(guān)Zuul

Spring Cloud的Zuul是什么

通過前面內(nèi)容的學(xué)習(xí),我們已經(jīng)可以基本搭建出一套簡(jiǎn)略版的微服務(wù)架構(gòu)了,我們有注冊(cè)中心 Eureka,可以將服務(wù)注冊(cè)到該注冊(cè)中心中,我們有 Ribbon 或Feign 可以實(shí)現(xiàn)對(duì)服務(wù)負(fù)載均衡地調(diào)用,我們有 Hystrix 可以實(shí)現(xiàn)服務(wù)的熔斷,但是我們還缺少什么呢?

我們首先來看一個(gè)微服務(wù)架構(gòu)圖:

在上面的架構(gòu)圖中,我們的服務(wù)包括:內(nèi)部服務(wù) Service A 和內(nèi)部服務(wù) ServiceB,這兩個(gè)服務(wù)都是集群部署,每個(gè)服務(wù)部署了 3 個(gè)實(shí)例,他們都會(huì)通過 EurekaServer 注冊(cè)中心注冊(cè)與訂閱服務(wù),而 Open Service 是一個(gè)對(duì)外的服務(wù),也是集群部署,外部調(diào)用方通過負(fù)載均衡設(shè)備調(diào)用 Open Service 服務(wù),比如負(fù)載均衡使用 Nginx,這樣的實(shí)現(xiàn)是否合理,或者是否有更好的實(shí)現(xiàn)方式呢?接下來我們主要圍繞該問題展開討論。

1、如果我們的微服務(wù)中有很多個(gè)獨(dú)立服務(wù)都要對(duì)外提供服務(wù),那么我們要如何去管理這些接口?特別是當(dāng)項(xiàng)目非常龐大的情況下要如何管理?

2、在微服務(wù)中,一個(gè)獨(dú)立的系統(tǒng)被拆分成了很多個(gè)獨(dú)立的服務(wù),為了確保安全,權(quán)限管理也是一個(gè)不可回避的問題,如果在每一個(gè)服務(wù)上都添加上相同的權(quán)限驗(yàn)證代碼來確保系統(tǒng)不被非法訪問,那么工作量也就太大了,而且維護(hù)也非常不方便。

為了解決上述問題,微服務(wù)架構(gòu)中提出了 API 網(wǎng)關(guān)的概念,它就像一個(gè)安檢站一樣,所有外部的請(qǐng)求都需要經(jīng)過它的調(diào)度與過濾,然后 API 網(wǎng)關(guān)來實(shí)現(xiàn)請(qǐng)求路由、負(fù)載均衡、權(quán)限驗(yàn)證等功能;

那么 Spring Cloud 這個(gè)一站式的微服務(wù)開發(fā)框架基于 Netflix Zuul 實(shí)現(xiàn)了Spring Cloud Zuul,采用 Spring Cloud Zuul 即可實(shí)現(xiàn)一套 API 網(wǎng)關(guān)服務(wù)。

使用Zuul構(gòu)建API網(wǎng)關(guān)

1、創(chuàng)建一個(gè)普通的 Spring Boot 工程名為 06-springcloud-api-gateway,然后添加相關(guān)依賴,這里我們主要添加兩個(gè)依賴 zuul 和 eureka 依賴:

<!--添加spring cloud的zuul的起步依賴-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!--添加spring cloud的eureka的客戶端依賴-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2、在入口類上添加@EnableZuulProxy 注解,開啟 Zuul 的 API 網(wǎng)關(guān)服務(wù)功能:

@EnableZuulProxy //開啟Zuul的API網(wǎng)關(guān)服務(wù)功能
@SpringBootApplication
public class Application {
        public static void main(String[] args) {
           SpringApplication.run(Application.class, args);
        }
}

3、在 application.properties 文件中配置路由規(guī)則:

#配置服務(wù)內(nèi)嵌的Tomcat端口
server.port=8080

#配置服務(wù)的名稱
spring.application.name=06-springcloud-api-gateway 

#配置路由規(guī)則
zuul.routes.api-wkcto.path=/api-wkcto/** 
zuul.routes.api-wkcto.serviceId=05-springcloud-service-feign 

#配置API網(wǎng)關(guān)到注冊(cè)中心上,API網(wǎng)關(guān)也將作為一個(gè)服務(wù)注冊(cè)到eureka-server上
eureka.client.service-url.defaultZone=http://eureka8761:8761/eureka/,http:/
/eureka8762:8762/eureka/

以上配置,我們的路由規(guī)則就是匹配所有符合/api-wkcto/**的請(qǐng)求,只要路徑中帶有/api-wkcto/都將被轉(zhuǎn)發(fā)到 05-springcloud-service-feign 服務(wù)上,至于05-springcloud-service-feign 服務(wù)的地址到底是什么則由 eureka-server 注冊(cè)中心去分析,我們只需要寫上服務(wù)名即可。

以我們目前搭建的項(xiàng)目為例,請(qǐng)求 http://localhost:8080/api-wkcto/web/hello 接口則相當(dāng)于請(qǐng)求 http://localhost:8082/web/hello(05-springcloud-service-feign 服務(wù)的地址為 http://localhost:8082/web/hello),路由規(guī)則中配置的 api-wkcto 是路由的名字,可以任意定義,但是一組 path 和serviceId 映射關(guān)系的路由名要相同。

如果以上測(cè)試成功,則表示們的 API 網(wǎng)關(guān)服務(wù)已經(jīng)構(gòu)建成功了,我們發(fā)送的符合路由規(guī)則的請(qǐng)求將自動(dòng)被轉(zhuǎn)發(fā)到相應(yīng)的服務(wù)上去處理。

Zuul進(jìn)行請(qǐng)求過濾

我們知道 Spring cloud Zuul 就像一個(gè)安檢站,所有請(qǐng)求都會(huì)經(jīng)過這個(gè)安檢站,所以我們可以在該安檢站內(nèi)實(shí)現(xiàn)對(duì)請(qǐng)求的過濾,下面我們以一個(gè)權(quán)限驗(yàn)證案例說這一點(diǎn):

1、我們定義一個(gè)過濾器類并繼承自 ZuulFilter,并將該 Filter 作為一個(gè) Bean:

@Component 
public class AuthFilter extends ZuulFilter { 
    @Override 
    public String filterType() { 
        return "pre"; 
    } 
    @Override 
    public int filterOrder() { 
        return 0; 
    } 
    @Override 
    public boolean shouldFilter() { 
        return true; 
    } 
    @Override 
    public Object run() throws ZuulException { 
        RequestContext ctx = RequestContext.getCurrentContext(); 
        HttpServletRequest request = ctx.getRequest(); 
        String token = request.getParameter("token"); 
        if (token == null) { 
            ctx.setSendZuulResponse(false); 
            ctx.setResponseStatusCode(401); 
            
ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8"); 
            ctx.setResponseBody("非法訪問"); 
        } 
        return null; 
    } 
} 

(1)filterType 方法的返回值為過濾器的類型,過濾器的類型決定了過濾器在哪個(gè)生命周期執(zhí)行,pre 表示在路由之前執(zhí)行過濾器,其他值還有 post、error、route 和 static,當(dāng)然也可以自定義。

(2)filterOrder 方法表示過濾器的執(zhí)行順序,當(dāng)過濾器很多時(shí),我們可以通過該方法的返回值來指定過濾器的執(zhí)行順序。

(3)shouldFilter 方法用來判斷過濾器是否執(zhí)行,true 表示執(zhí)行,false 表示不執(zhí)行。

(4)run 方法則表示過濾的具體邏輯,如果請(qǐng)求地址中攜帶了 token 參數(shù)的話,則認(rèn)為是合法請(qǐng)求,否則為非法請(qǐng)求,如果是非法請(qǐng)求的話,首先設(shè)置ctx.setSendZuulResponse(false); 表示不對(duì)該請(qǐng)求進(jìn)行路由,然后設(shè)置響應(yīng)碼和響應(yīng)值。這個(gè) run 方法的返回值目前暫時(shí)沒有任何意義,可以返回任意值。

2、通過 http://localhost:8080/api-wkcto/web/hello 地址訪問,就會(huì)被過濾器過濾。

Zuul的路由規(guī)則

1、 在前面的例子中:

#配置路由規(guī)則
zuul.routes.api-wkcto.path=/api-wkcto/**
zuul.routes.api-wkcto.serviceId=05-springcloud-service-feign

當(dāng)訪問地址符合/api-wkcto/**規(guī)則的時(shí)候,會(huì)被自動(dòng)定位到05-springcloud-service-feign  服務(wù)上,不過兩行代碼有點(diǎn)麻煩,還可以簡(jiǎn)化為:

zuul.routes.05-springcloud-service-feign=/api-wkcto/**
zuul.routes  后面跟著的是服務(wù)名,服務(wù)名后面跟著的是路徑規(guī)則,這種配置方式更簡(jiǎn)單。

2、 如果映射規(guī)則我們什么都不寫,系統(tǒng)也給我們提供了一套默認(rèn)的配置規(guī)則默認(rèn)的配置規(guī)則如下:

#默認(rèn)的規(guī)則
zuul.routes.05-springcloud-service-feign.path=/05-springcloud-service-feign/**
zuul.routes.05-springcloud-service-feign.serviceId=05-springcloud-service-feign

3、默認(rèn)情況下,Eureka 上所有注冊(cè)的服務(wù)都會(huì)被 Zuul 創(chuàng)建映射關(guān)系來進(jìn)行路由。

但是對(duì)于我這里的例子來說,我希望:05-springcloud-service-feign 提供服務(wù);而01-springcloud-service-provider 作為服務(wù)提供者只對(duì)服務(wù)消費(fèi)者提供服務(wù),不對(duì)外提供服務(wù)。

如果使用默認(rèn)的路由規(guī)則,則 Zuul 也會(huì)自動(dòng)為01-springcloud-service-provider 創(chuàng)建映射規(guī)則,這個(gè)時(shí)候我們可以采用如下方式來讓 Zuul 跳過 01-springcloud-service-provider 服務(wù),不為其創(chuàng)建路由規(guī)則:

#忽略掉服務(wù)提供者的默認(rèn)規(guī)則
zuul.ignored-services=01-springcloud-service-provider

不給某個(gè)服務(wù)設(shè)置映射規(guī)則,這個(gè)配置我們可以進(jìn)一步細(xì)化,比如說我不想給/hello 接口路由,那我們可以按如下方式配置:

#忽略掉某一些接口路徑
zuul.ignored-patterns=/**/hello/**

此外,我們也可以統(tǒng)一的為路由規(guī)則增加前綴,設(shè)置方式如下:

#配置網(wǎng)關(guān)路由的前綴
zuul.prefix=/myapi

此時(shí)我們的訪問路徑就變成了 http://localhost:8080/myapi/web/hello

4、 路由規(guī)則通配符的含義:

通配符 含義 舉例 說明

?

匹配任意單個(gè)字符

/05-springcloud-service-feign/?

匹配

/05-springcloud-service-feign/a,

/05-springcloud-service-feign/b,

/05-springcloud-service-feign/c 等

*

匹配任意數(shù)量的字符

/05-springcloud-service-feign/*

匹配

/05-springcloud-service-feign/aaa,

/05-springcloud-service-feign/bbb,

/05-springcloud-service-feign/ccc 等,

無法匹配

/05-springcloud-service-feign/a/b/c

**

匹配任意數(shù)量的字符

/05-springcloud-service-feign/**

匹配

/05-springcloud-service-feign/aaa,

/05-springcloud-service-feign/bbb,

/05-springcloud-service-feign/ccc 等,

也可以匹配

/05-springcloud-service-feign/a/b/c

5、一般情況下 API 網(wǎng)關(guān)只是作為各個(gè)微服務(wù)的統(tǒng)一入口,但是有時(shí)候我們可能也需要在 API 網(wǎng)關(guān)服務(wù)上做一些特殊的業(yè)務(wù)邏輯處理,那么我們可以讓請(qǐng)求到達(dá) API 網(wǎng)關(guān)后,再轉(zhuǎn)發(fā)給自己本身,由 API 網(wǎng)關(guān)自己來處理,那么我們可以進(jìn)行如下的操作:

在 06-springcloud-api-gateway 項(xiàng)目中新建如下 Controller:

@RestController 
public class GateWayController { 
    @RequestMapping("/api/local") 
    public String hello() { 
        return "exec the api gateway."; 
    } 
} 

然后在 application.properties 文件中配置:

zuul.routes.gateway.path=/gateway/**
zuul.routes.gateway.url=forward:/api/local

Zuul的異常處理

Spring Cloud Zuul 對(duì)異常的處理是非常方便的,但是由于 Spring Cloud 處于迅速發(fā)展中,各個(gè)版本之間有所差異,本案例是以 Finchley.RELEASE 版本為例,來說明 Spring Cloud Zuul 中的異常處理問題。

首先我們來看一張官方給出的 Zuul 請(qǐng)求的生命周期圖:

1、正常情況下所有的請(qǐng)求都是按照 pre、route、post 的順序來執(zhí)行,然后由 post返回 response。

2、在 pre 階段,如果有自定義的過濾器則執(zhí)行自定義的過濾器。

3、pre、routing、post 的任意一個(gè)階段如果拋異常了,則執(zhí)行 error 過濾器。

我們可以有兩種方式統(tǒng)一處理異常:

(1)禁用 zuul 默認(rèn)的異常處理 SendErrorFilter 過濾器,然后自定義我們自己的Errorfilter 過濾器

zuul.SendErrorFilter.error.disable=true
@Component 
public class ErrorFilter extends ZuulFilter { 
    private static final Logger logger = 
LoggerFactory.getLogger(ErrorFilter.class); 
    @Override 
    public String filterType() { 
        return "error"; 
    } 
    @Override 
    public int filterOrder() { 
        return 1; 
    } 
    @Override 
    public boolean shouldFilter() { 
        return true; 
    } 
    @Override 
    public Object run() throws ZuulException { 
        try { 
            RequestContext context = RequestContext.getCurrentContext(); 
            ZuulException exception = (ZuulException)context.getThrowable(); 
            logger.error("進(jìn)入系統(tǒng)異常攔截", exception); 
            HttpServletResponse response = context.getResponse(); 
            response.setContentType("application/json; charset=utf8"); 
            response.setStatus(exception.nStatusCode); 
            PrintWriter writer = null; 
            try { 
                writer = response.getWriter(); 
                writer.print("{code:"+ exception.nStatusCode +",message:\""+ 
exception.getMessage() +"\"}"); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } finally { 
                if(writer!=null){ 
                    writer.close(); 
                } 
            } 
        } catch (Exception var5) { 
            ReflectionUtils.rethrowRuntimeException(var5); 
第  44頁共    52頁
蛙課網(wǎng)【動(dòng)力節(jié)點(diǎn)旗下品牌】
http://www.wkcto.com

 
        } 
        return null; 
    } 
} 

(2)自定義全局 error  錯(cuò)誤頁面

@RestController 
public class ErrorHandlerController implements ErrorController { 
    /** 
     * 出異常后進(jìn)入該方法,交由下面的方法處理
     */ 
    @Override 
    public String getErrorPath() { 
        return "/error"; 
    } 
    @RequestMapping("/error") 
    public Object error(){ 
        RequestContext ctx = RequestContext.getCurrentContext(); 
        ZuulException exception = (ZuulException)ctx.getThrowable(); 
        return exception.nStatusCode + "--" + exception.getMessage(); 
    } 
} 

 

全部教程
主站蜘蛛池模板: 91视频精选 | 毛片www| 一级毛片特黄久久免费看 | 国产福利视频一区二区微拍 | 日韩 欧美 自拍 在线 视频 | 奇米第四色在线观看 | 在线成人亚洲 | 国产性做久久久久久 | 伊人不卡久久大香线蕉综合影院 | 国产精品免费视频一区二区三区 | 国产日韩中文字幕 | 中文字幕视频二区 | 亚洲爽爽| 精品一成人岛国片在线观看 | 91大学生视频 | 国产欧美一区二区精品久久久 | 九九毛片 | 我要看免费的毛片 | 亚洲视频在线观 | 日本精品中文字幕在线不卡 | 在线免费毛片 | 日批视频网址免费观看 | 视频在线观看入口一二三2021 | 123日本不卡在线观看 | 欧美jizz18性欧美 | 日韩免费在线观看 | 不卡视频在线 | 国产色产综合色产在线观看视频 | 国产福利在线播放 | 亚洲欧美精品一区 | 这里只有精品在线观看 | 国产亚洲综合一区在线 | 成人18免费网站 | 日本特一级毛片免费视频 | 黄色网在线 | 亚洲伦理久久 | 久久精品国产久精国产果冻传媒 | 久青草视频免费视频播放线路1 | 亚洲热久久 | 久久久久国产精品 | 性做久久 |