搭建一套ASP.NET Core+Nacos+Spring Cloud Gateway项目

前言

    伴随着随着微服务概念的不断盛行,与之对应的各种解决方案也层出不穷。这毕竟是一个信息大爆发的时代,各种编程语言大行其道,各有各的优势。但是有一点未曾改变,那就是他们服务的方式,工作的时候各司其职,但是需要提供服务的时候必须要高度统一,这也是微服务的概念之一。日常的工作学习中,我个人更喜欢通用的解决方案,特别是能将不同编程语言亦或者不同编程框架整合到一起的那种,这种解决方案拉近了编程语言之间的距离,让开发者能更清楚的意识到编程语言只是工具,解决问题才是王道。好了口遁到此结束,接下来我就搭建一套.Net体系结合Java体系的项目架构。

概念介绍

接下来我们用到的技术栈名词主要涉及到ASP.NET Core、Nacos、Spring Cloud Gateway,接下来我们分别介绍所使用的的三种框架。

Nacos

Nacos是阿里巴巴开源的致力于服务发现、配置和管理微服务的框架。提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。一般用到的最多的就是当做配置中心和注册中心。

  • 中文官网地址:https://nacos.io/zh-cn/

  • 官方GayHub GitHub地址:https://github.com/alibaba/nacos

  • 下载地址:https://github.com/alibaba/nacos/releases下载运行Nacos之前别忘了安装JDK,如何安装JDK请自行百度这里就不再详细介绍了。下载Nacos方式有两种。第一种是直接下载打包好的文件直接运行。第二种是下载源码自己编译,还需要安装maven,相对于第一个稍微复杂一些,我选择的是第一种方式。

ASP.NET Core

ASP.NET Core是微软开源跨平台的Web开发框架,这个作为.Net开发者相信大家已经非常熟悉了,目前最新的正式版本是3.1.5,也是我们本次搭建框架的重头戏,作为业务的真正执行者

  • 中文官网文档地址:https://docs.microsoft.com/en-us/aspnet/core/?view=aspnetcore-3.1

  • 官方GayHub GitHub地址:https://github.com/dotnet/aspnetcore

  • 安装Visual Studio 2019可以直接使用框架进行编程

Spring Cloud Gateway

Spring Cloud Gateway为Spring生态系统上的一个API网关组件,主要提供一种简单而有效的方式路由映射到指定的API,并为他们提供安全性、监控和限流等等。最主要的是可以轻松集成已有的Spring各种全家桶,比如咱们这次使用的Nacos,搭建使用起来非常方便。

  • 官网文档地址:https://spring.io/projects/spring-cloud-gateway/a>

  • 官方GayHub GitHub地址:https://github.com/spring-cloud/spring-cloud-gateway/

  • 我使用的是 IntelliJ IDEA 2019.2,能直接选择模板生成Spring Cloud Gateway项目非常方便

开始搭建

上面大致介绍了相关概念,相信大家也有了大致的了解。口说无凭,直接开干。

运行Nacos

运行启动Nacos,在浏览器输入输入http://localhost:8848/nacos/#会展示出如下界面。
本次我们主要是用Nacos作为注册中心,所以我们只需要关注服务管理模块即可。

搭建ASP.NET Core项目

    ASP.NET Core项目是我们业务接口的真正提供者,这里我搭建两个项目用于模拟订单系统和商品系统。用Visual Studio新建两个Web空项目,分别是OrderApi和ProductApi。OrderApi调用ProductApi属于内部之间调用,不走Gateway。由于我们使用Nacos作为注册中心,所以我们在需要对接到Nacos上。Nacos有一套Open API的接口对接方式(官方文档)[https://nacos.io/zh-cn/docs/open-api.html]有详细的介绍。自己写终究还是比较麻烦的,好在随着NET Core的日渐成熟,已经有大佬为我们实现了一套sdk基本上满足我们的使用非常的方便,GitHub地址为https://github.com/catcherwong/nacos-sdk-csharp别忘了给大佬个Star????????????,将程序包分别引入OrderApi和ProductApi

<PackageReference Include="nacos-sdk-csharp-unofficial.AspNetCore" Version="0.2.6" />

在appsettings.json中配置,本次展示默认使用的OrderApi作为演示,ProductApi配置方式一致,只需更换注册名称即可

"nacos": {"ServerAddresses": [ "localhost:8848" ],//Nacos地址"DefaultTimeOut": 15000,"Namespace": "","ListenInterval": 1000,"ServiceName": "orderservice" //注册到Nacos上的服务名}

Startup中配置如下

public void ConfigureServices(IServiceCollection services)
{//注册Nacos相关服务services.AddNacosAspNetCore(Configuration);services.AddScoped<NacosDiscoveryDelegatingHandler>();services.AddHttpClient(ServiceName.ProductService,client=> {//ServiceName是我为了方便定义的常量类用于承载我们可以使用到的服务名称这里即productserviceclient.BaseAddress = new Uri($"http://{ServiceName.ProductService}");}).AddHttpMessageHandler<NacosDiscoveryDelegatingHandler>();services.AddControllers();
}public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}//添加Nacos相关中间件app.UseNacosAspNetCore();app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});
}

上面我们提到过,OrderApi调用ProductApi属于内部系统间调用,所以我引入了HttpClientFactory。由于我们使用的是Nacos作为注册中心,所以我写了一个NacosDiscoveryDelegatingHandler配合HttpClientFactory,能更优雅的使用注册中心,如果对这种实现方式不熟悉的话可以参考我之前的博文.NET Core HttpClientFactory+Consul实现服务发现实现原理完全一致,具体代码如下

public class NacosDiscoveryDelegatingHandler: DelegatingHandler
{private readonly INacosServerManager _serverManager;private readonly ILogger<NacosDiscoveryDelegatingHandler> _logger;public NacosDiscoveryDelegatingHandler(INacosServerManager serverManager,ILogger<NacosDiscoveryDelegatingHandler> logger){_serverManager = serverManager;}protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken){var current = request.RequestUri;try{//通过nacos sdk获取注册中心服务地址,内置了随机负载均衡算法,所以只返回一条信息var baseUrl = await _serverManager.GetServerAsync(current.Host);request.RequestUri = new Uri($"{baseUrl}{current.PathAndQuery}");return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);}catch (Exception e){_logger?.LogDebug(e, "Exception during SendAsync()");throw;}finally{request.RequestUri = current;}}
}

由于我们需要模拟订单接口,所以我新建了OrderController,大致代码如下

[Route("orderapi/[controller]")]
public class OrderController : ControllerBase
{private List<OrderDto> orderDtos = new List<OrderDto>();private readonly IHttpClientFactory _clientFactory;public OrderController(IHttpClientFactory clientFactory){orderDtos.Add(new OrderDto { Id = 1,TotalMoney=222,Address="北京市",Addressee="me",From="淘宝",SendAddress="武汉" });orderDtos.Add(new OrderDto { Id = 2, TotalMoney = 111, Address = "北京市", Addressee = "yi", From = "京东", SendAddress = "北京" });orderDtos.Add(new OrderDto { Id = 3, TotalMoney = 333, Address = "北京市", Addressee = "yi念之间", From = "天猫", SendAddress = "杭州" });_clientFactory = clientFactory;}[HttpGet("get/{id}")]public OrderDto GetOrder(long id){return orderDtos.FirstOrDefault(i => i.Id == id);}[HttpGet("getdetails/{id}")]public async Task<OrderDto> GetOrderDetailsAsync(long id){OrderDto orderDto = GetOrder(id);if (orderDto != null){OrderDetailDto orderDetailDto = new OrderDetailDto{Id = orderDto.Id,TotalMoney = orderDto.TotalMoney,Address = orderDto.Address,Addressee = orderDto.Addressee,From = orderDto.From,SendAddress = orderDto.SendAddress};//内部调用ProductApi,配合自定义的NacosDiscoveryDelegatingHandler可以更优雅的使用注册中心方式var client = _clientFactory.CreateClient(ServiceName.ProductService);var response = await client.GetAsync($"/productapi/product/getall");var result = await response.Content.ReadAsStringAsync();orderDetailDto.Products = JsonConvert.DeserializeObject<List<OrderProductDto>>(result);return orderDetailDto;}return orderDto;}
}

ProductApi提供新建ProductController用于模拟提供商品信息

[Route("productapi/[controller]")]
public class ProductController : ControllerBase
{private List<ProductDto> productDtos = new List<ProductDto>();public ProductController(){productDtos.Add(new ProductDto { Id = 1,Name="酒精",Price=22.5m });productDtos.Add(new ProductDto { Id = 2, Name = "84消毒液", Price = 19.9m });productDtos.Add(new ProductDto { Id = 3, Name = "医用口罩", Price = 55 });}[HttpGet("get/{id}")]public ProductDto Get(long id){return productDtos.FirstOrDefault(i => i.Id == id);}[HttpGet("getall")]public IEnumerable<ProductDto> GetAll(){return productDtos;}
}

分别启动OrderApi和ProductApi,然后去Nacos上查看,展示如下,说明服务注册成功
我们每个服务只启动了一个实例,每个服务可以启动多个实例,实现高可用和负载均衡。到这里ASP.NET Core相关的代码我们已经搭建完成了,以上只是展示了大致的流程,具体的实现可以去下载Demo查看。

搭建Spring Cloud Gateway

如何搭建Spring Cloud Gateway网上有很多教程,IDEA搭建非常简单,基本上就是起个名字,我们本项目名称就叫apigateway,然后一直点下一步,由于本示例后端的业务系统都是对接到Nacos上的,所以需要在Gateway引入Nacos相关包,在pom.xml引入Nacos

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>2.2.1.RELEASE</version>
</dependency>

然后再启动类上加上@EnableDiscoveryClient注解

@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayApplication {public static void main(String[] args) {SpringApplication.run(ApiGatewayApplication.class, args);}
}

在application.yml中添加服务名称和nacos相关配置

server:#网关启动端口号port: 8080
spring:application:#网关服务名称,也就是注册到Nacos的名称name: apigateway#Nacos相关配置cloud:nacos:discovery:#Nacos服务地址server-addr: localhost:8848gateway:discovery:locator:enabled: truelower-case-service-id: true

启动网关项目apigateway,打开Nacos管理界面,刷新服务列表,如下图所示,说明网关项目注册成功
接下来我们要在网关配置转发相关内容,让apigateway可以转发请求到我们具体的OrderApi和ProductApi。Spring Cloud Gateway默认支持两种配置转发的方式,一种是基于编码的方式,另一种是通过配置的方式。我选用的是基于配置的方式,相对比较灵活一点。在application.yml中添加转发相关配置,如下

server:port: 8080
spring:application:name: apigatewayredis:host: localhostport: 6379database: 0cloud:nacos:discovery:server-addr: localhost:8848gateway:discovery:locator:enabled: truelower-case-service-id: true#转发相关配置gateway:routes:#唯一标识- id: productservice#服务在注册中心的地址uri: lb://productservice#转发匹配,即满足/productapi/相关的路径则转发到productservice相关服务predicates:- Path=/productapi/**- id: orderserviceuri: lb://orderservicepredicates:- Path=/orderapi/**

到这里网关相关的配置差不多先配置这么多,当然网关还需要集成许多核心组件比如限流相关熔断超时相关等等,Spring Cloud Gateway都是可以接入相关组件的比如阿里的Sentinel等等,在这里我们就不做演示了。

测试调用

可以下载本文演示Demo启动Postman进行测试,通过调用网关项目apigateway看看运行效果,首先调用OrderApi接口,OderDetails接口内部调用了ProductApi的接口。如下所示转发成功
然后我们在去调用ProductApi的相关接口,如图所示也是成功的
本文演示Demo下载

总结

    到这里我们的相关示例也就差不多了,能有一套公共的解决方案,使用起来还是非常方便的。这里我只是演示了非常基础的一种模式,就是为了展示技术通用性给我们带来的便利。我个人还是非常喜欢通用的解决方案的,这些方案能让我更关注问题本身,而非某种特定的语言。比如现在容器技术大行其道,我们其实可以忽略原有的许多技术细节,而通过容器平台本身的通用解决方案去解决,在我们使用的时候会非常方便。我也希望更多的开发者,能够关注技术本身或者解决方案本身带给我们的便利,而不是通过有色的眼光去看待这些。能解决的方案终究还是好的方案,它能指导我们的思想,提升我的思维方式,那我们为什么不去接触去学习呢?语言本身固然重要,但是解决问题的思维方式更是不可或缺。废话不多说,本次就到这里,欢迎大家评论区批评指导。

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

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

相关文章

如何在ASP.NET Core中集成ElasticSearch

本文来自&#xff1a;https://www.blexin.com/en-US/Article/Blog/How-to-integrate-ElasticSearch-in-ASPNET-Core-70图片我敢打赌&#xff0c;您肯定会被要求向Web应用程序中添加高级搜索功能&#xff0c;而且通常是全文的类似Google的搜索。在技术电子商务的开发过程中&…

了解下C#由转换二进制所引起的思考

【导读】最近遇到很有意思转换二进制的问题&#xff0c;有部分童鞋俨然已了解&#xff0c;可能也有一部分童鞋没碰到过也就不知情&#xff0c;这里我们来深入学习下转换二进制所带来的问题。在写此篇文章时&#xff0c;非常开心&#xff0c;收到再一次连任MVP的邮件&#xff0c…

如何利用.NETCore向Azure EventHubs准实时批量发送数据?

最近在做一个基于Azure云的物联网分析项目&#xff1a;.netcore采集程序向Azure事件中心(EventHubs)发送数据&#xff0c;通过Azure EventHubs Capture转储到Azure BlogStorage&#xff0c;供数据科学团队分析。为什么使用Azure事件中心&#xff1f;Azure事件中心是一种Azure上…

C++实现二叉树

代码如下: #include<iostream> #include <queue> #include <stack> using namespace std;class BinTree { private:class TreeNode{public:int data;TreeNode *left;TreeNode *right;TreeNode ():data(0),left(nullptr),right(nullptr){}TreeNode(int e):da…

MySql :Could not create connection to database server.

错误&#xff1a; Exception in thread “main” org.apache.ibatis.exceptions.PersistenceException:Error querying database. Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. The error …

Vue 3拖更,尤雨溪介绍最新进展

Vue.js 作者尤雨溪近日介绍了 Vue 3 的最新进展。尤雨溪表示&#xff0c;由于在 Vue 3 上花费的大部分时间都投入到了设计和构建稳定的内核上&#xff0c;不过要让整个框架处于"ready"状态&#xff0c;不仅仅是内核的问题&#xff0c;还需要有兼容版本的支持库 &…

Mysql@和@@符号的详细使用说明

一、概述 是用户变量&#xff0c;是系统变量。 二、使用语法及实践 用户自定义变量 1、用户定义变量语法 SET var_name expr [, var_name expr] 如&#xff1a;set t1 100; 2、获取用户定义变量值方式&#xff0c;如&#xff1a; select t1 from dual; 如下图 系统变…

探讨NET Core数据进行3DES加密或解密弱密钥问题

【导读】之前写过一篇《探讨.NET Core数据进行3DES加密和解密问题》&#xff0c;最近看到有人提出弱密钥问题&#xff0c;换个强密钥不就完了吗&#xff0c;猜测可能是与第三方对接导致很无奈不能更换密钥&#xff0c;所以产生本文解决.NET Core中3DES弱密钥问题&#xff0c;写…

C++实现表达式树

代码如下: #include <iostream> #include <string> #include <stack> #include <queue> using namespace std;class Tree { private:class Node{public:char val;Node * left;Node *right;Node(char val):val(val),left(nullptr),right(nullptr){}Nod…

redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作

前段时间在做用户画像的时候&#xff0c;遇到了这样的一个问题&#xff0c;记录某一个商品的用户购买群&#xff0c;刚好这种需求就可以用到Redis中的Set&#xff0c;key作为productID&#xff0c;value就是具体的customerid集合&#xff0c;后续的话&#xff0c;我就可以通过p…

IDEA如何在包下建立子包

idea如何在包下建立子包 第一次在包下建立子包时候出现了问题 在java > springmvc包下再new上一个package controller的时候就会出现这个样子 如何解决 在IDEA2019 中的Show Options Menu下有一个Compacket Middle Packages将它关闭即可 解决成功

.NET Core微服务开发选项

微服务开发的关注点有哪些&#xff1f;微服务构最终的目标是实现业务的价值&#xff0c;交付&#xff0c;为了让开发人员更加关注业务开发和交付&#xff0c;微服务需要一些比较底层的基础设置&#xff0c;我们也称为微服务公共关注点。配置管理&#xff1a;对微服务可变参数进…

gRPC真要取代WebApi了,你还学得过来吗?

今年1月份微软曾宣布要实验性的对.NET支持 gRPC-Web&#xff0c;然后在6月份已经正式发布了。这些天尝试了下&#xff0c;真的很强大&#xff0c;不负责任的预言下&#xff0c;RESTful的时代即将过去&#xff0c;而gRPC要成为革命者&#xff01;先别急眼&#xff0c;下面我来详…

Spring5 jar包下载

下载地址 https://repo.spring.io/simple/libs-release-local/org/springframework/spring/ Spring5最新版本的下载 选择最新版本5.2.3 下载前两项&#xff0c;解压放入文件夹中 项目中导包 ps&#xff1a;我使用的开发工具是idea 第一步&#xff1a;在file中选择project st…

优化 Azure 成本,实现财务目标

点击上方蓝字关注“汪宇杰博客”原文&#xff1a;Omar Khan General Manager, Microsoft Azure翻译&#xff1a;汪宇杰导语我们的许多客户都面临着如何满足关键 IT 项目的资金需求的困难决策。我们在此共同帮助您实现财务目标。确保 Azure 工作负载的成本得到优化有助于释放资金…

采用config方式灵活配置我们的Quarz.net中的Job,Trigger

经常在项目中遇到定时任务的时候&#xff0c;通常第一个想到的是Timer定时器&#xff0c;但是这玩意功能太弱鸡&#xff0c;实际上通常采用的是专业化的第三方调度框架&#xff0c;比如说Quartz&#xff0c;它具有功能强大和应用的灵活性&#xff0c;我想使用过的人都非常了解&…

对于任给的一张无向带权连通图,求出其最小生成树(C++)

对于任给的一张无向带权连通图&#xff0c;求出其最小生成树。 题目要求: (1)编程创建一幅图 (2)输出创建的图 (3)编写Prim算法代码&#xff0c;实现图的最小生成树求解&#xff0c;且输出最小生成树 (4)编写Kruskal算法代码&#xff0c;实现图的最小生成树求解&#xff0c;且…

使用.Net Core实现的一个图形验证码

SimpleCaptcha是一个使用简单&#xff0c;基于.Net Standard 2.0的图形验证码模块。它的灵感来源于Edi.Wang的这篇文章https://edi.wang/post/2018/10/13/generate-captcha-code-aspnet-core&#xff0c;我将其中生成验证码的代码抽取出来进行封装得到了这个模块。下面介绍一下…

Maven编译项目时报错:不再支持源选项 5。请使用 6 或更高版本。 不再支持目标选项 1.5。请使用 1.6 或更高版本。

在使用Maven编译项目时报错&#xff1a; 不再支持源选项 5。请使用 6 或更高版本。 不再支持目标选项 1.5。请使用 1.6 或更高版本。 在项目pom.xml文件中增加maven编译的jdk版本设置&#xff0c;maven.compiler.source和maven.compiler.target&#xff1a; <properties&…