首页 > 解决方案 > 将 Python 石墨烯与 Apollo Federation 集成的问题

问题描述

使用 python 跨多个微服务实现 GraphQL,有的使用 Ariadne,有的使用 graphene(和 graphene-Django)。由于微服务架构,选择 Apollo Federation 合并来自不同微服务的模式。

使用 Ariadne,它非常简单(首先是模式),还有一个小例子:

from ariadne import QueryType, gql, make_executable_schema, MutationType, ObjectType
from ariadne.asgi import GraphQL

query = QueryType()
mutation = MutationType()

sdl = """
type _Service {
    sdl: String
}

type Query {
    _service: _Service!
    hello: String
}
"""

@query.field("hello")
async def resolve_hello(_, info):
    return "Hello"


@query.field("_service")
def resolve__service(_, info):
    return {
        "sdl": sdl
    }

schema = make_executable_schema(gql(sdl), query)
app = GraphQL(schema, debug=True)

现在,阿波罗联邦可以毫无问题地接受这一点:

const { ApolloServer } = require("apollo-server");
const { ApolloGateway } = require("@apollo/gateway");


const gateway = new ApolloGateway({
    serviceList: [
      // { name: 'msone', url: 'http://192.168.2.222:9091' },
      { name: 'mstwo', url: 'http://192.168.2.222:9092/graphql/' },
    ]
  });

  (async () => {
    const { schema, executor } = await gateway.load();
    const server = new ApolloServer({ schema, executor });
    // server.listen();
    server.listen(
      3000, "0.0.0.0"
      ).then(({ url }) => {
      console.log(` Server ready at ${url}`);
    });
  })();

为此,我可以在3000.

但是,通过使用石墨烯,尝试实现与 Ariadne 相同的功能:

import graphene

class _Service(graphene.ObjectType):
    sdl = graphene.String()

class Query(graphene.ObjectType):

    service = graphene.Field(_Service, name="_service")
    hello = graphene.String()

    def resolve_hello(self, info, **kwargs):
        return "Hello world!"

    def resolve_service(self, info, **kwargs):
        from config.settings.shared import get_loaded_sdl
        res = get_loaded_sdl()  # gets the schema defined later in this file
        return _Service(sdl=res)

schema = graphene.Schema(query=Query)

# urls.py
urlpatterns = [
    url(r'^graphql/$', GraphQLView.as_view(graphiql=True)),
]

,... 现在导致来自 Apollo Federation 的错误:

GraphQLSchemaValidationError:类型查询必须定义一个或多个字段。

当我检查这件事时,我发现 apollo 使用以下 graphql 查询调用微服务:

query GetServiceDefinition { _service { sdl } }

通过 Insomnia/Postman/GraphiQL 和 Ariadne 在微服务上运行它可以得到:

{
  "data": {
    "_service": {
      "sdl": "\n\ntype _Service {\n    sdl: String\n}\n\ntype Query {\n    _service: _Service!\n    hello: String\n}\n"
    }
  }
}

# Which expanding the `sdl` part:
type _Service {
    sdl: String
}

type Query {
    _service: _Service!
    hello: String
}

在使用 Graphene 的微服务上:

{
  "data": {
    "_service": {
      "sdl": "schema {\n  query: Query\n}\n\ntype Query {\n  _service: _Service\n  hello: String\n}\n\ntype _Service {\n  sdl: String\n}\n"
    }
  }
}

# Which expanding the `sdl` part:
schema {
    query: Query
}

type Query {
    _service: _Service
    hello: String
}

type _Service {
    sdl: String
}

因此,它们对于定义如何获取都是相同的sdl,我检查了微服务响应,发现石墨烯响应也在发送正确的数据,Json 响应“数据”等于:

execution_Result:  OrderedDict([('_service', OrderedDict([('sdl', 'schema {\n  query: Query\n}\n\ntype Query {\n  _service: _Service\n  hello: String\n}\n\ntype _Service {\n  sdl: String\n}\n')]))])

那么 Apollo Federation 无法成功获得这个微服务模式的原因是什么?

标签: python-3.xgraphqlmicroservicesapolloapollo-server

解决方案


这个 pip 库可以帮助https://pypi.org/project/graphene-federation/

只需使用build_schema,它就会为您添加 _service{sdl} :

import graphene
from graphene_federation import build_schema


class Query(graphene.ObjectType):
    ...
    pass

schema = build_schema(Query)  # add _service{sdl} field in Query

推荐阅读