欢迎访问张朋的技术分享社区
当前位置: 首页 > 技术分享  > NET.Core

.NET Core微服务之基于Ocelot实现API网关服务

2018/11/16 9:57:07 人评论

一、啥是API网关?API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口。这样就可以明显的简化客户端实现和微服务应用程序之间的沟通方式。以前的话,客户端不得不去请求微服务A(假设为Customers),然后再到微服务B(假设为Orders),然…

一、啥是API网关?

381412-20180611222135221-64112379.png

API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口。这样就可以明显的简化客户端实现和微服务应用程序之间的沟通方式。以前的话,客户端不得不去请求微服务A(假设为Customers),然后再到微服务B(假设为Orders),然后是微服务C(假设为Invoices)。客户端需要去知道怎么去一起来消费这三个不同的service。使用API网关,我们可以抽象所有这些复杂性,并创建客户端们可以使用的优化后的端点,并向那些模块们发出请求。API网关的核心要点是:所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能(比如验证、鉴权、监控等等)。

二、开源项目:Ocelot

Ocelot是一个使用.NET Core平台上的一个API Gateway,这个项目的目标是在.NET上面运行微服务架构。Ocelot框架内部集成了IdentityServer(身份验证)和Consul(服务注册发现),还引入了Polly来处理进行故障处理。目前,腾讯和微软是Ocelot在官网贴出来的客户  Ocelot github : https://github.com/TomPallister/Ocelot

三、快速开始第一个API网关

3.1 首先,新建一个基于.net core的webapi项目 安装Ocelot:NuGet>Install-Package Ocelot

3.2 快速准备两个API服务

(1)准备一个ClientService

创建一个ASP.NET Core WebAPI程序,保留默认ValuesController,做一下修改:

[Route("api/[controller]")]

    public class ValuesController : Controller

    {

        // GET api/values

        [HttpGet]

        public IEnumerable<string> Get()

        {

            return new string[] { "ClinetService-value1", "ClinetService-value2" };

        }

    }

(2)准备一个ProductService

创建一个ASP.NET Core WebAPI程序,保留默认ValuesController,做一下修改:

[Route("api/[controller]")]

    public class ValuesController : Controller

    {

        // GET api/values

        [HttpGet]

        public IEnumerable<string> Get()

        {

            return new string[] { "ProductService-value1", "ProductService-value2" };

        }

    }

3.3 静态配置两个API服务

创建一个ASP.NET Core WebAPI程序,这里命名为APIGateway.

  (1)新建一个json文件:eg.configuration.json

  首先,一个最基本的配置文件如下:

{

    "ReRoutes": [],

    "GlobalConfiguration": {

        "BaseUrl": "https://api.mybusiness.com" //也就是IIS绑定的域名

    }

}

下面我们根据模板将刚刚创建并启动的两个Service的信息进行了配置:

{

  "ReRoutes": [

    // API:CAS.ClientService

    {

      "DownstreamPathTemplate": "/api/{url}",

      "DownstreamScheme": "http",

      "DownstreamHostAndPorts": [

        {

          "Host": "192.168.2.231",

          "Port": "8810"

        }

      ],

      "UpstreamPathTemplate": "/ClientService/{url}",

      "UpstreamHttpMethod": [ "Get", "Post" ]

    },

    // API:CAS.ProductService

    {

      "DownstreamPathTemplate": "/api/{url}",

      "DownstreamScheme": "http",

      "DownstreamHostAndPorts": [

        {

          "Host": "192.168.2.231",

          "Port": "8820"

        }

      ],

      "UpstreamPathTemplate": "/ProductService/{url}",

      "UpstreamHttpMethod": [ "Get", "Post" ]

    }

  ]

}

其中,我们得了解一下微服务架构中的上游服务器和下游服务器,一般下游服务器指的是提供API服务的REST Service Server(比如WebAPI、WCF App等),而上游服务器则指的是提供Web网页服务的Web Server(比如MVC Application,可能需要访问REST Service)。那么,这里我们可以了解到:

Downstream 是下游服务配置 => 即我们刚刚创建的提供API服务的配置,我们会指定PathTemplate,Host和Port等信息(具体调哪一台服务器是由我说了算)

UpStream 是上游服务配置 => 即服务消费方(eg.MVC Server, SPA App)的调用配置(你要怎么按照什么URL格式和什么HTTP类型调用我才能理解)

  通过配置文件,我们可以猜测Ocelot的实现原理大致应该就是把客户端对网关的请求(Request),按照configuration.json的映射配置,转发给对应的后端http service,然后从后端http service获取响应(Response)后,再返回给客户端。当然,具体细节应该十分复杂,等后面有时间深入看看实现机制。

  其他不再解释,可以看明白,另外,需要对这个配置文件进行以下设置:为了确保直接运行时能够找到这个configuration.json文件

381412-20180611230141300-165993363.png

通过配置文件可以完成对Ocelot的功能配置:路由、服务聚合、服务发现、认证、鉴权、限流、熔断、缓存、Header头传递等。在配置文件中包含两个根节点:ReRoutes和GlobalConfiguration。ReRoutes是一个数组,其中的每一个元素代表了一个路由,我们可以针对每一个路由进行以上功能配置。

  (2)改写Program和StartUp类,才能正常使用Ocelot

  ①在Program类的BuildWebHost中让程序读取configuration.json文件

public class Program

    {

        public static void Main(string[] args)

        {

            BuildWebHost(args).Run();

        }

        public static IWebHost BuildWebHost(string[] args)

        {

            return WebHost.CreateDefaultBuilder(args)

                            .UseStartup<Startup>()

                            .UseUrls($"http://{IP}:{Port}")

                            .ConfigureAppConfiguration((hostingContext, builder) =>

                            {

                                builder.AddJsonFile("configuration.json", false, true);

                            })

                            .Build();

        }

    }

②在StartUp类中为Ocelot注入配置,并启动Ocelot

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)

        {

            //services.AddMvc(); -- no need MVC

            // Ocelot

            services.AddOcelot(Configuration);

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }

            //app.UseMvc(); -- no need MVC

            // Ocelot

            app.UseOcelot().Wait();

        }

    }

3.3 测试一下

(1)先启动ClientService和ProductService => 也可以通过在VS中更改启动顺序来指定

381412-20180611231053296-664307984.png

(2)再启动APIGateway,在浏览器中直接访问API网关所在的地址和端口(这里是192.168.2.231:8800)进行测试:先请求ClientService,再请求ProductService,可以看到API网关对请求进行了转发,服务消费方不需要记住每个service所在的IP和端口,而是只需要告诉网关我需要消费哪个service即可。

381412-20180611231300396-1988195773.png

381412-20180611231401313-974467784.png

.

tip:这里配置的PathTemplate大小写不敏感,可以选择通过设置ReRouteIsCaseSensitive:true来实现大小写敏感

  到这里,第一个API网关的实现就结束了,但是对于众多的微服务,如果我们都一一硬编码地配置其IP和Port在配置文件中,不适合微服务架构的风格,因为众多的服务地址变化会让静态配置的工作变得越来越大。因此,我们学习了服务发现,那么是否可以结合服务发现呢?Ocelot + Consul的方式为我们给出了答案。


附件下载

相关技术

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?