解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
12.59 KiB
X
# ApiHttpClient 使用手册 ## 概述 `ApiHttpClient` 是 NewLife.Core 提供的 Http 应用接口客户端,是对多个服务地址的包装。它在底层管理多个 `HttpClient`,提供统一的负载均衡和故障转移能力。 ### 核心特性 - **多地址管理**:支持配置多个服务地址,自动进行负载均衡 - **故障转移**:节点不可用时自动切换到备用节点 - **负载均衡**:支持故障转移、加权轮询、竞速调用三种模式 - **令牌鉴权**:支持 Token 和 Authentication 两种鉴权方式 - **响应解析**:支持自定义状态码和数据字段名称,适配不同平台 - **可扩展性**:支持自定义 JsonHost、Filter、事件等 ## 快速开始 ### 基础用法 ```csharp // 创建客户端 var client = new ApiHttpClient("http://api.example.com"); // GET 请求 var result = await client.GetAsync<UserInfo>("user/info", new { id = 123 }); // POST 请求 var response = await client.PostAsync<ResultModel>("user/create", new { name = "test", age = 18 }); // 同步调用 var data = client.Get<String>("api/data"); ``` ### 多地址配置 ```csharp // 逗号分隔多个地址 var client = new ApiHttpClient("http://api1.example.com,http://api2.example.com,http://api3.example.com"); // 或者手动添加 var client = new ApiHttpClient(); client.Add("primary", "http://api1.example.com"); client.Add("backup", "http://api2.example.com"); ``` ## 负载均衡 ### 三种负载均衡模式 | 模式 | 枚举值 | 说明 | |------|--------|------| | 故障转移 | `LoadBalanceMode.Failover` | 优先使用主节点,失败时自动切换到备用节点,过一段时间自动切回 | | 加权轮询 | `LoadBalanceMode.RoundRobin` | 按权重分配请求到多个节点,自动屏蔽不可用节点 | | 竞速调用 | `LoadBalanceMode.Race` | 并行请求多个节点,取最快响应,取消其它请求 | ### 故障转移模式(默认) ```csharp var client = new ApiHttpClient("http://primary.example.com,http://backup.example.com") { LoadBalanceMode = LoadBalanceMode.Failover, // 默认值 ShieldingTime = 60 // 不可用节点屏蔽60秒 }; // 正常情况使用 primary,primary 不可用时自动切换到 backup // 60秒后会尝试切回 primary var result = await client.GetAsync<Object>("api/data"); ``` ### 加权轮询模式 ```csharp // 格式:name=weight*url var client = new ApiHttpClient("master=3*http://api1.example.com,slave=7*http://api2.example.com") { LoadBalanceMode = LoadBalanceMode.RoundRobin }; // master 权重3,slave 权重7 // 10次请求中,master 约3次,slave 约7次 ``` ### 竞速调用模式 ```csharp var client = new ApiHttpClient("http://api1.example.com,http://api2.example.com,http://api3.example.com") { LoadBalanceMode = LoadBalanceMode.Race }; // 并行请求所有节点,返回最快的响应 // 适用于对响应时间要求极高的场景 ``` ## 身份验证 ### Token 令牌 ```csharp var client = new ApiHttpClient("http://api.example.com") { Token = "your_access_token" }; // 请求头自动添加:Authorization: Bearer your_access_token ``` ### Authentication 属性 ```csharp var client = new ApiHttpClient("http://api.example.com") { Authentication = new AuthenticationHeaderValue("Bearer", "your_token") }; // 或者使用 Basic 认证 client.Authentication = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes("user:password"))); ``` ### 服务节点独立 Token ```csharp // 在 URL 中指定 Token var client = new ApiHttpClient(); client.Add("service1", "http://api1.example.com#token=token_for_api1"); client.Add("service2", "http://api2.example.com#token=token_for_api2"); ``` > **优先级**:`Token` 属性优先于 `Authentication` 属性。 ## 响应解析 ### 标准响应格式 默认支持以下响应格式: ```json { "code": 0, "message": "success", "data": { ... } } ``` ### 自定义字段名称 ```csharp var client = new ApiHttpClient("http://api.example.com") { CodeName = "status", // 状态码字段名,默认自动识别 code/errcode/status DataName = "result" // 数据字段名,默认 data }; // 适配响应格式:{"status": 0, "result": {...}} ``` ### 支持的状态码字段 - `code` - `errcode` - `status` ### 支持的消息字段 - `message` - `msg` - `errmsg` - `error` ## Http 方法 ```csharp var client = new ApiHttpClient("http://api.example.com"); // GET - 参数拼接到 URL var result = await client.GetAsync<T>("api/users", new { page = 1, size = 10 }); // POST - 参数 JSON 序列化到 Body var result = await client.PostAsync<T>("api/users", new { name = "test" }); // PUT var result = await client.PutAsync<T>("api/users/1", new { name = "updated" }); // PATCH var result = await client.PatchAsync<T>("api/users/1", new { name = "patched" }); // DELETE var result = await client.DeleteAsync<T>("api/users/1"); // 通用调用 var result = await client.InvokeAsync<T>(HttpMethod.Post, "api/action", args); ``` ## 高级配置 ### 超时设置 ```csharp var client = new ApiHttpClient("http://api.example.com") { Timeout = 30_000 // 30秒,默认15秒 }; ``` ### 代理设置 ```csharp var client = new ApiHttpClient("http://api.example.com") { UseProxy = true // 使用系统代理,默认false }; ``` ### SSL证书验证 ```csharp var client = new ApiHttpClient("https://api.example.com") { CertificateValidation = false // 不验证证书,默认false }; ``` ### 自定义 UserAgent ```csharp var client = new ApiHttpClient("http://api.example.com") { DefaultUserAgent = "MyApp/1.0" }; ``` ### 自定义 Json 序列化 ```csharp var client = new ApiHttpClient("http://api.example.com") { JsonHost = new FastJson() // 自定义 Json 序列化器 }; ``` ## 事件与过滤器 ### OnRequest 事件 ```csharp var client = new ApiHttpClient("http://api.example.com"); client.OnRequest += (sender, e) => { // 添加自定义请求头 e.Request.Headers.Add("X-Request-Id", Guid.NewGuid().ToString()); e.Request.Headers.Add("X-Timestamp", DateTime.Now.Ticks.ToString()); }; ``` ### OnCreateClient 事件 ```csharp client.OnCreateClient += (sender, e) => { // 配置 HttpClient e.Client.DefaultRequestHeaders.Add("X-App-Version", "1.0.0"); }; ``` ### Http 过滤器 ```csharp // 使用内置的令牌过滤器 var filter = new TokenHttpFilter { UserName = "app_id", Password = "app_secret" }; var client = new ApiHttpClient("http://api.example.com") { Filter = filter }; // 过滤器会自动处理令牌的获取和刷新 ``` ### 自定义过滤器 ```csharp public class MyHttpFilter : IHttpFilter { public Task OnRequest(HttpClient client, HttpRequestMessage request, Object? state, CancellationToken cancellationToken) { // 请求前处理 request.Headers.Add("X-Custom", "value"); return Task.CompletedTask; } public Task OnResponse(HttpClient client, HttpResponseMessage response, Object? state, CancellationToken cancellationToken) { // 响应后处理 return Task.CompletedTask; } public Task OnError(HttpClient client, Exception ex, Object? state, CancellationToken cancellationToken) { // 错误处理 return Task.CompletedTask; } } ``` ## 服务状态监控 ### 查看当前服务 ```csharp var client = new ApiHttpClient("http://api1.example.com,http://api2.example.com"); // 当前正在使用的服务 var current = client.Current; Console.WriteLine($"当前服务:{current?.Name} - {current?.Address}"); // 当前服务名称 Console.WriteLine($"服务源:{client.Source}"); ``` ### 查看服务列表状态 ```csharp foreach (var svc in client.Services) { Console.WriteLine($"服务:{svc.Name}"); Console.WriteLine($" 地址:{svc.Address}"); Console.WriteLine($" 权重:{svc.Weight}"); Console.WriteLine($" 调用次数:{svc.Times}"); Console.WriteLine($" 错误次数:{svc.Errors}"); Console.WriteLine($" 是否可用:{svc.IsAvailable()}"); Console.WriteLine($" 下次可用时间:{svc.NextTime}"); } ``` ## 链路追踪 ```csharp var client = new ApiHttpClient("http://api.example.com") { Tracer = DefaultTracer.Instance, // 设置链路追踪器 SlowTrace = 5_000 // 超过5秒记录慢调用日志 }; ``` ## 依赖注入 ### ASP.NET Core 集成 ```csharp // 注册服务 services.AddSingleton<IApiClient>(sp => { var config = sp.GetRequiredService<IConfiguration>(); var client = new ApiHttpClient(config["ApiServer:Urls"]) { Timeout = config.GetValue<Int32>("ApiServer:Timeout"), ServiceProvider = sp }; return client; }); // 使用配置中心 services.AddSingleton<IApiClient>(sp => { return new ApiHttpClient(sp, "ApiServerConfig"); // 从配置中心读取 }); ``` ### IConfigMapping 接口 ```csharp // ApiHttpClient 实现了 IConfigMapping 接口 // 可以通过配置中心动态更新服务地址 var configProvider = services.GetRequiredService<IConfigProvider>(); configProvider.Bind(client, true, "ApiServer"); // 绑定配置节 ``` ## 文件下载 ```csharp var client = new ApiHttpClient("http://download.example.com"); // 下载文件并校验哈希 await client.DownloadFileAsync( requestUri: "files/package.zip", fileName: "D:/downloads/package.zip", expectedHash: "sha256:abc123...", // 可选,支持 md5/sha1/sha256/sha512 cancellationToken: default ); ``` ## 异常处理 ### ApiException ```csharp try { var result = await client.GetAsync<Object>("api/data"); } catch (ApiException ex) { // 业务异常(服务端返回的错误码) Console.WriteLine($"错误码:{ex.Code}"); Console.WriteLine($"错误信息:{ex.Message}"); } catch (HttpRequestException ex) { // 网络异常 Console.WriteLine($"网络错误:{ex.Message}"); } ``` ## 最佳实践 ### 1. 复用客户端实例 ```csharp // ? 推荐:作为单例使用 public class MyService { private static readonly ApiHttpClient _client = new("http://api.example.com"); public Task<T> GetDataAsync<T>() => _client.GetAsync<T>("api/data"); } // ? 避免:每次请求创建新实例 public async Task<T> GetDataAsync<T>() { using var client = new ApiHttpClient("http://api.example.com"); // 不推荐 return await client.GetAsync<T>("api/data"); } ``` ### 2. 合理设置超时 ```csharp var client = new ApiHttpClient("http://api.example.com") { Timeout = 10_000, // 根据接口特性设置合理超时 SlowTrace = 3_000 // 慢调用阈值 }; ``` ### 3. 配置故障转移 ```csharp var client = new ApiHttpClient("http://primary.example.com,http://backup.example.com") { ShieldingTime = 30, // 故障节点屏蔽30秒 LoadBalanceMode = LoadBalanceMode.Failover }; ``` ### 4. 使用链路追踪 ```csharp var client = new ApiHttpClient("http://api.example.com") { Tracer = DefaultTracer.Instance, Log = XTrace.Log // 开启日志 }; ``` ## 完整示例 ```csharp using NewLife.Log; using NewLife.Remoting; // 创建客户端 var client = new ApiHttpClient("master=3*http://api1.example.com,slave=7*http://api2.example.com") { Token = "your_access_token", Timeout = 15_000, ShieldingTime = 60, LoadBalanceMode = LoadBalanceMode.RoundRobin, CodeName = "code", DataName = "data", Tracer = DefaultTracer.Instance, Log = XTrace.Log }; // 添加请求拦截 client.OnRequest += (sender, e) => { e.Request.Headers.Add("X-Request-Id", Guid.NewGuid().ToString()); }; try { // 发起请求 var users = await client.GetAsync<List<UserInfo>>("api/users", new { page = 1, size = 10 }); foreach (var user in users) { Console.WriteLine($"用户:{user.Name}"); } // 查看当前使用的服务 Console.WriteLine($"请求服务:{client.Source} - {client.Current?.Address}"); } catch (ApiException ex) { Console.WriteLine($"业务错误 [{ex.Code}]:{ex.Message}"); } catch (HttpRequestException ex) { Console.WriteLine($"网络错误:{ex.Message}"); } ``` ## 相关类型 | 类型 | 说明 | |------|------| | `ApiHttpClient` | Http 应用接口客户端 | | `ServiceEndpoint` | 服务端点,包含地址、权重、状态等信息 | | `ILoadBalancer` | 负载均衡器接口 | | `FailoverLoadBalancer` | 故障转移负载均衡器 | | `WeightedRoundRobinLoadBalancer` | 加权轮询负载均衡器 | | `RaceLoadBalancer` | 竞速负载均衡器 | | `IHttpFilter` | Http 过滤器接口 | | `TokenHttpFilter` | 令牌过滤器 | | `ApiException` | Api 业务异常 | ## 版本历史 - **v11.0+**:引入负载均衡模式枚举,支持竞速调用 - **v10.0+**:支持自定义 CodeName/DataName - **v9.0+**:支持链路追踪