.NetCore部署微服务(二)

news2024/11/19 15:13:46

目录

前言

概念

一 Consul注册服务中心

1.1 consul下载

1.2 consul运行

二 服务注册

2.1 安装Consul包

2.2 修改配置文件 

2.3 注入Consul服务

2.3 修改Controller,增加HealthCheck方法

三 运行服务

3.1 docker运行服务


前言

上一篇讲到微服务要灵活伸缩,需要一种特殊的机制去实现它,这个机制就是服务注册与发现,但是不肯定不是必须的,如果你的服务实例很少,并且非常稳定,那么就没有必要使用服务注册与发现了,毕竟写代码如此麻烦。

概念

什么叫服务注册与发现呢

服务注册:简单理解就是,有那么一个注册中心,我们每一个服务实例启动时,都去注册中心注册一下,告诉注册中心我的地址,端口等信息,同样的服务实例需要删除时,也去注册中心删除一下,注册中心就服务维护这些服务实例的信息。

服务发现:既然注册中心维护了各个服务实例的信息,那么客户端就可以通过注册中心很容易发现服务的变化了。

有了服务注册跟发现,客户端就不用再去配置各个服务实例的地址,就可以改为从注册中心统一获取,那么注册中心又怎么可以保证每个服务实例的可用状态呢,假如某一个实例挂了,我们肯定不可以让该挂掉的实例让客户端获取到,这个时候,就引入了另外一个概念,叫做,健康检查。

健康检查:每个服务都需要提供一个用于健康检查的接口,该接口不具备任何业务功能,服务注册时把这个接口的地址也告诉注册中心,注册中心会定时调用这个接口来检测服务是否正常,如果不正常,则将它移除,这样就可以保证服务的可用性。

常见的服务注册中心有Consul、ZooKeeper、etcd、Eureka。

一 Consul注册服务中心

1.1 consul下载

Consul官网地址:https://www.consul.io/icon-default.png?t=N7T8https://www.consul.io/

Consul提供的主要功能有服务注册与发现,健康检查,K-V存储,多数据中心等等功能。

Consul安装非常简单,在官网,点击download

由于我是在window中测试,所以我选择window版本

Consul安装:下载后,解压即可。解压后只有一个consul.exe可执行文件。

1.2 consul运行

Consul运行命令如下:

cd F:\工具\consul_1.17.1_windows_amd64
 .\consul.exe agent -dev

 运行该命令后,出现如下提示信息:

我们在浏览器中访问地址,http://localhost:8500/ 以判断我们的Consul服务是否运行成功。

访问结果如下:

这表示我们的consul已经运行成功了。

二 服务注册

2.1 安装Consul包

consul安装完成后,我们需要修改我们的服务实例的代码。

我们需要使用Nuget安装一下consul。

这个类库封装了consul的api方法,方便我们直接调用,当然你也可以直接写http请求去调用consul的接口。

接口文档说明:Consul HTTP API Overview | Consul | HashiCorp DeveloperLearn about the Consul REST API, which is the primary interface to all functionality available in Consul.icon-default.png?t=N7T8https://www.consul.io/api-docs

2.2 修改配置文件 

我们需要在appsettings中添加Consul配置信息

ConsulSetting.json的内容如下:

{
  "ConsulSetting": {
    "ServiceName": "OrderService",
    "ServiceIP": "localhost",
    "ServiceHealthCheck": "/healthcheck",
    "ConsulAddress": "http://host.docker.internal:8500", //注意,docker容器内部无法使用localhost访问宿主机器,如果是控制台启动的话就用localhost
    "ServicePort": "8050"
  }
}

注意,我们在使用 http://host.docker.internal:8500  

 之前,需要先检测一下当前版本的docker是否支持host.docker.internal,我们需要在DNS查询,输入如下命令

nslookup host.docker.internal

如果您看到类似于以下输出,表示您的 Docker 支持 host.docker.internal

Server:    192.168.65.1
Address 1: 192.168.65.1Name:      host.docker.internal
Address 1: 192.168.X.X   # 宿主机的 IP 地址

如果输出显示了宿主机的 IP 地址,则说明 Docker 支持 host.docker.internal 主机名。

如果查询失败或显示其他错误消息,则可能是因为您的 Docker 版本不支持 host.docker.internal

2.3 注入Consul服务

同时我们还需要注册Consul,我们需要写一个基于IServiceCollection的扩展方法ConsulExtendsion。

ConsulExtendsion的完整代码如下:

namespace ForumOrderApi
{
    public static class ConsulExtendsion
    {
        /// <summary>
        /// 服务注册到consul
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection RegisterConsul(this IServiceCollection services, IConfiguration configuration, IHostApplicationLifetime lifetime)
        {

            var consulClient = new ConsulClient(c =>
            {
                //consul地址
                c.Address = new Uri(configuration["ConsulSetting:ConsulAddress"]);
            });

            var registration = new AgentServiceRegistration()
            {
                ID = Guid.NewGuid().ToString(),//服务实例唯一标识
                Name = configuration["ConsulSetting:ServiceName"],//服务名
                Address = configuration["ConsulSetting:ServiceIP"], //服务IP
                Port = int.Parse(configuration["ConsulSetting:ServicePort"]),//服务端口 因为要运行多个实例,端口不能在appsettings.json里配置,在docker容器运行时传入
                Check = new AgentServiceCheck()
                {
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
                    Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔
                    HTTP = $"http://{configuration["ConsulSetting:ServiceIP"]}:{configuration["ConsulSetting:ServicePort"]}{configuration["ConsulSetting:ServiceHealthCheck"]}",//健康检查地址
                    Timeout = TimeSpan.FromSeconds(5)//超时时间
                }
            };

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

            //应用程序终止时,取消注册
            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(registration.ID).Wait();
            });

            return services;
        }
    }
}

同时我们在Program中调用该扩展方法,完整代码如下:

using Consul;
using ForumOrderApi;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.


builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();


var app = builder.Build();

//服务注册
builder.Services.RegisterConsul(builder.Configuration, app.Lifetime);

// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())
//{
app.UseSwagger();
    app.UseSwaggerUI();
//}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

2.3 修改Controller,增加HealthCheck方法

我们还需要修改OrderController方法,我们增加一个serviceport参数,方便我们更好的观察结果,完整代码如下:

namespace ForumOrderApi.Controllers
{
    [ApiController]
    [Route("order")]
    public class OrderController : ControllerBase
    {
        private readonly ILogger<OrderController> _logger;

        private readonly IConfiguration _configuration;

        public OrderController(ILogger<OrderController> logger, IConfiguration configuration)
        {
            _logger = logger;
            _configuration = configuration;
        }

        [HttpGet(Name = "GetOrder")]
        public Task<OrderEntity> GetOrder()
        {
            return Task.FromResult(new OrderEntity()
            {
                date_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                ip_address = Request.HttpContext.Connection.LocalIpAddress?.ToString(),
                ip_port = Request.HttpContext.Connection.LocalPort.ToString(),
                service_name = "订单服务",
                service_port= _configuration["ConsulSetting:ServicePort"]
            });

        }
    }


    public class OrderEntity
    {
        /// <summary>
        /// 当前时间
        /// </summary>
        public string? date_time { get; set; }

        /// <summary>
        /// Ip地址
        /// </summary>
        public string? ip_address { get; set; }


        /// <summary>
        /// Ip端口
        /// </summary>
        public string? ip_port { get; set; }


        /// <summary>
        /// 服务名称
        /// </summary>
        public string? service_name { get; set; }


        /// <summary>
        /// 服务端端口
        /// </summary>
        public string? service_port { get; set; }

    }
}

同时我们增加一个HealthCheck的接口,由于该接口只用于返回Ok,所以我们写一个基于app的扩展方法即可,我们可以将代码写入ConsulExtendsion中,完整代码如下:

public static void UseHealthCheckMiddleware(this IApplicationBuilder app, string checkPath = "/healthcheck")
{
    app.Map(checkPath, applicationBuilder => applicationBuilder.Run(async context =>
    {
        context.Response.StatusCode = (int)HttpStatusCode.OK;

        await context.Response.WriteAsync("OK");
    }));
}

同样我们需要在Program中注册该方法。

app.UseHealthCheckMiddleware();

 至此就完成了服务注册,取消注册,健康检查等功能的代码编写。

同样的方式我们改造一下产品服务,代码一模一样,这里我就不再重复黏贴了。

三 运行服务

3.1 docker运行服务

我们需要发布项目,然后在docker中运行项目,docker部署我就不再重复了。

然后我们需要在docker中运行实例。

运行OrderService

docker run -d -p 8060:80 --name orderapi1  ordercontainer:1.0 --ConsulSetting:ServicePort="8060"

docker run -d -p 8061:80 --name orderapi2  ordercontainer:1.0 --ConsulSetting:ServicePort="8061"

docker run -d -p 8062:80 --name orderapi3  ordercontainer:1.0 --ConsulSetting:ServicePort="8062"

运行ProductService

docker run -d -p 8050:80 --name productapi1 productcontainer:1.0 --ConsulSetting:ServicePort="8050"

docker run -d -p 8051:80 --name productapi2 productcontainer:1.0 --ConsulSetting:ServicePort="8051"

docker run -d -p 8052:80 --name productapi3 productcontainer:1.0 --ConsulSetting:ServicePort="8052"

然后这里注意一下 ConsulSetting:ServicePort="8061"
这里的意思是会替换appsetting.json 文件中的ConsulSetting配置文件中ServicePort的内容,这里可以方便后面启动多实例时指定对应端口,

然后访问 http://localhost:8500 查看Consul查看服务是否注册成功。

至此,6个服务器实例都已运行,并且成功注册到Consul。

随便停止2个服务:

docker stop orderapi1 productapi1

可以看到停止的服务已经在Consul中被移除。注意,这个是我们停止程序时主动调用Consul移除的。

//应用程序终止时,取消注册
lifetime.ApplicationStopping.Register(() =>
{
    consulClient.Agent.ServiceDeregister(registration.ID).Wait();
});

当然程序发生异常,健康检查不能正确响应的话,Consul也会移除,有一点区别。

那么注册,发现,健康检查功能都完成了,下一步就该考虑客户端如何拿到这些服务实例的地址了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1371281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第六讲_css盒子模式

css盒子模型 1. 长度单位2. 盒子模型的组成2.1 盒子模型内容2.2 盒子模型内边距2.3 盒子模型边框2.4 盒子模型外边距 1. 长度单位 px&#xff1a;像素em&#xff1a;相对于当前元素或父元素的 font-size 的倍数 <style>.parent {height: 500px;width: 500px;background…

控制注塑机PQ比例阀放大器

控制不带电反馈的单或双比例电磁铁的博世力士乐&#xff08;Bosch Rexroth&#xff09;、伊顿威格士&#xff08;EATON Vickers&#xff09;、油研&#xff08;YUKEN&#xff09;、贺德克&#xff08;HYDAC&#xff09;、大金&#xff08;DAIKIN&#xff09;、不二越&#xff0…

API(Math类,System类,Runtime类,Object类,Objects类,BigInteger类,BigDecimal类)

文章目录 课程目标1 Math类1.1 概述1.2 常见方法1.3 算法小题(质数)1.4 算法小题(自幂数)1.5 课后练习 2 System类2.1 概述2.2 常见方法 3 Runtime3.1 概述3.2 常见方法3.3 恶搞好基友 4 Object类4.1 概述4.2 常见方法 5 Objects类5.1 概述5.2 常见方法 6 BigInteger类6.1 引入…

微信小程序的生命周期函数有哪些?

面试官&#xff1a;说说微信小程序的生命周期函数有哪些&#xff1f; 一、是什么 跟vue、react框架一样&#xff0c;微信小程序框架也存在生命周期&#xff0c;实质也是一堆会在特定时期执行的函数 小程序中&#xff0c;生命周期主要分成了三部分&#xff1a; 应用的生命周期…

用React给XXL-JOB开发一个新皮肤(二):目录规划和路由初始化

目录 一. 简述二. 目录规划三. Vite 配置 3.1. 配置路径别名3.2. 配置 less 四. 页面 4.1. 入口文件4.2. 骨架文件4.3. 普通页面 五. 路由配置六. 预览启动 一. 简述 上一篇文章我们介绍了项目初始化&#xff0c;此篇文章我们会先介绍下当前项目的目录规划&#xff0c;接着对…

学习JavaEE的日子 day11 初识面相对象

day11 1.初识面相对象 1.1 类和对象的理解 类 * 类是对象的数据类型&#xff0c;类是具有相同属性和行为的一组对象的集合 * 简单理解&#xff1a;类就是对现实事物的一种描述 类的组成 * 属性&#xff1a;指事物的特征&#xff0c;例如&#xff1a;手机事物&#xff08;品牌…

【2023】java常用HTTP客户端对比以及使用(HttpClient/OkHttp/WebClient)

&#x1f4bb;目录 1、介绍2、使用2.1、添加配置2.1.1、依赖2.1.2、工具类2.1.3、实体2.1.4、Controller接口 2.2、Apache HttpClient使用2.3 、OkHttp使用2.4、WebClient使用 1、介绍 现在java使用的http客户端主要包括以下几种 而这些中使用得最频繁的主要是&#xff1a; A…

麒麟系统安装docker、mysql、clickhouse

1、查看麒麟系统版本信息 cat /etc/os-release 麒麟系统版本V10 64位操作系统 # uname -p x86_64 # uname -p aarch64 内核版本 # uname -r 4.19.90-24.4.v2101.ky10.x86_64 本操作为麒麟系统版本V10&#xff0c;x86_64操作系统 一&#xff0c;安装docker 文件&#xff1a…

基于uniapp封装的table组件

数据格式 tableData: [{elcInfo: [{tableData:[1,293021.1,293021.1,293021.1,293021.1,]}]},{elcInfo: [{tableData:[1,293021.1,293021.1,293021.1,293021.1,]}]},{elcInfo: [{tableData:[1,293021.1,293021.1,293021.1,293021.1,]}]},/* {title: "2",elcInfo: [{…

spring-mvc数据绑定和表单标签库(介绍)

spring-mvc数据绑定和表单标签库 1. WEB-INF下页面跳转2. ModelAttribute来注解非请求处理方法3. 表单标签4. 其他标签5. IDEA tomcat控制台中文乱码问题处理 1. WEB-INF下页面跳转 容器启动后&#xff0c;如何默认显示web-inf目录下的系统首页。 2. ModelAttribute来注解非…

mysql生成到当前时间的时间序列,报表按时间补0

生成本月每日的时间序列 SELECT DATE_FORMAT(date_add( CONCAT(YEAR(Date(curdate())),‘-0’,MONTH(Date(curdate())),‘-’,‘01’), INTERVAL ( cast( help_topic_id AS signed) ) DAY ) ,‘%Y-%m-%d’ ) FROM mysql.help_topic WHERE help_topic_id < DAY ( curdate( ) …

示例说明 Makefile 中的 $(@F),及其用法示例$$dir $@ $< $^ %.c

备忘一个不错的开源编辑器CudaText 下载网址&#xff1a; CudaText - Browse /release at SourceForge.net CudaText 主页&#xff1a; CudaText - Home 1&#xff0c;含义及验证 在 Makefile 中&#xff0c;$(F) 表示当前规则的目标文件名&#xff08;不包括路径部分&…

在Linux中使用Apache HTTP服务器

Apache HTTP服务器&#xff0c;也被称为Apache&#xff0c;是全球使用最广泛的Web服务器软件之一。它以其稳定性、强大的功能和灵活性而闻名&#xff0c;尤其在Linux操作系统上表现得尤为出色。以下是关于如何在Linux中使用Apache HTTP服务器的详细指南。 1. 安装Apache 首先…

AI墨墨交流群正式成立:探索科技前沿,共建智能未来

在这个充满变革的时代&#xff0c;AI技术正如涌泉般迸发&#xff0c;带来无限可能。我们深感&#xff0c;唯有汇聚智慧&#xff0c;方能更好地驾驭这股前沿科技的潮流。因此&#xff0c;我们自豪地宣布&#xff1a;AI墨墨交流群正式成立了&#xff01;这不仅是一个交流群&#…

日志系统一(elasticsearch+filebeat+logstash+kibana)

目录 一、es集群部署 安装java环境 部署es集群 安装IK分词器插件 二、filebeat安装&#xff08;docker方式&#xff09; 三、logstash部署 四、kibana部署 背景&#xff1a;因业务需求需要将nginx、java、ingress日志进行收集。 架构&#xff1a;filebeatlogstasheskib…

debug OpenBLAS library 和 应用示例

1. 构建openblas lib git clone gitgithub.com:OpenMathLib/OpenBLAS.git cd OpenBLAS/ 如果要安装在自定义文件夹中&#xff0c;可以修改 PREFIX 的定义&#xff1a; 将 PREFIX /opt/OpenBLAS 修改成 PREFIX ../local/ 然后构建&#xff1a; make -j make install 如果要…

【解决】Unity Project 面板资源显示丢失的异常问题处理

开发平台&#xff1a;Unity 2021.3.7f1c1   一、问题描述 在开发过程中&#xff0c;遭遇 Project 面板资源显示丢失、不全的问题。但 Unity Console 并未发出错误提示。   二、解决方案&#xff1a;删除 Library 目录 前往 “工程目录/Library” 删除内部所有文件并重打开该…

007-可调脉冲数触发之FPGA实现(Zynq也可驱动,带启动停止及完成中断输出)

文章目录 前言一、设计思路二、代码及仿真1.资源消耗2.具体代码3.仿真波形 总结 前言 此代码是在做显微镜高速聚焦系统中自己写的步进电机电机驱动源码&#xff0c;为了达到最快的驱动速度&#xff0c;因此选用脉冲触发方式进行驱动。在电机驱动的过程中往往需要对脉冲进行使能…

React Native 桥接原生实现 JS 调用原生方法

一、为什么需要桥接原生 为了满足在React 层无法实现的需求 复杂高性能的组件&#xff1a;复杂表格、视频播放原生层开发能力&#xff1a;传感器编程、widget平台属性&#xff1a;系统信息、设备信息对接第三方应用&#xff1a;相机、相册、地图 真实的开发过程中是不可能完…

OpenGL学习笔记-Blending

混合方程中&#xff0c;Csource是片段着色器输出的颜色向量&#xff08;the color output of the fragment shader&#xff09;&#xff0c;其权重为Fsource。Cdestination是当前存储在color buffer中的颜色向量&#xff08;the color vector that is currently stored in the …