现在软件就业环境不景气,各行各业都忙着裁员优化。作为一个小开发,咱也不能光等着别人来优化咱,也得想办法优化下自己。就拿手头上的工作来说吧,我发现我的微服务应用里,既有AgileConfig这个日志组件,又有一个Consul 服务发现组件。本来吧他俩也没啥事,各干个的。但是,我在操作AgileConfig的时候发现了一个事

然后我又一百度发现了这个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 提交了合并请求。

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

  1. 服务发现之consul的介绍、部署和使用

    什么是服务发现 微服务的框架体系中,服务发现是不能不提的一个模块.我相信了解或者熟悉微服务的童鞋应该都知道它的重要性.这里我只是简单的提一下,毕竟这不是我们的重点.我们看下面的一幅图片:     图中 ...

  2. 服务发现 - consul 的介绍、部署和使用

    什么是服务发现 相关源码: spring cloud demo 微服务的框架体系中,服务发现是不能不提的一个模块.我相信了解或者熟悉微服务的童鞋应该都知道它的重要性.这里我只是简单的提一下,毕竟这不是 ...

  3. 服务发现 - consul 的介绍、部署和使用(转)

    什么是服务发现 相关源码: spring cloud demo 微服务的框架体系中,服务发现是不能不提的一个模块.我相信了解或者熟悉微服务的童鞋应该都知道它的重要性.这里我只是简单的提一下,毕竟这不是 ...

  4. 服务发现之consul理论整理_结合Docker+nginx+Tomcat简单部署案例

    目录 一.理论概述 服务发现的概念简述 consul简述 二.部署docker+consul+Nginx案例 环境 部署 三.测试 四.总结 一.理论概述 服务发现的概念简述 在以前使用的是,N台机器 ...

  5. Ocelot+Consul实现微服务架构

    API网关 API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口.这样就可以明显的简化客户端实现和微服务应用程序之间的沟通方式.以前的话,客户端不得不去请求微服务A ...

  6. Api网关Kong集成Consul做服务发现及在Asp.Net Core中的使用

    写在前面   Api网关我们之前是用 .netcore写的 Ocelot的,使用后并没有完全达到我们的预期,花了些时间了解后觉得kong可能是个更合适的选择. 简单说下kong对比ocelot打动我的 ...

  7. 服务发现:Zookeeper vs etcd vs Consul

    [编者的话]本文对比了Zookeeper.etcd和Consul三种服务发现工具,探讨了最佳的服务发现解决方案,仅供参考. 如果使用预定义的端口,服务越多,发生冲突的可能性越大,毕竟,不可能有两个服务 ...

  8. Ocelot + Consul + Registrator 基于Docker 实现服务发现、服务自动注册

    目录 1. Consul集群搭建 1.1 F&Q Consul官方推荐的host网络模式运行 2. Registrator服务注册工具 2.1 F&Q Registrator悬挂服务 ...

  9. Ocelot + Consul实践

    关于Consul(https://www.consul.io)是一个分布式,高可用,支持多数据中心的服务发现和配置共享的服务软件,由 HashiCorp 公司用 Go 语言开发, 基于 Mozilla ...

  10. 服务发现:Zookeeper vs etcd vs Consul 参考自http://dockone.io/article/667

    服务发现:Zookeeper vs etcd vs Consul [编者的话]本文对比了Zookeeper.etcd和Consul三种服务发现工具,探讨了最佳的服务发现解决方案,仅供参考. 如果使用预 ...

随机推荐

  1. 云原生:使用HPA和VPA实现集群扩缩容

    1 背景 我们之前介绍过,随着业务流量上涨之后,我们的系统需要适时的进行扩容. 数据存储层我们也介绍过MySQL的扩容 Scale UP(纵向扩展) 和 Scale Out(横向扩展) 垂直拆分(Sc ...

  2. 【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.

    问题描述 PHP的Web Job,通过artisan来配置路径启动PHP任务,相关启动脚本如下: artisan_path = "d:\\home\\site\\wwwroot"; ...

  3. Educational Codeforces Round 135 (Rated for Div. 2)C. Digital Logarithm(思维)

    目录 题目链接 题意 题解 代码 题目链接 C. Digital Logarithm 题意 给两个长度位\(n\)的数组\(a\).\(b\),一个操作\(f\) 定义操作\(f\)为,\(a[i]= ...

  4. 告别os.path,拥抱pathlib

    pathlib 模块是在Python3.4版本中首次被引入到标准库中的,作为一个可选模块.从Python3.6开始,内置的 open 函数以及 os . shutil 和 os.path 模块中的各种 ...

  5. Python-使用openpyxl读取excel内容

    1. 本篇文章目标 将下面的excel中的寄存器表单读入并构建一个字典 2. openpyxl的各种基本使用方法 2.1 打开工作簿 wb = openpyxl.load_workbook('test ...

  6. 基于可穿戴的GPS定位存储模块方案特色解析

    前记   GPS作为一个位置定位手段,在日常生活中扮演着非常重要的角色.在研发动物可穿戴产品的同时.团队一直在做产品和模块标准化的事情,尽量把研发出来的东西标准化.按照任老板的说法,在追求理想主义的路 ...

  7. 毕设系列之Linux V4L2(图形图像采集篇)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  8. 应急响应靶机训练-Linux1

    靶机来源: 知攻善防实验室公众号 https://mp.weixin.qq.com/s/gCWGnBiwbqSnafXU1apJCA 我是在另一台主机上通过ssh连接到靶机进行解题的,以下为解题记录. ...

  9. 记录--vue刷新当前页面

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 背景 项目当中如果做新增/修改/删除等等操作通常情况下都需要刷新数据或者刷新当前页面. 思路 (1)如果页面简单,调用接口刷新数据即可. ...

  10. C# 通用OCR识别 文字识别 中文识别

    软件说明 基于以下两个开源项目,做了再次封装 https://github.com/paddlepaddle/PaddleOCR PaddleOCRSharp: 本项目是一个基于PaddleOCR的C ...