淺談基於 Laravel 開發的 MeEdu 的微服務架構設計

小滕發表於2020-01-03

MeEdu 是基於 Laravel 開發的線上教育點播收費系統。您可以通過 MeEdu 開啟您的線上教育事業。

https://github.com/Qsnh/meedu

本篇文章主要給小夥伴們介紹下MeEdu的微服務架構設計。首先,來看下MeEdu服務層的目錄結構:


# ./app/Services

.

├── Base

│   ├── Interfaces

│   │   ├── CacheServiceInterface.php

│   │   ├── ConfigServiceInterface.php

│   │   └── RenderServiceInterface.php

│   ├── Providers

│   │   └── BaseServiceRegisterProvider.php

│   └── Services

│   ├── CacheService.php

│   ├── ConfigService.php

│   └── RenderService.php

├── Course

│   ├── Interfaces

│   │   ├── CourseCommentServiceInterface.php

│   │   ├── CourseServiceInterface.php

│   │   ├── VideoCommentServiceInterface.php

│   │   └── VideoServiceInterface.php

│   ├── Models

│   │   ├── Base.php

│   │   ├── Course.php

│   │   ├── CourseChapter.php

│   │   ├── CourseComment.php

│   │   ├── Video.php

│   │   └── VideoComment.php

│   ├── Providers

│   │   └── CourseServiceRegisterProvider.php

│   ├── Proxies

│   │   ├── CourseServiceProxy.php

│   │   └── VideoServiceProxy.php

│   └── Services

│   ├── CourseCommentService.php

│   ├── CourseService.php

│   ├── VideoCommentService.php

│   └── VideoService.php

├── Member

└── README.md

由於篇幅,上面省略掉了部分服務,不過重點的已經在裡面了。微服務的架構設計從目錄上面就能看出很多東西。

微服務

首先,我們先來了解下微服務到底是什麼?下面是百度百科給出的解釋:

微服務可以在“自己的程式”中執行,並通過“輕量級裝置與HTTP型API進行溝通”。關鍵在於該服務可以在自己的程式中執行。通過這一點我們就可以將服務公開與微服務架構(在現有系統中分佈一個API)區分開來。在服務公開中,許多服務都可以被內部獨立程式所限制。如果其中任何一個服務需要增加某種功能,那麼就必須縮小程式範圍。在微服務架構中,只需要在特定的某種服務中增加所需功能,而不影響整體程式的架構。

總結來說,微服務就是講複雜的應用進行拆分獨立部署,高內聚,低耦合,配合DevOps實現快速敏捷迭代開發。

高內聚,低耦合

我想大家應該都有遇到過某些專案,這些專案的程式碼緊密的結合在一起,當看到程式碼之後,你腦子裡面想的第一個詞:“重構”。如果在專案開始之初,沒有嚴格的規範和約束,隨著業務範圍的擴張和開發人員的變動,專案會越來越複雜,越來越臃腫,經過一段時間的積累之後,後來接手專案的人就苦逼了。

為了避免出現這樣的問題,我們在設計專案的時候,就要考慮一個問題:“如何做到高內聚,低耦合?”

為了解決這個為,在傳統的MVC架構下,引入了很多的解決方案,對程式碼進行分割,對系統程式碼和業務程式碼進行分離,但是啊,我們可以看到的是,這些其實作用並不是很大,隨著產品需求的變更,原來一開始或許不錯的程式碼會變得越來越糟糕,為什麼會這樣呢?是因為設計的不合理嗎?其實也不是,我覺得最主要的原因就是程式碼寫在一起了!沒有做徹底的分離!

微服務的出現就不一樣了,對系統進行服務服務劃分之後,相應的開發人員負責自己的服務,它的程式碼範圍就侷限在自己的服務裡面,這樣就做到了高內聚,低耦合。更嚴格的情況下,不同的服務的資料庫也是不一樣的,這樣就更加獨立和自主了。

服務劃分

微服務最重要的一點就是對系統進行服務劃分,那怎麼樣的劃分最為合理呢?服務的界限以什麼為標準呢?

這其實沒有具體的標準,服務劃分的界限要考慮到很多東西,專案的架構,產品的業務範圍,技術人員,維護等。所以,這個界限標準,只要你的團隊都覺得合理,就可以了。但是有一點需要注意的是,服務並不是越細越好!

在MeEdu中,基於現有的功能,主要劃分了下面幾個服務:

| 服務 | 說明 |

| --- | --- |

| Base | 系統底層服務,主要有:快取,配置服務等 |

| Member | 會員服務,負責 MeEdu 系統的會員註冊/登入/找回密碼/會員等級等 |

| Course | 課程服務,主要提供課程/視訊線上觀看 |

| Order | 訂單服務,主要提供課程/視訊/會員的線上購買服務 |

| Other | 其它服務,主要是系統的一些小功能,包括像:上傳,簡訊傳送等 |

服務註冊/釋出

微服務的架構當中,每個服務需要將自己註冊到註冊中心,這樣消費者才可以消費服務。

MeEdu雖然是微服務的架構,但是畢竟沒有做到徹底的服務分離,所以,所有的服務還是寫在一個系統裡面的。那麼MeEdu的服務是怎麼註冊的呢?請看下下面的程式碼:


class  CourseServiceRegisterProvider  extends  ServiceProvider

{

public  function  register()

{

$this->app->instance(CourseServiceInterface::class,  $this->app->make(CourseServiceProxy::class));

$this->app->instance(VideoServiceInterface::class,  $this->app->make(VideoServiceProxy::class));

$this->app->instance(CourseCommentServiceInterface::class,  $this->app->make(CourseCommentService::class));

$this->app->instance(VideoCommentServiceInterface::class,  $this->app->make(VideoCommentService::class));

}

}

MeEdu是基於Laravel開發的,在這裡,我們將容器當做了服務的註冊中心,在需要用到的服務的時候,我們在容器裡面拿到我們想要的服務!

服務的治理

服務治理也是微服務架構設計中的一個必不可少的環節。在MeEdu的微服務設計中,也存在著服務治理的影子。我們將視線再次移到上面的服務註冊程式碼中,我們可以看到 CourseVideo 的註冊服務後面都帶有 Proxy 這個關鍵字!這裡的 Proxy 就是實現服務治理的目的!來看下 CourseServiceProxy 的程式碼:


class CourseServiceProxy extends ServiceProxy implements CourseServiceInterface

{

public function __construct(CourseService $service)

{

parent::__construct($service);

$this->cache['getLatestCourses'] = function ($limit) {

return new CacheInfo('c:cs:lc:'.$limit, $this->configService->getCacheExpire());

};

$this->cache['chapters'] = function ($courseId) {

return new CacheInfo('c:cs:cc:'.$courseId, $this->configService->getCacheExpire());

};

}

}

CourseServiceProxy 實現了 CourseServiceInterface 介面,所以,它可以被註冊到註冊中心。這裡我們需要關注下 ServiceProxy

由於篇幅的原因,這裡僅貼出核心的程式碼,全部程式碼可以到meedu的倉庫檢視。


public  function  __call($name,  $arguments)

{

// 鎖控制

if  (isset($this->lock[$name]))  {

return  $this->lockHandlerBefore($name,  $arguments);

}

// 限流

$this->limitHandler($name,  $arguments);

// 快取

$response  =  $this->cacheHandler($name,  $arguments);

return  $response;

}

上面的核心程式碼就是採用AOP設計思想實現了鎖控制,限流,快取等治理功能。

服務呼叫

這是最重要的一個環節,如果這個環節做不好,那麼微服務的架構設計就沒有意義了。許多專案就是因為程式碼之間的互相呼叫導致了程式碼越來越複雜,越來越看不懂。所以,限制服務之間的呼叫是必須要考慮的一點。

  • 在MeEdu的微服務架構設計中,我們規定,Base 服務可以被其它任何服務呼叫,除了 Base 服務之外,禁止呼叫其它任何服務。只有這樣嚴格的規定,才能做到真正的高內聚,低耦合。

  • 服務之外的任何地方都可以任意的呼叫各種服務的方法,沒有限制。

  • 所有的服務禁止手動初始化,必須通過容器的方式拿到服務的例項物件。

總結

微服務架構遠不止這麼簡單,真正做到微服務架構設計需要更多的專業知識和人力成本。MeEdu的微服務架構設計,目前僅僅是程式碼層面實現的架構設計,不過,在這個基礎上,後期如果切換真正的微服務架構也是非常簡單的。因為,路已經鋪好了!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章