整合多个 .NET Core 微服务的 Swagger 到 Spring Cloud Zuul
在 微服务架构下使用 Spring Cloud Zuul 作为网关将多个微服务整合到一个 Swagger 服务上 讲了如何整合多个服务的 Swagger 到 Zuul 网关上。
例子上的服务是 SpringBoot 的,而我现在的项目中多数是 .NET Core 的微服务。.NET Core 的 Swagger UI 使用的是 Swashbuckle.AspNetCore 3.0.0 。
Zuul 上的配置同上面的文章基本相同,主要是在 .NET Core 服务上需要一些设置。
Zuul 上的 Swagger 配置 SwaggerDocumentConfig.java
另外不要忘记在启动类上加
@EnableSwagger2
注解。javapackage 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; } }
Zuul 的配置 bootstrap.yml
这里服务没有使用统一的前缀,而且每个服务的
strip-prefix
配置也是false
(即转发请求到服务时不删除path
前缀)。
正是这个配置导致了 .NET Core 服务的一系列默认属性都要修改。
这个配置之所以为false
也是由于项目历史原因导致的。推荐搭建框架时还是最好保持默认值true
。yamlzuul: # 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
.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(); }
依次启动 服务注册中心(这里使用的是 Eureka)、Zuul 网关 和 微服务后,打开 Zuul 的 Swagger UI 地址,右上角的下拉框中就会显示所有的服务,选择一个服务页面则显示对应服务的 API 文档。