1. 程式人生 > >java架構之路-(微服務專題)feign的基本使用和nacos的配置中心

java架構之路-(微服務專題)feign的基本使用和nacos的配置中心

上次迴歸:

  上次我們說了ribbon的基本使用,包括裡面的內部演算法,演算法的細粒度配置,還有我們自己如何實現我們自己的演算法,主要還是一些基本使用的知識,還不會使用ribbon的小夥伴可以回去看一下上一篇部落格。

什麼是Feign:

  Feign是Netflix開發的宣告式、模板化的HTTP客戶端,其靈感來自Retrofit、JAXRS­2.0以及WebSocket。Feign 可幫助我們更加便捷、優雅地呼叫HTTP API,為什麼我們會選擇使用Feign呢?我們上次說到的ribbon也是可以呼叫遠端API的啊,但是你的請求地址引數很多呢?比如這樣https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=%E5%B0%8F%E8%8F%9C%E6%8A%80%E6%9C%AF&rsv_pq=c848f94a0022633c&rsv_t=82132w5e6o2pWnrOzzEl1kRwfItDYCuNU7FotoIqlCHTCjD2WiDKjarInW8&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=13&rsv_sug1=1&rsv_sug7=100&rsv_sug2=0&inputT=1408&rsv_sug4=1408,而且引數還總是變化的(客戶每天都在變需求),你每次都需要改寫程式碼,地址太長還容易寫錯,是不是覺得寫起來很吃力的樣子,我們這次學習的Feign就是來解決這個問題的。

Feign的常用配置詳解:

  剛才我們簡單的說到了Feign是做什麼的,我們來看一下,我們如何使用Feign吧。還是我們的兩個服務,一個使用者服務,一個訂單服務,我們分別來看一下配置。

  一、最簡單的啟動

  ①.首先加入父依賴包,在啟動類加入註解@EnableFeignClients

<!-- 加入Feign依賴-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
package com.xiaocaiFeign;

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

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

}

  ②.建立我們的訂單服務,建立一個介面,介面如下,需要加註解@FeignClient(name = "feign-order"),實現類你們自己去完成吧

package com.xiaocaiFeign.controller;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@FeignClient(name = "feign-order")
public interface OrderController {

    @RequestMapping("/getOrderData/{orderId}")
    String getOrderData(@PathVariable("orderId") String orderId);
}

  ③.修改我們的訂單服務的POM檔案,弄成一個jar包即可,不需要可執行的jar包。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
        </plugin>
    </plugins>
</build>

  ④.建立我們的使用者服務,將我們的訂單服務以jar包的形式引入進來。

<dependencies>
    <dependency>
        <groupId>com</groupId>
        <artifactId>feignOrder</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

  這裡千萬注意一個問題,你的訂單服務和你的使用者服務,包路徑一定要相同,不然springboot是掃描不到你的包的,切記~!!!

    ⑤.編寫我們的呼叫類(使用者服務)

package com.xiaocaiFeign.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private OrderController orderController;

    @GetMapping("/getOrder")
    public String getOrderData() {
        System.out.println("準備呼叫");
        String orderData = orderController.getOrderData("1");
        System.out.println(orderData);
        return orderData;
    }
}

  執行看結果

是不是超級簡單。

  二、列印日誌級別

  首先我們在訂單服務加入一個配置,千萬別寫@Configuration

package com.xiaocaiFeign.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;

public class FeignLogConfig {

    @Bean
    public Logger.Level level() {
        //return Logger.Level.NONE; //(預設)不列印任何日誌
        return Logger.Level.BASIC;//僅記錄請求方法、URL、響應狀態程式碼以及執行時間,生成一般用這個
        //return Logger.Level.HEADERS;//在BASIC基礎之上還記錄了請求和響應的header.
        //return Logger.Level.FULL;//記錄了請求和響應的header、body和元資料
    }
}

  然後在我們的介面類下面給予這個配置

package com.xiaocaiFeign.controller;

import com.xiaocaiFeign.config.FeignLogConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@FeignClient(name = "feign-order", configuration = FeignLogConfig.class)
public interface OrderController {

    @RequestMapping("/getOrderData/{orderId}")
    String getOrderData(@PathVariable("orderId") String orderId);

}

  最後我們在我們的使用者服務中開啟配置,注意xiaocaiFeign是你的包名。

logging:
  level:
    com:
      xiaocaiFeign: debug

  我們來看一下效果,我這隻演示一下FULL的吧~!

  三、額外我覺得沒用的配置,契約配置

  反正我是覺得沒啥大用,而且還不熟悉的,和我們的日誌差不多,加入一個自定義的配置類

package com.xiaocaiFeign.config;

import feign.Contract;
import org.springframework.context.annotation.Bean;


public class MyFeignConfig {
    /**
     * 根據SpringBoot自動裝配FeignClientsConfiguration 的FeignClient的契約是SpringMvc
     * 通過修改契約為預設的Feign的鍥約,那麼就可以使用預設的註解
     * @return
     */
    @Bean
    public Contract feiContract() {
        return new Contract.Default();
    }
}

  然後通過介面引入,但是這回介面必須要寫feign的註解了,我覺得沒這個必要,我還是比較習慣用springMVC的註解。

package com.xiaocaiFeign.controller;

import com.xiaocaiFeign.config.MyFeignConfig;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.openfeign.FeignClient;

@FeignClient(name = "feign-order", configuration = MyFeignConfig.class)
public interface OrderController {

    @RequestLine("GET /getOrderData/{orderId}")
    String getOrderData(@Param("orderId") String orderId);
}

  這寫就可以呼叫了,裡面都別寫錯了,寫錯了,使用者服務可能會啟動失敗的。

  四、請求頭傳遞

  最後一個例項了,假如我們這樣的,使用者服務呼叫訂單服務,訂單服務每次呼叫需要攜帶請求頭token進行驗證,我們又該如何來做呢?我們來看一下程式碼實現,先弄一個攔截器。

package com.xiaocaiFeign.config;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

public class MyRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        template.header("token", request.getHeader("token"));
    }
}

  然後將攔截器配置到Feign下面去。

package com.xiaocaiFeign.controller;

import com.xiaocaiFeign.config.FeignLogConfig;
import com.xiaocaiFeign.config.MyFeignConfig;
import com.xiaocaiFeign.config.MyRequestInterceptor;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@FeignClient(name = "feign-order",configuration = MyRequestInterceptor.class)
public interface OrderController {

    @RequestMapping("/getOrderData/{orderId}")
    String getOrderData(@PathVariable("orderId") String orderId);

//    @RequestLine("GET /getOrderData/{orderId}")
//    String getOrderData(@Param("orderId") String orderId);

    @RequestMapping("/getOrderToken")
    String getOrderToken();
}

  自己去測試一下呼叫結果吧,我弄這個弄了好久,保證沒問題的,我就不上圖了。

Feign的優化配置:

  我們的Feign底層還是使用Ribbon來呼叫的,第一次很多時候會呼叫的慢,我可以改為HTTPClient呼叫方式。

feign:
  client:
    config:
      connectTimeout: 5000 #連線超時時間(毫秒)
      readTimeout: 5000 # 讀取超時時間(毫秒)
      product-center:
        loggerLevel: full # 日誌級別
        contract: feign.Contract.Default #指定預設契約
  httpclient:
    enabled: true # 開啟httpClient
    max-connections: 200 # 最大連線數
    max-connections-per-route: 50 # 為每個url請求設定最大連線數

nacos配置中心詳解:

  nacos裡面還有一個配置中心還沒有去說,我們現在的專案很多都是微服務的,也知道微服務會拆分成很多個小的服務,加入你拆分的不多,10個服務,本地開發環境,公共開發環境,測試環境,生產環境,那麼你就意味著你需要弄40個配置檔案,而且你會暴露你的資料庫地址給開發,那麼我們這次就用nacos來看看配置中心是如何做的吧。我們先弄一個最簡單的測試類。

package com.nacosConfig.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConfigCenterController {

    @Value("${config.center.name}")
    private String name;

    @GetMapping("/")
    public String getData() {
        System.out.println(name);
        return name;
    }
}
server:
  port: 8080

config:
  center:
    name: "張三"

  先不用nacos配置中心,我們來測試一下。

  我們來看一下nacos是怎麼來配置的

  ①.加入依賴包。

<!-- 引入nacos配置依賴-->
<dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-nacos-config</artifactId>
</dependency>

  ②.新建一個叫做bootstrap.yml的配置,這個配置會優先於springboot自帶的application.yml配置。

spring:
  application:
    name: nacos 
  profiles:
    active: config
  cloud:
    nacos:
      config:
        server-addr: 192.168.138.119:8848
        namespace: 83cbe7a9-7713-4d5c-b052-a42ba1df9e84
        file-extension: yml

  來解釋一下我們的配置,第一個spring.application.name=nacos是我們的檔名字,spring.profiles.active=config還是我們的檔名字,spring.cloud.nacos.config.file-extension=yml是檔案字尾,就是說,我們會去拿名字為nacos-config.yml這個檔案。連線和命令空間這裡就不說了,在nacos的註冊中心講的已經很詳細了。

  ③.登入nacos頁面,點選配置列表,選擇對應的名稱空間,點選“+”進行新增。

   就這樣,一個簡單的配置中心就完成了(啟動會報錯,是因為你的註冊中心沒有註冊成功報錯的)。而且還可以檢視歷史版本,用起來還是不錯的,你可以在application.yml寫入你的註冊配置,如下所示

spring:
  application:
    name: nacos-config
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.138.119:8848

  這時專案啟動的時候會自動拉取nacos-config.yml配置檔案。這樣寫是什麼意思呢?就是你一個shoppingServer,你有不同的環境,我們寫一個通用的配置shoppingServer.yml,然後通過你的shoppingServer-dev.yml、shoppingServer-st.yml,等檔案來細化咱們的不同環境的配置。

  還有一個配置是這樣的。

spring:
  application:
    name: nacos-config
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        server-addr: 192.168.138.119:8848
        file-extension: yml
        shared-dataids: config1.yml,config2.yml

  就是說我們還有載入config1.yml和config2.yml配置檔案。現在我們說到四個配置檔案了,那麼他們的順序又是什麼呢?config1.yml<<<config2.yml<<<nacos-config.yml<<<nacos-config-dev.yml,越是在後面載入的,權利越大,就是後面的配置可以覆蓋掉前面的配置。這裡的shared-dataids: config1.yml,config2.yml一般用於不同系統中的通用配置,比如我們在使用者系統和訂單系統有通用配置,我們可以通過shared-dataids的方式來引入配置。

  還可以這樣來寫

spring:
  application:
    name: nacos-config
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        server-addr: 192.168.138.119:8848
        file-extension: yml
        shared-dataids: config1.yml,config2.yml
        refreshable-dataids: config1.yml,config2.yml
        ext-config:
          - data-id: config3.yml
            group: DEFAULT_GROUP
            refresh: true
          - data-id: config4.yml
            group: DEFAULT_GROUP
            refresh: true

  這回又多了一些檔案,順序是什麼樣子的呢?我再來寫一下config1.yml<<<config2.yml<<<config3.yml<<<config4.yml<<<nacos-config.yml<<<nacos-config-dev.yml。

spring:
  application:
    name: nacos-config
  profiles:
    active: dev
  cloud:
    refresh:
      enabled: true # 預設是true
    nacos:
      config:
        server-addr: 192.168.138.119:8848
        file-extension: yml
        shared-dataids: config1.yml,config2.yml
        refreshable-dataids: config1.yml,config2.yml
        ext-config:
          - data-id: config3.yml
            group: DEFAULT_GROUP
            refresh: true
          - data-id: config4.yml
            group: DEFAULT_GROUP
            refresh: false

  其中標紅的那個幾個值是控制是否可以動態重新整理的,就是說我們改了配置中心的配置,不用重啟服務,配置就可以生效的,需要在類上面加入@RefreshScope註解。

   最後一個問題,nacos改密碼和新增賬戶,我們叢集的時候連線一個mysql資料庫對吧,單機的比較頭疼,我們設定單機的內部是用一個Derby這個資料庫來連線的,我這裡只能用IDEA改本地的Derby然後拷貝到linux上去,暫時沒啥別的好辦法,用頁面也能改,但是無法新增使用者,而我們的叢集是用的mysql,我們可以自己操作啦,來一個新增使用者的操作,開啟我們的mysql的nacos庫,找到users表,新增使用者,然後我們用下面的方法來手動生成密碼。

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
        <version>1.2.2.RELEASE</version>
</dependency>
public static void main(String[] args) {
    String nacos = new BCryptPasswordEncoder().encode("nacos");
    System.out.println("nacos = " + nacos);
}

  然後把我們的密碼自己弄到mysql資料庫內就可以啦

總結:

  這次主要說了feign的基本使用,日誌級別的選擇,還有我們的請求頭如何傳遞,然後就是我們的Nacos的配置中心是如何去做的,我們配置檔案的載入順序,最後是我們的nacos如何新增使用者和修改密碼(頁面就可以改)。

 

最進弄了一個公眾號,小菜技術,歡迎大家的加入

&n