Trong bài viết này, mình chủ yếu giới thiệu cách sử dụng PHP để xây dựng kiến trúc microservice. Bởi vì PHP cũng đang tiến lên theo thời đại, nó cũng có khả năng hỗ trợ các kiến trúc microservice cho các hệ thống lớn.

1. Khó khăn của PHP với microservice

PHP sử dụng traditional framework (laravel, yii, symfony) để thực hiện microservice, hiệu quả rất thấp.

Tại sao?

Trong môi trường phát triển của fpm, vì không thể cung cấp bộ nhớ resident, mọi yêu cầu phải bắt đầu từ con số 0 bằng cách tải một quy trình để thoát quy trình, thêm rất nhiều những cái không cần thiết.

Ngoài ra, kết nối cơ sở dữ liệu không thể được sử dụng lại và không bảo mật. Đây cũng là vấn đề được nói nhiều do sự đơn giản trong môi trường phát triển fpm.

Nó không đủ thân thiện với các công cụ microservice như docker và phải dựa vào nginx để cung cấp dịch vụ.

Vì vậy, đây là những lý do tại sao Java phổ biến hơn trong nền tảng web so với PHP. Ngoài ra, PHP non-memory resident vẫn còn là vấn đề cần được giải quyết.

Vì thế, ta sẽ dùng Swoft triển khai microservice.

2. Swoft là gì?

Swoft là một framework của PHP microservices coroutine được base trên Swoole extension. Giống như Go, Swoft có một máy chủ web built-in coroutine và một máy khách common coroutine và nằm trong bộ nhớ, độc lập với PHP-FPM truyền thống.

Có những cái tương tự như Go, quản trị dịch vụ toàn diện, AOP linh hoạt và mạnh mẽ, triển khai thông số kỹ thuật PSR tiêu chuẩn, v.v.

3. Swoft Github

4. Chúng ta cần gì để xây dựng một microservice?

  • Application Framework hiệu suất cao.
  • Service Registration, Discovery.
  • Service Circuit Breaker.
  • Service Restriction.
  • Configuration Center.

Và tất cả đã có sẵn trong swoft.

5. Swoft’s hiệu suất cao

Ta có thể hình dung ra những lợi ích mà resident memory mang lại cho chúng ta.

  • Chỉ khởi tạo framework một lần: chúng ta có thể tập trung vào xử lý các request vì framework chỉ cần khởi tạo một lần trong bộ nhớ resident.
  • Gộp nhiều connection: nhiều người không hiểu và không sử dụng connections pool, hậu quả của việc tạo connections cho mọi request là gì? Nó ngốn quá nhiều tài nguyên cho một kết nối. Đối với một số dịch vụ cơ bản, chẳng hạn như Redis, cơ sở dữ liệu, các kết nối đó thực sự ngốn rất nhiều tài nguyên.

Vì vậy, có một cách, đó là sử dụng framework called Swoft. Swoft là framework RPC với tính năng Service Governance. Swoft là framework PHP resident memory coroutine full-stack đầu tiên, dựa trên khái niệm cốt lõi của Spring Boot, các convention được config tốt hơn.

Swoft cung cấp một cách đơn giản hơn để sử dụng các dịch vụ RPC như DubboSwoft có hiệu suất tương tự như Golang. Đây là kết quả kiểm tra hiệu suất Swoft trong máy tính của mình.

Tốc độ xử lý là rất cao. Với CPU core i7 thế hệ 8 và 16GB RAM, xử lý 100000 request trong vòng 5s. Với fpm thì 5s là không thể.

Thông số trên cũng đủ để chứng minh sự ổn định và hiệu suất cao của Swoft.

6. Service Registration, Discovery

Trong quá trình quản trị của microservice, việc đăng ký service được sử dụng cho các third-party clusters, chẳng hạn như consul/etcd, và các bên liên quan. Phần này sử dụng component swoft-consul trong framework Swoft để thực hiện đăng ký.

Còn đây là đoạn code:

<?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;
    }
}

7. Service Circuit Breaker

Khi nhà cung cấp dừng hoạt động của service, nó đảm bảo nhà cung cấp sẽ không được called khi circuit breaker hoạt động, nhưng ta cũng cần thêm một methods để reset circuit breaker sau khi nhà cung cấp tiếp tục service.

Có một giải pháp đó là circuit breaker periodically lắng nghe service của nhà cung cấp có được nối lại hay không. Sau khi được nối lại, trạng thái được đặt thành đóng. Khi circuit breaker được mở lại, trạng thái được đặt thành mở.

Việc sử dụng fuse rất nhanh và đơn giản. Nó được chú thích với a @Breaker. Fuse của Swoft có thể được sử dụng trong bất kỳ scenario nào, chẳng hạn như gọi đến một service. Nó có thể bị downgraded hoặc không được called khi đó là request của bên thứ ba.

<?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
    }
}

8. Service Restriction

Flow Restriction, Circuit Breaker, Service Downgrade. Những điều này có thể được nhấn mạnh nhiều lần vì chúng thực sự quan trọng. Khi dịch vụ không hoạt động, nó nên được dừng. Flow Restriction là một công cụ để bảo vệ chính nó. Nếu không có cơ chế tự bảo vệ và các connection được nhận cho dù có bao nhiêu, thì front-end chắc chắn sẽ bị treo với lưu lượng rất lớn trong khi back-end không thể xử lý tất cả các connection.

Mục đích của việc Flow Restriction là giới hạn tốc độ truy cập đồng thời và request cùng một lúc hoặc giới hạn tốc độ request trong một khoảng thời gian nhất định để bảo vệ hệ thống. Khi đạt đến giới hạn, các request có thể bị denied hoặc đưa vào queued.

Swoft flow restriction không chỉ giới hạn các controller, nó còn giới hạn các method và kiểm soát tốc độ truy cập của các method. Ví dụ sau đây là lời giải thích chi tiết:

<?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];
    }
}

Điều này hỗ trợ các expression symfony/expression-language. Nếu tốc độ bị giới hạn, method defined limiterFallback trong fallback sẽ được gọi.

9. Configuration Center

Trước khi nói về configuration center, hãy nói về tệp configuration. Chúng ta không xa lạ gì với nó. Nó cung cấp cho chúng ta khả năng modify một ứng dụng. Có một trích dẫn, đó là:

Dynamic adjustment of the flight attitude of the system runtime!

(Mình không giỏi tiếng anh nên không dịch rõ được 😁)

Đối với phiên bản stand-alone, ta gọi nó là configuration (tệp). Đối với hệ thống cụm phân tán, ta gọi nó là configuration center (hệ thống).

Phần này sử dụng Apollo làm ví dụ để pull configuration và bảo mật các restart services từ remote configuration center. Nếu bạn không quen thuộc Apollo, trước tiên bạn có thể xem component Apollo của Swoft extension. Đây là tài liệu chuẩn.

Phần này sử dụng Apollo trong Swoft làm ví dụ. Khi Apollo configuration thay đổi, hãy khởi động lại service (http-server / rpc-server / ws-server). Sau đây là một ví dụ:

<?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);
    }
}

Trên đây là cách pull configuration Apollo, ngoài cách này, Swoft-Apollo cung cấp nhiều cách sử dụng hơn.

Kết luận

Vừa rồi ta vừa xây dựng một framework microservice đơn giản của PHP sử dụng Swoft. Nếu ta sử dụng framework PHP truyền thống, sẽ rất khó để build, nhưng sử dụng Swoft rất dễ dàng. Hi vọng bài viết sẽ giúp ích cho các bạn trong các dự án riêng sử dụng microservice với PHP.

Tham khảo