您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關PHP中怎么實現(xiàn)一個微服務,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
單一應用的解決方案
對于一個大型的互聯(lián)網(wǎng)系統(tǒng),一般會包含多個應用,而且應用之間往往還存在共同的業(yè)務,并且應用之間還存在調(diào)用關系。除此之外 ,對于大型的互聯(lián)網(wǎng)系統(tǒng)還有一些其它的挑戰(zhàn),比如如何應對急劇增長的用戶,如何管理好研發(fā)團隊快速迭代產(chǎn)品研發(fā),如何保持產(chǎn)品升級更加穩(wěn)定等等 。
因此,為了使業(yè)務得到很好的復用,模塊更加容易拓展和維護,我們希望業(yè)務與應用分離,某個業(yè)務不再屬于一個應用,而是作為一個獨立的服務單獨進行維護。應用本身不再是一個臃腫的模塊堆積,而是由一個個模塊化的服務組件組合而成。
服務化
特點
那么采用服務化給有那些亮點的特色呢 ?
應用按業(yè)務拆分成服務
各個服務均可獨立部署
服務可被多個應用共享
服務之間可以通信
架構上系統(tǒng)更加清晰
核心模塊穩(wěn)定,以服務組件為單位進行升級,避免了頻繁發(fā)布帶來的風險
開發(fā)管理方便
單獨團隊維護、工作分明,職責清晰
業(yè)務復用、代碼復用
非常容易拓展
服務化面臨的挑戰(zhàn)
系統(tǒng)服務化之后, 增加了依賴關系復雜, 也會增加服務與服務之間交互的次數(shù). 在 fpm 的開發(fā)模式下. 因為無法常駐內(nèi)存給我們帶來了, 每一次請求都要從零開始加載到退出進程, 增加了很多無用的開銷, 數(shù)據(jù)庫連接無法復用也得不到保護, 由于fpm是以進程為單位的fpm的進程數(shù)也決定了并發(fā)數(shù), 這也是是fpm開發(fā)簡單給我們帶來的問題. 所以說為什么現(xiàn)在互聯(lián)網(wǎng)平臺Java比較流行了,.NET和PHP在這方面都不行。PHP非內(nèi)存常駐的就不用說了。除此之外,還有很多其他問題需要解決。
那么有沒有好的方案呢?答案是有的,它就是-Swoft。Swoft就是一個帶有服務治理功能的RPC框架。Swoft是首個 PHP常駐內(nèi)存協(xié)程全棧框架, 基于高性能協(xié)程swoole打造的一個 PHP界的Spring Boot
Swoft 提供了類似 Dubbo 更為優(yōu)雅的方式使用 RPC 服務, Swoft 性能是非常棒的有著類似Golang性能, 下面是 對Swoft 性能的壓測情況.
ab壓力測試處理速度十分驚人, 在 i78代CPU, 16GB 內(nèi)存下100000萬個請求只用了5s時間在fpm開發(fā)模式下基本不可能達到. 這也足以證明Swoft` 的高性能和穩(wěn)定性,
優(yōu)雅的服務治理
服務注冊與發(fā)現(xiàn)
微服務治理過程中,經(jīng)常會涉及注冊啟動的服務到第三方集群,比如 consul / etcd 等等,以 Swoft 框架中使用 swoft-consul 組件,實現(xiàn)服務注冊與發(fā)現(xiàn)為例。
實現(xiàn)邏輯
<?php declare(strict_types=1); namespace App\Common; use ReflectionException; use Swoft\Bean\Annotation\Mapping\Bean; use Swoft\Bean\Annotation\Mapping\Inject; use Swoft\Bean\Exception\ContainerException; use Swoft\Consul\Agent; use Swoft\Consul\Exception\ClientException; use Swoft\Consul\Exception\ServerException; use Swoft\Rpc\Client\Client; use Swoft\Rpc\Client\Contract\ProviderInterface; /** * Class RpcProvider * * @since 2.0 * * @Bean() */ class RpcProvider implements ProviderInterface { /** * @Inject() * * @var Agent */ private $agent; /** * @param Client $client * * @return array * @throws ReflectionException * @throws ContainerException * @throws ClientException * @throws ServerException * @example * [ * 'host:port', * 'host:port', * 'host:port', * ] */ public function getList(Client $client): array { // Get health service from consul $services = $this->agent->services(); $services = [ ]; return $services; } }
服務熔斷
在分布式環(huán)境下,特別是微服務結構的分布式系統(tǒng)中, 一個軟件系統(tǒng)調(diào)用另外一個遠程系統(tǒng)是非常普遍的。這種遠程調(diào)用的被調(diào)用方可能是另外一個進程,或者是跨網(wǎng)路的另外一臺主機, 這種遠程的調(diào)用和進程的內(nèi)部調(diào)用最大的區(qū)別是,遠程調(diào)用可能會失敗,或者掛起而沒有任何回應,直到超時。更壞的情況是, 如果有多個調(diào)用者對同一個掛起的服務進行調(diào)用,那么就很有可能的是一個服務的超時等待迅速蔓延到整個分布式系統(tǒng),引起連鎖反應, 從而消耗掉整個分布式系統(tǒng)大量資源。最終可能導致系統(tǒng)癱瘓。
斷路器(Circuit Breaker)模式就是為了防止在分布式系統(tǒng)中出現(xiàn)這種瀑布似的連鎖反應導致的災難。
基本的斷路器模式下,保證了斷路器在open狀態(tài)時,保護supplier不會被調(diào)用, 但我們還需要額外的措施可以在supplier恢復服務后,可以重置斷路器。一種可行的辦法是斷路器定期探測supplier的服務是否恢復, 一但恢復, 就將狀態(tài)設置成close。斷路器進行重試時的狀態(tài)為半開(half-open)狀態(tài)。
熔斷器的使用想到簡單且功能強大,使用一個 @Breaker 注解即可,Swoft 的熔斷器可以用于任何場景, 例如 服務調(diào)用的時候使用, 請求第三方的時候都可以對它進行熔斷降級
<?php declare(strict_types=1); namespace App\Model\Logic; use Exception; use Swoft\Bean\Annotation\Mapping\Bean; use Swoft\Breaker\Annotation\Mapping\Breaker; /** * Class BreakerLogic * * @since 2.0 * * @Bean() */ class BreakerLogic { /** * @Breaker(fallback="loopFallback") * * @return string * @throws Exception */ public function loop(): string { // Do something throw new Exception('Breaker exception'); } /** * @return string * @throws Exception */ public function loopFallback(): string { // Do something } }
服務限流
限流、熔斷、降級這個強調(diào)多少遍都不過分,因為確實很重要。服務不行的時候一定要熔斷。限流是一個保護自己最大的利器,如果沒有自我保護機制,不管有多少連接都會接收,如果后端處理不過來,前端流量又很大的時候肯定就掛了。
限流是對稀缺資源訪問時,比如秒殺,搶購的商品時,來限制并發(fā)和請求的數(shù)量,從而有效的進行削峰并使得流量曲線平滑。限流的目的是對并發(fā)訪問和并發(fā)請求進行限速,或者一個時間窗口內(nèi)請求進行限速從而來保護系統(tǒng),一旦達到或超過限制速率就可以拒絕服務,或者進行排隊等待等。
Swoft 限流器底層采用的是令牌桶算法,底層依賴于 Redis 實現(xiàn)分布式限流。
Swoft 限速器不僅可以限流控制器,也可以限制任何 bean 里面的方法,可以控制方法的訪問速率。這里以下面使用示例詳解
<?php declare(strict_types=1); namespace App\Model\Logic; use Swoft\Bean\Annotation\Mapping\Bean; use Swoft\Limiter\Annotation\Mapping\RateLimiter; /** * Class LimiterLogic * * @since 2.0 * * @Bean() */ class LimiterLogic { /** * @RequestMapping() * @RateLimiter(rate=20, fallback="limiterFallback") * * @param Request $request * * @return array */ public function requestLimiter2(Request $request): array { $uri = $request->getUriPath(); return ['requestLimiter2', $uri]; } /** * @param Request $request * * @return array */ public function limiterFallback(Request $request): array { $uri = $request->getUriPath(); return ['limiterFallback', $uri]; } }
key 這里支持 symfony/expression-language
表達式, 如果被限速會調(diào)用 fallback
中定義的limiterFallback
方法
說起配置中心前我們先說說配置文件,我們并不陌生,它提供我們可以動態(tài)修改程序運行能力。引用別人的一句話就是:
系統(tǒng)運行時(runtime)飛行姿態(tài)的動態(tài)調(diào)整!
我可以把我們的工作稱之為在快速飛行的飛機上修理零件。我們?nèi)祟惪偸菬o法掌控和預知一切。對于我們系統(tǒng)來說,我們總是需要預留一些控制線條,以便在我們需要的時候做出調(diào)整,控制系統(tǒng)方向(如灰度控制、限流調(diào)整),這對于擁抱變化的互聯(lián)網(wǎng)行業(yè)尤為重要。
對于單機版,我們稱之為配置(文件);對于分布式集群系統(tǒng),我們稱之為配置中心(系統(tǒng));
到底什么是分布式配置中心
隨著業(yè)務的發(fā)展、微服務架構的升級,服務的數(shù)量、程序的配置日益增多(各種微服務、各種服務器地址、各種參數(shù)),傳統(tǒng)的配置文件方式和數(shù)據(jù)庫的方式已無法滿足開發(fā)人員對配置管理的要求:
安全性:配置跟隨源代碼保存在代碼庫中,容易造成配置泄漏;
時效性:修改配置,需要重啟服務才能生效;
局限性:無法支持動態(tài)調(diào)整:例如日志開關、功能開關;
因此,我們需要配置中心來統(tǒng)一管理配置!把業(yè)務開發(fā)者從復雜以及繁瑣的配置中解脫出來,只需專注于業(yè)務代碼本身,從而能夠顯著提升開發(fā)以及運維效率。同時將配置和發(fā)布包解藕也進一步提升發(fā)布的成功率,并為運維的細力度管控、應急處理等提供強有力的支持。
關于分布式配置中心,網(wǎng)上已經(jīng)有很多開源的解決方案,例如:
Apollo是攜程框架部門研發(fā)的分布式配置中心,能夠集中化管理應用不同環(huán)境、不同集群的配置,配置修改后能夠?qū)崟r推送到應用端,并且具備規(guī)范的權限、流程治理等特性,適用于微服務配置管理場景。
以Apollo 為例,從遠端配置中心拉取配置以及安全重啟服務。如果對 Apollo 不熟悉,可以先看Swoft 擴展 Apollo 組件以及閱讀 Apollo 官方文檔。
以 Swoft 中使用 Apollo 為例,當 Apollo 配置變更后,重啟服務(http-server / rpc-server/ ws-server)。如下是一個 agent 例子:
<?php declare(strict_types=1); namespace App\Model\Logic; use Swoft\Apollo\Config; use Swoft\Apollo\Exception\ApolloException; use Swoft\Bean\Annotation\Mapping\Bean; use Swoft\Bean\Annotation\Mapping\Inject; /** * Class ApolloLogic * * @since 2.0 * * @Bean() */ class ApolloLogic { /** * @Inject() * * @var Config */ private $config; /** * @throws ApolloException */ public function pull(): void { $data = $this->config->pull('application'); // Print data var_dump($data); } }
看完上述內(nèi)容,你們對PHP中怎么實現(xiàn)一個微服務有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注億速云行業(yè)資訊頻道,感謝大家的支持。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。