zoukankan      html  css  js  c++  java
  • 让ASP.NET Core支持GraphQL之-GraphQL的实现原理

    众所周知RESTful API是目前最流行的软件架构风格之一,它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
    RESTful的优越性是毋庸置疑的,不过GraphQL也可以作为一种补充,让你的服务既支持RESTful的http调用,也容许客户端通过GraphQL支持的声明式语法调用服务。
    本篇文章并不想对比RESTful和GraphQL孰轻孰重,或者那种方式更好,相关比较可以参考GraphQL的前世今生。本文旨在介绍如何在ASP.NET Core应用中引入GraphQL,让你的应用既支持RESTFul,也能支持GraphQL。

    Web应用程序是如何工作的

    如果说一个Service能够提供一个功能,那么我们就可以给Service一个输入,从而得到一个输出。

    如果将若干个Service组合在一起形成一个应用程序,那么这个应用程序就可以提供若干个能力,当一个框架分别就输入和输出进行统一的约定和规范时,也就是人们常说的SOAP,RESTful等技术。

    对于RESTful来说,输入就是Http request,输出是一个json格式的字符串。而Web应用程序框架在做什么?根据某个输入(request),找到对应的controller, 击中合适的action,同时将Request绑定为action方法的参数,最后将结果格式化为json字符串并输出。

    GraphQL就是跟Web框架同一级别的技术,只不过输入(input)不再是Http request,而是GraphQL特有的语法结构,输出仍然为json字符串。

    GraphQL能够做些什么

    既然GraphQL是一种可以代替RESTful的技术,那么你一定很想知道他是怎么做到的。 如果能用一句话总结那就是: GraphQL是一种API资源的查询语言。GraphQL通过下面的三种类型来满足用户的需求:

    1. 查询

    我们都知道用户的请求可以分为两类:Query和Command,Query用于查询资源,调用一次和多次都不会影响资源的状态,一个简单的查询如下:

    query {
      hero {
        id
        name
      }
    }
    

    上面的查询语言可以理解为:查询hero资源的"id"和"name“属性

    2. mutation

    所谓mutation就是Command,意味着该用户请求能够改变服务端的状态,一个简单的mutation如下:

    mutation ($human:HumanInput!) {
      createHuman(human: $human) {
        id
        name
      }
    }
    variables: {
        "human": {
          "name": "Boba Fett",
          "homePlanet": "Kamino"
        }
      }
    

    上面的mutation可以理解为创建一个humman对象,输入对象是一个$human变量,最后把创建对象的`”id"和"name"属性查询出来。可以看出mutation一般都要配合一个变量使用,变量需要在"variables"中单独定义。

    3. Subscriptions

    Subscriptions用于提供类似websocket的功能,GraphQL Server是一个实现了Apollo GraphQL订阅协议的.NET Core服务器. 下面的例子需要同时打开两个浏览器窗口:
    Subscription用户订阅聊天消息:

    subscription MessageAdded {
      messageAdded {
        from { id displayName }
        content
      }
    }
    

    Mutation用户添加聊天内容:

    mutation AddMessage($message: MessageInputType!) {
      addMessage(message: $message) {
        from {
          id
          displayName
        }
        content
      }
    }
    
    variables:
    {
      "message": {
        "content": "Message",
        "fromId": "1"
      }
    }
    

    GraphQL是如何实现的

    我在用每一个开源框架或者类库时都习惯于先浏览源码,了解整个源码的大概结构和实现。下面的过程以一个简单的查询为例,分析GraphQL的实现原理:

    {
      query test {
        user{
            age
        }
      }
    }
    

    通过graphQL browser IDE发送请求:

    GrpahQL处理的整个过程如下:

    1.客户端将上面的GraphQL query通过http发送到服务端
    curl 'http://localhost:5000/graphql' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'DNT: 1' -H 'Origin: http://localhost:5000' --data-binary '{"query":"# Write your query or mutation here
    query test{
      user{
        age
      }
    }
    "}' --compressed
    
    2. 整个Request以json的格式发送到了服务端,服务端将Request反序列化为GraphQLRequest类型:
    public class GraphQLRequest
    {
        [JsonProperty("query")]
        public string Query { get; set; }
        
        [JsonProperty("variables")]
        public JObject Variables { get; set; }
        
        [JsonProperty("operationName")]
        public string OperationName { get; set; }
        
        public Inputs GetInputs()
        {
          return GraphQLRequest.GetInputs(this.Variables);
        }
    }
    

    针对上面的例子,实际上只有string Query属性被反序列化为”"# Write your query or mutation here query test{ user{ age } } "“

    3.服务端解析Query,解析Query的过程是一个语法分析的过程,通过Paser将Query解析为AST:
        var source = new Source(body);
        var result = _parser.Parse(source);
    

    Parse后的结果是一个Document类:

     public class Document : AbstractNode
    {
        public string OriginalQuery { get; set; }
        public Operations Operations { get; }
        public Fragments Fragments { get; }
    }
    

    本例的Query将会被解析为一个Operations,一个Operations将包含若干个有层次结构的Operation,解析Query的目的是为了知道客户端要查询user.Age这个属性。

    4.有了一个Parse后的Document,接下来的工作将有DocumentExecuter来完成,DocumentExecuter定义了整个调用服务端资源的流程:
    public async Task<ExecutionResult> ExecuteAsync(ExecutionOptions options)
    {
        //1. 打印开始时间
        //2. Parse Document
        //3. 验证Document是否是一个合法的GrapQL语法请求
        //4. 在流程的各个阶段执行Listener,用于在不同的时机切入代码,类似于ASP.NET Core中的Filter
        //5. 选择合适的执行策略
        //6. 执行服务端资源
        //7. 输出Response
    }
    
    

    以上就是GraphQL在.NET Core中的实现原理分析,下一篇将通过一个hello world级别的例子演示如何让你的ASP.NET应用程序支持GraphQL.

  • 相关阅读:
    机器学习-决策树
    第八章- 假设检验
    第七章-参数估计
    第六章-总体与样本
    第五章-大数定律&中心极限定理
    第三,四章-多维随机变量及其分布
    第二章-随机变量分布
    第一章, 随机事件
    第六章-二次型
    第五章-矩阵的特征值和特征向量
  • 原文地址:https://www.cnblogs.com/xiandnc/p/10398505.html
Copyright © 2011-2022 走看看