namespace Fengling.Console.Controllers; /// /// 网关管理控制器 /// 提供网关服务、路由、集群实例等配置管理功能 /// [ApiController] [Route("api/console/[controller]")] [Authorize(AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)] public class GatewayController(IGatewayService gatewayService, ILogger logger) : ControllerBase { /// /// 获取网关统计数据 /// /// 网关的整体统计信息,包括请求量、响应时间等指标 /// 成功返回网关统计数据 /// 服务器内部错误 [HttpGet("statistics")] [Produces("application/json")] [ProducesResponseType(typeof(GatewayStatisticsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task> GetStatistics() { try { var statistics = await gatewayService.GetStatisticsAsync(); return Ok(statistics); } catch (Exception ex) { logger.LogError(ex, "Error getting gateway statistics"); return StatusCode(500, new { message = ex.Message }); } } /// /// 获取网关服务列表 /// /// 是否只返回全局服务,默认为false /// 租户编码,用于筛选特定租户的服务 /// 网关服务列表,包含服务名称、地址、健康状态等信息 /// 成功返回网关服务列表 /// 服务器内部错误 [HttpGet("services")] [Produces("application/json")] [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task>> GetServices( [FromQuery] bool globalOnly = false, [FromQuery] string? tenantCode = null) { try { var services = await gatewayService.GetServicesAsync(globalOnly, tenantCode); return Ok(services); } catch (Exception ex) { logger.LogError(ex, "Error getting gateway services"); return StatusCode(500, new { message = ex.Message }); } } /// /// 获取单个网关服务详情 /// /// 服务名称 /// 租户编码,用于筛选特定租户的服务 /// 网关服务的详细信息 /// 成功返回服务详情 /// 服务不存在 /// 服务器内部错误 [HttpGet("services/{serviceName}")] [Produces("application/json")] [ProducesResponseType(typeof(GatewayServiceDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task> GetService( string serviceName, [FromQuery] string? tenantCode = null) { try { var service = await gatewayService.GetServiceAsync(serviceName, tenantCode); if (service == null) { return NotFound(new { message = $"Service {serviceName} not found" }); } return Ok(service); } catch (Exception ex) { logger.LogError(ex, "Error getting service {ServiceName}", serviceName); return StatusCode(500, new { message = ex.Message }); } } /// /// 注册新的网关服务 /// /// 创建服务所需的配置信息 /// 创建的服务详情 /// 成功创建服务 /// 请求参数无效或服务已存在 /// 服务器内部错误 [HttpPost("services")] [Produces("application/json")] [ProducesResponseType(typeof(GatewayServiceDto), StatusCodes.Status201Created)] [ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task> RegisterService([FromBody] CreateGatewayServiceDto dto) { try { var service = await gatewayService.RegisterServiceAsync(dto); return CreatedAtAction(nameof(GetService), new { serviceName = service.ServicePrefix }, service); } catch (InvalidOperationException ex) { logger.LogWarning(ex, "Validation error registering service"); return BadRequest(new { message = ex.Message }); } catch (Exception ex) { logger.LogError(ex, "Error registering service"); return StatusCode(500, new { message = ex.Message }); } } /// /// 注销网关服务 /// /// 要注销的服务名称 /// 租户编码,用于筛选特定租户的服务 /// 无内容响应 /// 成功注销服务 /// 服务不存在 /// 服务器内部错误 [HttpDelete("services/{serviceName}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task UnregisterService( string serviceName, [FromQuery] string? tenantCode = null) { try { var result = await gatewayService.UnregisterServiceAsync(serviceName, tenantCode); if (!result) { return NotFound(new { message = $"Service {serviceName} not found" }); } return Ok(new { message = "Service unregistered successfully" }); } catch (Exception ex) { logger.LogError(ex, "Error unregistering service {ServiceName}", serviceName); return StatusCode(500, new { message = ex.Message }); } } /// /// 获取网关路由列表 /// /// 是否只返回全局路由,默认为false /// 网关路由列表,包含路径匹配规则、转发目标等信息 /// 成功返回网关路由列表 /// 服务器内部错误 [HttpGet("routes")] [Produces("application/json")] [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task>> GetRoutes([FromQuery] bool globalOnly = false) { try { var routes = await gatewayService.GetRoutesAsync(globalOnly); return Ok(routes); } catch (Exception ex) { logger.LogError(ex, "Error getting gateway routes"); return StatusCode(500, new { message = ex.Message }); } } /// /// 创建新的网关路由 /// /// 创建路由所需的配置信息 /// 创建的路由详情 /// 成功创建路由 /// 请求参数无效 /// 服务器内部错误 [HttpPost("routes")] [Produces("application/json")] [ProducesResponseType(typeof(GatewayRouteDto), StatusCodes.Status201Created)] [ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task> CreateRoute([FromBody] CreateGatewayRouteDto dto) { try { var route = await gatewayService.CreateRouteAsync(dto); return Ok(route); } catch (InvalidOperationException ex) { return BadRequest(new { message = ex.Message }); } catch (Exception ex) { logger.LogError(ex, "Error creating gateway route"); return StatusCode(500, new { message = ex.Message }); } } /// /// 获取集群实例列表 /// /// 集群ID /// 指定集群下的所有服务实例列表 /// 成功返回实例列表 /// 服务器内部错误 [HttpGet("clusters/{clusterId}/instances")] [Produces("application/json")] [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task>> GetInstances(string clusterId) { try { var instances = await gatewayService.GetInstancesAsync(clusterId); return Ok(instances); } catch (Exception ex) { logger.LogError(ex, "Error getting instances for cluster {ClusterId}", clusterId); return StatusCode(500, new { message = ex.Message }); } } /// /// 添加服务实例到集群 /// /// 创建实例所需的配置信息 /// 创建的实例详情 /// 成功添加实例 /// 请求参数无效 /// 服务器内部错误 [HttpPost("instances")] [Produces("application/json")] [ProducesResponseType(typeof(GatewayInstanceDto), StatusCodes.Status201Created)] [ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task> AddInstance([FromBody] CreateGatewayInstanceDto dto) { try { var instance = await gatewayService.AddInstanceAsync(dto); return CreatedAtAction(nameof(GetInstances), new { clusterId = dto.ClusterId }, instance); } catch (InvalidOperationException ex) { return BadRequest(new { message = ex.Message }); } catch (Exception ex) { logger.LogError(ex, "Error adding instance to cluster {ClusterId}", dto.ClusterId); return StatusCode(500, new { message = ex.Message }); } } /// /// 移除服务实例 /// /// 实例ID /// 无内容响应 /// 成功移除实例 /// 实例不存在 /// 服务器内部错误 [HttpDelete("instances/{instanceId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task RemoveInstance(long instanceId) { try { var result = await gatewayService.RemoveInstanceAsync(instanceId); if (!result) { return NotFound(new { message = $"Instance {instanceId} not found" }); } return Ok(new { message = "Instance removed successfully" }); } catch (Exception ex) { logger.LogError(ex, "Error removing instance {InstanceId}", instanceId); return StatusCode(500, new { message = ex.Message }); } } /// /// 更新实例权重 /// 用于负载均衡策略中调整实例的请求分发权重 /// /// 实例ID /// 包含新权重值的请求体 /// 无内容响应 /// 成功更新权重 /// 实例不存在 /// 服务器内部错误 [HttpPut("instances/{instanceId}/weight")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task UpdateWeight(long instanceId, [FromBody] GatewayUpdateWeightDto dto) { try { var result = await gatewayService.UpdateInstanceWeightAsync(instanceId, dto.Weight); if (!result) { return NotFound(new { message = $"Instance {instanceId} not found" }); } return Ok(new { message = "Weight updated successfully" }); } catch (Exception ex) { logger.LogError(ex, "Error updating weight for instance {InstanceId}", instanceId); return StatusCode(500, new { message = ex.Message }); } } /// /// 重新加载网关配置 /// 触发网关重新加载所有配置,包括路由、服务、集群等配置 /// /// 无内容响应 /// 成功重新加载配置 /// 服务器内部错误 [HttpPost("reload")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status500InternalServerError)] public async Task ReloadGateway() { try { await gatewayService.ReloadGatewayAsync(); return Ok(new { message = "Gateway configuration reloaded successfully" }); } catch (Exception ex) { logger.LogError(ex, "Error reloading gateway configuration"); return StatusCode(500, new { message = ex.Message }); } } }