Ckli的blog

[绝不人云亦云] 只发亲测、完整的教程

从零构建共享API平台:基于Swoft 2.0的微服务架构实践


<本文介绍如何基于Swoft 2.0框架>
<构建共享API网关平台,探讨公益与技术,商业化的平衡之道。>

## 前言

做公益这件事,我走了好多年。中间有过委屈,有过难,甚至看着自己搭建的平台,明明能帮人,却因"不会吆喝"而少有人问津时,也会陷入迷茫。但每当想起乡镇里,有人为了赶一趟班车,天不亮就守在路边;残障朋友想找份能做的活,却被大平台的门槛挡在门外;还有那些假期里,为买不到票、怕堵车而发愁的乡亲们,我又觉得这件事必须得做下去。

——摘自《七家坡的"摆渡人"》

作为一名在PHP领域深耕近20年的后端工程师,我一直在思考:如何用技术力量帮助更多人,同时又能让技术实现可持续发展?本文将分享我基于Swoft 2.0框架构建共享API平台的实践经验。

## 项目背景

我的共享API平台目前已经支撑了多个公益项目:

- **七家坡基层互助站**
  (https://lo.lck.yn.cn/)
  为云南乡镇居民提供顺风车、用工信息等便民服务

- **AI算命站点**
  (https://ai.lck.yn.cn/)
  基于AI的传统文化服务

这些项目虽然面向不同场景,但都需要相同的底层能力:用户认证、地理定位、支付、数据存储等。为了避免重复造轮子,我决定构建一个**共享API平台**,让所有项目都能快速接入这些通用能力。

## 技术选型:为什么选择Swoft 2.0?

在选型时,我对比了多个PHP框架:

| 框架 | 协程支持 | 微服务 | 学习成本 | 性能 |
|------|---------|--------|---------|------|
| Laravel | 无 | 无 | 低 | 中 |
| Hyperf | 有 | 有 | 中 | 高 |
| Swoft 2.0 | 有 | 有 | 中 | 高 |

最终选择**Swoft 2.0**的原因:


1. **成熟的协程支持**:基于Swoole扩展,提供原生协程能力,性能接近Go语言

2. **gRPC原生支持**:内置gRPC支持,可与任何语言无缝对接

3. **微服务架构**:内置RPC服务注册与发现,完美契合我的分布式架构需求

4. **注解驱动**:类似Spring Cloud的注解机制,代码简洁优雅

5. **完善的生态**:内置连接池、AOP、任务调度等企业级功能


### 关于框架选择的真实思考


**Swoft 2.0的现状**:

- 官方早已停止维护,官网已无法访问

- 基本查不到相关资料,社区支持很少

- 很多功能文档缺失,需要自己摸索


**为什么还是选择了它?**


1. **协程性能优势**:Swoole扩展的性能优势难以替代

2. **架构设计优秀**:微服务、RPC、注解机制的设计理念先进

3. **自主掌控**:既然官方不维护,我就自己维护


**填坑之路**:

- 很多功能的实现方案,AI都无法给出正确答案

- 每个坑都花了超过一周的时间去研究、测试、验证

- 通过理解作者意图、结合实战经验、深入底层源码,最终全部实现


**给后来者的建议**:

技术选型不要盲目追求"官方维护",关键是否适合你的场景。

框架只是工具,你的技术积累和解决问题的能力才是核心。


## 架构设计

### 整体架构

```
┌─────────────────────────────────────────────────────────┐
│                    前端应用层                            │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐ │
│  │ 七家坡(H5/小程序) │ │ AI站点(H5/小程序) │ │  其他项目     │ │
│  └──────────────┘  └──────────────┘  └──────────────┘ │
└─────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────┐
│                   API网关层                               │
│  ┌──────────────────────────────────────────────────┐  │
│  │ Gateway (api.micro.lck.yn.cn)   │  │
│  │ - JWT认证  - 权限控制          │  │
│  │ - 限流  - 日志审计              │  │
│  └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────┐
│                   微服务层                               │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐       │
│  │ Traffic │ │  Stay   │ │  Admin  │ │  AIGC   │       │
│  │  (出行) │ │ (住宿)  │ │ (管理)  │ │ (AI服务)│       │
│  └─────────┘ └─────────┘ └─────────┘ └─────────┘       │
└─────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────┐
│                   数据存储层                              │
│  ┌─────────┐ ┌─────────┐ ┌─────────────┐               │
│  │ MySQL 8 │ │  Redis  │ │ 支付宝/微信  │               │
│  │(主从)   │ │ (缓存)  │ │  支付接口    │               │
│  └─────────┘ └─────────┘ └─────────────┘               │
└─────────────────────────────────────────────────────────┘
```

### 服务拆分

根据业务领域,我将服务拆分为以下模块(端口为示意配置,实际部署时可自定义):

| 服务 | 职责 | 端口 |
|------|------|------|
| **gateway** | API网关,负责认证、路由、限流 | 8080 |
| **admin** | 用户、地址、分类等基础服务 | 8306 |
| **traffic** | 顺风车、岗位信息等出行相关服务 | 8307 |
| **stay** | 住宿、民宿等住宿服务 | 8308 |
| **aigc** | AI算命、AI生成等AI服务 | 8309 |
| **user** | 用户、权限管理 | 8310 |
| **pay** | 支付订单管理 | 8311 |

## 核心功能实现

### 1. API网关设计

网关是整个系统的入口,负责:

- **JWT认证**:基于`Swoft\Auth`组件实现,支持token自动刷新
- **域授权机制**:根据请求来源域名进行授权控制
- **本地开发友好**:localhost/127.0.0.1等本地域名默认已授权
- **权限控制**:通过中间件拦截未授权请求
- **服务路由**:将请求转发到对应的微服务
- **限流保护**:使用`Swoft\Limiter`防止接口滥用
- **文档生成**:自动生成Swagger文档

网关配置示例(`config/beans.php`):

```php
return [
    'userAuth' => [
        'class' => Swoft\Auth\Manager::class,
        'name'  => 'user',
        'language' => 'zh',
        'ttl' => 7200, // token有效期2小时
        'refreshTtl' => 2592000, // 刷新token有效期30天
    ],
    'jwtAuth' => [
        'class' => Swoft\Auth\Parser\JWTAuthParser::class,
    ]
];
```

**Token自动刷新机制**:

```php
// 中间件中实现token自动刷新
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
    $token = $this->jwtAuth->parse($request);
    $payload = $token->payload();

    // 检查token是否即将过期(剩余时间小于10分钟)
    if ($payload['exp'] - time() < 600) {
        $newToken = $this->auth->refreshToken($token);
        // 在响应头中返回新token
        return $handler->handle($request)->withHeader('X-New-Token', $newToken);
    }

    return $handler->handle($request);
}
```

### 2. 地理位置查询优化(LBS)

顺风车和民宿服务都需要根据用户位置查询附近信息。这是典型的地理围栏查询场景。

#### 优化前的问题

传统使用`HAVING`计算距离的方式效率低下:

```sql
SELECT *, (6371 * ACOS(COS(RADIANS(lat)) * COS(RADIANS(24.88))
  * COS(RADIANS(lng) - RADIANS(102.83))
  + SIN(RADIANS(lat)) * SIN(RADIANS(24.88)))) AS distance
FROM sys_carpooling
HAVING distance < 10
ORDER BY distance
```

**问题**:
- 每次查询都要计算全表距离,性能极差
- 无法使用索引,随着数据量增加性能急剧下降

#### 优化方案

采用**边界框预过滤 + 空间索引**的双重优化策略:

```sql
SELECT *, ST_Distance_Sphere(
    location,
    ST_GeomFromText('POINT(102.83 24.88)')
) AS distance
FROM sys_carpooling
WHERE lat BETWEEN 24.01 AND 25.75
  AND lng BETWEEN 101.91 AND 103.75
  AND ST_Distance_Sphere(location, POINT(102.83, 24.88)) <= 10000
ORDER BY distance
LIMIT 20
```

**优化要点**:

1. **添加空间索引**:

```sql
ALTER TABLE sys_carpooling
ADD COLUMN location POINT NOT NULL COMMENT '位置坐标' AFTER lat,
ADD SPATIAL INDEX idx_location (location);
```

2. **范围级别参数化**:

```php
$rangeMap = [
    1 => 10,   // 10公里
    2 => 50,   // 50公里
    3 => 100,  // 100公里(默认)
];

$range = $rangeMap[$level] ?? 100;
```

3. **计算边界框**:

```php
$lngMin = $lng - $range / 111.32 / cos($lat * PI() / 180);
$lngMax = $lng + $range / 111.32 / cos($lat * PI() / 180);
$latMin = $lat - $range / 111.32;
$latMax = $lat + $range / 111.32;
```

**性能对比**:

| 数据量 | 优化前 | 优化后 | 提升 |
|--------|--------|--------|------|
| 1万条  | 2.5s   | 0.05s  | 50x |
| 10万条 | 25s    | 0.08s  | 312x |

### 3. RPC微服务通信

平台支持**gRPC协议**,这是微服务通信的最佳选择。

#### 为什么选择gRPC?

gRPC相比传统HTTP API有以下优势:

| 特性 | HTTP/REST | gRPC |
|------|-----------|------|
| 协议 | 文本(JSON) | 二进制(Protobuf) |
| 传输效率 | 低(数据大) | 高(数据小) |
| 序列化速度 | 慢 | 快(5-10倍) |
| 跨语言支持 | 需要手动适配 | 自动生成代码 |
| 流式传输 | 不支持 | 支持(单向流/双向流) |
| 代码量 | 手动解析 | 自动生成 |

**关键优势**:
- **任何语言对接**:支持Go、Java、Python、Node.js、C#、PHP等20+种语言
- **协程友好**:完美配合Swoole协程,无阻塞
- **内存运行**:常驻内存,无需每次请求启动
- **性能更快**:二进制协议,传输速度提升3-5倍
- **资源占用少**:相比传统HTTP API,内存占用降低50%以上

服务间通过RPC调用,Swoft提供了优雅的注解方式:

**定义Proto文件**(`traffic.proto`):

```protobuf
syntax = "proto3";

package traffic;

service TrafficService {
    rpc NearList(NearRequest) returns (NearResponse);
    rpc CreateCarpooling(CarpoolingRequest) returns (CommonResponse);
}

message NearRequest {
    float lng = 1;
    float lat = 2;
    int32 level = 3;
}

message NearResponse {
    repeated Carpooling items = 1;
    int32 total = 2;
}
```

**PHP服务端实现**:

```php
/**
 * @RpcService(name="trafficService", version="1.0")
 */
class TrafficService
{
    /**
     * 查询附近顺风车
     */
    public function nearList(float $lng, float $lat, int $level = 3): array
    {
        return CarpoolingDao::nearList($lng, $lat, $level);
    }
}
```

**服务消费者通过`@Reference`注解注入**:

```php
/**
 * @Reference(name="trafficService", version="1.0")
 */
private $trafficService;

public function near(Request $request): Response
{
    $data = $this->trafficService->nearList(
        $request->get('lng'),
        $request->get('lat'),
        $request->get('level', 3)
    );
    return context()->getResponse()->withData($data);
}
```

**跨语言调用示例**:

```go
// Go客户端
conn, _ := grpc.Dial("localhost:8307", grpc.WithInsecure())
client := pb.NewTrafficServiceClient(conn)

req := &pb.NearRequest{
    Lng: 102.83,
    Lat: 24.88,
    Level: 3,
}
resp, _ := client.NearList(context.Background(), req)
```

### 4. 支付系统集成

支付系统支持微信和支付宝,需要区分PC端和移动端:

```php
public function createOrder(Request $request): Response
{
    $deviceType = getDeviceType(); // H5/Pc

    // 支付方式判断
    $method = $this->getPaymentMethod($channel, $deviceType);
    // 微信PC端: Native, 支付宝PC端: PcWeb, 移动端: H5

    $order = [
        'ser_name' => 'aigc',
        'amount' => $amount * 100, // 转为分
        'channel' => $channel, // Wechat/Alipay
        'method' => $method,
        'body' => '套餐名称',
        'source' => '总部自营',
        'user_id' => $userId ?: null,
        'temp_id' => $tempId ?: null,
    ];

    return $this->orderApi->create($order);
}
```

### 5. 自动化部署

为了提高开发效率,我实现了完整的自动化部署流程:

```bash
# 部署脚本
#!/bin/bash
git pull origin master
composer install --no-dev
php bin/swoft stop
php bin/swoft start -d
```

Git提交后自动触发部署,无需人工干预。

## API文档管理

使用Swagger自动生成API文档,部署在:

- **生产环境**:
  https://api.micro.lck.yn.cn/swagger-ui.html

- **测试环境**:
  https://apitest.micro.lck.yn.cn/swagger-ui.html

文档配置(`composer.json`中的description):

```json
{
  "description": "共享API平台 - 5分钟快速接入\n1. 示例代码:Vue/React/微信小程序\n2. 成功案例:七家坡、AI站点\n3. 域授权:按项目域名授权,灵活接入\n4. 技术支持:微信 kmwmkj | 邮箱 admin@lck.yn.cn | 电话 15687658489"
}
```
```

## 接入模式与商业化思考

### 灵活的接入方式

平台提供两种接入模式,开发者可以根据项目发展阶段自由选择:

#### 1. 共享API模式(适合项目初期)

**适用场景**:
- 项目刚起步,用户量和并发较低
- 希望节省服务器和运维成本
- 快速验证商业想法

**优势**:
- **零运维成本**:无需搭建服务器、数据库等基础设施
- **快速上线**:5分钟即可完成接入
- **按需授权**:根据项目域名进行授权,灵活便捷
- **本地开发友好**:localhost等本地域名默认已授权,开发无忧

**授权方式**:
- 通过申请域名授权,绑定项目前端域名
- 本地开发环境(localhost、127.0.0.1)默认已授权
- 域名审核通过后,即可在生产环境使用

#### 2. 独立部署模式(适合项目成长期)

**适用场景**:
- 项目已有一定用户量和流量
- 需要更高的性能和稳定性
- 数据安全要求更高

**优势**:
- **完全独立**:网关、微服务、数据库全部独立部署
- **跨服务器架构**:可根据需要分布式部署
- **性能无上限**:根据业务需求灵活扩展
- **数据完全掌控**:所有数据存储在自有服务器

**部署灵活性**:
```
// 可以根据需求选择部署方式
方式1:单机部署(适合小型项目)
┌─────────────────────────────────┐
│  单服务器部署所有服务          │
└─────────────────────────────────┘

方式2:分布式部署(适合中大型项目)
┌──────────┐  ┌──────────┐  ┌──────────┐
│ 网关服务器│  │ 应用服务器│  │ 数据库   │
└──────────┘  └──────────┘  └──────────┘

方式3:集群部署(适合大型项目)
┌──────────┐  ┌──────────┐  ┌──────────┐
│ 网关集群  │  │ 应用集群  │  │ 数据库集群│
└──────────┘  └──────────┘  └──────────┘
```

### 无缝迁移路径

平台设计了平滑的迁移路径:

```
项目起步期          项目成长期          项目成熟期
    │                  │                  │
    ▼                  ▼                  ▼
共享API模式    →    独立部署模式    →    完全私有化
(零成本接入)        (逐步过渡)          (完全掌控)
```

**迁移优势**:
- **代码无需修改**:API接口保持一致
- **数据平滑迁移**:支持数据导出和导入
- **无缝切换**:域名授权即可切换模式

### 技术支持

提供多渠道技术支持:
- **微信**:kmwmkj
- **邮箱**:admin@lck.yn.cn
- **电话**:15687658489(微信同号)

### 公益与可持续

做公益不代表不能商业化,关键是找到平衡点:

**公益初心**:
- 始终记得为什么出发,不要因为商业化而偏离公益使命
- 为公益项目提供技术支持,降低公益项目的技术门槛

**可持续发展**:
- 公益也需要资金支持,合理的商业化能让平台走得更远
- 通过商业化项目反哺公益项目,形成良性循环

**开放共赢**:
- 欢迎更多公益项目接入,共同服务社会
- 建立开发者社区,共享技术资源和经验

## 经验总结

### 技术层面

1. **协程编程思维**:协程不是万能的,要避免阻塞操作,使用连接池、协程客户端等
2. **服务拆分粒度**:不要过度拆分,按业务领域划分,保持服务独立但不过于分散
3. **数据库优化**:善用MySQL 8.0的空间索引,地理位置查询性能提升显著
4. **监控告警**:建立完善的监控体系,及时发现和处理问题

### 产品层面

1. **文档先行**:好的API文档能让开发者快速上手,降低接入门槛
2. **示例代码**:提供Vue/React/小程序等多语言示例,覆盖主流技术栈
3. **渐进式开放**:先开放基础接口,逐步开放高级能力
4. **社区运营**:建立开发者社区,收集反馈,持续改进

### 商业层面

1. **灵活接入**:提供共享API和独立部署两种模式,满足不同阶段需求
2. **公益初心**:始终记得为什么出发,为公益项目降低技术门槛
3. **可持续发展**:合理的商业化能让平台更好地服务公益
4. **开放共赢**:欢迎更多项目接入,共同创造价值

## 展望

未来计划:

1. **扩展服务**:增加更多通用服务(短信、邮件、对象存储等)
2. **多区域部署**:在更多地区部署节点,降低延迟
3. **AI能力开放**:将AI算命等服务标准化后对外开放
4. **社区建设**:建立开发者社区,鼓励共享代码和经验
5. **接入示例**:提供更多接入示例(Vue、React、微信小程序等)
6. **管理后台**:开发可视化的域授权管理系统

## 接入指南

### 快速接入

1. **联系授权**:通过微信、邮箱或电话申请域名授权
2. **获取密钥**:获取项目的API密钥和配置信息
3. **配置调用**:根据文档配置API调用
4. **测试上线**:本地测试通过后即可上线

**本地开发说明**:
- localhost、127.0.0.1等本地域名默认已授权
- 开发过程中无需额外配置

### 技术支持

- **微信**:kmwmkj
- **邮箱**:admin@lck.yn.cn
- **电话**:15687658489(微信同号)
- **API文档**:https://api.micro.lck.yn.cn/swagger-ui.html

## 结语

技术不仅是工具,更是一种改变世界的力量。作为一名开发者,我有幸能用自己的专长帮助他人,这让我感到无比充实。

我希望通过这个共享API平台,降低技术门槛,让更多人能够快速实现自己的想法。无论你是想做公益项目,还是想开发商业应用,都可以在这里找到你需要的基础能力。

如果你也想接入我的共享API平台,欢迎联系我。让我们一起用技术创造价值,让世界变得更美好一点。

**联系方式**:
- 微信:kmwmkj
- 邮箱:admin@lck.yn.cn
- 电话:15687658489(微信同号)
- 网关地址:https://api.micro.lck.yn.cn/

---

**作者简介**:李成坤(Ckli),后端工程师,系统架构师,技术总监。从事PHP开发近20年,现任云南某科技公司技术总监。热衷于公益事业,用技术帮助需要帮助的人。

个人主页:https://www.lck.yn.cn/
技术博客:https://blog.lck.yn.cn/


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

«   2026年2月   »
1
2345678
9101112131415
16171819202122
232425262728
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
    文章归档
    网站收藏
    友情链接
    • RainbowSoft Studio Z-Blog
    • 订阅本站的 RSS 2.0 新闻聚合

    Powered By Z-BlogPHP 1.5.2 Zero

    Copyright Ckli Rights Reserved.