Python 3.x Python石墨烯与阿波罗联盟的集成问题
使用python跨多个微服务实现GraphQL,有些使用Ariadne,有些使用graphene(和graphene Django)。由于微服务体系结构,阿波罗联合会将合并来自不同微服务的模式 对于Ariadne,它非常简单(首先是模式),下面是一个小示例:Python 3.x Python石墨烯与阿波罗联盟的集成问题,python-3.x,graphql,microservices,apollo,apollo-server,Python 3.x,Graphql,Microservices,Apollo,Apollo Server,使用python跨多个微服务实现GraphQL,有些使用Ariadne,有些使用graphene(和graphene Django)。由于微服务体系结构,阿波罗联合会将合并来自不同微服务的模式 对于Ariadne,它非常简单(首先是模式),下面是一个小示例: 从ariadne导入QueryType、gql、make_executable_schema、MutationType、ObjectType 从ariadne.asgi导入图形ql query=QueryType() 突变=突变类型() s
从ariadne导入QueryType、gql、make_executable_schema、MutationType、ObjectType
从ariadne.asgi导入图形ql
query=QueryType()
突变=突变类型()
sdl=”“”
类型服务{
sdl:字符串
}
类型查询{
_服务:_服务!
你好:字符串
}
"""
@query.field(“hello”)
异步定义解析\u你好(\u,信息):
回复“你好”
@查询字段(“\u服务”)
def解析服务(信息):
返回{
“sdl”:sdl
}
schema=make_executable_schema(gql(sdl),查询)
app=GraphQL(模式,调试=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(`The solution is actually a slight hack the schema that is automatically generated via graphene
. I thought I had tried this already and it still worked, but I just did it again now but it broke.
So if in Ariadne, I add
schema {
query: Query
}
const{ApolloServer}=require(“阿波罗服务器”);
const{apollo gateway}=require(“@apollo/gateway”);
const gateway=新网关({
服务列表:[
//{name:'msone',url:'http://192.168.2.222:9091' },
{name:'mstwo',url:'http://192.168.2.222:9092/graphql/' },
]
});
(异步()=>{
const{schema,executor}=wait gateway.load();
const server=new服务器({schema,executor});
//server.listen();
服务器,听(
3000, "0.0.0.0"
)。然后({url})=>{
log(`这个解决方案实际上是对通过graphene
自动生成的模式进行了一点小小的修改。我以为我已经尝试过了,它仍然有效,但我现在又做了一次,但是它坏了
所以如果在阿里阿德涅,我补充说
def resolve_service(self, info, **kwargs):
from config.settings.shared import get_loaded_sdl
res = get_loaded_sdl()
res = res.replace("schema {\n query: Query\n}\n\n", "")
return _Service(sdl=res)
Apollo Federation在sdl
中还提出了类型查询必须定义一个或多个字段。
。没有它,它可以正常工作。因此,我也转到了graphene,并在解析服务中执行了以下操作:
schema {
query: Query
}
现在石墨烯也可以工作了,所以我想问题是我忽略了,阿波罗联盟似乎无法处理以下的模式语法:
GraphQLSchemaValidationError: Field "_Service.sdl" can only be defined once.
更新1
我在阿波罗的网站上没有注意到一句话:
此SDL不包括上述联合规范的新增内容。给定如下输入:
在联合中将服务组合在一起时,这一点很明显,因为这将引发错误:
schema = ""
class ServiceField(graphene.ObjectType):
sdl = String()
def resolve_sdl(parent, _):
string_schema = str(schema)
string_schema = string_schema.replace("\n", " ")
string_schema = string_schema.replace("type Query", "extend type Query")
string_schema = string_schema.replace("schema { query: Query mutation: MutationQuery }", "")
return string_schema
class Service:
_service = graphene.Field(ServiceField, name="_service", resolver=lambda x, _: {})
class Query(
# ...
Service,
graphene.ObjectType,
):
pass
schema = graphene.Schema(query=Query, types=CUSTOM_ATTRIBUTES_TYPES)
因此,尽管在带有define\u Service.sdl
的微服务的完整模式中,我们希望完整模式的字符串中没有该信息,该字符串作为\u Service.sdl
的返回字符串返回
更新2
阿波罗联盟现在工作正常,确保sdl
字段返回的字符串不包含联盟规范
在graphene中,我认为每个实现可能有所不同,但通常您希望替换以下内容:
res=get\u loaded\u sdl()
res=res.replace(“模式{\n查询:查询\n}\n\n”,“”)
res=res.replace(“类型_服务{\n sdl:String\n}”,”)
res=res.replace(“\n\u服务:\u服务!”,”)
在Ariadne中,只需要定义两个sdl,一个包含联合规范(用于服务返回的模式),另一个不包含联合规范(由sdl
字段返回的)你在另一个答案上走的很好,但是看起来你需要从印刷版上去掉一些东西
这是我在工作中使用的方法
我在这里总结我的代码:
import graphene
from graphene_federation import build_schema
class Query(graphene.ObjectType):
...
pass
schema = build_schema(Query) # add _service{sdl} field in Query
这个pip库可以提供帮助
只需使用build_schema
,它将为您添加_服务{sdl}:
interface x implements y, z {
...
}
如果有人想知道,这是因为graphene v2在接口中使用逗号而不是符号
import re
from myproject import Query, Mutation
from graphene_federation import service, build_schema
# monkey patch old get_sdl
old_get_sdl = service.get_sdl
def get_sdl(schema, custom_entities):
string_schema = old_get_sdl(schema, custom_entities)
string_schema = string_schema.replace('\n', ' ')
pattern_types_interfaces = r'type [A-Za-z]* implements ([A-Za-z]+\s*,?\s*)+'
pattern = re.compile(pattern_types_interfaces)
string_schema = pattern.sub(lambda matchObj: matchObj.group().replace(',', ' &'), string_schema)
return string_schema
service.get_sdl = get_sdl
schema = build_schema(Query, mutation=Mutation)
这种语法已经不起作用了,一种解决方法是使用monkey patch获取_sdl
联邦服务需要实现。在Apollo中,这是通过使用buildFederatedSchema
函数来实现的。我不确定graphene。据我所知,在成功实现Ariadne之后,联邦服务需要在模式中有一个\u service
字段,即ype\u Service
,它有一个字段sdl
,whcih以字符串形式返回整个架构。这很奇怪,因为这只是重复,基本上在架构中有一个字段,返回所述架构。您是正确的,graphene本机不支持这一点,但几乎每个后端都不支持utilize graphql,像Ariadne一样,我们只是定义了他们的文档所说的需要。替换(“类型查询”,“扩展类型查询”)
是否存在缺陷?在这个替换之后,当您扩展现在不存在的东西(查询
)时,模式如何有效?当我开始工作的时候,我也会尝试一下。所以我刚刚尝试了你的解决方案,但仍然失败,因为联邦认为sdl
属于ServiceField
类型,应该是\u Service
。我在更新1
中的回答中还声明,从sdl
返回的sdl不包含联邦元素,我现在将添加update2
,以更清楚地记录这一点。您应该能够定义SerficeField的名称,对我来说没有问题。您实际上不需要替换扩展查询,它对我和我都有效。您需要的唯一联邦元素是端点及其类型,您不需要定义查询如果你看一下我在这篇评论中链接的完整实现,你会发现这一切都是可行的:)这很好,但对我来说仍然不起作用,我会接受我自己的答案,因为它确实解决了问题。