【问题标题】:How do you make Schema Stitching in Apollo Server faster?如何让 Apollo Server 中的 Schema Stitching 更快?
【发布时间】:2018-12-20 20:17:32
【问题描述】:

最初,我尝试使用无服务器 Lambda 函数来处理我的 API 的架构拼接,但我开始转向 Elastic Beanstalk 服务器,以避免需要获取每个请求的初始架构。

即便如此,对我的主 API 服务器的请求从其中一个子 API 服务器获取结果的时间可能是我的子服务器的十倍。我不确定是什么让请求如此长,但似乎有什么东西阻止了请求的快速解决。

这是我的父 API 代码:

import * as express from 'express';

import { introspectSchema, makeRemoteExecutableSchema, mergeSchemas } from 'graphql-tools';

import { ApolloServer } from 'apollo-server-express';
import { HttpLink } from 'apollo-link-http';
import fetch from 'node-fetch';

async function run () {

    const createRemoteSchema = async (uri: string) => {
        const link = new HttpLink({ uri, fetch });

        const schema = await introspectSchema(link);

        return makeRemoteExecutableSchema({
            schema,
            link
        });
    };

    const remoteSchema = await createRemoteSchema(process.env.REMOTE_URL);

    const schema = mergeSchemas({
        schemas: [remoteSchema]
    });

    const app = express();

    const server = new ApolloServer({
        schema,
        tracing: true,
        cacheControl: true,
        engine: false
    });

    server.applyMiddleware({ app });

    app.listen({ port: 3006 });
};

run();

知道为什么这么慢吗?

更新:

对于任何试图在本地环境中拼接模式的人,我通过直接获取 127.0.0.1 而不是通过 localhost 获得了显着的速度提升。

http://localhost:3002/graphql > http://127.0.0.1:3002/graphql

这对我来说根本不是阿波罗的问题。

【问题讨论】:

  • 在我的测试中,最大的时间消耗是 makeRemoteExecutableSchema,在我的 8 核机器上使用本地模式文件需要 400-600 毫秒。

标签: graphql apollo graphql-js apollo-server


【解决方案1】:

我建议使用 Apollo 引擎来观察每个请求的实际情况,如下图所示:

您可以将其添加到您的 Apollo 服务器配置中

engine: {
    apiKey: "service:xxxxxx-xxxx:XXXXXXXXXXX"
},

此外,在缓存控件上定义 defaultMaxAge 时,我体验到了更好的性能:

cacheControl: {
    defaultMaxAge: 300, // 5 min
    calculateHttpHeaders: true,
    stripFormattedExtensions: false
},

另一件可以帮助的事情是在拼接对象上添加更长的最大缓存期限,如果它确实有意义的话,您可以通过在模式拼接解析器中添加缓存提示来做到这一点:

 mergeSchemas({
                    schemas: [avatarSchema, mediaSchema, linkSchemaDefs],
                    resolvers: [
                        {
                            AvatarFlatFields: {
                                faceImage: {
                                    fragment: 'fragment AvatarFlatFieldsFragment on AvatarFlatFields { faceImageId }',
                                    resolve(parent, args, context, info) {
                                        info.cacheControl.setCacheHint({maxAge: 3600});
                                        return info.mergeInfo.delegateToSchema({
                                            schema: mediaSchema,
                                            operation: 'query',
                                            fieldName: 'getMedia',
                                            args: {
                                                mediaId: parseInt(parent.faceImageId),
                                            },
                                            context,
                                            info,
                                        });
                                    }
                                },
                            }
                        },

最后,使用dataLoaders 可以在启用批处理和数据加载器缓存时更快地处理请求,在他们的 github 上阅读更多内容,代码将如下所示:

public avatarLoader = (context): DataLoader<any, any> => {
    return new DataLoader(ids => this.getUsersAvatars(dataLoadersContext(context), ids)
            .then(results => new Validation().validateDataLoaderArrayResults(ids, results))
        , {batch: true, cache: true});
};

【讨论】:

  • 嗨,Adel,您能否分享一些 github 链接以获取有关相同信息的项目?我希望在网关级别进行模式拼接。
猜你喜欢
  • 2021-03-03
  • 2019-11-05
  • 2020-08-12
  • 2019-07-02
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-22
相关资源
最近更新 更多