1. 程式人生 > 實用技巧 >mybatis collection association 的用法

mybatis collection association 的用法

  在分散式系統中,每個服務都有一個單獨的配置,服務增多的情況下,配置檔案會變得非常多,維護配置檔案比較麻煩。所以需要一套集中的、動態的配置管理設施是必不可少的。

  Springcloud提供了一個ConfigServer來解決這個問題。

1.Config簡介

1.是什麼

  Springcloud Config為微服務中的微服務提供集中化的外部配置支援,配置伺服器為各個不同微服務應用的所有環境提供了一箇中心化的外部配置。

  其結構如上圖。所有的配置中心在git上維護配置文,本地config服務與git上一致,然後客戶端從config服務獲取自己需要的配置。

2.結構

  springcloud config分為server端和client端。配置伺服器預設採用git來儲存配置資訊,這樣有助於對環境配置進行版本管理,並且可以通過git客戶端來方便的管理和訪問配置內容。

  server端也稱為分散式配置中心,它是一個獨立的微服務應用,用來連線配置伺服器並且為客戶端提供配置資訊、加密\解密等訪問介面。

  客戶端則是通過指定的配置中心來管理資源,以及與業務相關的配置內容,並在啟動的時候從配置中心獲取和載入配置資訊。

3.主要作用

1.集中管理配置檔案

2.不同環境不同配置,動態化的配置更新,分環境部署,比如dev\test\prod\beta\release

3.執行期間動態調整,不再需要在每個服務部署的機器上編寫配置檔案,服務會向配置中心統一拉取配置自己的資訊。

4.當配置發生變動時,服務不需要重啟即可感知到配置的變化並應用新的配置

5.將配置資訊以REST介面的形式暴露

2.使用

1.github搭建配置檔案專案

master分支和dev分支各有三個檔案,如下:

(1)master/config-dev.yml

config:
  info: master-dev,版本:1

(2)master/config-prod.yml

config:
  info: master-prod,版本:1

(3)master/config-test.yml

config:
  info: master-test,版本:1

(4)dev/config-dev.yml

config:
  info: dev-dev,版本:1

(5)dev/config-prod.yml

config:
  info: dev
-prod,版本:1

(6)dev/config-test.yml

config:
  info: dev-test,版本:1

2.新建cloud-config-center-3344子模組

1.新建moudle

2.修改pom

<?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">
    <parent>
        <artifactId>cloud</artifactId>
        <groupId>cn.qz.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-center-3344</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3.修改yml

server:
  port: 3344

spring:
  application:
    name:  cloud-config-center #註冊進Eureka伺服器的微服務名
  cloud:
    config:
      server:
        git:
          uri: https://github.com/qiao-zhi/springcloud-config.git #GitHub上面的git倉庫名字
        ####搜尋目錄
          search-paths:
            - springcloud-config
#            預設的分支,如果不配置的話預設是master分支
#          default-label: dev
#          username: 公有的不需要賬號密碼
#          password: 公有的不需要賬號密碼
      ####讀取分支
      label: master

#服務註冊到eureka地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka

4.主啟動類:

package cn.qz.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

/**
 * @Author: qlq
 * @Description
 * @Date: 22:44 2020/10/21
 */
@SpringBootApplication
@EnableConfigServer
public class ConfigCenterMain3344 {
    public static void main(String[] args) {
        SpringApplication.run(ConfigCenterMain3344.class, args);
    }
}

5.啟動後訪問測試:預設讀取的是master分支,可以修改。

hyyd@HYYD-M905AEEE MINGW64 /f/IDEASPACE/springcloud (master)
$ curl -X GET http://localhost:3344/config-prod.yml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    41  100    41    0     0     10      0  0:00:04  0:00:03  0:00:01    10config:
  info: master-prod,版本:1


hyyd@HYYD-M905AEEE MINGW64 /f/IDEASPACE/springcloud (master)
$ curl -X GET http://localhost:3344/master/config-prod.yml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    41  100    41    0     0     25      0  0:00:01  0:00:01 --:--:--    25config:
  info: master-prod,版本:1


hyyd@HYYD-M905AEEE MINGW64 /f/IDEASPACE/springcloud (master)
$ curl -X GET http://localhost:3344/dev/config-prod.yml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    38  100    38    0     0     33      0  0:00:01  0:00:01 --:--:--    33config:
  info: dev-prod,版本:1

補充:springcloud有一套自己的訪問規則,如下:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

{application} 就是應用名稱,對應到配置檔案上來,就是配置檔案的名稱部分。比如對應config。

{profile} 就是配置檔案的版本,我們的專案有開發版本、測試環境版本、生產環境版本,dev、prod、test等。

{label} 表示 git 分支,預設是 master 分支,如果專案是以分支做區分也是可以的,那就可以通過不同的 label 來控制訪問不同的配置檔案了。

例如:以/{application}/{profile}[/{label}]方式訪問:

hyyd@HYYD-M905AEEE MINGW64 /f/IDEASPACE/springcloud (master)
$ curl -X GET http://localhost:3344/config/prod
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   266    0   266    0     0    200      0 --:--:--  0:00:01 --:--:--   200{"name":"config","profiles":["prod"],"label":null,"version":"9fbb23c5f96fb32a9a99ee5c10480abd443f9ab0","state":null,"propertySources":[{"name":"https://github.com/qiao-zhi/springcloud-config.git/config-prod.yml","source":{"config.info":"master-prod,版本:1"}}]}

hyyd@HYYD-M905AEEE MINGW64 /f/IDEASPACE/springcloud (master)
$ curl -X GET http://localhost:3344/config/prod/dev
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   264    0   264    0     0    234      0 --:--:--  0:00:01 --:--:--   234{"name":"config","profiles":["prod"],"label":"dev","version":"24102d09cce20c48fafac63445624ec1b8c2b433","state":null,"propertySources":[{"name":"https://github.com/qiao-zhi/springcloud-config.git/config-prod.yml","source":{"config.info":"dev-prod,版本:1"}}]}

3.建立cloud-config-client-3355專案

  該模組從上面3344服務端拿取自己的配置檔案。

1.新建子模組

2.修改pom:

<?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">
    <parent>
        <artifactId>cloud</artifactId>
        <groupId>cn.qz.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-client-3355</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!--引入自己抽取的工具包-->
        <dependency>
            <groupId>cn.qz.cloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--監控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--熱部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

3.新建bootstrap.yml

server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #Config客戶端配置
    config:
      label: master #分支名稱
      name: config #配置檔名稱
      profile: dev #讀取字尾名稱 上訴3個綜合就是 master分支上 config-dev.yml
      uri: http://localhost:3344

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/

補充:bootstrap.yml和application.yml的區別

  applicaiton.yml是使用者級的資源配置項,bootstrap.yml是系統級的,優先順序更高。

  Springcloud會建立一個"Bootstrap Context",作為Spring應用的"Application Context"的上下文。初始化的時候,BootstrapContext負責從外部源載入配置屬性並解析配置。這兩個上下文共享一個外部的Environment。

  bootstrap.yml通常用於“使用Spring Cloud Config Server時,應在bootstrap.yml中指定spring.application.name和spring.cloud.config.server.git.uri”以及一些加密/解密資訊。例如,當使用Spring Cloud時,通常從伺服器載入“real”配置資料。為了獲取URL(和其他連線配置,如密碼等),您需要一個較早的或“bootstrap”配置。因此,您將配置伺服器屬性放在bootstrap.yml中,該屬性用於載入實際配置資料(通常覆蓋application.yml [如果存在]中的內容)。

  另外,由於application.yml後加載,所以如果有相同屬性的情況下,會以application.yml的為準。而且兩個檔案可以用${varname}互相取檔案中的變數。

4.新建主啟動類:

package cn.qz.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3355 {

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

5.新建controller

package cn.qz.cloud.controller;

import cn.qz.cloud.utils.JSONResultUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConfigClientController {

    @Value("${config.info}")
    private String configInfo;

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/configInfo")
    public JSONResultUtil<String> configInfo() {
        String result = "serverPort: " + serverPort + ";configInfo: " + configInfo;
        return JSONResultUtil.successWithData(result);
    }
}

6.測試

liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl http://localhost:3355/configInfo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   100    0   100    0     0   3225      0 --:--:-- --:--:-- --:--:--  6666{          "success":true,"code":"200","msg":"","data":"serverPort: 3355;configInfo: maste          r-dev,版本:1"}

liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl http://localhost:3344/config-dev.yml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    40  100    40    0     0      2      0  0:00:20  0:00:17  0:00:03    10config:
  info: master-dev,版本:1

3.存在的問題

  git上修改配置之後,都不重啟服務的情況下。3344server可以及時更新,3355客戶端不能及時更新

1.上面從github上面修改master/config-dev.yml

config:
  info: master-dev,版本:2

2.測試:

liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl http://localhost:3344/config-dev.yml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    40  100    40    0     0      2      0  0:00:20  0:00:18  0:00:02    10config:
  info: master-dev,版本:2


liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl http://localhost:3355/configInfo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   100    0   100    0     0   3225      0 --:--:-- --:--:-- --:--:--   97k{"success":true,"code":"200","msg":"","data":"serverPort: 3355;configInfo: master-dev,版本:1"}

  發現3344可以及時更新,3355只有重啟之後才可以更新。

3.解決辦法:通過配置可以手動觸發重新整理

(1)修改bootstrap.yml

server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #Config客戶端配置
    config:
      label: master #分支名稱
      name: config #配置檔名稱
      profile: dev #讀取字尾名稱 上訴3個綜合就是 master分支上 config-dev.yml
      uri: http://localhost:3344

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/

# 暴露監控端點(可以暴露健康狀態等,這裡暴露所有)
management:
  endpoints:
    web:
      exposure:
        include: "*"

(2)修改Controller,增加@RefreshScope註解

(3)重啟之後檢視:

liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl http://localhost:3355/configInfo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   100    0   100    0     0    917      0 --:--:-- --:--:-- --:--:--  1063{"success":true,"code":"200","msg":"","data":"serverPort: 3355;configInfo: master-dev,版本:2"}

(4)git上面修改config-dev.yml

liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl http://localhost:3355/configInfo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   100    0   100    0     0    917      0 --:--:-- --:--:-- --:--:--  1063{"success":true,"code":"200","msg":"","data":"serverPort: 3355;configInfo: master-dev,版本:2"}

(5)檢視3344和3355配置

liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl http://localhost:3344/config-dev.yml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    40  100    40    0     0      1      0  0:00:40  0:00:21  0:00:19    12config:
  info: master-dev,版本:3


liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl http://localhost:3355/configInfo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   100    0   100    0     0   3225      0 --:--:-- --:--:-- --:--:--  6250{"success":true,"code":"200","msg":"","data":"serverPort: 3355;configInfo: master-dev,版本:2"}

  發現3355還是沒有自動同步

(6)手動訪問URL觸發更新

liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl -X POST http://localhost:3355/actuator/refresh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    39    0    39    0     0      0      0 --:--:--  0:00:43 --:--:--    11["config.client.version","config.info"]

liqiang@root MINGW64 /e/IDEAWorkSpace/cloud (master)
$ curl http://localhost:3355/configInfo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   100    0   100    0     0   3225      0 --:--:-- --:--:-- --:--:--  6666{"success":true,"code":"200","msg":"","data":"serverPort: 3355;configInfo: master-dev,版本:3"}

  通過上面的設定,改動完git上配置之後需要手動通過post請求通知服務重新整理配置。當然如果服務增多的情況可以通過批處理指令碼批量通知。

  仍然不是一個較好的解決方案,因此需要引入springcloud Bus訊息匯流排。