大家好,好久没有输出博文了,一是因为比较忙,另外一个原因是最近主要的精力是在给 AgileConfig 添加一个新的功能:服务注册与发现。
先说说为什么会添加这个功能。我自己的项目是用 Consul 来做为服务注册发现组件的。自从我上线了 AgileConfig 做为配置中心后,我就很少去 Consul 观察服务的在线状态了,因为 AgileConfig 客户端列表已经在一定程度上能代表服务的状态了。服务注册发现与配置中心其实本质上都是解决了一类问题,那就是配置的动态化,所以大家会看到业界著名的组件很多都是同时实现这2个功能的,如 Consul,Nacos 等。所以我想干脆把这个功能给加上吧,这样可以省去部署一个组件。
当然也有同学说我不务正业,不去好好搞配置中心去搞什么服务注册发现。但是我还是做了。。。
不过大家放心 AgileConfig 的主业还是在配置中心上,服务注册发现只是附赠的小菜,可以用也可以不用,决定权完全在你。在实现上我也是对两个功能是完全解耦的。也就是说这2个功能都是互不影响独立运行的。唯一有交集的一个地方是,如果配置中心的客户端的 websocket 通道建立成功的时候,服务的心跳会借用这个通道。
✨✨✨Github地址:https://github.com/dotnetcore/AgileConfig 开源不易,欢迎star✨✨✨
✨✨✨Gitee地址:https://gitee.com/kklldog/AgileConfig ✨✨✨
首先先让我们回顾下服务注册发现的概念。
在实施微服务之后,我们的调用都变成了服务间的调用。服务间调用需要知道IP、端口等信息。再没有微服务之前,我们的调用信息一般都是写死在调用方的配置文件里(当然这话不绝对,有些公司会把这些信息写到数据库等公共的地方,以方便维护)。又由于业务的复杂,每个服务可能依赖N个其他服务,如果某个服务的IP,端口等信息发生变更,那么所有依赖该服务的服务的配置文件都要去修改,这样显然太麻烦了。有些服务为了负载是有个多个实例的,而且可能是随时会调整实例的数量。如果每次调整实例数量都要去修改其他服务的配置并重启那太麻烦了。
为了解决这个问题,业界就有了服务注册发现组件。
假设我们有服务A需要调用服务B,并且有服务注册发现组件R。整个大致流程将变成大概3部:
服务B启动向服务R注册自己的信息
服务A从服务R拉取服务B的信息
服务A调用服务B
有了服务注册发现组件之后,当修改A服务信息的时候再也不用去修改其他相关服务了。
参考我的另外一篇:.Net Core with 微服务 - Consul 注册中心
使用服务注册与发现功能需要更新服务端与客户端至 1.6.0 及以上版本。
服务端更新至 latest 镜像或 v-1.6.0 以上的镜像。
使用 docker 运行服务端实例:
sudo docker run \ --name agile_config \ -e TZ=Asia/Shanghai \ -e adminConsole=true \ -e db:provider=sqlite \ -e db:conn="Data Source=agile_config.db" \ -p 5000:5000 \ #-v /your_host_dir:/app/db \ -d kklldog/agile_config:latest
基本的使用没有太大的变化,只是在界面上添加了服务的相关管理界面,这里不在赘述。
相关教程:.Net Core & Agile Config配置中心
客户端需要从 nuget 上安装 1.6.0 版本以上的 client 包。
Install-Package AgileConfig.Client -Version 1.6.0
新版的 client 简化了使用方式,以下以 .net6 为示例:
调用 UseAgileConfig 扩展方法即可注入 AgileConfig client .
var builder = WebApplication.CreateBuilder(args); //use agileconfig client builder.Host.UseAgileConfig(); ...
在 appsettings.json 添加配置信息:
"AgileConfig": { "appId": "test_app", "secret": "test_app", "nodes": "http://agileconfig_server.xbaby.xyz/", "name": "client123", "tag": "tag123", "serviceRegister": { //服务注册信息,如果不配置该节点,则不会启动任何跟服务注册相关的服务 可选 "serviceId": "net6", //服务id,全局唯一,用来唯一标示某个服务 "serviceName": "net6MVC服务测试", //服务名,可以重复,某个服务多实例部署的时候这个serviceName就可以重复 "ip": "127.0.0.1", //服务的ip 可选 "port": 5005, //服务的端口 可选 }
其中 appId , secret 等配置同原来配置中心的使用方式没有任何改变。serviceRegister
节点描述的是服务注册信息(如果删除这个节点那么服务注册功能就不会启动):
{ "serviceId":"0001", "serviceName":"xxxx", "time":"2022-01-01T12:00:000", "status":"Unhealty", "message": "服务不健康" }
当配置好客户端后,启动对应的应用程序,服务信息会自动注册到服务端并且开始心跳。如果服务正确注册到服务端,控制台的服务管理界面可以查看:
现在服务已经注册上去了,那么怎么才能拿到注册中心所有的服务呢?同样非常简单,在程序内只要注入IDiscoveryService
接口就可以通过它拿到所有的注册的服务。
public interface IDiscoveryService { string DataVersion { get; } List<ServiceInfo> UnHealthyServices { get; } List<ServiceInfo> HealthyServices { get; } List<ServiceInfo> Services { get; } Task RefreshAsync(); }
除了接口内置的方法,还有几个扩展方法方便用户使用,比如随机一个服务:
public static class DiscoveryServiceExtension { public static IEnumerable<ServiceInfo> GetByServiceName(this IDiscoveryService ds, string serviceName) { return ds.Services.GetByServiceName(serviceName); } public static ServiceInfo GetByServiceId(this IDiscoveryService ds, string serviceId) { return ds.Services.GetByServiceId(serviceId); } public static ServiceInfo RandomOne(this IDiscoveryService ds, string serviceName) { return ds.Services.RandomOne(serviceName); } }
至此服务的注册与发现就已经完成了。
以上就是服务注册发现的简单使用,但是还有一些比较重要的信息希望大家在使用之前能够了解,这样有利于更好的使用以及出现问题的时候定位问题。
同 AgileConfig 的配置中心功能一样,服务注册后最后都是写到了数据库里。AgileConfig 的服务端可以部署多个来防止单点故障,同时可以分担压力。所以高可用的最佳实践就是部署 2 个以上的服务端节点,然后数据库做高可用方案。这样足够应付大多数要求不是特别高的场景。
同上 AgileConfig 通过数据库保证多个节点部署的时候的一致性问题。
服务的健康检测一般有2种方案:
我们的 client 在启动后会拉取一次全量的服务列表。但是服务是会不断的上线,下线的,所以服务状态的更新是需要通知客户端的,然后客户端去拉取新的服务列表。AgileConfig 同样有2个策略来保证服务列表的即时刷新:
删除serviceRegister
配置节点或不要配置任何信息。
✨✨✨Github地址:https://github.com/dotnetcore/AgileConfig 开源不易,欢迎star✨✨✨
✨✨✨Gitee地址:https://gitee.com/kklldog/AgileConfig ✨✨✨