微服务介绍,通讯,注册和发现

带着两个问题 什么是微服务 ,什么是架构

什么是架构:

1、架构实际上就是指解决某一个问题的一系列的组织实践活动
2、架构实际上就是指解决某一个软件问题的一系列的软件组织元素实践活动
 
软件开发都围绕四个要素: 问题 问题边界(谁的问题)  生命周期 拆分
 
问题和问题的边界(约束)得到领域模型
 
生命周期 (产品----出生----死亡)===》拆分主体

 

然后引出什么是微服务的思考:

都围绕一个领域模型,下面就是微服务架构

 

 下面是一个完成的微服务架构图 :

 

 微服务的约束总结:

1、单一职责原则
2、有且只有一个服务
3、一个服务升级更新,不会影响到其他服务
 
微服务的设计模式有哪几种(4种):
1 如上面的 是聚合这只模式
2 链式设计模式
3 数据共享设计模式

 

4.异步消息控制模式

 

 

上面的设计模式要根据问题的边界去选择 

最通用的方式是聚合设计模式

选择设计模式注意:1业务特点 2公司组织 3公司每个人的利益

 

为什么要使用微服务架构:

 

 

 

 

 

 

 

 

 

 重点微服务如何拆分:

 

微服务拆分方法:

微服务拆分拆分方法
根据名词和动词拆分
生命周期拆分方法
根据领域模型拆分
业务里面有多少个名词和动词
都可以是微服务
名词概念会有层级
动词是生命周期
微服务粒度名词(概念)
组织利益决定粒度问题
动词:支付 推送 打印 下单(查询)登录
总结
名词====都一定要要拆分
组织
 
根据
1、组织越大,粒度越细
2、组织越小,粒度越粗
 
如何形成一套微服务架构?
1、微服务内部结构?
2、微服务之间如何通信?

 微服务内部结构

每次拆分因为有生命周期每个生命周期都会出现新的领域每个领域都会有新的主体每个主体都会有边界,每个边界和主体都会生产一个领域模型。

http 是restful    rpc 是 rpc 和 grpc 

 

领域模型其实就是model  interface是解耦model的  services是为了处理一些业务逻辑的  respositories是和数据库打交道的

webapi 是 Resful的落地方式

例如 团队管理项目 他的边界是公司

销售  技术 售后 售前 人事等等

上面这些团队都是有成员的,成员也是有位置的上班地点 所以更具名词拆分 得到 团队=====成员=====成员位置

出现了 团队 和 成员 两个名词 这里就可以拆分为两个服务 团队服务 成员服务 和 位置服务

粒度问题如何决定

1 组织--如果公司只有一个人==单体

2 业务本身

3 如果公司有2个人 ==拆分为两个服务  (团队服务 成员服务)  位置服务

一个简单的微服务代码构造如图:

 什么是注册中心?

 

 

 

 

如何在项目中运用注册中心?
注册中心有哪些?
 

 

 

如何使用consul?

consul三个概念
1、server  提供存储服务
2、client   操作server
3、agent 进程启动 agent 守护进程 

 

如何使用Consul

步骤

​ 1、Consul下载地址

​ 官网地址: https://www.consul.io/

​ 下载地址: https://releases.hashicorp.com/consul/1.7.2/ 或 https://www.consul.io/downloads.html

下载后解开压缩包.拷贝Consul到你的PATH路径中,在Unix系统中~/bin/usr/local/bin是通常的安装目录.根据你是想为单个用户安装还是给整个系统安装来选择.

在Windows系统中有可以安装到%PATH%的路径中.

​ 2、服务端启动

 完成安装后,通过打开一个新终端窗口检查consul安装是否成功.通过执行 consul你应该看到类似下面的输出

 

 

 启动服务  consul agent -dev  开发模式

                  consul agent -server  生产模式 

开发模式和生产模式是一样的只是生产模式会数据持久化

1.开发模式启动命令:

 

 Version :consul版本

​ Node ID : consul当前启动节点编号(guid)

​ Node Name:节点名称(默认为电脑名称)

​ Datacenter:数据中心

​ Server:启动是服务端模式,否则就为客户端模式

​ Client Addr:客户端连接地址,支持http,https,gRPC,DNS。默认我们使用HTTP方式

​ Cluster Addr:集群地址,就是Server模式下 启动方式

​ Encrypt:安全

生产模式启动命令:

 consul agent -server -bootstrap-expect 1 -data-dir d:/consul/data

 会出现错误:提示

 

 

 ​ 主要原因:服务端模式启动的时候,默认绑定的地址是0.0.0.0.希望绑定默认的ip地址

consul agent -server -bind=127.0.0.1 -bootstrap-expect 1 -data-dir d:/consul/data

客户端模式启动

​ 直接使用net程序来进行启动

示例:先下载consul包

 

复制代码
// 1、创建consul客户端连接var consulClient = new ConsulClient(configuration =>
           ​{
               ​//1.1 建立客户端和服务端连接
               ​configuration.Address = new Uri("http://127.0.0.1:8500");
           ​});
       ​// 2、获取服务内部地址
// 3、创建consul服务注册对象var registration = new AgentServiceRegistration()
       ​{
           ​ID =  Guid.NewGuid().ToString(),
           ​Name = "teamservice",
           ​Address = "http://localhos",
           ​Port = "5001",
           ​Tags = new string[],
           ​Check = new AgentServiceCheck
           ​{
               ​// 3.1、consul健康检查超时间
               ​Timeout = TimeSpan.FromSeconds(10),
               ​// 3.2、服务停止5秒后注销服务
               ​DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
               ​// 3.3、consul健康检查地址
               ​HTTP = serviceNode.HealthCheckAddress,
               ​// 3.4 consul健康检查间隔时间
               ​Interval = TimeSpan.FromSeconds(10),
           ​}
       ​};

       ​// 4、注册服务
       ​consulClient.Agent.ServiceRegister(registration).Wait();
复制代码

项目结构展示:

 

 

 

复制代码
  public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // 1、注册上下文到IOC容器
            services.AddDbContext<TeamContext>(options => {
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
            });
            // 2、注册团队service
            services.AddScoped<ITeamService, TeamServiceImpl>();

            // 3、注册团队仓储
            services.AddScoped<ITeamRepository, TeamRepository>();

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            // 注册团队服务
            // 1、创建consul客户端连接
            var consulClient = new ConsulClient(configuration =>
            {
                //1.1 建立客户端和服务端连接
                configuration.Address = new Uri("http://127.0.0.1:8500");
            });
           
            // 2、创建consul服务注册对象
            var registration = new AgentServiceRegistration()
            {
                ID = Guid.NewGuid().ToString(),//指定服务的编号
                Name = "teamservice",//服务的名字
                Address = "https://localhost",//服务地址
                Port = 5004,//服务的端口
                Check = new AgentServiceCheck
                {
                    // 3.1、consul健康检查超时间
                    Timeout = TimeSpan.FromSeconds(10),
                    // 3.2、服务停止5秒后注销服务
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                    // 3.3、consul健康检查地址
                    HTTP = "https://localhost:5004/HealthCheck",
                    // 3.4 consul健康检查间隔时间
                    Interval = TimeSpan.FromSeconds(3),
                }
            };

            // 1、不好扩展(集群配置)
            // 2、不好维护
            // 3、完全和业务无关
            // 封装
            
            // 3、注册服务
            consulClient.Agent.ServiceRegister(registration).Wait();

            Console.WriteLine("consul注册成功");



            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
复制代码

 微服务聚合服务:

 最后微服务发现者进行获取,服务发现代码如下:

复制代码
// 1、创建consul客户端连接var consulClient = new ConsulClient(configuration =>
           ​{
               ​//1.1 建立客户端和服务端连接
               ​configuration.Address = new Uri("http://127.0.0.1:8500");
           ​});
      ​// 2、consul查询服务,根据具体的服务名称查询var queryResult = await consulClient.Catalog.Service("teamservice");

       ​// 3、将服务进行拼接var list = new List<ServiceUrl>();
       ​foreach (var service in queryResult.Response)
       ​{
           ​list.Add(new ServiceUrl { Url = service.ServiceAddress + ":" + service.ServicePort });
       ​}    
复制代码
复制代码
 /// <summary>
    /// 服务调用实现
    /// </summary>
    public class HttpTeamServiceClient : ITeamServiceClient
    {
        
        private readonly IHttpClientFactory httpClientFactory;
        
        public HttpTeamServiceClient(IHttpClientFactory httpClientFactory)
        {
            this.httpClientFactory = httpClientFactory;
        }

        public async Task<IList<Team>> GetTeams()
        {

            // 开始消费
            // 1、创建consul客户端连接
            var consulClient = new ConsulClient(configuration =>
            {
                //1.1 建立客户端和服务端连接
                configuration.Address = new Uri("http://127.0.0.1:8500");
            });
            // 2、consul查询服务,根据具体的服务名称查询
            var queryResult = await consulClient.Catalog.Service("teamservice");

            // 3、将服务进行拼接
            var list = new List<string>();
            foreach (var service in queryResult.Response)
            {
                list.Add(service.ServiceAddress + ":" + service.ServicePort );
            }


            // 1、建立请求
            HttpClient httpClient = httpClientFactory.CreateClient();
            HttpResponseMessage response = await httpClient.GetAsync(list[0]+"/Teams");

            // 1.1json转换成对象
            IList<Team> teams = null;
            if (response.StatusCode == HttpStatusCode.OK)
            {
                string json = await response.Content.ReadAsStringAsync();
                
                teams = JsonConvert.DeserializeObject<List<Team>>(json);
            }
            
            return teams;
        }
    }
复制代码
复制代码
 public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // 1、注册restfulapi调用
            services.AddHttpClient();

            // 2、service注入到ioc容器
            services.AddScoped<ITeamServiceClient, HttpTeamServiceClient>();
            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
复制代码

注意注册服务心跳发现部分:

复制代码
Check = new AgentServiceCheck
                {
                    // 3.1、consul健康检查超时间
                    Timeout = TimeSpan.FromSeconds(10),
                    // 3.2、服务停止5秒后注销服务
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                    // 3.3、consul健康检查地址
                    HTTP = "https://localhost:5004/HealthCheck",
                    // 3.4 consul健康检查间隔时间
                    Interval = TimeSpan.FromSeconds(3),
                }
复制代码

上面的服务注册和服务发现 都是硬编码的

 1、不好扩展(集群配置)
 2、不好维护
 3、完全和业务无关
所以我们应该封装一个工具类库 Core

 

 定义注册和发现接口

复制代码
  /// <summary>
   /// 服务发现
   /// </summary>
   public interface IServiceDiscovery
   {
        /// <summary>
        /// 服务发现
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns></returns>
        Task<IList<ServiceUrl>> Discovery(string serviceName);
    }

   /// <summary>
    /// 服务注册
    /// </summary>
   public interface IServiceRegistry
   {
        /// <summary>
        /// 注册服务
        /// </summary>
        void Register(ServiceRegistryConfig serviceNode);

        /// <summary>
        /// 撤销服务
        /// </summary>
        void Deregister(ServiceRegistryConfig serviceNode);
    }
复制代码

注册和发现的配置类:

复制代码
   /// <summary>
    /// 服务发现配置
    /// </summary>
    public class ServiceDiscoveryConfig
    {
        /// <summary>
        /// 服务注册地址
        /// </summary>
        public string RegistryAddress { set; get; }
    }

   /// <summary>
   /// 服务注册节点
   /// </summary>
   public class ServiceRegistryConfig
   {
        // 服务ID
        public string Id { get; set; }

        // 服务名称
        public string Name { get; set; }

        // 服务标签(版本)
        public string[] Tags { set; get; }

        // 服务地址(可以选填 === 默认加载启动路径)
        public string Address { set; get; }

        // 服务端口号(可以选填 === 默认加载启动路径端口)
        public int Port { set;get; }

        // 服务注册地址
        public string RegistryAddress { get; set; }

        // 服务健康检查地址
        public string HealthCheckAddress { get; set; }
    }
复制代码

服务Url类

   /// <summary>
    /// 服务url
    /// </summary>
    public class ServiceUrl
    {
        public string Url { set; get; }
    }

 consul服务注册实现

复制代码
    /// <summary>
    /// consul服务注册实现
    /// </summary>
    public class ConsulServiceRegistry : IServiceRegistry
    {
        /// <summary>
        /// 注册服务
        /// </summary>
        /// <param name="serviceNode"></param>
        public void Register(ServiceRegistryConfig serviceNode)
        {
            // 1、创建consul客户端连接
            var consulClient = new ConsulClient(configuration =>
            {
                //1.1 建立客户端和服务端连接
                configuration.Address = new Uri(serviceNode.RegistryAddress);
            });

            // 2、获取服务内部地址

            // 3、创建consul服务注册对象
            var registration = new AgentServiceRegistration()
            {
                ID = serviceNode.Id,
                Name = serviceNode.Name,
                Address = serviceNode.Address,
                Port = serviceNode.Port,
                Tags = serviceNode.Tags,
                Check = new AgentServiceCheck
                {
                    // 3.1、consul健康检查超时间
                    Timeout = TimeSpan.FromSeconds(10),
                    // 3.2、服务停止5秒后注销服务
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                    // 3.3、consul健康检查地址
                    HTTP = serviceNode.HealthCheckAddress,
                    // 3.4 consul健康检查间隔时间
                    Interval = TimeSpan.FromSeconds(10),
                }
            };

            // 4、注册服务
            consulClient.Agent.ServiceRegister(registration).Wait();

            // 5、关闭连接
            consulClient.Dispose();
        }

        /// <summary>
        /// 注销服务
        /// </summary>
        /// <param name="serviceNode"></param>
        public void Deregister(ServiceRegistryConfig serviceNode)
        {
            // 1、创建consul客户端连接
            var consulClient = new ConsulClient(configuration =>
            {
                //1.1 建立客户端和服务端连接
                configuration.Address = new Uri(serviceNode.RegistryAddress);
            });

            // 2、注销服务
            consulClient.Agent.ServiceDeregister(serviceNode.Id);

            // 3、关闭连接
            consulClient.Dispose();
        }

    }
复制代码

consul服务发现实现:

复制代码
    /// <summary>
    /// consul服务发现实现
    /// </summary>
    public class ConsulServiceDiscovery : IServiceDiscovery
    {
        private readonly IConfiguration configuration;
        public ConsulServiceDiscovery(IConfiguration configuration)
        {
            this.configuration = configuration;
        }

        public async Task<IList<ServiceUrl>> Discovery(string serviceName)
        {
            ServiceDiscoveryConfig serviceDiscoveryConfig = configuration.GetSection("ConsulDiscovery").Get<ServiceDiscoveryConfig>();

            // 1、创建consul客户端连接
            var consulClient = new ConsulClient(configuration =>
            {
                //1.1 建立客户端和服务端连接
                configuration.Address = new Uri(serviceDiscoveryConfig.RegistryAddress);
            });

            // 2、consul查询服务,根据具体的服务名称查询
            var queryResult = await consulClient.Catalog.Service(serviceName);

            // 3、将服务进行拼接
            var list = new List<ServiceUrl>();
            foreach (var service in queryResult.Response)
            {
                list.Add(new ServiceUrl { Url = service.ServiceAddress + ":" + service.ServicePort });
            }
            return list;
        }
    }
复制代码

微服务注册发现使用扩展:

复制代码
/// <summary>
    /// 微服务注册发现使用扩展
    /// </summary>
   public static class MicroServiceConsulApplicationBuilderExtensions
   {
        public static IApplicationBuilder UseConsulRegistry(this IApplicationBuilder app)
        {
            // 1、从IOC容器中获取Consul服务注册配置
            var serviceNode = app.ApplicationServices.GetRequiredService<IOptions<ServiceRegistryConfig>>().Value;

            // 2、获取应用程序生命周期
            var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();

            // 2.1 获取服务注册实例
            var serviceRegistry = app.ApplicationServices.GetRequiredService<IServiceRegistry>();

            // 3、获取服务地址
            var features = app.Properties["server.Features"] as FeatureCollection;
            var address = features.Get<IServerAddressesFeature>().Addresses.First();
            var uri = new Uri(address);

            // 4、注册服务
            serviceNode.Id = Guid.NewGuid().ToString();
            serviceNode.Address = $"{uri.Scheme}://{uri.Host}";
            serviceNode.Port = uri.Port;
            serviceNode.HealthCheckAddress = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceNode.HealthCheckAddress}";
            serviceRegistry.Register(serviceNode);

            // 5、服务器关闭时注销服务
            lifetime.ApplicationStopping.Register(() =>
            {
                serviceRegistry.Deregister(serviceNode);
            });

            return app;
        }
   }
复制代码

注册中心扩展:

复制代码
    /// <summary>
     /// Console 注册中心扩展(加载配置)
    /// </summary>
    public static class MicroServiceConsulServiceCollectionExtensions
    {
        // consul服务注册
        public static IServiceCollection AddConsulRegistry(this IServiceCollection services, IConfiguration configuration)
        {
            // 1、加载Consul服务注册配置
            services.Configure<ServiceRegistryConfig>(configuration.GetSection("ConsulRegistry"));

            // 2、注册consul注册
            services.AddSingleton<IServiceRegistry, ConsulServiceRegistry>();
            return services;
        }

        // consul服务发现
        public static IServiceCollection AddConsulDiscovery(this IServiceCollection services,IConfiguration configuration)
        {
            // 1、加载Consul服务发现配置
           // services.Configure<ServiceDiscoveryConfig>(configuration.GetSection("ConsulDiscovery"));

            // 2、注册consul服务发现
            services.AddSingleton<IServiceDiscovery, ConsulServiceDiscovery>();
            return services;
        }

    }
复制代码

微服务种的StartUp

复制代码
 public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // 1、注册上下文到IOC容器
            services.AddDbContext<TeamContext>(options => {
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
            });
            // 2、注册团队service
            services.AddScoped<ITeamService, TeamServiceImpl>();

            // 3、注册团队仓储
            services.AddScoped<ITeamRepository, TeamRepository>();

            // 5、添加服务注册条件
            services.AddConsulRegistry(Configuration);

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            // 1、consul服务注册
            app.UseConsulRegistry();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
复制代码

 

 

 

 

 

posted @   根仔  阅读(145)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示