GraphQL返回的额外信息正在减慢初始加载速度

问题描述

我在graphql结果中得到了一些额外的信息。 除了数据和最后的错误我正在

  • 文档
  • 操作
  • 性能
  • 扩展名

因此结果变得非常庞大。我注意到的另一种想法是,文档和智能手机的初始加载时间很长。

您知道我如何摆脱这些额外的数据吗?

graphQL查询结果:

Result of the graphQL query

GraphQL控制器

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ElectronConnectQuery.GraphQL;
using GraphQL;
using GraphQL.DataLoader;
using GraphQL.NewtonsoftJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace ElectronConnectQuery.Controllers.v1
{
    [Route("[controller]")]
    public class GraphQLController : Controller
    {
        private readonly IDocumentExecuter _documentExecuter;
        private readonly ISchema _schema;
        private readonly DataLoaderDocumentListener _listener;
        private readonly ILogger<GraphQLController> _logger;

        public GraphQLController(ISchema schema,IDocumentExecuter documentExecuter,DataLoaderDocumentListener listener,ILogger<GraphQLController> logger)
        {
            _schema = schema;
            _documentExecuter = documentExecuter;
            _listener = listener;
            _logger = logger;
        }

        [HttpPost]
        public async Task<IActionResult> Post([FromBody] GraphQLQuery query,[FromServices] IEnumerable<IValidationRule> validationRules)
        {
            if (query == null) { throw new ArgumentNullException(nameof(query)); }
            _logger.LogDebug("GraphQL received query:{Query}",query.Query);
            var inputs = query.Variables.ToInputs();
            var executionoptions = new Executionoptions
            {
                Schema = _schema,Query = query.Query,Inputs = inputs,ValidationRules = validationRules,EnableMetrics = false
            };

#if (DEBUG)
            executionoptions.EnableMetrics = true;
#endif

            executionoptions.Listeners.Add(_listener);

            var result = await _documentExecuter.ExecuteAsync(executionoptions).ConfigureAwait(false);

            if (result.Errors?.Count > 0)
            {
                return BadRequest(result);
            }

            return Ok(result);
        }
    }
}

解决方法

如果您自己编写结果,请使用IDocumentWriter,它将正确序列化结果。

/// <summary>
/// Serializes an object hierarchy to a stream. Typically this would be serializing an instance of the ExecutionResult class into a JSON stream.
/// </summary>
public interface IDocumentWriter
{
    /// <summary>
    /// Asynchronously serializes the specified object to the specified stream.
    /// </summary>
    Task WriteAsync<T>(Stream stream,T value,CancellationToken cancellationToken = default);
}

还有一种扩展方法可以序列化为string

public static async Task<string> WriteToStringAsync<T>(this IDocumentWriter writer,T value)

此示例显示了使用中间件还是使用控制器,但是想法是相同的。

https://github.com/graphql-dotnet/examples/blob/529b530d7a6aad878b2757d776282fdc1cdcb595/src/AspNetCoreCustom/Example/GraphQLMiddleware.cs#L75-L81

private async Task WriteResponseAsync(HttpContext context,ExecutionResult result)
{
    context.Response.ContentType = "application/json";
    context.Response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;

    await _writer.WriteAsync(context.Response.Body,result);
}

您需要包含GraphQL.SystemTextJsonGraphQL.NewtonSoftJson来选择IDocumentWriter的实现。

https://www.nuget.org/packages/GraphQL.SystemTextJson https://www.nuget.org/packages/GraphQL.NewtonsoftJson

,

我对控制器所做的更改是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using ElectronConnectQuery.GraphQL;
using GraphQL;
using GraphQL.DataLoader;
using GraphQL.Instrumentation;
using GraphQL.NewtonsoftJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace ElectronConnectQuery.Controllers.v1
{
    [Route("[controller]")]
    public class GraphQLController : Controller
    {
        private readonly IDocumentExecuter _documentExecuter;
        private readonly ISchema _schema;
        private readonly DataLoaderDocumentListener _listener;
        private readonly ILogger<GraphQLController> _logger;
        private readonly IDocumentWriter _writer;

        public GraphQLController(ISchema schema,IDocumentExecuter documentExecuter,DataLoaderDocumentListener listener,ILogger<GraphQLController> logger,IDocumentWriter writer)
        {
            _schema = schema;
            _documentExecuter = documentExecuter;
            _listener = listener;
            _logger = logger;
            _writer = writer;
        }

        [HttpPost]
        public async Task Post([FromBody] GraphQLQuery query,[FromServices] IEnumerable<IValidationRule> validationRules)
        {
            if (query == null) { throw new ArgumentNullException(nameof(query)); }
            _logger.LogDebug("GraphQL received query:{Query}",query.Query);
            var inputs = query.Variables.ToInputs();
            var executionOptions = new ExecutionOptions
            {
                Schema = _schema,Query = query.Query,Inputs = inputs,ValidationRules = validationRules,EnableMetrics = false,};

            executionOptions.Listeners.Add(_listener);

            var result = await _documentExecuter.ExecuteAsync(opts =>
            {   
                opts.Schema = _schema;
                opts.Query = query.Query;
                opts.Inputs = inputs;
                opts.ValidationRules = validationRules;
                opts.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
                opts.EnableMetrics = true;
            }).ConfigureAwait(false);

            result.EnrichWithApolloTracing(DateTime.Now);

            await _writer.WriteAsync(Response.Body,result);
        }


        private async Task WriteResponseAsync(HttpResponse response,ExecutionResult result)
        {
            response.ContentType = "application/json";
            response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;
            await _writer.WriteAsync(response.Body,result);
        }
    }
}

Startup.cs ConfigureServices 我添加了以下几行

  // kestrel
            services.Configure<KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            // IIS
            services.Configure<IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

我还注册了DocumentWriter

services.AddScoped<IDocumentWriter,GraphQL.NewtonsoftJson.DocumentWriter>();