python-3.x - 将 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 无法成功获得这个微服务模式的原因是什么?
解决方案
这个 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
推荐阅读
- python - 如何传递 tk.StringVar 变量并将它们插入到 sqlite 数据库表中?
- ruby-on-rails - 根据 Zeitwerk 的要求重命名工人(Rails 5.2.3 到 6 升级)
- css - svg中的css动画变量
- javascript - 使用 Squarespace 的交叉观察者导航
- gitlab - 从 Gitlab 中的数据库(SQL 和 repo 文件夹)中删除存储库?
- bash - 使用 bash 批量替换文件中的特定行
- python - 如何在 Faster RCNN 中实现 RPN 进行目标检测?
- reactjs - 需要更改时的只读状态
- next.js - .woff 和 .woff2 版本都加载到现场版本的站点上,而不是本地主机上
- c# - 消耗过滤器如何与操作选择一起使用?