跟我學SpringCloud | 第十二篇:Spring Cloud Gateway初探

来源:https://www.cnblogs.com/babycomeon/archive/2019/07/12/11161073.html
-Advertisement-
Play Games

SpringCloud系列教程 | 第十二篇:Spring Cloud Gateway初探 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如無特殊說明,本系列教程全採用以上版本 前面我們在聊服務網關Zuul的時候提到了Gateway,那麼Z ...


SpringCloud系列教程 | 第十二篇:Spring Cloud Gateway初探

Springboot: 2.1.6.RELEASE

SpringCloud: Greenwich.SR1

如無特殊說明,本系列教程全採用以上版本

前面我們在聊服務網關Zuul的時候提到了Gateway,那麼Zuul和Gateway都是服務網關,這兩個有什麼區別呢?

1. Zuul和Gateway的恩怨情仇

1.1 背景

Zuul是Netflix開源的一個項目,Spring只是將Zuul集成在了Spring Cloud中。而Spring Cloud Gateway是Spring Cloud的一個子項目。

還有一個版本的說法是Zuul2的連續跳票和Zuul1的性能並不是很理想,從而催生了Spring Cloud Gateway。

1.2 性能比較

網上很多地方都說Zuul是阻塞的,Gateway是非阻塞的,這麼說是不嚴謹的,準確的講Zuul1.x是阻塞的,而在2.x的版本中,Zuul也是基於Netty,也是非阻塞的,如果一定要說性能,其實這個真沒多大差距。

而官方出過一個測試項目,創建了一個benchmark的測試項目:spring-cloud-gateway-bench,其中對比了:

  • Spring Cloud Gateway
  • Zuul1.x
  • Linkerd
組件 RPS(request per second)
Spring Cloud Gateway Requests/sec: 32213.38
Zuul Requests/sec: 20800.13
Linkerd Requests/sec: 28050.76

從結果可知,Spring Cloud Gateway的RPS是Zuul1.x的1.6倍。

下麵,我們進入正題,開始聊聊Spring Cloud Gateway的一些事情。

2. Spring Cloud Gateway

Spring Cloud Gateway 是 Spring Cloud 的一個全新項目,該項目是基於 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發的網關,它旨在為微服務架構提供一種簡單有效的統一的 API 路由管理方式。

Spring Cloud Gateway 作為 Spring Cloud 生態系統中的網關,目標是替代 Netflix Zuul,其不僅提供統一的路由方式,並且基於 Filter 鏈的方式提供了網關基本的功能,例如:安全,監控/指標,和限流。

2.1 特征

  • 基於 Spring Framework 5,Project Reactor 和 Spring Boot 2.0

  • 動態路由

  • Predicates 和 Filters 作用於特定路由

  • 集成 Hystrix 斷路器

  • 集成 Spring Cloud DiscoveryClient

  • 易於編寫的 Predicates 和 Filters

  • 限流

  • 路徑重寫

2.2 術語

  • Route(路由):這是網關的基本構建塊。它由一個 ID,一個目標 URI,一組斷言和一組過濾器定義。如果斷言為真,則路由匹配。

  • Predicate(斷言):這是一個 Java 8 的 Predicate。輸入類型是一個 ServerWebExchange。我們可以使用它來匹配來自 HTTP 請求的任何內容,例如 headers 或參數。

  • Filter(過濾器):這是org.springframework.cloud.gateway.filter.GatewayFilter的實例,我們可以使用它修改請求和響應。

2.3 流程

客戶端向 Spring Cloud Gateway 發出請求。然後在 Gateway Handler Mapping 中找到與請求相匹配的路由,將其發送到 Gateway Web Handler。Handler 再通過指定的過濾器鏈來將請求發送到我們實際的服務執行業務邏輯,然後返回。過濾器之間用虛線分開是因為過濾器可能會在發送代理請求之前(“pre”)或之後(“post”)執行業務邏輯。

3.快速上手

Spring Cloud Gateway 網關路由有兩種配置方式:

  • 在配置文件 yml 中配置

  • 通過@Bean自定義 RouteLocator,在啟動主類 Application 中配置

這兩種方式是等價的,建議使用 yml 方式進配置。

3.1 項目依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springcloud</groupId>
    <artifactId>gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Spring Cloud Gateway 是使用 netty+webflux 實現因此不需要再引入 web 模塊。

3.2 配置文件

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://blog.csdn.net
          predicates:
            - Path=/meteor_93

各欄位含義如下:

  • id:我們自定義的路由 ID,保持唯一
  • uri:目標服務地址
  • predicates:路由條件,Predicate 接受一個輸入參數,返回一個布爾值結果。該介面包含多種預設方法來將 Predicate 組合成其他複雜的邏輯(比如:與,或,非)。

上面這段配置的意思是,配置了一個 id 為 gateway-service 的路由規則,當訪問地址 http://localhost:8080/meteor_93時會自動轉發到地址:http://localhost:8080/meteor_93。

3.3 測試

現在我們啟動服務,在瀏覽器中訪問地址http://localhost:8080/meteor_93 時會展示頁面展示如下:

證明頁面轉發成功。

3.4 另一種路由配置方式

轉發功能同樣可以通過代碼來實現,我們可以在啟動類 GateWayApplication 中添加方法 customRouteLocator() 來定製轉發規則。

package com.springcloud.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class GatewayApplication {

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

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route", r -> r.path("/meteor_93")
                        .uri("https://blog.csdn.net"))
                .build();
    }

}

我們在yaml配置文件中註銷掉相關路由的配置,重啟服務,訪問鏈接:http://localhost:8080/meteor_93, 可以看到和上面一樣的頁面,證明我們測試成功。

上面兩個示例中 uri 都是指向了我的CSDN博客,在實際項目使用中可以將 uri 指向對外提供服務的項目地址,統一對外輸出介面。

以上便是 Spring Cloud Gateway 最簡單的兩個請求示例,Spring Cloud Gateway 還有更多實用的功能接下來我們一一介紹。

4. 路由規則

Spring Cloud Gateway 的功能很強大,我們僅僅通過 Predicates 的設計就可以看出來,前面我們只是使用了 predicates 進行了簡單的條件匹配,其實 Spring Cloud Gataway 幫我們內置了很多 Predicates 功能。

Spring Cloud Gateway 是通過 Spring WebFlux 的 HandlerMapping 做為底層支持來匹配到轉發路由,Spring Cloud Gateway 內置了很多 Predicates 工廠,這些 Predicates 工廠通過不同的 HTTP 請求參數來匹配,多個 Predicates 工廠可以組合使用。

4.1 Predicate 介紹

Predicate 來源於 Java 8,是 Java 8 中引入的一個函數,Predicate 接受一個輸入參數,返回一個布爾值結果。該介面包含多種預設方法來將 Predicate 組合成其他複雜的邏輯(比如:與,或,非)。可以用於介面請求參數校驗、判斷新老數據是否有變化需要進行更新操作。

在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性實現了各種路由匹配規則,有通過 Header、請求參數等不同的條件來進行作為條件匹配到對應的路由。網上有一張圖總結了 Spring Cloud 內置的幾種 Predicate 的實現。

說白了 Predicate 就是為了實現一組匹配規則,方便讓請求過來找到對應的 Route 進行處理,接下來我們接下 Spring Cloud GateWay 內置幾種 Predicate 的使用。

4.2 通過時間匹配

Predicate 支持設置一個時間,在請求進行轉發的時候,可以通過判斷在這個時間之前或者之後進行轉發。比如我們現在設置只有在2019年1月1日才會轉發到我的博客,在這之前不進行轉發,我就可以這樣配置:

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - After=2019-01-01T00:00:00+08:00[Asia/Shanghai]

Spring 是通過 ZonedDateTime 來對時間進行的對比,ZonedDateTime 是 Java 8 中日期時間功能里,用於表示帶時區的日期與時間信息的類,ZonedDateTime 支持通過時區來設置時間,中國的時區是:Asia/Shanghai。

After Route Predicate 是指在這個時間之後的請求都轉發到目標地址。上面的示例是指,請求時間在 2019年1月1日0點0分0秒之後的所有請求都轉發到地址https://blog.csdn.net。+08:00是指時間和UTC時間相差八個小時,時間地區為Asia/Shanghai。

添加完路由規則之後,訪問地址http://localhost:8080會自動轉發到https://www.baidu.com。

Before Route Predicate 剛好相反,在某個時間之前的請求的請求都進行轉發。我們把上面路由規則中的 After 改為 Before,如下:

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Before=2019-01-01T00:00:00+08:00[Asia/Shanghai]

就表示在這個時間之前可以進行路由,在這時間之後停止路由,修改完之後重啟項目再次訪問地址http://localhost:8080,頁面會報 404 沒有找到地址。

除過在時間之前或者之後外,Gateway 還支持限制路由請求在某一個時間段範圍內,可以使用 Between Route Predicate 來實現。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Between=2019-01-01T00:00:00+08:00[Asia/Shanghai], 2019-07-01T00:00:00+08:00[Asia/Shanghai]

這樣設置就意味著在這個時間段內可以匹配到此路由,超過這個時間段範圍則不會進行匹配。通過時間匹配路由的功能很酷,可以用在限時活動的一些場景中。

Cookie Route Predicate 可以接收兩個參數,一個是 Cookie name ,一個是正則表達式,路由規則會通過獲取對應的 Cookie name 值和正則表達式去匹配,如果匹配上就會執行路由,如果沒有匹配上則不執行。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Cookie=sessionId, test

使用 curl 測試,命令行輸入:

curl http://localhost:8080 --cookie "sessionId=test"

則會返回頁面代碼,如果去掉--cookie "sessionId=test",後臺彙報 404 錯誤。

4.4 通過 Header 屬性匹配

Header Route Predicate 和 Cookie Route Predicate 一樣,也是接收 2 個參數,一個 header 中屬性名稱和一個正則表達式,這個屬性值和正則表達式匹配則執行。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Header=X-Request-Id, \d+

使用 curl 測試,命令行輸入:

curl http://localhost:8080  -H "X-Request-Id:88" 

則返回頁面代碼證明匹配成功。將參數-H "X-Request-Id:88"改為-H "X-Request-Id:spring"再次執行時返回404證明沒有匹配。

4.5 通過 Host 匹配

Host Route Predicate 接收一組參數,一組匹配的功能變數名稱列表,這個模板是一個 ant 分隔的模板,用.號作為分隔符。它通過參數中的主機地址作為匹配規則。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Host=**.baidu.com

使用 curl 測試,命令行輸入:

curl http://localhost:8080  -H "Host: www.baidu.com" 
curl http://localhost:8080  -H "Host: md.baidu.com" 

經測試以上兩種 host 均可匹配到 host_route 路由,去掉 host 參數則會報 404 錯誤。

4.6 通過請求方式匹配

可以通過是 POST、GET、PUT、DELETE 等不同的請求方式來進行路由。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Method=GET

使用 curl 測試,命令行輸入:

# curl 預設是以 GET 的方式去請求
curl http://localhost:8080

測試返回頁面代碼,證明匹配到路由,我們再以 POST 的方式請求測試。

# curl 預設是以 GET 的方式去請求
curl -X POST http://localhost:8080

返回 404 沒有找到,證明沒有匹配上路由

4.7 通過請求路徑匹配

Path Route Predicate 接收一個匹配路徑的參數來判斷是否走路由。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: http://ityouknow.com
          order: 0
          predicates:
            - Path=/foo/{segment}

如果請求路徑符合要求,則此路由將匹配,例如:/foo/1 或者 /foo/bar。

使用 curl 測試,命令行輸入:

curl http://localhost:8080/foo/1
curl http://localhost:8080/foo/xx
curl http://localhost:8080/boo/xx

經過測試第一和第二條命令可以正常獲取到頁面返回值,最後一個命令報404,證明路由是通過指定路由來匹配。

4.8 通過請求參數匹配

Query Route Predicate 支持傳入兩個參數,一個是屬性名一個為屬性值,屬性值可以是正則表達式。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Query=smile

這樣配置,只要請求中包含 smile 屬性的參數即可匹配路由。

使用 curl 測試,命令行輸入:

curl localhost:8080?smile=x&id=2

經過測試發現只要請求彙總帶有 smile 參數即會匹配路由,不帶 smile 參數則不會匹配。

還可以將 Query 的值以鍵值對的方式進行配置,這樣在請求過來時會對屬性值和正則進行匹配,匹配上才會走路由。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Query=keep, pu.

這樣只要當請求中包含 keep 屬性並且參數值是以 pu 開頭的長度為三位的字元串才會進行匹配和路由。

使用 curl 測試,命令行輸入:

curl localhost:8080?keep=pub

測試可以返回頁面代碼,將 keep 的屬性值改為 pubx 再次訪問就會報 404,證明路由需要匹配正則表達式才會進行路由。

4.9 通過請求 ip 地址進行匹配

Predicate 也支持通過設置某個 ip 區間號段的請求才會路由,RemoteAddr Route Predicate 接受 cidr 符號(IPv4 或 IPv6 )字元串的列表(最小大小為1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子網掩碼)。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - RemoteAddr=192.168.1.1/24

可以將此地址設置為本機的 ip 地址進行測試。

curl localhost:8080

如果請求的遠程地址是 192.168.1.10,則此路由將匹配。

4.10 組合使用

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Host=**.foo.org
            - Path=/headers
            - Method=GET
            - Header=X-Request-Id, \d+
            - Query=foo, ba.
            - Query=baz
            - Cookie=chocolate, ch.p
            - After=2018-01-20T06:06:06+08:00[Asia/Shanghai]

各種 Predicates 同時存在於同一個路由時,請求必須同時滿足所有的條件才被這個路由匹配。

一個請求滿足多個路由的謂詞條件時,請求只會被首個成功匹配的路由轉發

以上就是今天的內容,我們主要聊了Gateway的基礎路由規則,後面的章節我們接著聊更多的高級內容,比如:Filter、熔斷和限流等。

示例代碼-Github

參考:

https://cloud.spring.io/spring-cloud-gateway/single/spring-cloud-gateway.html
http://www.ityouknow.com/springcloud/2018/12/12/spring-cloud-gateway-start.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 需求 在開發vue的項目中有遇到了這樣一個需求:一個視頻列表頁面,展示視頻名稱和是否收藏,點擊進去某一項觀看,可以收藏或者取消收藏,返回的時候需要記住列表頁面的頁碼等狀態,同時這條視頻的收藏狀態也需要更新, 但是從其他頁面進來視頻列表頁面的時候不緩存這個頁面,也就是進入的時候是視頻列表頁面的第一頁 ...
  • 一、什麼是組件? 組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以表現為用 is 特性進行了擴展的原生 HTML 元素。 <body> < ...
  • 本文介紹TypeScript中泛型的概念,以簡單直白的方式,向那些不瞭解此概念,但渴望在工作中使用它的開發者,提供入門指導。 ...
  • 以上是效果圖,本圖表使用d3.js v4製作。圖表主要功能是在六邊形格子中顯示數據,點擊底部圖標可以切換指定格子高亮顯示,圖表可以隨瀏覽器任意縮放。 1.圖表的主體結構是由正六邊形組成,使用d3生成六邊形可以使用d3-hexbin.js,生成六邊形比較方便,只要給定中心點坐標和半徑即可生成六邊形路徑 ...
  • 問題一、微信瀏覽器中無法使用reload重載文檔【VUE框架】 問題分析: 微信不支持location.reload()方法,在微信瀏覽器中會失效 Vue中的路由跳轉是類似於ajax局部刷新,因此使用location.href=‘xxx+時間戳’ 這種方法時,頁面不會重載 Vue自帶的this.$r ...
  • 1.地圖繪製過程原理 給定範圍邊界經緯度數據,再給它個名字就構成了繪製地圖的基礎。也就是說,你可以繪製任意形狀的地圖版塊。 2.地圖數據生成 中國以及省市縣等地圖的基礎數據可以從這裡生成與下載。 "http://datav.aliyun.com/tools/atlas" 有了地圖範圍數據,在 ech ...
  • 哈哈,久違了各位。我又回來了,最近在做畢設,所以難免會遇到很多問題,需要解決很多問題,在萬能的博友幫助下,終於解決了Element-ui中輪播圖的圖片高度問題,話不多說上代碼。 那個axios的使用不重要,大致思路就是頁面渲染前拿到當前視窗的寬度*圖片比例給輪播圖一個初始的高度,當窗後大小發生變化時 ...
  • 本人剛學先上鏈接(別人寫的挺好的)後期同步補上😄!!! 網站鏈接:https://blog.csdn.net/baozhiqiangjava/article/details/81178694 GitHub:https://github.com/JsAaron/jQuery ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...