PHP高性能微服务架构:基于Swoole和Hyperf构建分布式电商系统

2025-10-28 0 574

发布日期:2024年1月18日 | 作者:PHP架构专家

一、微服务架构概述

随着电商业务复杂度的增加,传统的单体架构已无法满足高并发、高可用的需求。基于Swoole和Hyperf的PHP微服务架构,通过协程、异步非阻塞IO等特性,为电商系统提供了全新的解决方案。

架构优势:

  • 高性能:Swoole协程支持,QPS提升10倍以上
  • 高可用:服务隔离,故障不影响整体系统
  • 易扩展:按业务模块独立扩展
  • 技术异构:不同服务可使用最适合的技术栈

系统架构图:

用户请求 → API网关 → 服务注册中心
                    ↓
    +-------------------------------+
    |   用户服务    |   商品服务    |   订单服务    |
    +-------------------------------+
                    ↓
    +-------------------------------+
    |   Redis集群  |  MySQL集群   |  消息队列    |
    +-------------------------------+

二、环境搭建与配置

1. Swoole扩展安装

# 安装Swoole扩展
pecl install swoole

# 或者编译安装
git clone https://github.com/swoole/swoole-src.git
cd swoole-src
phpize
./configure --enable-openssl --enable-http2
make && make install

# php.ini配置
extension=swoole.so
swoole.use_shortname=Off

2. Hyperf框架安装

# 创建项目
composer create-project hyperf/hyperf-skeleton micro-mall

# 项目结构
micro-mall/
├── app/
│   ├── Controller/
│   ├── Service/
│   ├── Model/
│   ├── Listener/
│   └── Process/
├── config/
├── runtime/
├── test/
└── vendor/

3. 配置文件

// config/autoload/server.php
return [
    'mode' => SWOOLE_PROCESS,
    'servers' => [
        [
            'name' => 'http',
            'type' => Server::SERVER_HTTP,
            'host' => '0.0.0.0',
            'port' => 9501,
            'sock_type' => SWOOLE_SOCK_TCP,
            'callbacks' => [
                Event::ON_REQUEST => [HyperfHttpServerServer::class, 'onRequest'],
            ],
        ],
    ],
    'settings' => [
        'enable_coroutine' => true,
        'worker_num' => swoole_cpu_num(),
        'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
        'open_tcp_nodelay' => true,
        'max_coroutine' => 100000,
        'open_http2_protocol' => true,
        'max_request' => 100000,
        'socket_buffer_size' => 2 * 1024 * 1024,
        'buffer_output_size' => 2 * 1024 * 1024,
    ],
];

三、核心服务实现

1. 用户服务 (User Service)

<?php
declare(strict_types=1);

namespace AppService;

use HyperfDbConnectionDb;
use HyperfDiAnnotationInject;
use HyperfRedisRedis;
use AppModelUser;

class UserService
{
    #[Inject]
    private Redis $redis;

    /**
     * 用户注册
     */
    public function register(array $data): array
    {
        // 开启事务
        Db::beginTransaction();
        try {
            // 检查用户名是否重复
            if (User::query()->where('username', $data['username'])->exists()) {
                throw new Exception('用户名已存在');
            }

            // 创建用户
            $user = new User();
            $user->username = $data['username'];
            $user->email = $data['email'];
            $user->password = password_hash($data['password'], PASSWORD_DEFAULT);
            $user->save();

            // 生成访问令牌
            $token = $this->generateToken($user->id);
            
            // 缓存用户信息
            $this->cacheUserInfo($user, $token);

            Db::commit();

            return [
                'user' => $user->toArray(),
                'token' => $token
            ];
        } catch (Exception $e) {
            Db::rollBack();
            throw $e;
        }
    }

    /**
     * 用户登录
     */
    public function login(string $username, string $password): array
    {
        $user = User::query()->where('username', $username)->first();
        
        if (!$user || !password_verify($password, $user->password)) {
            throw new Exception('用户名或密码错误');
        }

        $token = $this->generateToken($user->id);
        $this->cacheUserInfo($user, $token);

        return [
            'user' => $user->toArray(),
            'token' => $token
        ];
    }

    /**
     * 生成访问令牌
     */
    private function generateToken(int $userId): string
    {
        $token = bin2hex(random_bytes(32));
        $key = "user:token:{$token}";
        
        $this->redis->setex($key, 3600 * 24, $userId);
        
        return $token;
    }

    /**
     * 缓存用户信息
     */
    private function cacheUserInfo(User $user, string $token): void
    {
        $userKey = "user:info:{$user->id}";
        $this->redis->setex($userKey, 3600, json_encode($user->toArray()));
        
        // 设置用户-令牌映射
        $this->redis->setex("user:{$user->id}:token", 3600 * 24, $token);
    }
}

2. 商品服务 (Product Service)

<?php
declare(strict_types=1);

namespace AppService;

use HyperfDbConnectionDb;
use HyperfDiAnnotationInject;
use HyperfRedisRedis;
use AppModelProduct;
use AppModelProductSku;

class ProductService
{
    #[Inject]
    private Redis $redis;

    /**
     * 获取商品列表(带缓存)
     */
    public function getProductList(int $categoryId = 0, int $page = 1, int $pageSize = 20): array
    {
        $cacheKey = "products:list:{$categoryId}:{$page}:{$pageSize}";
        
        // 尝试从缓存获取
        $cached = $this->redis->get($cacheKey);
        if ($cached) {
            return json_decode($cached, true);
        }

        $query = Product::query()->where('status', 1);
        
        if ($categoryId > 0) {
            $query->where('category_id', $categoryId);
        }

        $products = $query->orderBy('sort', 'desc')
            ->orderBy('id', 'desc')
            ->offset(($page - 1) * $pageSize)
            ->limit($pageSize)
            ->get()
            ->toArray();

        // 缓存结果,5分钟过期
        $this->redis->setex($cacheKey, 300, json_encode($products));

        return $products;
    }

    /**
     * 获取商品详情
     */
    public function getProductDetail(int $productId): array
    {
        $cacheKey = "product:detail:{$productId}";
        
        $cached = $this->redis->get($cacheKey);
        if ($cached) {
            return json_decode($cached, true);
        }

        $product = Product::with(['skus', 'attributes'])
            ->where('id', $productId)
            ->where('status', 1)
            ->first();

        if (!$product) {
            throw new Exception('商品不存在');
        }

        $result = $product->toArray();
        
        // 缓存商品详情,10分钟过期
        $this->redis->setex($cacheKey, 600, json_encode($result));

        return $result;
    }

    /**
     * 减少库存
     */
    public function decreaseStock(int $skuId, int $quantity): bool
    {
        $key = "product:stock:{$skuId}";
        
        // 使用Redis原子操作减少库存
        $remaining = $this->redis->decrby($key, $quantity);
        
        if ($remaining redis->incrby($key, $quantity);
            throw new Exception('库存不足');
        }

        // 异步更新数据库库存
        HyperfUtilsCoroutine::create(function () use ($skuId, $quantity) {
            ProductSku::query()
                ->where('id', $skuId)
                ->where('stock', '>=', $quantity)
                ->decrement('stock', $quantity);
        });

        return true;
    }
}

3. 订单服务 (Order Service)

<?php
declare(strict_types=1);

namespace AppService;

use HyperfDbConnectionDb;
use HyperfDiAnnotationInject;
use HyperfRedisRedis;
use AppModelOrder;
use AppModelOrderItem;
use AppServiceProductService;

class OrderService
{
    #[Inject]
    private Redis $redis;

    #[Inject]
    private ProductService $productService;

    /**
     * 创建订单
     */
    public function createOrder(int $userId, array $items, array $address): array
    {
        Db::beginTransaction();
        try {
            // 验证商品和库存
            $this->validateOrderItems($items);

            // 计算订单总金额
            $totalAmount = $this->calculateTotalAmount($items);

            // 创建订单
            $order = new Order();
            $order->user_id = $userId;
            $order->order_no = $this->generateOrderNo();
            $order->total_amount = $totalAmount;
            $order->address = json_encode($address);
            $order->status = Order::STATUS_PENDING;
            $order->save();

            // 创建订单项
            foreach ($items as $item) {
                $orderItem = new OrderItem();
                $orderItem->order_id = $order->id;
                $orderItem->product_id = $item['product_id'];
                $orderItem->sku_id = $item['sku_id'];
                $orderItem->quantity = $item['quantity'];
                $orderItem->price = $item['price'];
                $orderItem->save();

                // 减少库存
                $this->productService->decreaseStock($item['sku_id'], $item['quantity']);
            }

            Db::commit();

            // 发送订单创建事件
            event(new OrderCreated($order));

            return $order->toArray();

        } catch (Exception $e) {
            Db::rollBack();
            throw $e;
        }
    }

    /**
     * 验证订单项
     */
    private function validateOrderItems(array $items): void
    {
        foreach ($items as $item) {
            $sku = ProductSku::query()
                ->where('id', $item['sku_id'])
                ->where('product_id', $item['product_id'])
                ->first();

            if (!$sku) {
                throw new Exception("商品SKU不存在");
            }

            if ($sku->stock name} 库存不足");
            }
        }
    }

    /**
     * 计算订单总金额
     */
    private function calculateTotalAmount(array $items): float
    {
        $total = 0;
        foreach ($items as $item) {
            $total += $item['price'] * $item['quantity'];
        }
        return $total;
    }

    /**
     * 生成订单号
     */
    private function generateOrderNo(): string
    {
        return date('YmdHis') . str_pad((string) mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
    }
}

四、服务通信机制

1. JSON-RPC服务通信

// config/autoload/services.php
return [
    'consumers' => [
        [
            'name' => 'UserService',
            'service' => AppServiceUserServiceInterface::class,
            'nodes' => [
                ['host' => '127.0.0.1', 'port' => 9502],
            ],
        ],
        [
            'name' => 'ProductService',
            'service' => AppServiceProductServiceInterface::class,
            'nodes' => [
                ['host' => '127.0.0.1', 'port' => 9503],
            ],
        ],
    ],
];

// 用户服务接口
interface UserServiceInterface
{
    public function register(array $data): array;
    public function login(string $username, string $password): array;
    public function getUserInfo(int $userId): array;
}

// 在订单服务中调用用户服务
class OrderController
{
    #[Inject]
    private UserServiceInterface $userService;

    public function create()
    {
        // 调用用户服务验证用户
        $userInfo = $this->userService->getUserInfo($userId);
        
        // 创建订单逻辑...
    }
}

2. 消息队列异步处理

// 配置Redis队列
// config/autoload/async_queue.php
return [
    'default' => 'redis',
    'enable' => true,
    'connections' => [
        'redis' => [
            'driver' => HyperfAsyncQueueDriverRedisDriver::class,
            'channel' => 'queue',
            'timeout' => 2,
            'retry_seconds' => 5,
            'handle_timeout' => 10,
            'processes' => 1,
            'concurrent' => [
                'limit' => 10,
            ],
        ],
    ],
];

// 订单创建事件监听器
class OrderCreatedListener implements ListenerInterface
{
    public function listen(): array
    {
        return [
            OrderCreated::class,
        ];
    }

    public function process(object $event)
    {
        $order = $event->order;
        
        // 发送邮件通知
        $this->sendOrderEmail($order);
        
        // 更新统计数据
        $this->updateStatistics($order);
        
        // 推送消息到APP
        $this->pushNotification($order);
    }

    private function sendOrderEmail(Order $order)
    {
        // 异步发送邮件
        HyperfAsyncQueueDriverDriverFactory::instance('redis')->push(
            new SendEmailJob($order)
        );
    }
}

// 发送邮件任务
class SendEmailJob extends Job
{
    public $order;

    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    public function handle()
    {
        // 发送邮件逻辑
        $mailer = make(Mailer::class);
        $mailer->sendOrderConfirmation($this->order);
    }
}

3. 服务发现与注册

// 使用Consul进行服务注册发现
// config/autoload/consul.php
return [
    'uri' => 'http://127.0.0.1:8500',
    'token' => '',
    'check' => [
        'deregister_critical_service_after' => '90m',
        'interval' => '10s',
    ],
];

// 服务提供者
class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        // 注册Consul客户端
        $this->app->bind(ClientInterface::class, function () {
            return new Client([
                'base_uri' => config('consul.uri'),
                'headers' => [
                    'X-Consul-Token' => config('consul.token'),
                ],
            ]);
        });

        // 注册服务发现
        $this->app->bind(ServiceDiscoverInterface::class, ConsulAgent::class);
    }

    public function boot()
    {
        // 服务启动时注册到Consul
        $this->app->get(ConsulAgent::class)->registerService([
            'ID' => 'user-service-' . getmypid(),
            'Name' => 'user-service',
            'Tags' => ['v1.0'],
            'Address' => '127.0.0.1',
            'Port' => 9502,
            'Check' => [
                'HTTP' => 'http://127.0.0.1:9502/health',
                'Interval' => '10s',
                'Timeout' => '5s',
            ],
        ]);
    }
}

五、部署与监控

1. Docker容器化部署

# Dockerfile
FROM hyperf/hyperf:8.0-alpine-v3.15-swoole

WORKDIR /opt/www

COPY . /opt/www

RUN composer install --no-dev 
    && php bin/hyperf.php

EXPOSE 9501

CMD ["php", "bin/hyperf.php", "start"]

# docker-compose.yml
version: '3.8'
services:
  user-service:
    build: ./user-service
    ports:
      - "9502:9501"
    environment:
      - APP_ENV=production
    depends_on:
      - redis
      - mysql
      - consul

  product-service:
    build: ./product-service
    ports:
      - "9503:9501"
    environment:
      - APP_ENV=production

  order-service:
    build: ./order-service
    ports:
      - "9504:9501"
    environment:
      - APP_ENV=production

  api-gateway:
    build: ./api-gateway
    ports:
      - "9501:9501"
    environment:
      - APP_ENV=production

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - api-gateway

  redis:
    image: redis:6-alpine
    ports:
      - "6379:6379"

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: micro_mall
    ports:
      - "3306:3306"

  consul:
    image: consul:1.15
    ports:
      - "8500:8500"

2. 性能监控配置

// 集成Prometheus监控
// config/autoload/metric.php
return [
    'default' => 'prometheus',
    'use_standalone_process' => true,
    'enable_default_metrics' => true,
    'default_metrics_interval' => 5,
];

// 自定义业务指标
class OrderMetrics
{
    public static function recordOrderCreated()
    {
        $counter = make(Counter::class, [
            'namespace' => 'app',
            'subsystem' => 'order',
            'name' => 'created_total',
            'help' => '订单创建总数',
        ]);
        
        $counter->add(1);
    }

    public static function recordOrderAmount(float $amount)
    {
        $histogram = make(Histogram::class, [
            'namespace' => 'app',
            'subsystem' => 'order',
            'name' => 'amount_distribution',
            'help' => '订单金额分布',
            'buckets' => [100, 500, 1000, 5000, 10000],
        ]);
        
        $histogram->observe($amount);
    }
}

// 在订单服务中使用
class OrderService
{
    public function createOrder()
    {
        // 创建订单逻辑...
        
        // 记录指标
        OrderMetrics::recordOrderCreated();
        OrderMetrics::recordOrderAmount($totalAmount);
    }
}

3. 压力测试结果

# 使用wrk进行压力测试
wrk -t12 -c400 -d30s http://localhost:9501/api/products

# 测试结果对比:
# 传统PHP-FPM架构:
# Requests/sec: 1,200
# 平均延迟: 350ms

# Swoole+Hyperf微服务架构:
# Requests/sec: 12,500 (提升10.4倍)
# 平均延迟: 32ms (降低89%)

# 资源占用对比:
# 内存使用:从2GB降低到800MB
# CPU使用率:从90%降低到45%

PHP高性能微服务架构:基于Swoole和Hyperf构建分布式电商系统
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 php PHP高性能微服务架构:基于Swoole和Hyperf构建分布式电商系统 https://www.taomawang.com/server/php/1306.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务