聊一聊Yarp结合Nacos完成服务发现

背景

Yarp 这个反向代理出来后,相信还是有不少人在关注的。

在 Yarp 中,反向代理的配置默认也是基于配置文件的,也有不少大佬已经把这个配置做成了数据库配置+可视化界面。

仔细想了想,做成数据库配置,好像只是便于配置的管理,对服务注册和发现这一块还是偏弱。

好比订单服务加了 3 个实例,这个时候要去配置一下,把这 3 个实例加进去。

如果增加的服务多了,频率高了,肯定是不太想人工去介入的,会嫌麻烦。

尤其是在引入了注册中心的情况下,都会想让它自动适配这些变化。

基于这个情况,老黄花时间尝试了一下把 Yarp 和 Nacos 结合,让服务和实例的新增、减少做了一个适配,可以动态化,一定程度减少了人为的干预。

下面简单看看。

示例服务

准备下面的服务

  • YarpWithNacosSample 反向代理集成
  • OrderSvcA 订单服务-A
  • OrderSvcB 订单服务-B
  • UserSvc 用户服务

其中两个订单服务是为了模拟服务实例上下线的,用户服务是模拟服务上下线的。

下面三个业务服务,代码基本一样

只贴出用户服务的。

using Nacos.AspNetCore.V2;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddNacosAspNet(builder.Configuration);

builder.Services.AddControllers();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/", () =>
    {
        return Results.Ok("user svc 9001");
    });
});

app.Run("http://*:9001");

然后是配置

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning",
      "Nacos.AspNetCore": "Information",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "nacos": {
    "ServerAddresses": [ "http://localhost:8848" ],
    "DefaultTimeOut": 15000,
    "Namespace": "yarp",
    "ListenInterval": 1000,
    "ServiceName": "usersvc",
    "GroupName": "DEFAULT_GROUP",
    "ClusterName": "DEFAULT",
    "Weight": 100,
    "RegisterEnabled": true,
    "InstanceEnabled": true,
    "Ephemeral": true,
    "Secure": false,
    "ConfigUseRpc": true,
    "NamingUseRpc": true
  }
}

再来看看重点的反向代理这一块。

using global::Nacos.V2.DependencyInjection;
using Yarp.ReverseProxy.Configuration;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddNacosV2Naming(x =>
{
    x.ServerAddresses = new List<string> { "http://localhost:8848/" };
    x.Namespace = "yarp";

    x.NamingUseRpc = true;
});

builder.Services.AddReverseProxy()
    .AddNacosServiceDiscovery(
    groupNames: "DEFAULT_GROUP", 
    percount:100,
    enableAutoRefreshService: true,
    autoRefreshPeriod: 30);

var app = builder.Build();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/yarp", (IProxyConfigProvider provider) =>
    {
        var res = provider.GetConfig();
        return Results.Ok(res);
    });
    endpoints.MapReverseProxy();
});

app.Run("http://*:9091");

可以看到,反向代理这个项目并没有注册到 Nacos 上面去,因为它只需要发现其他服务,并不需要被其他服务发现。

先启动 OrderSvcA,让其注册到 Nacos。

聊一聊Yarp结合Nacos完成服务发现

再启动反向代理项目,这个时候可以看到日志,有输出 OrderSvcA 加入的痕迹。

聊一聊Yarp结合Nacos完成服务发现

然后访问 localhost:9091/yarp 看一下当前的配置。

聊一聊Yarp结合Nacos完成服务发现

再通过反向代理访问一下 OrderSvc。

聊一聊Yarp结合Nacos完成服务发现

接下来启动 OrderSvcB,让其注册到 Nacos。

聊一聊Yarp结合Nacos完成服务发现

这个时候,反向代理项目会显示把这个新实例加进去了。

聊一聊Yarp结合Nacos完成服务发现

这个时候访问会有负载均衡的策略去访问 ordersvc。

聊一聊Yarp结合Nacos完成服务发现

最后再来看看新服务上线的情况,启动 UserSvc。

聊一聊Yarp结合Nacos完成服务发现

再访问的话,也是正常的。

聊一聊Yarp结合Nacos完成服务发现

这里需要注意的是,新加的服务,不会实时更新到配置中,取决于自动刷新的间隔,因为 Nacos 目前没有提供服务变动的通知,只有服务实例的,所以这一块是要定时主动去查询的。

到这里的话,基本上演示就结束了。

不过有人应该会对转发规则那一块有疑问,为什么是 【反向代理地址/服务名/服务的相对路径】

这一个是默认的实现,因为规则这一块,一百个人就会有一百个不一样的,有想放请求头的,查询参数的等等,所以这一个是开放的,可以*替换。

写在最后

Yarp 还是个比较有意思的项目,后面应该会有不少人使用。

目前这个扩展包还是预览版,没有发布正式版,主要是想丰富一下内容。

nacos-sdk-csharp 的地址 :https://github.com/nacos-group/nacos-sdk-csharp

nacos-csharp-extensions 的地址: https://github.com/catcherwong/nacos-csharp-extensions

本文示例代码的地址 :https://github.com/catcherwong-archive/2021/tree/main/YarpWithNacosSample

上一篇:【ZeyFraのJavaEE开发小知识01】@DateTimeFomat和@JsonFormat


下一篇:Android基础之Notification通知 | PendingIntent | 带源码