天天看點

分布式項目的學而思2:SpringCloud Alibaba的nacos作為注冊中心和配置中心,feign 遠端調用,gateway網關

SpringCloud Alibaba

簡介和緣由

SpringCloud 的幾大痛點
  SpringCloud 部分元件停止維護和更新,給開發帶來不便;比如eureka停止運維
  SpringCloud 部分環境搭建複雜,沒有完善的可視化界面,我們需要大量的二次開發和定制
  SpringCloud 配置複雜,難以上手,部配置設定置差别難以區分和合理應用
SpringCloud Alibaba 的優勢:
  阿裡使用過的元件經曆了考驗,性能強悍,設計合理,現在開源出來大家用
  成套的産品搭配完善的可視化界面給開發運維帶來極大的便利
  搭建簡單,學習曲線低。
結合 SpringCloud Alibaba 我們最終的技術搭配方案:
  SpringCloud Alibaba - Nacos:注冊中心(服務發現/注冊)
  SpringCloud Alibaba - Nacos:配置中心(動态配置管理)
  SpringCloud - Ribbon:負載均衡
  SpringCloud - Feign:聲明式 HTTP 用戶端(調用遠端服務)
  SpringCloud Alibaba - Sentinel:服務容錯(限流、降級、熔斷)
  SpringCloud - Gateway:API 網關(webflux 程式設計模式)
  SpringCloud - Sleuth:調用鍊監控
  SpringCloud Alibaba -      

版本選擇

由于 Spring Boot 1 和 Spring Boot 2 在 Actuator 子產品的接口和注解有很大的變更,
且spring-cloud-commons 從 1.x.x 版本更新到 2.0.0 版本也有較大的變更,
是以我們采取跟SpringBoot 版本号一緻的版本:
  1.5.x 版本适用于 Spring Boot 1.5.x
  2.0.x 版本适用于 Spring Boot 2.0.x
  2.1.x 版本适用于 Spring Boot 2.1.x      

項目中導入依賴

​​參考官網​​

在 common 項目中引入如下。進行統一管理
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>      

SpringCloud Alibaba-Nacos作為注冊中心

​​參考官網​​

首先,修改 pom.xml 檔案,引入 Nacos Discovery Starter。
<dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>      
然後在應用的 /src/main/resources/application.properties 配置檔案中配置 Nacos Server 位址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848      
使用 @EnableDiscoveryClient 注解開啟服務注冊與發現功能

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication 
{
  public static void main(String[] args) 
  {
    SpringApplication.run(ProviderApplication.class, args);
  }

  @RestController
  class EchoController 
  {
    @GetMapping(value = "/echo/{string}")
    public String echo(@PathVariable String string) 
    {
        return string;
    }
  }
}      
最後還需要給應用起一個名字才能注冊到服務中心
spring:
  datasource:
    username: root
    password: 123
    url: jdbc:mysql://10.235.140.206:3306/gulimall_oms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.jdbc.Driver
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: coupon


mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml
  global-config:
    db-config:
      id-type:      

feign 遠端調用

注冊剩下的服務上去,然後使用open-feign進行服務之間的遠端調用      

Feign 聲明式遠端調用

簡介      
Feign 是一個聲明式的 HTTP 用戶端,它的目的就是讓遠端調用更加簡單。Feign 提供了 HTTP
請求的模闆,通過編寫簡單的接口和插入注解,就可以定義好 HTTP 請求的參數、格式、地
址等資訊。
Feign 整合了 Ribbon(負載均衡)和 Hystrix(服務熔斷),可以讓我們不再需要顯式地使用這
兩個元件。
SpringCloudFeign 在 NetflixFeign 的基礎上擴充了對 SpringMVC 注解的支援,在其實作下,我
們隻需建立一個接口并用注解的方式來配置它,即可完成對服務提供方的接口綁定。簡化了
SpringCloudRibbon 自行封裝服務調用用戶端的開發量。      
使用      
1、引入依賴
  <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-openfeign</artifactId>
  </dependency>      

​​我出現這樣的錯誤​​

2、開啟 feign 功能
package com.jane.shop.member;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * 遠端調用服務的步驟:
 *  1.首先得引入openfeign
 *  2.編寫一個接口,告訴spring cloud這個接口需要調用的遠端服務
 *      接口裡面聲明的方法都是調用哪個遠端服務的哪個請求
 *  3.開啟遠端調用功能,裡面的basePackages說明遠端調用的接口在哪裡
 */
@EnableFeignClients(basePackages = "com.jane.shop.member.feign")
@SpringBootApplication
@EnableDiscoveryClient
public class MemberApplication
{

    public static void main(String[] args)
    {
        SpringApplication.run(MemberApplication.class, args);
    }
}      
3、聲明遠端接口
package com.jane.shop.member.feign;

import com.jane.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author jane
 * @create 2021-03-03 15:05
 * 首先得@FeignClient("coupon")聲明這是個遠端用戶端,裡面寫在注冊中心注冊的服務名
 * 然後再接口裡面寫對應這個服務提供服務的抽象方法,路徑要寫完整的路徑
 */
@FeignClient("coupon")
public interface CouponFeignService
{
    @RequestMapping("/coupon/coupon/member/list")
    public R membercoupon();
}      

SpringCloud Alibaba-Nacos作為配置中心

​​參考官網​​

分布式項目的學而思2:SpringCloud Alibaba的nacos作為注冊中心和配置中心,feign 遠端調用,gateway網關
/**
 * 1、如何使用Nacos作為配置中心統一管理配置
 *
 * 1)、引入依賴,
 *         <dependency>
 *             <groupId>com.alibaba.cloud</groupId>
 *             <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
 *         </dependency>
 * 2)、建立一個bootstrap.properties。
 *      spring.application.name=coupon
 *      spring.cloud.nacos.config.server-addr=127.0.0.1:8848
 * 3)、需要給配置中心預設添加一個叫 資料集(Data Id)coupon.properties。預設規則,應用名.properties
 * 4)、給 應用名.properties 添加任何配置
 * 5)、動态擷取配置。
 *      @RefreshScope:動态擷取并重新整理配置
 *      @Value("${配置項的名}"):擷取到配置。
 *      如果配置中心和目前應用的配置檔案中都配置了相同的項,優先使用配置中心的配置。
 */      
這裡我暫時是有bug,解決不了      

​​我出現的bug​​

配置中心的細節

命名空間

用來做配置隔離的,預設使用的是public(保留白間)
  預設新增的所有配置都在public空間。

比如我們有開發環境,測試環境,生産環境:利用命名空間來做環境隔離。
        注意:在bootstrap.properties;配置上,需要說明使用哪個命名空間下的配置,
        spring.cloud.nacos.config.namespace=69c39f7b-107c-4995-b0b3-643ff4a392ff      
分布式項目的學而思2:SpringCloud Alibaba的nacos作為注冊中心和配置中心,feign 遠端調用,gateway網關
比如我們每個微服務都有自己的配置,配置檔案衆多,      
分布式項目的學而思2:SpringCloud Alibaba的nacos作為注冊中心和配置中心,feign 遠端調用,gateway網關

配置集

所有的配置的集合      

配置集ID

配置集ID:類似檔案名。
Data ID:類似檔案名      

配置分組

預設所有的配置集都屬于:DEFAULT_GROUP;
比如雙十一使用111,
還有其他的節日活動:618,1212
然後需要在配置檔案裡面配置(DEFAULT_GROUP就是對應的組名)
  spring.cloud.nacos.config.group=DEFAULT_GROUP      
然後現在我們想的是:      
分布式項目的學而思2:SpringCloud Alibaba的nacos作為注冊中心和配置中心,feign 遠端調用,gateway網關

同時加載多個配置集

1)、微服務任何配置資訊,任何配置檔案都可以放在配置中心中
2)、隻需要在bootstrap.properties說明加載配置中心中哪些配置檔案即可
3)、@Value,@ConfigurationProperties。。。
  以前SpringBoot任何方法從配置檔案中擷取值,都能使用。
  配置中心有的優先使用配置中心中的,      
比如現在我們按照資料庫的配置,mybatis的配置,和其他配置的分類
将配置分類,然後再在bootstrap.properties進行說明
  spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml
  spring.cloud.nacos.config.ext-config[0].group=dev
  spring.cloud.nacos.config.ext-config[0].refresh=true
  
  spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml
  spring.cloud.nacos.config.ext-config[1].group=dev
  spring.cloud.nacos.config.ext-config[1].refresh=true
  
  spring.cloud.nacos.config.ext-config[2].data-id=other.yml
  spring.cloud.nacos.config.ext-config[2].group=dev
  spring.cloud.nacos.config.ext-config[2].refresh=true      

spring cloud的gateway網關

動态上下線:
  發送請求需要知道商品服務的位址,如果商品伺服器有123伺服器,1号掉線後,還得改,
  是以需要網關動态地管理,他能從注冊中心中實時地感覺某個服務上線還是下線。
  【先通過網關,網關路由到服務提供者】

攔截:請求也要加上詢問權限,看使用者有沒有權限通路這個請求,也需要網關。

是以我們使用spring cloud的gateway元件做網關功能。

網關是請求流量的入口,常用功能包括路由轉發,權限校驗,限流控制等。
springcloud gateway取代了zuul網關。      

​​官方文檔​​

三大核心概念

Route: 
  The basic building block of the gateway. 
  It is defined by an ID, a destination URI, a collection of predicates,
   and a collection of filters. 
   A route is matched if the aggregate predicate is true.
  發一個請求給網關,網關要将請求路由到指定的服務。
  路由有id,目的地uri,斷言的集合,比對了斷言就能到達指定位置,
  
Predicate斷言: 
  This is a Java 8 Function Predicate. 
  The input type is a Spring Framework ServerWebExchange. 
  This lets you match on anything from the HTTP request,
  such as headers or parameters.
  就是java裡的斷言函數,比對請求裡的任何資訊,包括請求頭等。根據請求頭路由哪個服務
  
Filter: 
  These are instances of Spring Framework GatewayFilter that have been 
  constructed with a specific factory. 
  Here, you can modify requests and responses before or after 
  sending the downstream request.      
用戶端發請求給服務端。中間有網關。先交給映射器,
如果能處理就交給handler處理,然後交給一系列filer,
然後給指定的服務,再傳回回來給用戶端。      
分布式項目的學而思2:SpringCloud Alibaba的nacos作為注冊中心和配置中心,feign 遠端調用,gateway網關
spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]      
比如上面的斷言,-代表數組,後面還可以寫很多的斷言
The After route predicate factory takes one parameter, 
a datetime (which is a java ZonedDateTime). 
This predicate matches requests that happen after the specified datetime.      
spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red,      
The AddRequestHeader GatewayFilter factory takes a name and value parameter. 
The following example configures an AddRequestHeader GatewayFilter
這個過濾器沒有斷言,是以所有的請求都會來到這裡,然後路由到uri去
但是經過這個過濾器的都會在請求頭加上X-Request-red :      

建立網關

建立,使用initilizer,
Group:com.jane.shop,
Artifact: gateway,
package:com.jane.shop.gateway。 
搜尋gateway選中。

pom.xml裡加上common依賴, 修改jdk版本,

開啟注冊服務發現@EnableDiscoveryClient
配置nacos注冊中心位址applicaion.properties      
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.application.name=gateway
server.port=88      
bootstrap.properties 填寫nacos配置中心位址
在nacos配置好相應的配置      
spring.application.name=gateway
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=48b8175f-ceab-40f4-9042-899f966e6858
spring.cloud.nacos.config.group=dev      
在項目裡建立application.yml,根據條件轉發到uri等      
spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=red, gree.
The preceding route matches if the request contained a red query parameter 
whose value matched the gree. regexp, so green and greet would match.
根據官網,這是比對請求中帶有參數red,并且參數的值是gree的正規表達式      
下面我們寫成這樣測試去百度行不行
spring:
  cloud:
    gateway:
      routes:
      - id: test_route
        uri: https://www.baidu.com
        predicates:
          - Query=url,baidu      

繼續閱讀