apisix~graphQL的支持
<ul><li>https://apisix.apache.org/blog/2022/03/02/apisix-integration-graphql/</li>
<li>https://juejin.cn/post/7072557615833677837?is_preload=1&module_name=iOS_tt_url&share_token=5F541E05-B8E8-43A4-B76D-660A0461924C&tt_from=copy_link&upstream_biz=iOS_url&utm_campaign=client_share&utm_medium=toutiao_ios&utm_source=copy_link</li>
<li>https://learning.postman.com/docs/sending-requests/graphql/graphql-overview</li>
</ul>
<h1 id="graphql-是什么">GraphQL 是什么?</h1>
<p>GraphQL 是一种用于 API 的<strong>查询语言</strong>和<strong>运行时</strong>,由 Facebook 于 2012 年内部开发并于 2015 年公开。它的核心作用是为客户端提供一种<strong>精确、灵活且高效</strong>的方式来从服务端获取所需的数据。</p>
<h3 id="一graphql-是什么">一、GraphQL 是什么?</h3>
<p>你可以将 GraphQL 理解为客户端与服务器之间的一种“对话协议”。客户端通过它向服务器发送一份结构化的“数据需求清单”(即查询语句),服务器则严格按照这份清单的格式和要求,返回恰好满足需求的数据,不多不少。</p>
<p>这与您更熟悉的 REST API 形成鲜明对比。在 REST 中,客户端通过访问不同的 URL 端点(如 <code>/users</code> 或 <code>/posts</code>)来获取数据,而每个端点返回的数据结构是固定的。GraphQL 则通常只有一个端点(如 <code>/graphql</code>),客户端通过改变查询语句的内容来决定具体要什么。</p>
<h3 id="二graphql-的核心作用与优势">二、GraphQL 的核心作用与优势</h3>
<p>其作用主要体现在解决传统 API(如 REST)在复杂应用场景下面临的几个关键痛点:</p>
<ol>
<li>
<p><strong>精准获取,避免“过度获取”与“获取不足”</strong></p>
<ul>
<li><strong>问题</strong>:在 REST 中,请求一个用户信息端点 <code>/users/123</code> 可能会返回该用户的所有字段(如姓名、邮箱、地址、好友列表等),即使客户端只需要姓名。反之,如果需要展示一个博客文章及其作者信息,可能需要先调用 <code>/posts/456</code>,再根据返回的作者ID去调用 <code>/users/789</code>,产生多次往返请求(获取不足)。</li>
<li><strong>GraphQL 解决方案</strong>:客户端在查询中明确指定所需的字段。只需要文章标题和作者姓名?查询就只写这两个字段。服务器一次性返回这些精确的数据,避免了不必要的数据传输,也减少了请求次数。</li>
</ul>
</li>
<li>
<p><strong>单一端点,强大的类型系统</strong></p>
<ul>
<li><strong>问题</strong>:REST API 的端点随着业务增长而膨胀(<code>/users</code>, <code>/posts</code>, <code>/comments</code>, <code>/users/{id}/posts</code> 等),难以维护和让前端开发者全面了解。</li>
<li><strong>GraphQL 解决方案</strong>:只有一个端点。所有可用的数据和操作(查询、变更)都通过一个严格的<strong>模式</strong> 来定义。这个模式像一份强类型的“合同”或“说明书”,明确列出了所有可查询的对象、字段、参数及其数据类型。前端开发者可以通过工具(如 GraphiQL)直观地浏览和测试所有能力。</li>
</ul>
</li>
<li>
<p><strong>灵活适应快速迭代的前端需求</strong></p>
<ul>
<li><strong>问题</strong>:移动端、Web 端、桌面端可能需要同一数据的不同视图。为每个视图创建或修改 REST 端点会拖慢前后端开发效率。</li>
<li><strong>GraphQL 解决方案</strong>:前端掌握数据需求的主动权。当 UI 组件需要新字段时,前端开发者只需在查询中添加该字段,无需后端专门为此修改 API 或创建新版本。这极大地提升了产品迭代速度。</li>
</ul>
</li>
</ol>
<h3 id="三一个简单类比">三、一个简单类比</h3>
<p>想象一下去餐厅点餐:</p>
<ul>
<li><strong>REST 方式</strong>:就像点固定套餐。点“A套餐”,你会得到开胃菜、主菜、甜点和饮料(可能包含你不喜欢的)。</li>
<li><strong>GraphQL 方式</strong>:就像单点。你拿到一张完整的菜单(<strong>Schema</strong>),然后精确地写下:“我要一份牛排(<strong>查询</strong>),要五分熟(<strong>参数</strong>),并且只搭配薯条,不要沙拉(<strong>选择字段</strong>)”。厨房(<strong>服务器</strong>)会严格按照你的单子准备。</li>
</ul>
<h3 id="四核心概念与工作原理">四、核心概念与工作原理</h3>
<ol>
<li><strong>查询</strong>:用于获取数据的只读操作。<pre><code class="language-graphql"># 客户端发送的查询
query {
user(id: "123") {
name
posts(limit: 2) { # 嵌套查询
title
}
}
}
</code></pre>
</li>
<li><strong>变更</strong>:用于修改数据(增、删、改)的操作,语法类似查询。<pre><code class="language-graphql">mutation {
createPost(title: "New Post", content: "Hello") {
id # 返回新创建帖子的ID
}
}
</code></pre>
</li>
<li><strong>模式</strong>:GraphQL API 的“蓝图”,使用 <strong>模式定义语言</strong> 编写。它是客户端和服务器之间的契约。<pre><code class="language-graphql">type Query {
user(id: ID!): User
}
type User {
id: ID!
name: String!
email: String
posts:
}
type Post {
id: ID!
title: String!
}
</code></pre>
</li>
<li><strong>解析器</strong>:服务器端为模式中的每个字段定义的函数,用于告诉 GraphQL 如何获取或计算该字段对应的数据。</li>
</ol>
<h3 id="五主要应用场景">五、主要应用场景</h3>
<ul>
<li><strong>复杂应用与微服务后端</strong>:前端需要聚合来自多个微服务的数据时,GraphQL 可以作为 <strong>BFF</strong>,提供一个统一的、灵活的接口。</li>
<li><strong>移动端优先的应用</strong>:在弱网环境下,减少数据流量至关重要,GraphQL 的精准查询优势明显。</li>
<li><strong>公有 API</strong>:允许第三方开发者根据自己的需求定制数据响应,提升 API 的友好度和适用性。</li>
<li><strong>与您之前讨论的 APISIX 结合</strong>:API 网关(如 APISIX)可以利用 GraphQL 的查询信息(如操作类型、字段名)来实现<strong>更智能的路由、缓存、限流和安全策略</strong>。例如,可以为“查询”和“变更”设置不同的速率限制,或者只缓存特定的查询操作。</li>
</ul>
<p><strong>总结</strong>:GraphQL 的核心价值在于<strong>将数据需求的掌控权交给了客户端</strong>,通过声明式的查询、强类型的契约和单一的端点,解决了 API 开发中数据获取效率低下、接口僵化、前后端耦合过紧等问题,是现代复杂应用,特别是数据驱动型应用的高效数据层解决方案。您在 APISIX 中探讨的相关插件和路由功能,正是为了在网关层面更好地管理和服务这些 GraphQL API 请求。</p>
<h1 id="apisix中的graphql">apisix中的graphQL</h1>
<p>根据搜索结果,APISIX 确实支持 GraphQL,但<strong>不是通过单一的 <code>graphql.lua</code> 插件</strong>来实现。在 APISIX 3.10 中,GraphQL 功能主要通过以下几种方式提供:</p>
<h2 id="1-核心路由的-graphql-属性匹配内置功能">1. <strong>核心路由的 GraphQL 属性匹配</strong>(内置功能)</h2>
<p>这是 APISIX 对 GraphQL 的<strong>原生支持</strong>,集成在核心路由匹配逻辑中,而不是独立的插件。</p>
<h3 id="支持的路由匹配属性">支持的路由匹配属性:</h3>
<ul>
<li><strong><code>graphql_operation</code></strong>:匹配 GraphQL 操作类型(query、mutation、subscription)</li>
<li><strong><code>graphql_name</code></strong>:匹配 GraphQL 操作名称</li>
<li><strong><code>graphql_root_fields</code></strong>:匹配 GraphQL 根字段数组</li>
</ul>
<h3 id="配置示例">配置示例:</h3>
<pre><code class="language-bash">curl http://127.0.0.1:9080/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
-X PUT -d '{
"methods": ["POST"],
"uri": "/graphql",
"vars": [
["graphql_operation", "==", "query"],
["graphql_name", "==", "getUser"]
],
"upstream": {
"nodes": {
"192.168.1.200:1982": 1
},
"type": "roundrobin"
}
}'
</code></pre>
<h3 id="源码位置">源码位置:</h3>
<ul>
<li>核心 GraphQL 解析逻辑在 <strong><code>apisix/core/graphql.lua</code></strong> 或相关模块中</li>
<li>路由匹配逻辑在 <strong><code>apisix/http/router.lua</code></strong> 或 <strong><code>apisix/core/matcher.lua</code></strong> 中集成</li>
</ul>
<h2 id="2-graphql-proxy-cache-插件独立插件">2. <strong>graphql-proxy-cache 插件</strong>(独立插件)</h2>
<p>这是一个<strong>独立的缓存插件</strong>,专门用于缓存 GraphQL 查询响应。</p>
<h3 id="主要功能">主要功能:</h3>
<ul>
<li>缓存 GET 和 POST 的 GraphQL 请求</li>
<li>基于 MD5 算法生成缓存键</li>
<li>支持磁盘和内存缓存</li>
<li>自动绕过包含 mutation 操作的请求</li>
</ul>
<h3 id="插件文件位置">插件文件位置:</h3>
<pre><code>apisix/plugins/graphql-proxy-cache.lua
</code></pre>
<h2 id="3-degraphql-插件rest-转-graphql">3. <strong>degraphql 插件</strong>(REST 转 GraphQL)</h2>
<p>这是从 <strong>APISIX 3.2.0 LTS</strong> 开始新增的插件,用于将 RESTful 请求转换为 GraphQL 查询。</p>
<h3 id="主要功能-1">主要功能:</h3>
<ul>
<li>REST API 到 GraphQL API 的转换</li>
<li>请求验证和查询解析</li>
<li>响应转换</li>
</ul>
<h3 id="插件文件位置-1">插件文件位置:</h3>
<pre><code>apisix/plugins/degraphql.lua
</code></pre>
<h2 id="为什么在源码中找不到-graphqllua">为什么在源码中找不到 <code>graphql.lua</code>?</h2>
<h3 id="可能原因">可能原因:</h3>
<ol>
<li><strong>版本差异</strong>:不同 APISIX 版本的组织结构可能不同</li>
<li><strong>功能集成</strong>:GraphQL 核心解析功能可能被集成到其他模块中</li>
<li><strong>插件命名</strong>:相关功能可能以其他名称存在</li>
</ol>
<h3 id="查找建议">查找建议:</h3>
<pre><code class="language-bash"># 在 APISIX 源码目录中搜索 GraphQL 相关文件
find . -name "*.lua" -type f | xargs grep -l "graphql" | grep -v test
# 可能的文件位置
./apisix/core/graphql.lua # 核心 GraphQL 解析库
./apisix/plugins/graphql-proxy-cache.lua# 缓存插件
./apisix/plugins/degraphql.lua # REST 转 GraphQL 插件
./apisix/http/router.lua # 路由匹配(集成 GraphQL 支持)
</code></pre>
<h2 id="实际使用场景">实际使用场景</h2>
<h3 id="场景1基于-graphql-属性的路由控制">场景1:基于 GraphQL 属性的路由控制</h3>
<pre><code class="language-json">{
"uri": "/graphql",
"vars": [
["graphql_operation", "==", "mutation"],
["graphql_root_fields", "has", "deleteUser"]
],
"plugins": {
"authz-keycloak": {
"permission": "user:delete"
}
}
}
</code></pre>
<h3 id="场景2graphql-查询缓存">场景2:GraphQL 查询缓存</h3>
<pre><code class="language-json">{
"plugins": {
"graphql-proxy-cache": {
"cache_ttl": 300,
"cache_key": ["$query", "$variables"],
"cache_strategy": "memory"
}
}
}
</code></pre>
<h3 id="场景3rest-接口暴露为-graphql">场景3:REST 接口暴露为 GraphQL</h3>
<pre><code class="language-json">{
"plugins": {
"degraphql": {
"query": "query($id: ID!) { user(id: $id) { name email } }",
"variables": ["id"],
"upstream": {
"url": "http://user-service/graphql"
}
}
}
}
</code></pre>
<h2 id="总结">总结</h2>
<table>
<thead>
<tr>
<th>功能类型</th>
<th>实现方式</th>
<th>文件位置</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>路由匹配</strong></td>
<td>核心功能</td>
<td><code>apisix/core/graphql.lua</code></td>
<td>内置 GraphQL 解析和属性匹配</td>
</tr>
<tr>
<td><strong>查询缓存</strong></td>
<td>独立插件</td>
<td><code>apisix/plugins/graphql-proxy-cache.lua</code></td>
<td>GraphQL 响应缓存</td>
</tr>
<tr>
<td><strong>REST 转换</strong></td>
<td>独立插件</td>
<td><code>apisix/plugins/degraphql.lua</code></td>
<td>RESTful API 转 GraphQL</td>
</tr>
<tr>
<td><strong>权限控制</strong></td>
<td>Serverless 插件</td>
<td>自定义 Lua 脚本</td>
<td>基于 GraphQL 操作的白名单</td>
</tr>
</tbody>
</table>
<p><strong>建议</strong>:</p>
<ol>
<li>检查你的 APISIX 版本是否包含 <code>degraphql</code> 插件(3.2.0+)</li>
<li>确认 <code>graphql-proxy-cache</code> 插件是否已编译到你的 APISIX 中</li>
<li>查看 <code>apisix/core/</code> 目录下的 GraphQL 相关核心模块</li>
</ol>
<p>如果你确实需要 <code>graphql.lua</code> 文件,可能需要:</p>
<ol>
<li>从官方仓库的对应版本分支查找</li>
<li>检查是否被重命名或重构到其他模块</li>
<li>考虑使用上述的替代方案实现你的需求</li>
</ol>
<h1 id="postman中测试">postman中测试</h1>
<p><img src="https://img2024.cnblogs.com/blog/118538/202604/118538-20260414092847543-1683147431.png" alt="image" loading="lazy"></p>
<h1 id="graphql-lua库">graphql-lua库</h1>
<p>你提到的 <strong><code>graphql-lua</code></strong> 库(bjornbytes/graphql-lua)与 APISIX 中的 GraphQL 支持有明确的<strong>层级关系</strong>和<strong>功能定位区别</strong>。</p>
<h2 id="1-graphql-lua-库底层-graphql-解析引擎">1. <strong><code>graphql-lua</code> 库:底层 GraphQL 解析引擎</strong></h2>
<h3 id="作用">作用:</h3>
<p>这是一个<strong>独立的 Lua GraphQL 实现库</strong>,提供 GraphQL 的核心功能:</p>
<ul>
<li><strong>语法解析</strong>:解析 GraphQL 查询语句</li>
<li><strong>类型系统</strong>:定义 GraphQL Schema 和类型</li>
<li><strong>查询执行</strong>:执行 GraphQL 查询并返回结果</li>
<li><strong>验证</strong>:验证查询的合法性</li>
</ul>
<h3 id="源码结构">源码结构:</h3>
<pre><code>graphql/
├── execute.lua # 查询执行
├── parse.lua # 语法解析
├── schema.lua # Schema 定义
├── types.lua # 类型系统
├── validate.lua # 查询验证
└── ...其他模块
</code></pre>
<h3 id="独立使用示例">独立使用示例:</h3>
<pre><code class="language-lua">local graphql = require('graphql')
local schema = graphql.Schema{
query = graphql.ObjectType{
name = 'Query',
fields = {
hello = {
type = graphql.String,
resolve = function() return 'world' end
}
}
}
}
</code></pre>
<h2 id="2-apisix-中的-graphql-支持集成应用层">2. <strong>APISIX 中的 GraphQL 支持:集成应用层</strong></h2>
<h3 id="关系">关系:</h3>
<p>APISIX <strong>内部依赖</strong> <code>graphql-lua</code> 库来实现 GraphQL 解析功能。</p>
<h3 id="集成方式">集成方式:</h3>
<ol>
<li><strong>核心路由匹配</strong>:APISIX 使用 <code>graphql-lua</code> 解析请求,提取 <code>graphql_operation</code>、<code>graphql_name</code> 等属性进行路由匹配</li>
<li><strong>插件扩展</strong>:基于解析结果实现缓存、转换、安全控制等高级功能</li>
</ol>
<h3 id="apisix-源码中的集成点">APISIX 源码中的集成点:</h3>
<pre><code class="language-bash"># 可能的位置
apisix/core/graphql.lua # APISIX 对 graphql-lua 的封装
apisix/http/router.lua # 路由匹配逻辑(调用 graphql 解析)
</code></pre>
<h2 id="3-两者区别对比">3. <strong>两者区别对比</strong></h2>
<table>
<thead>
<tr>
<th>维度</th>
<th><strong><code>graphql-lua</code> 库</strong></th>
<th><strong>APISIX GraphQL 支持</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>定位</strong></td>
<td>底层 GraphQL 解析引擎</td>
<td>API 网关的 GraphQL 功能集成</td>
</tr>
<tr>
<td><strong>功能</strong></td>
<td>语法解析、类型系统、查询执行</td>
<td>路由匹配、流量控制、安全策略</td>
</tr>
<tr>
<td><strong>使用场景</strong></td>
<td>任何需要 GraphQL 的 Lua 项目</td>
<td>API 网关层的 GraphQL API 管理</td>
</tr>
<tr>
<td><strong>输出</strong></td>
<td>GraphQL 查询结果</td>
<td>路由决策、插件执行结果</td>
</tr>
<tr>
<td><strong>依赖关系</strong></td>
<td>独立库</td>
<td>依赖 <code>graphql-lua</code> 作为解析引擎</td>
</tr>
</tbody>
</table>
<h2 id="4-实际工作流程">4. <strong>实际工作流程</strong></h2>
<p>当客户端发送 GraphQL 请求到 APISIX:</p>
<pre><code>客户端请求
↓
APISIX 接收请求
↓
调用 graphql-lua 解析请求体
↓
提取 graphql_operation、graphql_name 等属性
↓
基于属性进行路由匹配
↓
执行相关插件(缓存、认证、限流等)
↓
转发到上游服务
</code></pre>
<h2 id="5-为什么在-apisix-310-源码中看不到-graphqllua">5. <strong>为什么在 APISIX 3.10 源码中看不到 <code>graphql.lua</code>?</strong></h2>
<h3 id="可能原因-1">可能原因:</h3>
<ol>
<li><strong>模块化重构</strong>:GraphQL 功能可能被重构到多个模块中</li>
<li><strong>依赖管理</strong>:<code>graphql-lua</code> 可能作为外部依赖,不在主代码库中</li>
<li><strong>版本差异</strong>:不同版本的 APISIX 集成方式可能不同</li>
</ol>
<h3 id="验证方法">验证方法:</h3>
<pre><code class="language-bash"># 检查 APISIX 的依赖声明
find . -name "*.rockspec" -o -name "Makefile" -o -name "requirements.txt"
# 搜索 GraphQL 相关代码
grep -r "graphql" --include="*.lua" apisix/
</code></pre>
<h2 id="6-开发建议">6. <strong>开发建议</strong></h2>
<h3 id="如果你需要">如果你需要:</h3>
<ol>
<li>
<p><strong>在 APISIX 中扩展 GraphQL 功能</strong>:</p>
<ul>
<li>使用现有的 <code>graphql_operation</code>、<code>graphql_name</code> 等路由属性</li>
<li>开发自定义插件,利用 APISIX 的插件框架</li>
</ul>
</li>
<li>
<p><strong>在 Lua 项目中实现 GraphQL 服务</strong>:</p>
<ul>
<li>直接使用 <code>graphql-lua</code> 库</li>
<li>示例:<code>luarocks install graphql-lua</code></li>
</ul>
</li>
<li>
<p><strong>调试 APISIX 的 GraphQL 解析</strong>:</p>
<pre><code class="language-bash"># 启用调试日志
curl -X PUT http://127.0.0.1:9080/apisix/admin/plugin_metadata/debug \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
-d '{"log_level": "debug"}'
</code></pre>
</li>
</ol>
<h2 id="总结-1">总结</h2>
<p><strong><code>graphql-lua</code></strong> 是<strong>基础工具库</strong>,提供 GraphQL 的核心解析能力;而 <strong>APISIX 的 GraphQL 支持</strong>是<strong>应用层集成</strong>,在基础解析之上构建了 API 网关所需的路由、安全、监控等高级功能。</p>
<p>这种分层设计是典型的软件架构模式:底层库专注单一功能,上层系统集成多个底层库实现复杂业务逻辑。APISIX 通过集成 <code>graphql-lua</code>,避免了重复造轮子,同时专注于 API 网关的核心价值。</p>
</div>
<div id="MySignature" role="contentinfo">
<p></p>
<div class="navgood">
<p>作者:仓储大叔,张占岭,<br>
荣誉:微软MVP<br>QQ:853066980</p>
<p><strong>支付宝扫一扫,为大叔打赏!</strong>
<br><img src="https://images.cnblogs.com/cnblogs_com/lori/237884/o_IMG_7144.JPG"></p>
</div><br><br>
来源:https://www.cnblogs.com/lori/p/19863294
頁:
[1]