fengling-activity/docs/GATEWAY_INTEGRATION.md
sam ab8d12527e refactor: major project restructuring and cleanup
Changes:

- Remove deprecated Fengling.Activity and YarpGateway.Admin projects

- Add points processing services with distributed lock support

- Update Vben frontend with gateway management pages

- Add gateway config controller and database listener

- Update routing to use header-mixed-nav layout

- Add comprehensive test suites for Member services

- Add YarpGateway integration tests

- Update package versions in Directory.Packages.props

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-15 10:34:07 +08:00

274 lines
7.1 KiB
Markdown

# Activity Service Gateway Integration Guide
## Overview
This document describes how to integrate the Activity Engine microservice with the YARP reverse proxy gateway.
## Architecture
```
Client Request
┌─────────────────────────────────┐
│ YARP Gateway │
│ │
│ Route: /api/activity/** │
│ Cluster: activity-service │
└─────────────────────────────────┘
┌─────────────────────────────────┐
│ Activity Service │
│ http://localhost:5001 │
│ │
│ GET /api/activity/campaigns │
│ POST /api/activity/campaigns │
│ GET /api/activity/campaigns/.. │
└─────────────────────────────────┘
```
## Configuration Steps
### Option 1: Using Command Line Script
#### Bash (Linux/macOS)
```bash
# Make script executable
chmod +x scripts/gateway/register-activity-service.sh
# Register with global route (all tenants)
./scripts/gateway/register-activity-service.sh \
--gateway-url "http://localhost:5000" \
--service-name "activity" \
--cluster-id "activity-service" \
--address "http://localhost:5001"
# Register with tenant-specific route
./scripts/gateway/register-activity-service.sh \
--gateway-url "http://localhost:5000" \
--tenant-code "tenant001" \
--service-name "activity" \
--address "http://localhost:5001"
```
#### PowerShell (Windows)
```powershell
# Register with global route
pwsh scripts/gateway/Register-ActivityService.ps1 `
-GatewayUrl "http://localhost:5000" `
-ServiceName "activity" `
-ClusterId "activity-service" `
-InstanceAddress "http://localhost:5001" `
-IsGlobal
# Register with tenant-specific route
pwsh scripts/gateway/Register-ActivityService.ps1 `
-GatewayUrl "http://localhost:5000" `
-TenantCode "tenant001" `
-ServiceName "activity" `
-InstanceAddress "http://localhost:5001"
```
### Option 2: Using Gateway Management API
#### 1. Add Service Instance
```bash
curl -X POST "http://localhost:5000/api/gateway/clusters/activity-service/instances" \
-H "Content-Type: application/json" \
-d '{
"destinationId": "activity-1",
"address": "http://localhost:5001",
"weight": 1
}'
```
#### 2. Add Global Route
```bash
curl -X POST "http://localhost:5000/api/gateway/routes/global" \
-H "Content-Type: application/json" \
-d '{
"serviceName": "activity",
"clusterId": "activity-service",
"pathPattern": "/api/activity/{**path}"
}'
```
#### 3. Reload Configuration
```bash
curl -X POST "http://localhost:5000/api/gateway/reload"
```
### Option 3: Database Direct Insert
#### Insert Service Instance
```sql
INSERT INTO "ServiceInstances" (
"Id",
"ClusterId",
"DestinationId",
"Address",
"Health",
"Weight",
"Status",
"CreatedTime"
)
VALUES (
EXTRACT(EPOCH FROM NOW())::bigint * 1000,
'activity-service',
'activity-1',
'http://localhost:5001',
1,
1,
1,
NOW()
);
```
#### Insert Global Route
```sql
INSERT INTO "TenantRoutes" (
"Id",
"TenantCode",
"ServiceName",
"ClusterId",
"PathPattern",
"Priority",
"Status",
"IsGlobal",
"CreatedTime"
)
VALUES (
EXTRACT(EPOCH FROM NOW())::bigint * 1000 + 1,
'',
'activity',
'activity-service',
'/api/activity/{**path}',
0,
1,
true,
NOW()
);
```
## API Endpoints
After configuration, the following endpoints will be available through the gateway:
| Method | Path | Description |
|--------|------|-------------|
| POST | `/api/activity/api/campaigns` | Create a new campaign |
| GET | `/api/activity/api/campaigns` | List all campaigns |
| GET | `/api/activity/api/campaigns/{id}` | Get campaign by ID |
| POST | `/api/activity/api/campaigns/{id}/publish` | Publish a campaign |
## Health Check
The Activity service exposes a health check endpoint at `/health`:
```bash
# Direct access
curl http://localhost:5001/health
# Through gateway
curl http://localhost:5000/api/activity/health
```
## Multiple Instances
For high availability, add multiple service instances:
```bash
# Add second instance
curl -X POST "http://localhost:5000/api/gateway/clusters/activity-service/instances" \
-H "Content-Type: application/json" \
-d '{
"destinationId": "activity-2",
"address": "http://localhost:5002",
"weight": 1
}'
# Reload configuration
curl -X POST "http://localhost:5000/api/gateway/reload"
```
## Load Balancing
The gateway uses **Distributed Weighted Round Robin** load balancing by default. Adjust weights for traffic distribution:
```bash
# Increase weight for a high-performance instance
curl -X PUT "http://localhost:5000/api/gateway/instances/12345" \
-H "Content-Type: application/json" \
-d '{"weight": 2}'
```
## Monitoring
### View Routes
```bash
# Global routes
curl http://localhost:5000/api/gateway/routes/global
# Tenant routes
curl http://localhost:5000/api/gateway/tenants/{tenantCode}/routes
```
### View Instances
```bash
curl http://localhost:5000/api/gateway/clusters/activity-service/instances
```
## Troubleshooting
### Route Not Working
1. Check if route is configured: `GET /api/gateway/routes/global`
2. Verify instance health: `GET /api/gateway/clusters/{clusterId}/instances`
3. Reload configuration: `POST /api/gateway/reload`
### 404 Not Found
- Ensure the path pattern matches the request URL
- Check if the route is active (Status = 1)
### 502 Bad Gateway
- Verify the service instance is running
- Check the service address is accessible from the gateway
- Verify health check endpoint: `GET /health`
## Configuration Reference
### GwServiceInstance Fields
| Field | Type | Description |
|-------|------|-------------|
| ClusterId | string | Unique cluster identifier |
| DestinationId | string | Unique destination identifier |
| Address | string | Service address (http://host:port) |
| Weight | int | Load balancing weight (default: 1) |
| Health | int | Health status (1 = healthy) |
| Status | int | Active status (1 = active) |
### GwTenantRoute Fields
| Field | Type | Description |
|-------|------|-------------|
| TenantCode | string | Tenant identifier (empty for global) |
| ServiceName | string | Logical service name |
| ClusterId | string | Target cluster identifier |
| PathPattern | string | URL path pattern with placeholders |
| Priority | int | Route priority (lower = higher priority) |
| IsGlobal | bool | Whether route applies to all tenants |
## Path Pattern Syntax
YARP uses ASP.NET Core routing syntax for path patterns:
| Pattern | Description |
|---------|-------------|
| `/api/activity` | Exact match |
| `/api/activity/{**path}` | Catch-all segment |
| `/api/activity/{id}` | Parameter segment |
| `/api/activity/{id}/rewards` | Multiple parameters |
For more details, see [ASP.NET Core Routing](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing)