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

7.1 KiB

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)

# 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)

# 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

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

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

curl -X POST "http://localhost:5000/api/gateway/reload"

Option 3: Database Direct Insert

Insert Service Instance

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

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:

# 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:

# 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:

# 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

# Global routes
curl http://localhost:5000/api/gateway/routes/global

# Tenant routes
curl http://localhost:5000/api/gateway/tenants/{tenantCode}/routes

View Instances

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