基于GraphQL-Java的数据网关系统设计

数据网关系统设计

项目背景

随着业务的发展,可以预期到平台的相关子系统,会出现大量依赖外部系统的API服务以及内部系统之间数据流转的情况。如何高效维护这些内部和外部的API,低成本接入外部的服务成了一个棘手的问题

问题发现

  • 平台内子系统在对接外部系统数据源时,可能有需求重复,导致重复接入增加各子系统开发成本成N*M倍增长;
  • 系统中维护大量的数据API和相关的聚合逻辑,增加系统后期的维护和开发成本;
  • 和前端交互中,前端页面需要不同的数据聚合,需要服务端提供大量的API和相关聚合逻辑,提升开发成本;

解决方案

  • 数据中心,作为在对接外部系统是作为总的数据接入方统一接入,减少重复接入;
  • 数据中心将接入的数据进行拆解、进行多层数据关联聚合,减少重复数据聚合逻辑;
  • 使用GraphQL查询引擎,借助DSL查询语言减少提供的API,一次接入;
  • 使用GraphQL查询引擎,聚合查询数据,减少子业务聚合逻辑开发导致的成本;

技术设计

GraphQL介绍

  • GraphQL是一种新的API标准,它提供了一种更高效、强大和灵活的数据提供方式,本质上是一种基于api的查询语言

    它是由Facebook开发和开源.

    现在大多数应用程序都需要从服务器中获取数据,这些数据存储可能存储在数据库中,API的职责是提供与应用程序需求相匹配的存储数据的接口。

  • GraphQL是api的查询语言,而不是数据库

    从这个意义上说,它是数据库无关的,而且可以在使用API的任何环境中有效使用,我们可以理解为GraphQL是基于API之上的一层封装,目的是为了更好,更灵活的适用于业务的需求变化。

  • 区别于Restful,客户端可以通过GraphQL的DSL自定义返回的数据和相关的聚合

设计框架

消费方通过数据中心的Thrift接口接入,传入要查询的DSL语句到数据中心,数据中心将各方接入的数据聚合后返回结果

功能与使用

  • 支持通用GraphQL的Query查询\聚合等功能
  • 支持GraphQL的DSL配置功能
  • 支持接入方\字段等维度的鉴权功能
  • 支持自定义的数据计算\转换功能
  • 支持接入方维度的限流

基础的请求语法可以参考

 举例有如下待查数据结构Student:
 public class Student {
     private String name;
     private Integer id;
     private Integer teacherId;
 }

数据查询

基本的GraphQL的查询功能,传入Query+Variables,得到返回结果

请求语句:
query GetStudent($req:GetStudentRequest){
  getStudents(request:$req){
    students{
            id,
            name
    }
  }
}

请求参数:
{
    "req":{
      "name":"liuzhuan"
    }
}

返回结果
{
  "data": {
    "getStudents": {
      "students": [
        {
          "id": "102",
          "name": "S2"
        },
        {
          "id": "103",
          "name": "S3"
        },
        {
          "id": "104",
          "name": "S4"
        },
        {
          "id": "105",
          "name": "S5"
        }
      ]
    }
  }
}

数据聚合

基本的GraphQL的聚合功能,传入Query+Variables,得到返回结果

 请求语句:
 query GetStudent($req:GetStudentRequest){
   getStudents(request:$req){
     students{
             id,
             name,
             teacher{
                name
             }
     }
   }
 }
 
 请求参数:
 {
     "req":{
       "name":"liuzhuan"
     }
 }
 
 返回结果
 {
   "data": {
     "getStudents": {
       "students": [
         {
           "id": "102",
           "name": "S2",
           "teacher":{
                "name":"teacherA"
           }
         },
         {
           "id": "103",
           "name": "S3",
           "teacher":{
               "name":"teacherA"
            }
         },
         {
           "id": "104",
           "name": "S4",
           "teacher":{
               "name":"teacherA"
            }
         },
         {
           "id": "105",
           "name": "S5"
           "teacher":{
               "name":"teacherA"
            }
         }
       ]
     }
   }
 }

数据计算

支持在传入Query时,对指定的字段,按照其携带的groovy的语句进行处理

如下面的groovy字段和teacher.name字段的处理

该功能可以在需要对一些字段做展示处理时,减少业务层的展示逻辑

请求语句:
query GetStudent($req:GetStudentRequest){
  getStudents(request:$req){
    students{
            id,
            name,
      groovy @groovy(patterns:["first=${if(id>103) return 'id大于103' else return 'id小于103'}","second=${'名字='+name}"]),
      teacher {
        id,
        name @groovy(pattern:"${'姓名是'+name}")
      }
    }
  }
}
请求参数:
{
    "req":{
      "name":"liuzhuan"
    }
}

返回结果:
{
  "data": {
    "getStudents": {
      "students": [
        {
          "id": "102",
          "name": "S2",
          "groovy": {
            "first": "id小于103",
            "second": "名字=s2"
          },
          "teacher": {
            "id": "2",
            "name": "姓名是teacher"
          }
        },
        {
          "id": "103",
          "name": "S3",
          "groovy": {
            "first": "id小于103",
            "second": "名字=s3"
          },
          "teacher": {
            "id": "3",
            "name": "姓名是teacher"
          }
        },
        {
          "id": "104",
          "name": "S4",
          "groovy": {
            "first": "id大于103",
            "second": "名字=s4"
          },
          "teacher": {
            "id": "4",
            "name": "姓名是teacher"
          }
        },
        {
          "id": "105",
          "name": "S5",
          "groovy": {
            "first": "id大于103",
            "second": "名字=s5"
          },
          "teacher": {
            "id": "5",
            "name": "姓名是teacher"
          }
        }
      ]
    }
  }
}

字段鉴权

可以指定对某些字段(Field\Object)的限制请求,该功能目前只能在数据中心的服务端实现配置

type Student @auth(psm:["test"]) {    //对Student的访问,只有psm为test
    id: ID
    name: String @uppercase
    sex: Int
    teacher: Teacher @auth(psm:["test","$auth_psm"])  //对teacher的访问,只有psm为test或者auth_psm中的来源才能通过
    groovy: JSON
}

数据灰度

对接入的数据源,可以根据下游传来的请求的灰度标识,判断其调用上游的灰度服务

接入方式

[Thrift文件]

[Thrift接口定义]

Query方法说明

  • 不携带参数的请求使用方法

     {
         "Query":"query {getStudents(request:{name:\"liuzhuan\"}){students{id,name}}}",
         "Psm":"test",
         "Token":"abcdefghijk123124"
     }
    
  • 携带参数请求方法

    建议使用该方法,将query语句和具体的业务动态变量分开,便于业务方动态调整参数

    {
        "Query":"query GetStudents($req:GetStudentRequest){getStudents(request:$req){students{id,name}}}", //query语句
        "Variables":"{\"req\":{\"name\":\"liuzhuan\"}}", //入参
        "Psm":"test",
        "Token":"token"
    }
    
    
  • 请求实现配置好的DSL的请求方法:

    部分情况下,query语句可以在数据中心进行配置,使用方只需要传入对应的queryId以及动态参数即可

       {
           "QueryId":"queryId_1",
           "Variables":"{\"req\":{\"name\":\"liuzhuan\"}}",
           "Psm":"test",
           "Token":"token"
       }
    
    
  • 返回结果说明:

    正常情况下,数据会以json字符串的形式返回在Data中

    {
       "Data": "{\"getStudents\":{\"students\":[{\"id\":\"102\",\"name\":\"S2\"},{\"id\":\"103\",\"name\":\"S3\"},{\"id\":\"104\",\"name\":\"S4\"},{\"id\":\"105\",\"name\":\"S5\"}]}}",
       "Errors": null,
       "BaseResp": {
           "StatusMessage": "success",
           "StatusCode": 200,
           "statusCode": 200,
           "statusMessage": "success",
           "setStatusMessage": true,
           "setStatusCode": true
       }
    }
    
    
  • 异常描述:

    {
        "Data": null,
        "Errors": [
            "cannot find query"
        ],
        "Code": 0,
        "BaseResp": {
            "StatusMessage": "system fail",
            "StatusCode": 502,
            "statusCode": 502,
            "statusMessage": "system fail",
            "setStatusMessage": true,
            "setStatusCode": true
        }
    }
    
    

后续

配置化

新接入数据源通过配置实现,提供对外的配置页面供业务接入方灵活接入

业务场景扩展
新功能开发

系统稳定性和响应指标
datafetcher的使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值