GraphQl usług 网关模式

Posted

技术标签:

【中文标题】GraphQl usług 网关模式【英文标题】:GraphQl usług Gateway pattern 【发布时间】:2019-06-16 18:56:27 【问题描述】:

1) EAA 目录中的网关模式 使用网关模式隐藏了“业务微服务”的复杂性。该组件负责根据配置将请求正确重定向到适当的服务。前端应用程序只能与该组件通信。

链接: https://martinfowler.com/eaaCatalog/gateway.html

我想知道GraphQl 如何处理这种模式? 如果每个微服务都有一个GraphQl 端点,我们如何实现这种模式?

回复答案 - 编辑:

在我的项目中,有架构,然后有网关,zuul 将其发送给另一个(它通过URL 从请求中知道)。 GraphQl 是一个端点,所以 zuul 不会工作。 所以我们只有两个步骤(总是 - 可以在 zipkin 中检查),例如:

Gateway microservice -> Microservice X

关于:

也许你实现了另一个 GraphQL API 来整合这些 微服务的 GraphQL API

这就是我的想法。 在我的项目中,只有API gateway 可用于internet。 但在这种情况下,我想知道我们是否得到了这样的查询,5 queries 到微服务 A 和 3 queries 到微服务 B 我如何在这个微服务网关中传递它们 - 我不想削减它一块一块地发送,所以我会从它向微服务 B 发送一个一个(总计 3 个)查询 - 但一次发送 3 个。 微服务 A 也是如此 -> 我想一次性从 graphQL 发送。

如果我只使用这些:

    <dependency>
        <groupId>com.graphql-java</groupId>
        <artifactId>graphql-spring-boot-starter</artifactId>
        <version>5.0.2</version>
    </dependency>
    <dependency>
        <groupId>com.graphql-java</groupId>
        <artifactId>graphiql-spring-boot-starter</artifactId>
        <version>4.0.0</version> <!--5.0.2 http://localhost:8999/graphiql fails to load-->
    </dependency>

然后在microservice X 我得到了架构和一些查询,例如:

type Query 
    getAllItems: [TestEntity]
    getDataTypes: [DictionaryType]
    (...)

在控制器中我有:

private DataFetcher<List<TestEntity>> allDictionaryItemsFetcher;
private DataFetcher<Set<DictionaryType>> dictionaryTypeFetcher;

@Value("classpath:test.graphqls")
private Resource schemaResource;
private GraphQL graphQL;
(...)
        allDictionaryItemsFetcher = dataFetchingEnvironment -> dictionaryService.getAllDictionaryItemsAsStrings();
        dictionaryTypeFetcher = dataFetchingEnvironment -> dictionaryService.getDictionaryTypes();


@PostConstruct
private void loadSchema() throws IOException 
    File schemaFile = schemaResource.getFile();
    TypeDefinitionRegistry registry = new SchemaParser().parse(schemaFile);
    RuntimeWiring wiring = buildWiring();
    GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(registry, wiring);
    graphQL = GraphQL.newGraphQL(schema).build();


private RuntimeWiring buildWiring() 
    return RuntimeWiring.newRuntimeWiring()
            .type("Query", typeWriting -> typeWriting
                    .dataFetcher("getAllItems", allDictionaryItemsFetcher)
                    .dataFetcher("getDataTypes", dictionaryTypeFetcher)

            )
            .build();

如果我们使Gateway microservice 具有与GraphQl 相同的依赖关系,我们将在schema 中拥有:

type Query 
    getAllItems: [TestEntity] # from microservice A
    getDataTypes: [DictionaryType] # from microservice A
    (...) # Other from microservice A,B,C,(...)

如果用户发送one requestMicroserivce A 获取我getAllItemsgetDataTypes 并从microservice B 获取Z resources 我如何发送两个查询: 首先用getAllItemsgetDataTypesMicroservice A 第二个 Zmicroservice B 请求?

我怎样才能以这种方式分隔GraphQL 请求?

我不想一一发送请求 - 例如,当我得到: 让我 getAllItemsgetDataTypesMicroserivce A 我不想拨打两次Microservice A 一次: getAllItems 第二次使用getDataTypes

我怎样才能轻松地仅通过microservice 分隔查询?

例如制作多个schemas(每个microservice) inGraphQL gatewayandconfiguringone endpoint with manyschemas` - 有可能吗?或者其他解决方法?

也许这是我对GraphQL 的误解,但我认为在上面的case 中,我们必须在microservice 中为java 配置一个GraphQl

我不希望GraphQL gateway 使用经典的REST api(不是GraphQL)射向microservice X,因为我们以这种方式丢失了许多东西,例如fetching optimization,请参见此处: https://youtu.be/1zIHHi2MaQE?t=1369 或者发出N 请求而不是one 到具体的microservice X

【问题讨论】:

【参考方案1】:

基本上是指以下架构。 GraphQL API 是位于不同 API 前面的网关,例如旧版 Soap API、REST 微服务 API、3rd-partly API、数据库或 blalablab。

图片来自this

该组件负责正确重定向请求 到基于配置的适当服务。

GraphQL 类型/查询/突变的每个字段都有自己的解析器函数,它们定义了自己的逻辑以从不同的后端服务获取值。因此,GraphQL 类型系统及其解析器函数是一种配置,定义了如何请求重定向到适当的服务以获取数据。

EAA 目录中的网关模式 微服务”是通过使用网关模式隐藏的。前端 应用程序只能与该组件通信。

在添加 GraphQL API 之前,让数据显示在 UI 中。用户可以先调用FooService获取一部分数据,然后基于一些FooService数据,他必须调用BarService获取另一部分数据。然后基于一些BarService 数据,他必须调用BazService 来获取另一个数据。然后基于一些BazService,他不得不blablabla........这是一个非常繁琐和麻烦的过程。更不用说不同的 API 使用不同的名称来表示相同的业务概念。

添加 GraphQL API 后,我们将这些麻烦的工作转移到 GraphQL API 中。用户只需要直接与 GraphQL API 通信(所以它是一个网关)。他们只需调用一个 API 即可获得他们想要的数据,而不是调用许多 API。

此外,GraphQL 将在不同服务中具有不同名称和解释的业务概念整合到一个 API 中。所以从用户的角度来看,它隐藏了“业务微服务”的复杂性,因为它更易于使用开发

如果我们每个节点都有一个 GraphQl 端点,我们如何实现这种模式 微服务?

也许你实现了另一个 GraphQL API 来整合这些微服务的 GraphQL API

【讨论】:

我已经更新了这个问题 - 我也想到了Maybe you implement another GraphQL API that consolidate these microservices 's GraphQL API,但我在这里担心。 如果我写的不够清楚,请在评论中问我。通过GraphQL gateway(仅在互联网上可用)-> 其他microservicesGraphQL,我们可以轻松地削减schemaGraphQL gateway 组件中可用的内容。如果我们有很多产品/内部queries 等,这会很有帮助

以上是关于GraphQl usług 网关模式的主要内容,如果未能解决你的问题,请参考以下文章

模式拼接两个远程 Prisma/GraphQL 模式

Apollo 联合网关背后的 Hasura GraphQL 端点

模式缝合的graphql微服务约定之间的通信

GraphQL 和 Zuul:Graphql 将作为一个休息端点工作,zuul 作为 api 网关

GraphQL 通过公共网关服务订阅内部服务

使用 Amazon api 网关用 REST API 包装 graphQL(appsync)