Skip to content

整合多个 .NET Core 微服务的 Swagger 到 Spring Cloud Zuul

🏷️ Swagger .NET Core Zuul

微服务架构下使用 Spring Cloud Zuul 作为网关将多个微服务整合到一个 Swagger 服务上 讲了如何整合多个服务的 Swagger 到 Zuul 网关上。

例子上的服务是 SpringBoot 的,而我现在的项目中多数是 .NET Core 的微服务。.NET Core 的 Swagger UI 使用的是 Swashbuckle.AspNetCore 3.0.0

Zuul 上的配置同上面的文章基本相同,主要是在 .NET Core 服务上需要一些设置。

  1. Zuul 上的 Swagger 配置 SwaggerDocumentConfig.java

    另外不要忘记在启动类上加 @EnableSwagger2 注解。

    java
    package com.octopus.middle.zuul.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.stereotype.Component;
    import springfox.documentation.swagger.web.SwaggerResource;
    import springfox.documentation.swagger.web.SwaggerResourcesProvider;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @Component
    @Primary
    public class SwaggerDocumentConfig implements SwaggerResourcesProvider {
        @Override
        public List<SwaggerResource> get() {
            List resources = new ArrayList<>();
            resources.add(swaggerResource("A 服务", "/api/a/swagger/v1/swagger.json", "1.0"));
            resources.add(swaggerResource("B 服务", "/api/b/swagger/v1/swagger.json", "1.0"));
            // ...
            return resources;
        }
    
        private SwaggerResource swaggerResource(String name, String location, String version) {
            SwaggerResource swaggerResource = new SwaggerResource();
            swaggerResource.setName(name);
            swaggerResource.setLocation(location);
            swaggerResource.setSwaggerVersion(version);
            return swaggerResource;
        }
    }
  2. Zuul 的配置 bootstrap.yml

    这里服务没有使用统一的前缀,而且每个服务的 strip-prefix 配置也是 false(即转发请求到服务时不删除 path 前缀)。
    正是这个配置导致了 .NET Core 服务的一系列默认属性都要修改。
    这个配置之所以为 false 也是由于项目历史原因导致的。推荐搭建框架时还是最好保持默认值 true

    yaml
    zuul:
        # prefix: /api #为 zuul 设置一个公共的前缀
        routes:
            order:
                path: /api/a/**
                strip-prefix: false
                service-id: SERVICE-A
            product:
                path: /api/b/**
                strip-prefix: false
                service-id: SERVICE-B
  3. .NET Core 微服务的 Startup.cs

    通过 services.AddSwaggerGen 方法指定资源文件的位置。

    通过 app.UseSwagger 指定生成的 swagger.json 文件的路径。该路径默认值为 swagger/{documentName}/swagger.json
    因为 Zuul 中 strip-prefix 配置为 false,所以转发过来的请求 URL 是带 /api/a 这样的前缀的,如果不修改 swagger.json 文件的地址,会导致无法通过 Zuul 访问该文件。
    如果 strip-prefix 配置为 true 应该就没有这种问题了。

    通过 app.UseSwaggerUI 方法指定路由前缀和 swagger.json 文件地址也是同样的原因。

    csharp
    /// <summary>
    /// This method gets called by the runtime. Use this method to add services to the container.
    /// </summary>
    /// <param name="services"></param>
    public void ConfigureServices(IServiceCollection services)
    {
        //配置 swagger
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc(version, new Info
            {
                Version = "v1",
                Title = "A 服务接口文档",
                Description = "RESTful API",
                TermsOfService = "None"
            });
            c.CustomSchemaIds(x => x.FullName);
            var basePath = PlatformServices.Default.Application.ApplicationBasePath;
            var xmlPath = Path.Combine(basePath, "ServicesA.xml");
            c.IncludeXmlComments(xmlPath);
        });
        //配置服务发现
        services.AddDiscoveryClient(Configuration);
        //配置 MVC
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }
    
    /// <summary>
    /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    /// </summary>
    /// <param name="app"></param>
    /// <param name="env"></param>
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMvc();
    
        //使用 Swagger
        app.UseSwagger(o => {
            o.RouteTemplate = "api/a/swagger/{documentName}/swagger.json";
        });
        app.UseSwaggerUI(c =>
        {
            c.RoutePrefix = "api/a/swagger";
            c.SwaggerEndpoint("v1/swagger.json", "ServicesA");
            c.DocExpansion(DocExpansion.None);
            c.DefaultModelsExpandDepth(-1);
        });
    
        //使用服务发现
        app.UseDiscoveryClient();
    }
  4. 依次启动 服务注册中心(这里使用的是 Eureka)、Zuul 网关 和 微服务后,打开 Zuul 的 Swagger UI 地址,右上角的下拉框中就会显示所有的服务,选择一个服务页面则显示对应服务的 API 文档。