前言

一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目。正好由于最近刚好辞职,有了时间可以写写自己感兴趣的东西,所以在此想把自己了解的微服务相关的概念和技术框架使用实现记录在一个完整的工程中,由于本人技术有限,所以错误的地方希望大家指出。\

项目地址:https://github.com/yingpanwang/fordotnet/tree/dev

什么是Api网关

  由于微服务把具体的业务分割成单独的服务,所以如果直接将每个服务都与调用者直接,那么维护起来将相当麻烦与头疼,Api网关担任的角色就是整合请求并按照路由规则转发至服务的实例,并且由于所有所有请求都经过网关,那么网关还可以承担一系列宏观的拦截功能,例如安全认证,日志,熔断

为什么需要Api网关

 因为Api网关可以提供安全认证,日志,熔断相关的宏观拦截的功能,也可以屏蔽多个下游服务的内部细节

有哪些有名的Api网关项目

  • Zuul Spring Cloud 集成
  • Kong 一款lua轻量级网关项目
  • Ocelot .NETCore网关项目

Ocelot使用

1.通过Nuget安装Ocelot

2.准备并编辑Ocelot配置信息

Ocelot.json

{
"ReRoutes": [
// Auth
{
"UpstreamPathTemplate": "/auth/{action}", // 上游请求路径模板
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ], // 上游请求方法
"ServiceName": "Auth", // 服务名称
"UseServiceDiscovery": true, // 是否使用服务发现
"DownstreamPathTemplate": "/connect/{action}", // 下游匹配路径模板
"DownstreamScheme": "http", // 下游请求
"LoadBalancerOptions": { // 负载均衡配置
"Type": "RoundRobin"
}
//,
// 如果不采用服务发现需要指定下游host
//"DownstreamHostAndPorts": [
// {
// "Host": "10.0.1.10",
// "Port": 5000
// },
// {
// "Host": "10.0.1.11",
// "Port": 5000
// }
//]
}
],
"GlobalConfiguration": { // 全局配置信息
"BaseUrl": "http://localhost:5000", // 请求 baseurl
"ServiceDiscoveryProvider": { //服务发现提供者
"Host": "106.53.199.185",
"Port": 8500,
"Type": "Consul" // 使用Consul
}
}
}

3.添加Ocelot json文件到项目中

将Config目录下的ocelot.json添加到项目中

4.在网关项目中 StartUp ConfigService中添加Ocelot的服务,在Configure中添加Ocelot的中间件(由于我这里使用了Consul作为服务发现,所以需要添加Consul的依赖的服务AddConsul,如果不需要服务发现的话可以不用添加)

5.将需要发现的服务通过代码在启动时注册到Consul中

我这里自己封装了一个注册服务的扩展(写的比较随意没有在意细节)

appsettings.json 中添加注册服务配置信息

"ServiceOptions": {
"ServiceIP": "localhost",
"ServiceName": "Auth",
"Port": 5800,
"HealthCheckUrl": "/api/health",
"ConsulOptions": {
"Scheme": "http",
"ConsulIP": "localhost",
"Port": 8500
}
}

扩展代码 ConsulExtensions(注意:3.1中 IApplicationLifetime已废弃 所以使用的是IHostApplicationLifetime 作为程序生命周期注入的方式)


using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System; namespace ForDotNet.Common.Consul.Extensions
{
/// <summary>
/// 服务配置信息
/// </summary>
public class ServiceOptions
{
/// <summary>
/// 服务ip
/// </summary>
public string ServiceIP { get; set; } /// <summary>
/// 服务名称
/// </summary>
public string ServiceName { get; set; } /// <summary>
/// 协议类型http or https
/// </summary>
public string Scheme { get; set; } = "http"; /// <summary>
/// 端口
/// </summary>
public int Port { get; set; } /// <summary>
/// 健康检查接口
/// </summary>
public string HealthCheckUrl { get; set; } = "/api/values"; /// <summary>
/// 健康检查间隔时间
/// </summary>
public int HealthCheckIntervalSecond { get; set; } = 10; /// <summary>
/// consul配置信息
/// </summary>
public ConsulOptions ConsulOptions { get; set; }
} /// <summary>
/// consul配置信息
/// </summary>
public class ConsulOptions
{
/// <summary>
/// consul ip
/// </summary>
public string ConsulIP { get; set; } /// <summary>
/// consul 端口
/// </summary>
public int Port { get; set; } /// <summary>
/// 协议类型http or https
/// </summary>
public string Scheme { get; set; } = "http";
} /// <summary>
/// consul注册客户端信息
/// </summary>
public class ConsulClientInfo
{
/// <summary>
/// 注册信息
/// </summary>
public AgentServiceRegistration RegisterInfo { get; set; } /// <summary>
/// consul客户端
/// </summary>
public ConsulClient Client { get; set; }
} /// <summary>
/// consul扩展(通过配置文件配置)
/// </summary>
public static class ConsulExtensions
{
private static readonly ServiceOptions serviceOptions = new ServiceOptions(); /// <summary>
/// 添加consul
/// </summary>
public static void AddConsulServiceDiscovery(this IServiceCollection services)
{
var config = services.BuildServiceProvider().GetService<IConfiguration>();
config.GetSection("ServiceOptions").Bind(serviceOptions);
//config.Bind(serviceOptions); if (serviceOptions == null)
{
throw new Exception("获取服务注册信息失败!请检查配置信息是否正确!");
}
Register(services);
} /// <summary>
/// 添加consul(通过配置opt对象配置)
/// </summary>
/// <param name="app"></param>
/// <param name="life">引用生命周期</param>
/// <param name="options">配置参数</param>
public static void AddConsulServiceDiscovery(this IServiceCollection services, Action<ServiceOptions> options)
{
options.Invoke(serviceOptions);
Register(services);
} /// <summary>
/// 注册consul服务发现
/// </summary>
/// <param name="app"></param>
/// <param name="life"></param>
public static void UseConsulServiceDiscovery(this IApplicationBuilder app, IHostApplicationLifetime life)
{
var consulClientInfo = app.ApplicationServices.GetRequiredService<ConsulClientInfo>();
if (consulClientInfo != null)
{
life.ApplicationStarted.Register( () =>
{
consulClientInfo.Client.Agent.ServiceRegister(consulClientInfo.RegisterInfo).Wait();
}); life.ApplicationStopping.Register( () =>
{
consulClientInfo.Client.Agent.ServiceDeregister(consulClientInfo.RegisterInfo.ID).Wait();
});
}
else
{
throw new NullReferenceException("未找到相关consul客户端信息!");
}
} private static void Register(this IServiceCollection services)
{
if (serviceOptions == null)
{
throw new Exception("获取服务注册信息失败!请检查配置信息是否正确!");
}
if (serviceOptions.ConsulOptions == null)
{
throw new ArgumentNullException("请检查是否配置Consul信息!");
} string consulAddress = $"{serviceOptions.ConsulOptions.Scheme}://{serviceOptions.ConsulOptions.ConsulIP}:{serviceOptions.ConsulOptions.Port}"; var consulClient = new ConsulClient(opt =>
{
opt.Address = new Uri(consulAddress);
}); var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(10), // 服务启动多久后注册
Interval = TimeSpan.FromSeconds(serviceOptions.HealthCheckIntervalSecond), // 间隔
HTTP = $"{serviceOptions.Scheme}://{serviceOptions.ServiceIP}:{serviceOptions.Port}{serviceOptions.HealthCheckUrl}",
Timeout = TimeSpan.FromSeconds(10)
}; var registration = new AgentServiceRegistration()
{
Checks = new[] { httpCheck },
ID = Guid.NewGuid().ToString(),
Name = serviceOptions.ServiceName,
Address = serviceOptions.ServiceIP,
Port = serviceOptions.Port,
}; services.AddSingleton(new ConsulClientInfo()
{
Client = consulClient,
RegisterInfo = registration
});
}
}
}

6.启动运行

  • 启动consul
  • 启动 Auth,Gateway项目
  • 通过网关项目访问Auth

启动Consul

为了方便演示这里是以开发者启动的consul

在consul.exe的目录下执行

consul agent -dev -ui // 开发者模式运行带ui

启动 Auth,Gateway项目

启动项目和可以发现我的们Auth服务已经注册进来了

通过网关访问Auth

我们这里访问 http://localhost:5000/auth/token 获取token

我们可以看到网关项目接收到了请求并在控制台中打印出以下信息



然后在Auth项目中的控制台中可以看到已经成功接收到了请求并响应

.NETCore微服务探寻(一) - 网关的更多相关文章

  1. .NETCore微服务探寻(三) - 分布式日志

    前言 一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目 ...

  2. .NETCore微服务探寻(二) - 认证与授权

    前言 一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目 ...

  3. .NETCore微服务探寻(三) - 远程过程调用(RPC)

    前言 一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目 ...

  4. AspNetCore微服务下的网关-Kong(一)

    Kong是Mashape开源的高性能高可用API网关和API服务管理层.它基于OpenResty,进行API管理,并提供了插件实现API的AOP.Kong在Mashape 管理了超过15,000 个A ...

  5. (1)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- 什么是微服务架构,.netCore微服务选型

    开发工具:VS2017 .Net Core 2.1 什么是微服务?单体结构: 缺点: 1)只能采用同一种技术,很难用不同的语言或者语言不同版本开发不同模块: 2)系统耦合性强,一旦其中一个模块有问题, ...

  6. (1).NET CORE微服务 Micro-Service ---- 什么是微服务架构,.netCore微服务选型

    开发工具:VS2017 .Net Core 2.1 什么是微服务?单体结构: 缺点:1)只能采用同一种技术,很难用不同的语言或者语言不同版本开发不同模块:2)系统耦合性强,一旦其中一个模块有问题,整个 ...

  7. 什么是微服务架构,.netCore微服务选型

    什么是微服务架构,.netCore微服务选型 https://www.cnblogs.com/uglyman/p/9182485.html 开发工具:VS2017 .Net Core 2.1 什么是微 ...

  8. .NetCore微服务Surging新手傻瓜式 入门教程 学习日志---先让程序跑起来(一)

    原文:.NetCore微服务Surging新手傻瓜式 入门教程 学习日志---先让程序跑起来(一) 写下此文章只为了记录Surging微服务学习过程,并且分享给广大想学习surging的基友,方便广大 ...

  9. .NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二)

    原文:.NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二) 先上项目解决方案图: 以上可以看出项目结构可以划分为4大块,1是surging的核心底层,2,3,4都可以 ...

随机推荐

  1. Web Scraper——轻量数据爬取利器

    日常学习工作中,我们多多少少都会遇到一些数据爬取的需求,比如说写论文时要收集相关课题下的论文列表,运营活动时收集用户评价,竞品分析时收集友商数据. 当我们着手准备收集数据时,面对低效的复制黏贴工作,一 ...

  2. Elasticsearch SSL认证/证书制作

    制作目的 在上一篇<elasticsearch7.X x-pack破解>中,我们启用了x-pack模块,elasticsearch集群中,如果使用了x-pack,那么集群中的各节点之间通讯 ...

  3. Java8中的Lambda表达式

    Lambda是什么 Lambda表达式,也可称为闭包,是java8的新特性,作用是取代大部分内部类,优化java代码结构,让代码变得更加简洁紧凑. Lambda的基本语法 (expression)-& ...

  4. PIC单片机编译器自带的延时程序

    https://wenku.baidu.com/view/3c94e2934028915f814dc205.html

  5. python3.7 64bit安装pygame1.9.3

    https://blog.csdn.net/xiaolixi199311/article/details/79209506/

  6. [Python基础]003.语法(2)

    语法(2) 运算符 数学运算 比较运算 逻辑运算 位运算 赋值运算 其他运算 代码规范 代码缩进 多行 注释 流程控制 pass if while for break continue 运算符 数学运 ...

  7. [Python基础]005.语法(4)

    语法(4) 类 创建 self 方法 变量 综合例子 继承 类 创建 与其他大部分语言一样,Python也用 class 来创建类. class Person: # Person类 pass # 空语 ...

  8. 05 . Python入门值循环语句

    一.Python循环语句 程序一般情况下是按照顺序执行的 编程语言提供了各种控制结构,允许更复杂的执行路径 Python中的循环语句有for和while但没有do while 循环语句允许我们执行一个 ...

  9. 【Android】SDK的配置

    1:Android Studio 下载   安装后创建项目 2:  打开settings 3:下载后,配置SDK 4:下载jdk1.8.0_74.rar 解压   加入环境变量 5:下载夜神模拟器,加 ...

  10. Rocket - diplomacy - AddressAdjuster分析

    https://mp.weixin.qq.com/s/UYVSO3XFJmhe5bUD_XbMLg   先介绍如何使用AddressAdjuster,然后分析UI参数的生成及使用.   ​​   1. ...