Использование python для реализации GraphQL на нескольких микросервисах, некоторые используют Ariadne, а некоторые используют графен (и графен-Django).Из-за архитектуры микросервиса было выбрано, что Федерация Аполлона будет объединять схемы из разных микросервисов.
С 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}`);
});
})();
, для которого я могу запускать запросы graphql к серверу на 3000
.
Но, используя графен,Попытка реализовать ту же функциональность, что и у Ариадны:
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:
GraphQLSchemaValidationError: Тип Query должен определять одно или несколько полей.
Когда я проверил это, я обнаружил, что 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
}
и на микросервисе с графеном:
{
"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')]))])
Так что может быть причиной того, что Федерация Аполлона не смоглауспешно получить эту микросервисную схему?