.Net6注入Consul服务
直接上代码了(参考了一下其他博客进行总结一下),我这边项目工程是模拟微服务模式,新建类库把服务打包成了nuget方便调用
现在先大致介绍一下,结尾放demo案例代码
consul心跳 心跳的地址要于下面配置文件的地址一样 这里先定义一会配置文件也要相同
/// <summary> /// 写个中间件---扩展 /// </summary> public static class HealthCheckMiddlewareExtension { /// <summary> /// 设置心跳响应 /// </summary> /// <param name="app"></param> /// <param name="checkPath">默认是/Health</param> /// <returns></returns> public static void UseHealthCheckMiddleware(this IApplicationBuilder app, string checkPath = "/healthcheck") { app.Map(checkPath, applicationBuilder => applicationBuilder.Run(async context => { Console.WriteLine($"This is Health Check"); context.Response.StatusCode = (int)HttpStatusCode.OK; await context.Response.WriteAsync("OK"); })); } }
配置实体
public class ConsulRegisterOptions { /// <summary> /// Consul 客户端地址 /// </summary> public string Address { get; set; } /// <summary> /// 健康检查地址 /// </summary> public string HealthCheck { get; set; } /// <summary> /// 服务名 /// </summary> public string Name { get; set; } /// <summary> /// 服务绑定Ip /// </summary> public string Ip { get; set; } /// <summary> /// 服务绑定端口 /// </summary> public string Port { get; set; } }
接口定义
public interface IConsulRegister { Task ConsulRegistAsync(); }
//服务注入完后需要在app启动管道中调用方法注入到consul中
public class ConsulRegister : IConsulRegister { private readonly ConsulRegisterOptions _consulRegisterOptions; public ConsulRegister(IOptionsMonitor<ConsulRegisterOptions> consulRegisterOptions) { _consulRegisterOptions = consulRegisterOptions.CurrentValue; } public async Task ConsulRegistAsync() { var client = new ConsulClient(options => { options.Address = new Uri(_consulRegisterOptions.Address); // Consul客户端地址 }); var registration = new AgentServiceRegistration { ID = Guid.NewGuid().ToString(), // 唯一Id Name = _consulRegisterOptions.Name, // 服务名(分组--多个实例组成的集群) Address = _consulRegisterOptions.Ip, // 服务绑定IP Port = Convert.ToInt32(_consulRegisterOptions.Port), // 服务绑定端口 //Tag 标签 Check = new AgentServiceCheck { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), // 服务启动多久后注册 Interval = TimeSpan.FromSeconds(10), // 健康检查时间间隔 HTTP = $"http://{_consulRegisterOptions.Ip}:{_consulRegisterOptions.Port}{_consulRegisterOptions.HealthCheck}", // 健康检查地址 Timeout = TimeSpan.FromSeconds(5) // 超时时间 } }; await client.Agent.ServiceRegister(registration); } }
扩展调度策略 ConsulExtend
public static class ConsulExtend { //public static void AddConsulRegister(this IServiceCollection services) //{ // services.AddTransient<IConsulRegister, ConsulRegister>(); //} /// <summary> /// 注册Consul调度策略 /// </summary> /// <param name="services"></param> /// <param name="consulDispatcherType"></param> public static void AddConsulDispatcher(this IServiceCollection services, ConsulDispatcherType consulDispatcherType) { switch (consulDispatcherType) { case ConsulDispatcherType.Average: services.AddTransient<AbstractConsulDispatcher, AverageDispatcher>(); break; case ConsulDispatcherType.Polling: services.AddTransient<AbstractConsulDispatcher, PollingDispatcher>(); break; case ConsulDispatcherType.Weight: services.AddTransient<AbstractConsulDispatcher, WeightDispatcher>(); break; default: break; } } public enum ConsulDispatcherType { Average = 0, Polling = 1, Weight = 2 } }
AbstractConsulDispatcher
public abstract class AbstractConsulDispatcher { protected ConsulRegisterOptions _consulRegisterOptions; protected KeyValuePair<string, AgentService>[] _CurrentAgentServiceDictionary; public AbstractConsulDispatcher(IOptionsMonitor<ConsulRegisterOptions> consulClientOption) { this._consulRegisterOptions = consulClientOption.CurrentValue; } /// <summary> /// 负载均衡获取地址 /// </summary> /// <param name="mappingUrl">Consul映射后的地址</param> /// <returns></returns> public string GetAddress(string mappingUrl) { Uri uri = new Uri(mappingUrl); string serviceName = uri.Host; string addressPort = this.ChooseAddress(serviceName); return $"{uri.Scheme}://localhost:{addressPort}{uri.PathAndQuery}"; } protected virtual string ChooseAddress(string serviceName) { ConsulClient client = new ConsulClient(c => { c.Address = new Uri($"http://localhost:8500/"); }); AgentService agentService = null; var response = client.Agent.Services().Result.Response;//获取Consul全部服务清单 var dictionary = response.Where(s => s.Value.Service.Equals(serviceName, StringComparison.OrdinalIgnoreCase)).ToArray(); var entrys = client.Health.Service(serviceName).Result.Response; List<KeyValuePair<string, AgentService>> serviceList = new List<KeyValuePair<string, AgentService>>(); for (int i = 0; i < entrys.Length; i++) { serviceList.Add(new KeyValuePair<string, AgentService>(i.ToString(), entrys[i].Service)); } this._CurrentAgentServiceDictionary = serviceList.ToArray(); int index = this.GetIndex(); agentService = this._CurrentAgentServiceDictionary[index].Value; return $"{agentService.Port}"; } protected abstract int GetIndex(); }
AverageDispatcher、PollingDispatcher、WeightDispatcher 剩下的三种实现就不细说了 一会自行下载 打包好后 引入包
或者 把这里调用一下进行注入
然后是配置文件 配置文件要跟上面心跳地址相同
"ConsulRegisterOptions": { "Address": "http://xxx.xxx.xx.xx:8500", //consul集群客户端的服务地址 "HealthCheck": "/healthcheck", //consul调用健康检查地址url "Name": "VipUser", //当前服务的服务名 "Ip": "xxx.xx.xx.xxx", //当前api部署在哪台服务器是的ip "Port": "5001" //当前api服务端口 }
以上.net6注入consul进行打包发布完毕
参考的博客:https://blog.csdn.net/sD7O95O/article/details/128630643
demo地址:https://github.com/fengzhonghao8-24/ConsulIntroduction
然后进行打包发布
发布方式有我常用的一种方式是,在本地把代码发布成dll文件,然后通过服务器目录挂载读取DockerFile文件,之前用的方式是把代码直接推到服务器上然后发布后bulid成镜像再run起来,这种方式没docker-compose方便
创建Dockerfile文件进行修改 注意挂载的端口,修改完后要选中dockerfile文件属性设置为始终复制,不能可能出现这里修改完映射端口后但线上容器的端口还是80的情况
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base ENV TZ=Asia/Shanghai WORKDIR /app EXPOSE 5001 5001 RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list RUN sed -i 's|security.debian.org/debian-security|mirrors.ustc.edu.cn/debian-security|g' /etc/apt/sources.list RUN apt-get clean RUN apt-get update # 安装libgdiplus库解决System.Drawing引起的Bug RUN apt-get install -y --allow-unauthenticated libgdiplus libc6-dev fontconfig RUN ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll COPY ./ ./ ENTRYPOINT ["dotnet", "OneLove.VipUser.Interface.dll"]
然后发布成dll
接下来进行服务器编写consul.yml (需要注意文件挂载的路径)
version: '3' services: # 项目vipuser vipuser_api: build: ./vipuser_api/api/publish container_name: vipuser_api restart: always volumes: - ./vipuser_api/api/publish:/app # 方式1:挂载全部的程序文件 + 配置文件 #- ./configs:/app/configs # 方式2:只挂载配置文件 #- ./logs:/logs # 日志文件 - /var/run/docker.sock:/var/run/docker.sock # 容器内部通过 unix socket 使用宿主机 docker engine user: root # 必须确保容器以 root 用户启动!(这样它才有权限读写 docker.socket) ports: - 5001:5001
然后直接 docker-compose -f consul.yml up -d
然后开始输入 ip:端口/healthcheck 访问是否正常
正常响应后 查看 ip:8500查看consul集群服务是否正常
这样就 ok了 查看日志也能看到consul心跳记录
标签:服务,string,Consul,public,consul,new,Net6,consulRegisterOptions,注入 From: https://www.cnblogs.com/OneSeting/p/17297151.html