SpringCloud 微服務最佳開發實踐

JAVA日知錄發表於2021-07-08

現在基於SpringCloud的微服務開發日益流行,網上各種開源專案層出不窮。我們在實際工作中可以參考開源專案實現很多開箱即用的功能,但是必須要遵守一定的約定和規範。

本文結合我們實際的開發中遇到的一些問題整理出了一份微服務開發的實踐規範,歡迎各位大佬拍磚指點。

Maven規範

  1. 所有專案必須要有一個統一的parent模組

    所有微服務工程都依賴這個parent,parent用於管理依賴版本,maven倉庫,jar版本的統一升級維護

    在parent下層可以有 core,starter,rate-limit 等自定義模組

  2. core 核心包的作用:

  • 以POJO形式約定各種開發規範;如BaseEntity,統一入參,返參
  • 各種二方、三方元件開箱即用AutoConfig;
  • 各種提高開發效率的幫助類等 XXXUtil

注意:core包所有依賴的scope必須是provided,避免傳遞依賴,同時配合Condition註解按條件載入Bean 如 @ConditionalOnClass(Ribbon.class),@ConditionalOnBean(StringRedisTemplete.class)

  1. starter模組

    如果你每個服務都需要依賴10幾個starter,可以建一個統一的starter模組幫他們統一依賴進來,管理依賴集,簡化依賴

  2. rate-limit模組

    用於放置非通用的自開發元件

  3. 正確區分Release版本 和 Snapshot版本

    說明:如果是Snapshot版本,那麼在mvn deploy時會自動釋出到快照版本庫中,而使用快照版本的模組,在不更改版本號的情況下,直接編譯打包時,Maven自動從映象伺服器上下載最新的快照版本

    如果是Release版本,那麼在mvn deploy時會自動釋出到正式版本庫中,而使用正式版本的模組,在不更改版本號的情況下,編譯打包時如果本地已經存在該版本的模組則不會主動去映象伺服器上下載

    簡而言之:

    Release : 正式版,有bug不能再繼續使用這個版本號

    Snapshot:快照版,有bug可以繼續使用同一版本號,可以自動升級,推薦使用

服務呼叫規範

  1. 服務間通過引入sdk呼叫,服務消費者需要依賴生產者提供的api,配合snapshot方便升級
account
	account-api
	account-service

account-api 模組中放消費方需要用到的東西,api介面,vo,入參等...

public interface AccountApi {
    ...
}

account-service實現account-api提供的介面

@RestController
@Log4j2
@Api(tags = "使用者介面")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AccountController implements AccountApi {
    ...
}
  1. 消費者通過feign呼叫生產者,直接整合生產者提供的介面並處理熔斷
@Component
@FeignClient(name = "account-service",fallbackFactory = AccountClientFallbackFactory.class)
public interface AccountClient extends AccountApi {
    ...
}

@Component
public class AccountClientFallbackFactory implements FallbackFactory<AccountClient> {

    @Override
    public AccountClient create(Throwable throwable) {
        AccountClientFallback accountClientFallback = new AccountClientFallback();
        accountClientFallback.setCause(throwable);
        return accountClientFallback;
    }

}

@Slf4j
public class AccountClientFallback implements AccountClient {
    @Setter
    private Throwable cause;

    @Override
    public ResultData<AccountDTO> getByCode(String accountCode) {
        log.error("查詢失敗,介面異常" ,cause);
        AccountDTO account = new AccountDTO();
        account.setAccountCode("000");
        account.setAccountName("測試Feign");
        return ResultData.success(account);
    }

}

Restful設計規範

一個 API 是一個開發者的 UI - 就像其他任何 UI 一樣, 確保使用者體驗被認真的考慮過是很重要的!

可以使用以下兩種格式:

  1. /版本/訪問控制/域物件
  2. /版本/訪問控制/域物件/動作

域物件需要遵循以下幾條約束:

  1. 域物件 用名詞而非動詞
  2. 直接使用域物件名 使用/ticket而不是複數/tickets
  3. 域物件關係表達 最大不超過2層,如/ticket/12/message
  4. 需要正確區分 GET PUT POST DELETE 請求方法
  5. 無法用名詞 + 請求方法表述的可以擴充套件為 /域物件/動詞 如 POST /user/login

在閘道器層對介面進行訪問控制,訪問控制的規則分為:

pb - public 所有請求均可訪問

pt - protected 需要進行token認證通過後方可訪問

pv - private 無法通過閘道器訪問,只能微服務內部呼叫

df - default 閘道器請求token認證,並且請求引數和返回結果進行加解密

版本:

以微服務為力度,整個服務進行升級

例如,一個微服務有如下API

GET /v1/pb/user

POST /v1/pb/user

PUT /v1/pb/user

如果 POST /v1/pb/user 需要升級,則需要將整個微服務 /v1 升級到 /v2,同時保證版本相容的api老版本可以繼續訪問

GET /v2/pb/user 等價於 GET /v1/pb/user

POST /v1/pb/user 標記為已廢棄

POST /v2/pb/user

PUT /v2/pb/user 等價於 PUT /v1/pb/user

程式碼實現:

  1. GET方式{version}可以是任意值,v1,v2均可,如:@GetMapping("/{version}/pb/user")
  2. POST方法強制使用 V1 ,並標記為已廢棄,但是仍可使用
@Deprecated
@PostMapping("/v1/pb/user")
  1. POST {version}應是當前版本,只能是v2
@PostMapping("/{version}/pb/user")

閘道器

  1. 可以不承擔微服務鑑權功能,由自己服務實現(簡單服務可以直接在閘道器層鑑權)
    閘道器鑑權與微服務鑑權的差異在我其他文章中有詳細說明,可參考此文:http://t.hk.uy/2c3
  2. 需要實現訪問控制許可權,結合上文的Restful規範,遮蔽/pv/** 等特殊請求
  3. 需要實現灰度釋出功能
    開發聯調的時候需要將伺服器流量匯入到本地,結合nacos的後設資料與請求頭可實現服務例項的篩選。參考此文實現:http://t.hk.uy/2c6

求贊求關注

飄渺Jam,一位寫程式碼的架構師,做架構的程式設計師,他的公眾號主要分享Java後端,SpringCloud微服務架構,資料庫等方向的文章,如果你對微服務比較感興趣,建議掃描下方二維碼加個關注!

相關文章