前言
微服务架构已经成为搭建高效、可扩展系统的关键技术之一,然而,现有许多微服务框架往往过于复杂,使得我们普通开发者难以快速上手并体验到微服务带了的便利。为了解决这一问题,于是作者精心打造了一款最接地气的 .NET 微服务框架,帮助我们轻松构建和管理微服务应用。
本框架不仅支持 Consul 服务注册与发现,还自带了一系列高级特性,包括配置中心、链路跟踪(APM)、服务网关等,极大地简化了微服务的开发和运维过程。
此外框架还实现了 Saga 分布式事务、RabbitMQ 事件总线等功能,确保系统能够高效处理复杂的业务逻辑。更重要的是提供了一个人性化的 Dashboard 管理面板,使得监控和管理微服务集群变得方便。
通过本文的介绍大家可以学习到如何快速上手并充分利用这些特性,从而构建出既高效又稳定的微服务应用。
项目介绍
Wing 致力于打造一个功能强大且易于使用的 .NET 微服务框架,支持 .NET 6+ 运行平台。
该框架具备以下特点:
1、服务注册与发现:支持 Consul 服务注册与发现机制,确保服务间的自动发现和动态管理。
2、服务间通讯:支持 HTTP 和 gRPC 两种调用方式,内置负载均衡器,实现高效的服务间通信。
3、服务策略与异常处理:提供服务策略配置,支持服务异常降级处理,确保系统的稳定性和可靠性。
4、Saga 分布式事务:支持三种恢复策略(向前恢复、向后恢复、先前再后),确保事务的一致性和完整性。
5、配置中心:内置配置中心,实现服务配置的在线集中统一管理。
6、链路追踪与性能监控:支持 HTTP/gRPC/SQL 的链路追踪(APM)及耗时分析统计,帮助开发者快速定位性能瓶颈。
7、服务网关:内置服务网关,支持全局服务策略和个性化服务策略配置,简化服务入口管理。
8、事件总线:支持 RabbitMQ 事件总线,实现服务间的异步通信和事件传递。
9、管理界面:提供人性化的 Dashboard 管理界面,便于监控和管理整个微服务集群。
Wing 框架为开发者提供一个强大而直观的开发平台,帮助快速构建和管理高效、可扩展的微服务应用。
快速入门
1、服务注册
什么是服务注册?
服务注册是指服务启动后将该服务的IP、端口等信息注册到Consul
。
创建一个Web API 项目
提前准备:安装并启动Consul
打开 Visual Studio 2022 并创建Web API项目
安装依赖包
dotnet add package Wing.Consul
Program代码
builder.Services.AddWing();
添加配置
{ // 是否启用配置中心,默认启用 "ConfigCenterEnabled": false, "Consul": { "Url": "http://localhost:8500", "Service": { //Http Grpc "Option": "Http", "HealthCheck": { "Url": "http://localhost:1210/health", //单位:秒 "Timeout": 10, //单位:秒 "Interval": 10 }, "Name": "Wing.Demo_1.2.1", "Host": "localhost", "Port": 1210, "Tag": "", "LoadBalancer": { //RoundRobin WeightRoundRobin LeastConnection "Option": "WeightRoundRobin", //权重 "Weight": 60 }, "Scheme": "http", "Developer": "linguicheng" }, //定时同步数据时间间隔,单位:秒 小于等于0表示立即响应 "Interval": 10, //数据中心 "DataCenter": "dc1", //等待时间,单位:分钟 "WaitTime": 3 } }
查看运行效果
程序运行后,打开consul UI管理界面,可以看到注册服务Wing.Demo_1.2
,具体如下图所示:
2、启动UI
Wing.UI
是Wing
微服务框架中的一个可视化操作管理系统,主要功能有服务治理、配置中心、APM管理、Saga分布式事务查询。
安装依赖包
安装服务注册nuget包Wing.Consul
,UI可视化界面管理nuget包Wing.UI
,选择对应的数据库驱动(参考FreeSql官网),以SqlServer为例,安装FreeSql.Provider.SqlServer
。
dotnet add package Wing.UI
dotnet add package FreeSql.Provider.SqlServer
Program代码
using Wing; var builder = WebApplication.CreateBuilder(args); builder.Host.AddWing(builder => builder.AddConsul()); builder.Services.AddWing().AddWingUI(FreeSql.DataType.SqlServer);
查看运行效果
程序运行后,浏览器访问 ,运行效果如下图:
可以看到示例 1.2 注入的服务`Wing.Demo_1.2
3、服务发现与调用
什么是服务发现?
服务发现是指服务启动后将服务注册信息定时同步刷新到本地或实时获取Consul
的服务信息。
安装依赖包
dotnet add package Wing.Consul
Grpc健康检查
protobuf文件
syntax = "proto3"; package grpc.health.v1; message HealthCheckRequest { string service = 1; } message HealthCheckResponse { enum ServingStatus { UNKNOWN = 0; SERVING = 1; NOT_SERVING = 2; } ServingStatus status = 1; } service Health { rpc Check(HealthCheckRequest) returns (HealthCheckResponse); rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse); }
HealthCheck代码
public class HealthCheck : Health.HealthBase { public override Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context) { return Task.FromResult(new HealthCheckResponse() { Status = HealthCheckResponse.Types.ServingStatus.Serving }); } public override async Task Watch(HealthCheckRequest request, IServerStreamWriter<HealthCheckResponse> responseStream, ServerCallContext context) { await responseStream.WriteAsync(new HealthCheckResponse() { Status = HealthCheckResponse.Types.ServingStatus.Serving }); } }
Program代码
using Wing; var builder = WebApplication.CreateBuilder(args); builder.Host.AddWing(builder => builder.AddConsul()); // Add services to the container. builder.Services.AddGrpc(); builder.Services.AddWing(); var app = builder.Build(); // Configure the HTTP request pipeline. app.MapGrpcService<GreeterService>(); app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909"); app.Run();
运行效果
运行当前程序并启动示例 1.3,浏览器访问 ,可以看到注入的Grpc服务Wing.Demo_1.4
,运行效果如下图:
在示例 1.2 中调用当前Grpc服务中SayHello
方法,代码如下:
[HttpGet("hello")] public Task<string> SayHello() { return _serviceFactory.InvokeAsync("Wing.Demo_1.4", async serviceAddr => { var channel = GrpcChannel.ForAddress(serviceAddr.ToString()); var greeterClient = new Greeter.GreeterClient(channel); var result = await greeterClient.SayHelloAsync(new HelloRequest { Name = "Wing" }); return result.Message; }); }
运行示例 1.2,浏览器访问 http://localhost:1210/weatherforecast/hello ,运行效果如下图:
4、启动服务网关
服务网关是系统对外的唯一入口,它封装了系统内部架构,为每个客户端提供了定制的API,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有非业务功能。
安装依赖包
安装服务注册nuget包Wing.Consul
,服务网关nuget包Wing.Gateway
,选择对应的数据库驱动(参考FreeSql官网open in new window),以SqlServer为例,安装FreeSql.Provider.SqlServer
,请求日志支持本地消息队列和分布式消息队列进行异步持久化,基本上不影响网关性能。如果不想记录请求日志,可以不安装该包。
如果想启用EventBus
记录请求日志,需要安装RabbitMQ nuget包Wing.RabbitMQ
。
dotnet add package Wing.Consul
dotnet add package Wing.Gateway
dotnet add package Wing.RabbitMQ
dotnet add package FreeSql.Provider.SqlServer
Program代码
using Wing; var builder = WebApplication.CreateBuilder(args); builder.Host.AddWing(builder => builder.AddConsul()); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddWing() .AddPersistence(FreeSql.DataType.SqlServer) .AddGateWay() .AddEventBus();// 如果不想使用EventBus记录请求日志,可以删除此行代码 var app = builder.Build(); // Configure the HTTP request pipeline. app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
添加配置
{ // 是否启用配置中心,默认启用 "ConfigCenterEnabled": false, "Consul": { "Url": "http://localhost:8500", "Service": { //Http Grpc "Option": "Http", "HealthCheck": { "Url": "http://localhost:1510/health", //单位:秒 "Timeout": 10, //单位:秒 "Interval": 10 }, "Name": "Wing.Demo_1.5", "Host": "localhost", "Port": 1510, "LoadBalancer": { //RoundRobin WeightRoundRobin LeastConnection "Option": "WeightRoundRobin", //权重 "Weight": 50 }, "Scheme": "http", "Developer": "linguicheng" }, //定时同步数据时间间隔,单位:秒 小于等于0表示立即响应 "Interval": 10, //数据中心 "DataCenter": "dc1", //等待时间,单位:分钟 "WaitTime": 3 }, "ConnectionStrings": { "Wing": "Data Source=192.168.56.96;User Id=sa;Password=wing123.;Initial Catalog=Wing;TrustServerCertificate=true;Pooling=true;Min Pool Size=1" }, //自动同步实体结构到数据库 "UseAutoSyncStructure": true, // 如果不启用EventBus,可以删除RabbitMQ配置 "RabbitMQ": { "HostName": "192.168.56.99", "UserName": "admin", "Password": "admin", "VirtualHost": "/", "Port": 5672, //消息过期时间,单位:毫秒,过期会自动路由到死信队列,小于或等于0则永久有效 "MessageTTL": 0, "ExchangeName": "Sample.GateWay", //每次投递消息数量 "PrefetchCount": 1 }, "Gateway": { // 请求日志 "Log": { // 是否启用网关日志记录 "IsEnabled": true, // 是否启用事件总线(RabbitMQ)存储日志,生产环境推荐启用,可以提升程序的性能 "UseEventBus": false } } }
查看运行效果
运行示例 1.2 并启动当前示例程序,浏览器访问,运行效果如下图:
运行示例 1.3,浏览器访问,可以看到网关请求日志,运行效果如下图:
服务地址组成
请求服务地址默认是{网关IP或域名}/{服务名}/{服务路由},例如:http://localhost:1510/Wing.Demo_1.2/weatherforecast
注意:更多具体内容可以访问Wing 官方文档,具体内容如下所示
项目地址
Github:https://linguicheng.github.io/Wing
Gitee:https://gitee.com/linguicheng/Wing
文档地址:https://linguicheng.github.io/Wing
示例地址:https://gitee.com/linguicheng/wing-demo
开源协议:基于MIT协议永久开源免费使用
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!