consul:啥?我被优化没了?AgileConfig+Yarp替代Ocelot+Consul实现服务发现和自动网关配置

这篇具有很好参考价值的文章主要介绍了consul:啥?我被优化没了?AgileConfig+Yarp替代Ocelot+Consul实现服务发现和自动网关配置。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

现在软件就业环境不景气,各行各业都忙着裁员优化。作为一个小开发,咱也不能光等着别人来优化咱,也得想办法优化下自己。就拿手头上的工作来说吧,我发现我的微服务应用里,既有AgileConfig这个配置中心组件,又有一个Consul 服务发现组件。本来吧他俩也没啥事,各干个的。但是,我在操作AgileConfig的时候发现了一个事consul:啥?我被优化没了?AgileConfig+Yarp替代Ocelot+Consul实现服务发现和自动网关配置
然后我又一百度发现了这个AgileConfig 1.6.0 发布 - 支持服务注册与发现 - Agile.Zhou - 博客园 (cnblogs.com),有点意思。稍微一思索,我们现在的微服务解决方案里网关用的ocelot+consul 作为HTTP api网关,同时 还是用了 yarp做 grpc的网关,明显可以看出来有一套多余的网关在这里。基于目前的情况,我是一直想优化掉 ocelot+consul这个组合。改用 agileConfig+yarp,奈何前期对微服务机制不是很熟悉,有堆坑要填。现在看到agileconfig的服务列表,又勾起了我这个优化的想法。说干就干,我理想的目标是可以直接从agileconfig上获取到所有注册的服务,然后用代码来动态给yarp添加代理配置。这样既可以优化掉一个consul服务,又可以免去每次服务部署时繁琐的网关配置。

首先第一个任务就是解决yarp如何用代码实现动态配置的问题。bing 里搜索 yarp 动态配置 ,优先看博客园的博主发的文章,事实上我也就只看了这一篇Welcome to YARP - 2.2 配置功能 - 配置提供者(Configuration Providers) - coding-y - 博客园 (cnblogs.com) 。完美,问题解决。下面就是代码时间。

通过上面两篇文章我们知道,agileconfig会提供一个IDiscoveryService 接口来供程序获取注册的服务信息。同时 yarp也提供了从内存中提供配置的 InMemoryConfigProvider ,那我们只需要在agileconfig 注册之后 通过 IDisconverService接口 获取所有已注册服务,然后再让yarp应用上内存中的配置即可实现服务注册后自动配置代理的需求。

下面我们动动手指头 按下 ctrl c ,ctrl v实现如下代码:代码不具备通用性 需要进一步优化 建议已给出。

using AgileConfig.Client;
using AgileConfig.Client.RegisterCenter;
using Newtonsoft.Json.Linq;

using Yarp.ReverseProxy.Configuration;
using Yarp.ReverseProxy.Transforms;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class AgileConfigProxyConfigProviderExtend
    {
        const string NotProxyStr = "notProxy";
        const string TransformsStr = "Transforms";
        static readonly ILogger _Logger = LoggerFactory.Create(b => { }).CreateLogger("AgileConfigProxyConfigProviderExtend");
        public static RouteConfig[] GetRoutes(this IDiscoveryService discoveryService)
        {
            var routes = new List<RouteConfig>();
            foreach (var item in discoveryService.Services)
            {
                if (item.MetaData.Any(r=>r.Equals(NotProxyStr, StringComparison.OrdinalIgnoreCase)))
                {
                    continue;
                }
                var route = new RouteConfig
                {
                    RouteId = item.ServiceId,
                    ClusterId = item.ServiceName,
                    Match = new RouteMatch
                    {
                        Path = $"/{item.ServiceName}/{{**all}}"
                    }
                };
                //.WithTransformPathRouteValues(pattern: new PathString("/{**all}"))
                try
                {
                    var transformStr = item.MetaData.FirstOrDefault(r => r.StartsWith(TransformsStr));
                    if (transformStr is not null)
                    {
                        var jobj = JObject.Parse(transformStr.Split(':')[1]);
                        foreach (var k in jobj)
                        {
                            route.WithTransform(d => d.Add(k.Key, k.Value?.ToString() ?? ""));
                        }
                    }
                }
                catch (Exception e)
                {
                    _Logger.LogError(e,"生成路由【转换】配置时出错");
                }

                routes.Add(route);
                _Logger.LogTrace("添加路由{RouteId}", route.RouteId);
            }
            return routes.ToArray();
        }
        public static ClusterConfig[] GetClusters(this IDiscoveryService discoveryService)
        {
            var clusters = new List<ClusterConfig>();
            var proxyServices = discoveryService.Services
                                    .Where(r => !r.MetaData.Any(r => r.Equals(NotProxyStr, StringComparison.OrdinalIgnoreCase)))
                                    .GroupBy(p => p.ServiceName);

            foreach (var item in proxyServices)
            {
                var destinations = new Dictionary<string, DestinationConfig>(StringComparer.OrdinalIgnoreCase);
                foreach (var service in item)
                {
                    destinations.Add(service.ServiceId, new DestinationConfig() {
                        Address=service.AsHttpHost()
                    });
                }

                clusters.Add(new ClusterConfig
                {
                    ClusterId = item.Key,
                    Destinations = destinations
                });
            }

            return clusters.ToArray();
        }
        //可以再加一个重载 支持传入一个委托 来自定义构造配置。
        public static IReverseProxyBuilder LoadFromAgileConfigByInMemoryConfigProvider(this IReverseProxyBuilder builder, ConfigClient client)
        {
            var discoveryService = client.DiscoveryService();
            discoveryService ??= new DiscoveryService(client, LoggerFactory.Create(b => b.SetMinimumLevel(LogLevel.Information)));

            var configProvider = new InMemoryConfigProvider(discoveryService.GetRoutes(), discoveryService.GetClusters());

            builder.Services.AddSingleton(configProvider);
            builder.Services.AddSingleton<IProxyConfigProvider>(configProvider);

            discoveryService.ReLoaded += () =>
            {
                configProvider.Update(discoveryService.GetRoutes(), discoveryService.GetClusters());
            };
            return builder;
        }
    }
}

现在只需要调用如下代码,即可给原有的yarp服务加上自动生成代理配置的功能了。

builder.Services.AddReverseProxy()//添加ReverseProxy相关服务到DI

.LoadFromAgileConfigByInMemoryConfigProvider((ConfigClient)client);

注意:注册AgileConfig时候请使用 UseAgileConfig()方法注册。Addxxx方法会导致无法获取到agileConfig上的已注册服务对信息。
代码已传gitee:https://gitee.com/dotnetfans/yarp-auto-proxy.-agile-config
同时也个给agileConfig 提交了合并请求。文章来源地址https://www.toymoban.com/news/detail-845940.html

到了这里,关于consul:啥?我被优化没了?AgileConfig+Yarp替代Ocelot+Consul实现服务发现和自动网关配置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [golang 微服务] 5. 微服务服务发现介绍,安装以及consul的使用,Consul集群

    上一节讲解了使用 gRPC创建微服务,客户端的一个接口可能需要调用 N个服务 ,而不同服务可能存在 不同的服务器 ,这时,客户端就必须知道所有服务的 网络位置(ip+port) ,来进行连接服务器操作,如下图所示: 以往的做法是把 服务的地址 放在 配置文件 或者 数据库 中,这样就

    2024年02月08日
    浏览(46)
  • Docker容器:docker consul的注册与发现及consul-template守护进程

    (1)服务注册与发现是微服务架构中不可或缺的重要组件。 (2)为解决服务都是单节点的,不保障高可用性,也不考虑服务的压力承载,服务之间调用单纯的通过接口访问的问题 (1)consul是google开源的一个使用go语言开发的服务管理软件。支持多数据中心、分布式高可用的

    2024年02月11日
    浏览(33)
  • [golang 微服务] 6. GRPC微服务集群+Consul集群+grpc-consul-resolver案例演示

    上一节讲解了consul集群: [golang 微服务] 5. 微服务服务发现介绍,安装以及consul的使用,Consul集群,这样的话,当一台server挂掉之后,集群就会从另一台server中获取服务,这就保证了客户端访问consul集群的负载均衡性. 这里还有一个问题: 就是当终端的对应的 微服务挂掉 了,consul集群se

    2024年02月09日
    浏览(30)
  • 网关服务gateway注册Consul时报错Consul service ids must not be empty

    网关服务gateway启动时,初始化Consul相关配置时报错。 详细的错误信息如下: 网关gateway的 bootstrap.yml如下: 分析: 网关服务gateway在初始化Consul的相关配置时,未读取到ip,导致相关配置内初始化失败,就未能初始化instance-id。修改配置如下: 最终服务能正常启动。 参考:

    2024年02月21日
    浏览(34)
  • 【Consul】基于Golang实现Consul服务的注册、注销、修改、监控注册的服务变化、实时同步服务信息机制

    大家好 我是寸铁👊 总结了一篇【Consul】基于Go实现Consul服务的注册、注销、修改、监控注册的服务变化、实时同步服务信息机制✨ 这应该是目前全网最全的使用golang手搓Consul服务信息机制✨ 喜欢的小伙伴可以点点关注 💝 consul常常被用来作服务注册与服务发现,而它的wa

    2024年04月09日
    浏览(33)
  • thinkphp使用consul

    service层 controller层

    2024年02月12日
    浏览(23)
  • 关于consul的下载方法

      验证[终端输入consul即可]

    2024年02月13日
    浏览(23)
  • Consul屏蔽api

    配置config.json 启动consul时使用该配置: 再访问api,屏蔽成功

    2024年02月14日
    浏览(25)
  • 【consul】

    服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的,不保障高可用性,也不考虑服务的压力承载,服务之间调用单纯的通过接口访问。直到后来出现了多个节点的分布式架构,起初的解决手段是在服务前端负载均衡,这样前端必须要知道所有后端服

    2024年02月11日
    浏览(12)
  • Docker consul

    目录 consul服务更新和服务发现 服务注册与发现 consul consul 部署 consul服务器  建立 Consul 服务 查看集群信息 通过 http api 获取集群信息 registrator服务器 安装 Gliderlabs/Registrator 测试服务发现功能是否正常 验证 http 和 nginx 服务是否注册到 consul consul-template  准备 template nginx 模板

    2024年02月06日
    浏览(18)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包