你想了解的「SpringCloud」都在這裏

前言: 以前咱們已經瞭解了「什麼是微服務?」,如今咱們開始瞭解「微服務」關鍵字下比較熱門的「Spring Cloud」...html

1、傳統架構發展史


部分引用自:從架構演進的角度聊聊Spring Cloud都作了些什麼? - 純潔的微笑前端

單體架構

單體架構在小微企業比較常見,典型表明就是一個應用、一個數據庫、一個web容器就能夠跑起來。java

在兩種狀況下可能會選擇單體架構:一是在企業發展的初期,爲了保證快速上線,採用此種方案較爲簡單靈活;二是傳統企業中垂直度較高,訪問壓力較小的業務。在這種模式下對技術要求較低,方便各層次開發人員接手,也能知足客戶需求。git

下面是單體架構的架構圖:程序員

在單體架構中,技術選型很是靈活,優先知足快速上線的要求,也便於快速跟進市場。github

垂直架構

在單體架構發展一段時間後,公司的業務模式獲得了承認,交易量也慢慢的大起來,這時候有些企業爲了應對更大的流量,就會對原有的業務進行拆分,好比說:後臺系統、前端系統、交易系統等。web

在這一階段每每會將系統分爲不一樣的層級,每一個層級有對應的職責,UI層負責和用戶進行交互、業務邏輯層負責具體的業務功能、數據庫層負責和上層進行數據交換和存儲。spring

下面是垂直架構的架構圖:數據庫

服務化架構

若是公司進一步的作大,垂直子系統會變的愈來愈多,系統和系統之間的調用關係呈指數上升的趨勢。在這樣的背景下,不少公司都會考慮服務的 SOA 化。SOA 表明面向服務的架構,將應用程序根據不一樣的職責劃分爲不一樣的模塊,不一樣的模塊直接經過特定的協議和接口進行交互。這樣使整個系統切分紅不少單個組件服務來完成請求,當流量過大時經過水平擴展相應的組件來支撐,全部的組件經過交互來知足總體的業務需求。c#

SOA服務化的優勢是,它能夠根據需求經過網絡對鬆散耦合的粗粒度應用組件進行分佈式部署、組合和使用。服務層是SOA的基礎,能夠直接被應用調用,從而有效控制系統中與軟件代理交互的人爲依賴性。

服務化架構是一套鬆耦合的架構,服務的拆分原則是服務內部高內聚,服務之間低耦合。

下面是服務化架構圖:

在這個階段可使用 WebService 或者 Dubbo 來服務治理。

咱們發現從單體架構到服務化架構,應用數量都在不斷的增長,慢慢的下沉的就成了基礎組建,上浮的就成爲業務系統。從上述也能夠看出架構的本質就是不斷的拆分重構:分的過程是把系統拆分爲各個子系統/模塊/組件,拆的時候,首先要解決每一個組件的定位問題,而後才能劃分彼此的邊界,實現合理的拆分。合就是根據最終要求,把各個分離的組件有機整合在一塊兒。拆分的結果使開發人員可以作到業務聚焦、技能聚焦,實現開發敏捷,合的結果是系統變得柔性,能夠因需而變,實現業務敏捷。

微服務架構

微服務是一種軟件架構風格,它是以專一於單一責任與功能的小型功能區塊爲基礎,利用模組化的方式組合出複雜的大型應用程序,各功能區塊使用與語言無關的 API(例如 REST)集相互通信,且每一個服務能夠被單獨部署,它具有如下三個核心特色:

  • 微服務爲大型系統而生。隨着業務的快速增加,會帶來系統流量壓力和複雜度的上升,系統的可維護性和可擴展性成爲架構設計的主要考慮因素,微服務架構設計理念經過小而美的業務拆分,經過分而自治來實現複雜系統的優雅設計實現。
  • 微服務架構是面向結果的。微服務架構設計風格的產生並不是是出於學術或爲標準而標準的設計,而是在軟件架構設計領域不斷演進過程當中,面對實際工業界所遇到問題,而出現的面向解決實際問題的架構設計風格。
  • 專一於服務的可替代性來設計。微服務架構設計風格核心要解決的問題之一即是如何便利地在大型系統中進行系統組件的維護和替換,且不影響總體系統穩定性。

SOA微服務 的不一樣在於:

  • 服務拆分粒度更細。微服務能夠說是更細維度的服務化,小到一個子子模塊,只要該模塊依賴的資源與其餘模塊都沒有關係,那麼就能夠拆分紅一個微服務。
  • 服務獨立部署。每一個服務都嚴格遵循獨立打包部署的準則,互不影響。好比一臺物理機上能夠部署多個 Docker 實例,每一個 Docker 實例能夠部署一個微服務的代碼。
  • 服務獨立維護。每一個微服務均可以交由一個小團隊甚至我的來開發、測試、發佈和運維,並對整個生命週期負責。
  • 服務治理能力要求高。由於拆分爲微服務以後,服務的數量變多,所以須要有統一的服務治理平臺,來對各個服務進行管理。

2、引入 Spring Cloud


什麼是 Spring Cloud?

Spring 全家桶在 Java 開發中擁有舉足輕重的地位,其中的一系列產品不只僅大大簡化和方便了 Java 的開發,其中的 AOP 和 IoC 等一系列的理念也深入地影響着 Java 程序員們。

Spring 全家桶產品衆多,總結起來大概就是:

  • Spring 一般指 Spring IOC。
  • Spring Framework 包含了 Spring IOC,同時包含了 Spring AOP,並實現與其它 J2EE 框架的整合。
  • Spring Boot 是對 Spring Framework 的補充,讓框架的集成變得更簡單,致力於快速開發 獨立的 Spring 應用。
  • Spring Cloud 是基於 Spring Boot 設計的一套微服務規範,並加強了應用上下文。

咱們也不妨來看看官網的介紹:

總結起來就是: Spring Cloud 是一系列框架的有序集合。咱們可以使用基於 Spring Boot 設計的 Spring Cloud 方便快速的搭建起本身的可靠、協調一致的分佈式系統。

爲何是 Spring Cloud?

微服務的框架那麼多好比:Dubbo、Kubernetes,爲何就要使用 Spring Cloud 的呢?

  • 產出於 Spring 你們族,Spring 在企業級開發框架中無人能敵,來頭很大,能夠保證後續的更新、完善。好比 Dubbo 如今就差很少死了
  • 有 Spring Boot 這個獨立干將能夠省不少事,大大小小的活 Spring Boot 都搞的挺不錯。
  • 做爲一個微服務治理的你們夥,考慮的很全面,幾乎服務治理的方方面面都考慮到了,方便開發開箱即用。
  • Spring Cloud 活躍度很高,教程很豐富,遇到問題很容易找到解決方案。
  • 輕輕鬆鬆幾行代碼就完成了熔斷、均衡負載、服務中心的各類平臺功能。

3、Spring Cloud 可以幫咱們作什麼?


前面咱們說到了,「Spring Cloud」是一系列框架的集合,能夠幫助咱們解決分佈式/微服務的各類問題,那麼「Spring Cloud」究竟能幫助咱們作什麼呢?

SpringCloud的基礎功能包括:

  • 服務治理: Spring Cloud Eureka
  • 客戶端負載均衡: Spring Cloud Ribbon
  • 服務容錯保護: Spring Cloud Hystrix
  • 聲明式服務調用: Spring Cloud Feign
  • API網關服務: Spring Cloud Zuul
  • 分佈式配置中心: Spring Cloud Config

固然 Spring Cloud 還包括一些高級的功能:

  • 消息總線: Spring Cloud Bus
  • 消息驅動的微服務: Spring Cloud Stream
  • 分佈式服務跟蹤: Spring Cloud Sleuth

服務治理:Eureka

微服務很重要的一點就是「無狀態」,也就是說每個服務之間應該是獨立的,因此當微服務架構搭起來以後各個獨立的「微服務」之間應該如何通信成了首要的問題。

假設咱們的 A服務 須要訪問 B服務,那麼咱們首先須要知道對方的 ip地址,因此咱們調用起來可能就像:

彷佛並無什麼問題,可是若是 B服務 的 ip地址 變動了,那麼咱們就只能手動的去更改 A服務 的配置,若是咱們的服務有不少,而且不止 A服務 調用了 B服務,那麼手動更改這些配置將會是一場噩夢。

Eureka 是 Netflix 開源的一款提供服務註冊和發現的產品,它提供了完整的 Service Registry 和 Service Discovery 實現。也是 Spring Cloud 體系中最重要最核心的組件之一。

用大白話講,Eureka 就是一個服務中心,將全部的能夠提供的服務都註冊到它這裏來管理,其它各調用者須要的時候去註冊中心獲取,而後再進行調用,避免了服務之間的直接調用,方便後續的水平擴展、故障轉移等。以下圖:

固然服務中心這麼重要的組件一但掛掉將會影響所有服務,所以須要搭建 Eureka 集羣來保持高可用性,生產中建議最少兩臺。隨着系統的流量不斷增長,須要根據狀況來擴展某個服務,Eureka 內部已經提供均衡負載的功能,只須要增長相應的服務端實例既可。那麼在系統的運行期間某個實例掛了怎麼辦?Eureka 內容有一個心跳檢測機制, 若是某個實例在規定的時間內沒有進行通信則會自動被剔除掉,避免了某個實例掛掉而影響服務。

所以使用了Eureka就自動具備了註冊中心、負載均衡、故障轉移的功能。若是想對Eureka進一步瞭解能夠參考這篇文章:註冊中心Eureka

客戶端負載均衡: Ribbon

Ribbon 是一個基於 HTTP 和 TCP 客戶端的負載均衡器。Ribbon 能夠在經過客戶端中配置的 ribbonServerList 服務端列表去輪詢訪問以達到均衡負載的做用。

當 Ribbon 與 Eureka 聯合使用時,ribbonServerList 會被 DiscoveryEnabledNIWSServerList 重寫,擴展成從 Eureka 註冊中心中獲取服務端列表。同時它也會用 NIWSDiscoveryPing 來取代 IPing,它將職責委託給 Eureka 來肯定服務端是否已經啓動。

  • 實戰:

Spring Cloud構建微服務架構(二)服務消費者 - http://blog.didispace.com/springcloud2/

服務容錯保護: Hystrix

在微服務架構中一般會有多個服務層調用,基礎服務的故障可能會致使級聯故障,進而形成整個系統不可用的狀況,這種現象被稱爲服務雪崩效應。服務雪崩效應是一種因「服務提供者」的不可用致使「服務消費者」的不可用,並將不可用逐漸放大的過程。

以下圖所示:A做爲服務提供者,B爲A的服務消費者,C和D是B的服務消費者。A不可用引發了B的不可用,並將不可用像滾雪球同樣放大到C和D時,雪崩效應就造成了。

在這種狀況下就須要整個服務機構具備故障隔離的功能,避免某一個服務掛掉影響全局。在 Spring Cloud 中 Hystrix 組件就扮演這個角色。

Hystrix 會在某個服務連續調用 N 次不響應的狀況下,當即通知調用端調用失敗,避免調用端持續等待而影響了總體服務。Hystrix 間隔時間會再次檢查此服務,若是服務恢復將繼續提供服務。

繼續瞭解Hystrix能夠參考:熔斷器Hystrix

Hystrix Dashboard 和 Turbine

當熔斷髮生的時候須要迅速的響應來解決問題,避免故障進一步擴散,那麼對熔斷的監控就變得很是重要。熔斷的監控如今有兩款工具:Hystrix-dashboard 和 Turbine

Hystrix-dashboard 是一款針對Hystrix進行實時監控的工具,經過 Hystrix Dashboard 咱們能夠直觀地看到各 Hystrix Command 的請求響應時間, 請求成功率等數據。可是隻使用 Hystrix Dashboard 的話, 你只能看到單個應用內的服務信息, 這明顯不夠. 咱們須要一個工具能讓咱們彙總系統內多個服務的數據並顯示到 Hystrix Dashboard 上, 這個工具就是 Turbine. 監控的效果圖以下:

想了解具體都監控了哪些指標,以及如何監控能夠參考這篇文章:熔斷監控Hystrix Dashboard和Turbine

聲明式服務調用:Feign

上面咱們介紹了 Ribbon 和 Hystrix 了,能夠發現:這兩個能夠做爲基礎工具類普遍的嵌入到各個微服務中。爲了簡化咱們的開發,Spring Cloud Feign 出現了!它基於 Netflix Feign 實現,整合了 Spring Cloud Ribbon 與 Spring Cloud Hystrix, 除了整合這二者的強大功能以外,它還提供了聲明式的服務調用(再也不經過RestTemplate)。

Feign 是一種聲明式、模板化的HTTP客戶端。在 Spring Cloud 中使用 Feign, 咱們能夠作到使用HTTP請求遠程服務時能與調用本地方法同樣的編碼體驗,開發者徹底感知不到這是遠程方法,更感知不到這是個 HTTP 請求。

下面就簡單看看Feign是怎麼優雅地實現遠程調用的:

服務綁定:

// value --->指定調用哪一個服務
// fallbackFactory--->熔斷器的降級提示
@FeignClient(value = "MICROSERVICECLOUD-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {

    // 採用Feign咱們可使用SpringMVC的註解來對服務進行綁定!
    @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
    public Dept get(@PathVariable("id") long id);

    @RequestMapping(value = "/dept/list", method = RequestMethod.GET)
    public List<Dept> list();

    @RequestMapping(value = "/dept/add", method = RequestMethod.POST)
    public boolean add(Dept dept);
}

Feign 中使用熔斷器:

/**
 * Feign中使用斷路器
 * 這裏主要是處理異常出錯的狀況(降級/熔斷時服務不可用,fallback就會找到這裏來)
 */
@Component // 不要忘記添加,不要忘記添加
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
    @Override
    public DeptClientService create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public Dept get(long id) {
                return new Dept().setDeptno(id).setDname("該ID:" + id + "沒有沒有對應的信息,Consumer客戶端提供的降級信息,此刻服務Provider已經關閉")
                        .setDb_source("no this database in MySQL");
            }

            @Override
            public List<Dept> list() {
                return null;
            }

            @Override
            public boolean add(Dept dept) {
                return false;
            }
        };
    }
}

調用:

API 網關服務:Zuul

在微服務架構模式下,後端服務的實例數通常是動態的,對於客戶端而言很難發現動態改變的服務實例的訪問地址信息。所以在基於微服務的項目中爲了簡化前端的調用邏輯,一般會引入 API Gateway 做爲輕量級網關,同時 API Gateway 中也會實現相關的認證邏輯從而簡化內部服務之間相互調用的複雜度。

Spring Cloud 體系中支持 API Gateway 落地的技術就是 Zuul。Spring Cloud Zuul 路由是微服務架構中不可或缺的一部分,提供動態路由,監控,彈性,安全等的邊緣服務。Zuul 是 Netflix 出品的一個基於 JVM 路由和服務端的負載均衡器。

它的具體做用就是服務轉發,接收並轉發全部內外部的客戶端調用。使用 Zuul 能夠做爲資源的統一訪問入口,同時也能夠在網關作一些權限校驗等相似的功能。

具體使用參考這篇文章:服務網關zuul

分佈式配置中心:Config

隨着業務的不斷髮展,咱們的「微服務」可能會愈來愈多,而每個微服務都會有本身的配置文件,在研發過程當中有測試環境、UAT環境、生產環境,所以每一個微服務又對應至少三個不一樣環境的配置文件。這麼多的配置文件,若是須要修改某個公共服務的配置信息,如:緩存、數據庫等,不免會產生混亂,這個時候就須要引入 Spring Cloud 另一個組件:Spring Cloud Config。

Spring Cloud Config 是一個解決分佈式系統的配置管理方案。它包含了 Client 和 Server 兩個部分,Server 提供配置文件的存儲、以接口的形式將配置文件的內容提供出去,Client 經過接口獲取數據、並依據此數據初始化本身的應用。

其實就是 Server 端將全部的配置文件服務化,須要配置文件的服務實例去 Config Server 獲取對應的數據。將全部的配置文件統一整理,避免了配置文件碎片化。配置中心git實例參考:配置中心git示例

若是服務運行期間改變配置文件,服務是不會獲得最新的配置信息,須要解決這個問題就須要引入 Refresh。能夠在服務的運行期間從新加載配置文件,具體能夠參考這篇文章:配置中心svn示例和refresh

當全部的配置文件都存儲在配置中心的時候,配置中心就成爲了一個很是重要的組件。若是配置中心出現問題將會致使災難性的後果,所以在生產中建議對配置中心作集羣,來支持配置中心高可用性。具體參考:配置中心服務化和高可用

消息總線:Bus

上面的 Refresh 方案雖然能夠解決單個微服務運行期間重載配置信息的問題,可是在真正的實踐生產中,可能會有 N 多的服務須要更新配置,若是每次依靠手動 Refresh 將是一個巨大的工做量,這時候 Spring Cloud 提出了另一個解決方案:Spring Cloud Bus

Spring Cloud Bus 經過輕量消息代理鏈接各個分佈的節點。這會用在廣播狀態的變化(例如配置變化)或者其它的消息指令中。Spring Cloud Bus 的一個核心思想是經過分佈式的啓動器對Spring Boot應用進行擴展,也能夠用來創建一個或多個應用之間的通訊頻道。目前惟一實現的方式是用 AMQP 消息代理做爲通道。

Spring Cloud Bus 是輕量級的通信組件,也能夠用在其它相似的場景中。有了 Spring Cloud Bus 以後,當咱們改變配置文件提交到版本庫中時,會自動的觸發對應實例的 Refresh,具體的工做流程以下:

也能夠參考這篇文章來了解:配置中心和消息總線

消息驅動的微服務:Stream

Spring Cloud Stream 是一個用來爲微服務應用構建消息驅動能力的框架。它能夠基於 Spring Boot 來建立獨立的、可用於生產的 Spring 應用程序。它經過使用 Spring Integration 來鏈接消息代理中間件以實現消息事件驅動的微服務應用。

下圖是官方文檔中對於 Spring Cloud Stream 應用模型的結構圖。從中咱們能夠看到,Spring Cloud Stream 構建的應用程序與消息中間件之間是經過綁定器 Binder 相關聯的,綁定器對於應用程序而言起到了隔離做用,它使得不一樣消息中間件的實現細節對應用程序來講是透明的。因此對於每個 Spring Cloud Stream 的應用程序來講,它不須要知曉消息中間件的通訊細節,它只須要知道 Binder 對應用程序提供的概念去實現便可。以下圖案例,在應用程序和 Binder 之間定義了兩條輸入通道和三條輸出通道來傳遞消息,而綁定器則是做爲這些通道和消息中間件之間的橋樑進行通訊。

Spring Cloud Stream 爲一些供應商的消息中間件產品提供了個性化的自動化配置實現,而且引入了發佈-訂閱、消費組以及消息分區這三個核心概念。簡單的說,Spring Cloud Stream 本質上就是整合了 Spring Boot 和 Spring Integration,實現了一套輕量級的消息驅動的微服務框架。經過使用 Spring Cloud Stream,能夠有效地簡化開發人員對消息中間件的使用複雜度,讓系統開發人員能夠有更多的精力關注於核心業務邏輯的處理。因爲 Spring Cloud Stream 基於 Spring Boot 實現,因此它秉承了 Spring Boot 的優勢,實現了自動化配置的功能幫忙咱們能夠快速的上手使用,可是目前爲止 Spring Cloud Stream 只支持 RabbitMQKafka 兩個著名的消息中間件的自動化配置:

分佈式服務跟蹤:Sleuth

隨着服務的愈來愈多,對調用鏈的分析會愈來愈複雜,如服務之間的調用關係、某個請求對應的調用鏈、調用之間消費的時間等,對這些信息進行監控就成爲一個問題。在實際的使用中咱們須要監控服務和服務之間通信的各項指標,這些數據將是咱們改進系統架構的主要依據。所以分佈式的鏈路跟蹤就變的很是重要,Spring Cloud 也給出了具體的解決方案:Spring Cloud Sleuth 和 Zipkin

Spring Cloud Sleuth 爲服務之間調用提供鏈路追蹤。經過 Sleuth 能夠很清楚的瞭解到一個服務請求通過了哪些服務,每一個服務處理花費了多長時間。從而讓咱們能夠很方便的理清各微服務間的調用關係。

Zipkin 是 Twitter 的一個開源項目,容許開發者收集 Twitter 各個服務上的監控數據,並提供查詢接口

分佈式鏈路跟蹤須要 Sleuth + Zipkin 結合來實現,具體操做參考這篇文章:分佈式鏈路跟蹤(Sleuth)

總結

咱們從總體上來看一下Spring Cloud各個組件如何來配套使用:

從上圖能夠看出 Spring Cloud 各個組件相互配合,合做支持了一套完整的微服務架構。

  • 其中 Eureka 負責服務的註冊與發現,很好將各服務鏈接起來
  • Hystrix 負責監控服務之間的調用狀況,連續屢次失敗進行熔斷保護。
  • Hystrix dashboard,Turbine 負責監控 Hystrix 的熔斷狀況,並給予圖形化的展現
  • Spring Cloud Config 提供了統一的配置中心服務
  • 當配置文件發生變化的時候,Spring Cloud Bus 負責通知各服務去獲取最新的配置信息
  • 全部對外的請求和服務,咱們都經過 Zuul 來進行轉發,起到 API 網關的做用
  • 最後咱們使用 Sleuth + Zipkin 將全部的請求數據記錄下來,方便咱們進行後續分析

Spring Cloud 從設計之初就考慮了絕大多數互聯網公司架構演化所需的功能,如服務發現註冊、配置中心、消息總線、負載均衡、斷路器、數據監控等。這些功能都是以插拔的形式提供出來,方便咱們系統架構演進的過程當中,能夠合理的選擇須要的組件進行集成,從而在架構演進的過程當中會更加平滑、順利。

微服務架構是一種趨勢,Spring Cloud 提供了標準化的、全站式的技術方案,意義可能會堪比當前 Servlet 規範的誕生,有效推動服務端軟件系統技術水平的進步。

引用自:從架構演進的角度聊聊Spring Cloud都作了些什麼? - http://www.ityouknow.com/springcloud/2017/11/02/framework-and-springcloud.html

4、Spring Cloud 版本


剛接觸的「Spring Cloud」的童鞋可能會對它的版本感到奇怪,什麼 AngleBrixtonFinchley,這些都是啥啊?「爲何會有這麼多種看起來不一樣的 Spring Cloud?」

從上面咱們能夠知道:Spring Cloud 是一個擁有諸多子項目的大型綜合項目(功能不止上面的介紹),原則上其子項目也都維護着本身的發佈版本號。那麼每個Spring Cloud的版本都會包含不一樣的子項目版本,爲了要管理每一個版本的子項目清單,避免版本名與子項目的發佈號混淆,因此沒有采用版本號的方式,而是經過命名的方式。

這些版本名字採用了倫敦地鐵站的名字,根據字母表的順序來對應版本時間順序,好比:最先的Release版本:Angel,第二個Release版本:Brixton,以此類推……

當一個項目到達發佈臨界點或者解決了一個嚴重的 BUG 後就會發佈一個 "service Release" 版本, 簡稱 SR(X)版本,x 表明一個遞增數字。

Spring Cloud & Spring Boot 版本對照表

經過查閱官網:https://spring.io/projects/spring-cloud,咱們能夠看到一個「Release train Spring Boot compatibility」表:

Release Train Boot Version
Greenwich 2.1.x
Finchley 2.0.x
Edgware 1.5.x
Dalston 1.5.x

上表能夠看出,最新的「Spring Cloud」版本已經出到了 Greenwich... 每一個版本都能查閱到當前版本所包含的子項目,以及子項目的版本號,咱們能夠經過此來決定須要選擇怎麼樣的版本。

參考資料


1. 外行人都能看懂的SpringCloud,錯過了血虧! - https://juejin.im/post/5b83466b6fb9a019b421cecc#heading-19
2. 從架構演進的角度聊聊Spring Cloud都作了些什麼? - http://www.ityouknow.com/springcloud/2017/11/02/framework-and-springcloud.html
3. 聊聊Spring Cloud版本的那些事兒 - http://blog.didispace.com/springcloud-version/
4. Spring Cloud 從入門到精通 - http://blog.didispace.com/spring-cloud-learning/
5. Spring Cloud 中文網 - https://springcloud.cc/


按照慣例黏一個尾巴:

歡迎轉載,轉載請註明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz 歡迎關注公衆微信號:wmyskxz 分享本身的學習 & 學習資料 & 生活 想要交流的朋友也能夠加qq羣:3382693

相關文章
相關標籤/搜索