news 2026/9/19 13:40:19

在 Google Cloud Functions 上部署 Hasura 远程 GraphQL Schema:Node.js + Apollo Server 实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Google Cloud Functions 上部署 Hasura 远程 GraphQL Schema:Node.js + Apollo Server 实战指南

在 Google Cloud Functions 上部署 Hasura 远程 GraphQL Schema:Node.js + Apollo Server 实战指南

【免费下载链接】graphql-engineBlazing fast, instant realtime GraphQL APIs on all your data with fine grained access control, also trigger webhooks on database events.项目地址: https://gitcode.com/gh_mirrors/gr/graphql-engine

本指南以 Hasura GraphQL Engine 仓库中的官方样板代码(boilerplate)为核心,讲解如何用 Node.js + Apollo Server 编写一个自定义 GraphQL 服务,并将其部署到 Google Cloud Functions,最终与 Hasura 自动生成的 GraphQL API 合并(Merge)为统一端点。读完本文,你将掌握该样板代码的文件结构与 Schema/Resolver 实现、本地开发流程、gcloud部署命令,以及通过 Console / CLI / Metadata API 三种方式把远程服务接入 GraphQL Engine 的完整链路。

为什么需要"远程 Schema"样板代码

Hasura GraphQL Engine 的核心能力是围绕数据库自动生成 CRUD + 实时 GraphQL API,并内置细粒度授权与访问控制。但业务中常常存在无法用数据库 CRUD 直接表达的逻辑——例如支付 API、调用天气等第三方数据源、在插入前执行校验的定制 Mutation。remote-schemas.md(仓库根目录)明确给出了远程 Schema 的典型适用场景:

  • 定制 Mutation(例如在 insert 前执行业务校验);
  • 在 GraphQL Engine 的统一 API 之后接入支付等功能,提供一致的访问接口;
  • 从其他数据源拉取异构数据(如天气 API 或另一个数据库)。

实现方式也很直接:自行编写一个任意语言/框架的 GraphQL 服务,把 HTTP 端点交给 Hasura,由 GraphQL Engine 自动完成 Schema 合并(schema stitching)community/boilerplates/remote-schemas/README.md中给出了面向不同云平台的样板代码索引:AWS Lambda、Azure Functions、Google Cloud Functions、Zeit Now 等。本文聚焦其中 Google Cloud Functions 下的 Node.js 版本,其样板代码位于 community/boilerplates/remote-schemas/google-cloud-functions/nodejs。

整个合并机制可用下图概括:业务侧 GraphQL 服务与 Hasura 生成的 API 统一暴露给客户端,由 GraphQL Engine 在中间完成 Schema 拼接与转发。

样板代码目录结构与技术栈

先看该 boilerplate 的文件构成(相对仓库根目录):

community/boilerplates/remote-schemas/google-cloud-functions/nodejs/ ├── README.md # 官方使用说明(本文的原始依据) ├── index.js # Schema(typeDefs) 与 Resolvers 定义 ├── localDev.js # 本地开发服务器入口(Apollo Server) ├── googleCtx.js # Cloud Functions 部署入口(导出 handler) └── package.json # 依赖清单(main 指向 googleCtx.js)

按 README.md 的记录,该样板的技术栈为:

  • 运行时:Node.js 8.10(对应部署命令中的--runtime nodejs8,这是样板代码创作时代的记录;如今 Google Cloud Functions 的运行时版本已迭代多代,实际部署时应选用当时仍受支持的 Node 运行时并相应调整依赖版本);
  • 平台:Google Cloud Functions(HTTP 触发的 serverless 函数);
  • 框架/库:Apollo Server(GraphQL 服务框架),Cloud Functions 场景下使用其适配包apollo-server-cloud-functions

依赖声明位于 package.json:

{ "name": "google-cloud-functions-nodejs", "version": "1.0.0", "main": "googleCtx.js", "dependencies": { "apollo-server-cloud-functions": "^2.4.8", "graphql": "^0.13.1", "graphql-tag": "^2.10.1" } }

注意main字段指向googleCtx.js,说明面向 Cloud Functions 的真正部署入口是googleCtx.js中导出的handler;而index.js只是被复用的 Schema/Resolver 定义模块。这种"定义与运行环境分离"的结构,正是同一套 GraphQL 定义既能本地调试、又能无改动部署到云函数的可移植设计。

Schema 与 Resolver:最小可运行的 GraphQL 定义

核心业务定义全部收敛在 index.js 中:

const gql = require('graphql-tag'); const typeDefs = gql` type Query { hello: String } `; const resolvers = { Query: { hello: () => "world", }, }; exports.typeDefs = typeDefs; exports.resolvers = resolvers;

要点拆解:

  • typeDefs使用graphql-tag的模板标签语法声明 Schema,只有一个Query.hello: String根字段;
  • resolvershello提供实现() => "world"
  • 通过exports导出typeDefsresolvers,供本地开发与云函数两个入口复用。

对一个将要接入 Hasura 的远程 Schema 而言,这段代码虽小,却体现了三个必须满足的契约:

  1. 必须是标准 GraphQL Schema,且类型名与字段名全局唯一(Hasura 合并远程 Schema 时要求跨所有合并 Schema 类型名/节点名唯一,详见 remote-schemas.md 的 Caveats 一节);
  2. 必须提供HTTP 端点供 GraphQL Engine 转发请求;
  3. 生产环境中通常会继续扩展Mutation、加入鉴权 headers、接入数据库等,样板只演示最小闭环。

本地开发:一条命令起一个 GraphQL Playground

在进入云函数部署之前,先在本地验证 Schema 与 Resolver 的行为。README.md 给出的流程是:

# 进入样板目录 cd community/boilerplates/remote-schemas/google-cloud-functions/nodejs # 安装依赖(--no-save 表示不写入 package.json,示例环境可按需调整) npm i --no-save apollo-server # 启动本地开发服务器 node localDev.js

启动成功后控制台输出Server ready at http://localhost:4000/,浏览器访问localhost:4000即可打开 GraphQL Playground,执行:

{ hello }

得到{ "data": { "hello": "world" } }

本地入口 localDev.js 的实现如下:

const { ApolloServer } = require('apollo-server'); const { typeDefs, resolvers } = require('./index'); const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`schema ready at ${url}`); });

这里使用的是通用版apollo-server包,server.listen()默认监听4000端口并自带 Playground 界面;一旦确认本地可查询,就可以放心地把它部署到云端——因为 Schema 与 Resolver 是从index.js共享出来的同一份定义。

部署到 Google Cloud Functions

1. 准备 gcloud CLI

按 README.md 的步骤,首先安装gcloud命令行工具并完成登录、选择项目(gcloud config set project <your-project-id>)等初始化操作。

2. 编写云函数入口

部署入口 googleCtx.js 使用apollo-server-cloud-functions适配器把 Apollo Server 包装为 Cloud Functions 的 HTTP handler:

const { ApolloServer } = require("apollo-server-cloud-functions"); const { typeDefs, resolvers } = require('./index'); const server = new ApolloServer({ typeDefs, resolvers, playground: true, introspection: true, context: ({ req, res }) => ({ headers: req.headers, req, res, }), }); exports.handler = server.createHandler({ cors: { origin: '*', credentials: true, allowedHeaders: 'Content-Type, Authorization' }, });

这段代码值得注意的工程细节:

  • playground: trueintrospection: true允许在线上打开 Playground 与内省查询,方便调试(生产环境可按需关闭);
  • context把 Cloud Functions 的req/res及请求 headers 注入到每个 GraphQL 请求的 context 中,后续 Resolver 可以读取客户端传来的 headers——这与 Hasura 远程 Schema 的 header 转发机制可以很好地配合;
  • createHandler中显式配置了CORSorigin: '*'配合credentials: true,允许任意来源携带Content-TypeAuthorization头访问。由于 Hasura GraphQL Engine 通常运行在其他域名/容器中,正确的 CORS 配置是远程 Schema 能被 Engine 正常调用的关键前提

3. 执行 gcloud 部署命令

在原样板目录下运行(命令取自 README.md):

gcloud functions deploy hello-graphql --entry-point handler --runtime nodejs8 --trigger-http

参数含义:

参数作用
hello-graphql云函数名称
--entry-point handler指定函数入口为googleCtx.js导出的handler
--runtime nodejs8Node.js 运行时版本(样板记录时的版本,请按 GCP 现行支持的运行时调整)
--trigger-http使用 HTTP 触发器,返回可被公网访问的 HTTPS URL

部署成功后,gcloud会输出函数的触发信息,格式如下(示例):

httpsTrigger: url: https://us-central1-hasura-test.cloudfunctions.net/hello-graphql

httpsTrigger.url的值记录下来——这就是要交给 Hasura 的 GraphQL 端点。

把部署好的服务接入 Hasura GraphQL Engine

远程服务上线后,下一步是把它合并进 GraphQL Engine。官方文档 adding-schema.mdx 提供了 Console、CLI、Metadata API 三种等价方式。

方式一:Console 图形界面

在 Hasura Console 左侧进入Remote Schemas页签,点击Add,填写:

  • Remote Schema name:该远程 Schema 的别名,在同一个 GraphQL Engine 实例上必须唯一;
  • GraphQL server URL:上一步拿到的httpsTrigger.url,也可通过环境变量注入;
  • Headers(可选):可勾选"转发客户端全部 headers",也可追加静态 header 或"header 名-环境变量名"形式的动态 header。

点击Add Remote Schema完成合并,即可在 GraphiQL 页签中查询hello字段。

方式二:CLI 与 Metadata 文件

metadata/remote_schemas.yaml中添加条目:

- name: hello-graphql definition: url: https://us-central1-hasura-test.cloudfunctions.net/hello-graphql timeout_seconds: 60 forward_client_headers: true

然后应用元数据:

hasura metadata apply

方式三:Metadata API

/v1/metadata发送add_remote_schema请求(以 admin 角色为例):

POST /v1/metadata HTTP/1.1 Content-Type: application/json X-Hasura-Role: admin { "type": "add_remote_schema", "args": { "name": "hello-graphql", "definition": { "url": "https://us-central1-hasura-test.cloudfunctions.net/hello-graphql", "forward_client_headers": true, "timeout_seconds": 60 } } }

集成注意事项

  • 网络可达性:如果 GraphQL Engine 运行在 Docker 容器中,必须确保容器能访问云函数端点;用环境变量注入 URL 时,需在docker run时通过-e REMOTE_SCHEMA_ENDPOINT=...传入;
  • 环境变量必须在添加远程 Schema 时就存在且有效,因为 Engine 是在添加时解析并保存 URL/header 值的;
  • 当前合并机制的限制(见 remote-schemas.md Caveats):所有合并 Schema 的类型名/节点名必须全局唯一(大小写敏感);同一查询中的所有顶层节点必须来自同一个 GraphQL 服务;远程服务的 Subscription 暂不支持。

实战演进建议

这个hello样板只完成了"最小闭环",在实际项目中通常会沿以下几个方向扩展(均可在本样板结构内完成):

  1. 扩展 Schema 与 Resolver:在index.js中加入Mutation、更多 Query 字段,或通过graphql-toolsmakeExecutableSchema组合多个模块;
  2. 接入数据源:在 Resolver 中调用 REST API、数据库或第三方 GraphQL 服务,这正是远程 Schema 解决"数据库之外的自定义逻辑"的核心价值;
  3. 鉴权与 header 透传:利用googleCtx.js注入的context.headers读取客户端鉴权信息,配合 Hasura 的forward_client_headers与自定义 headers 配置完成端到端安全链路;
  4. 升级运行时与依赖:样板记录的 Node 8.10 /nodejs8运行时与apollo-server-cloud-functions ^2.4.8graphql ^0.13.1均属历史版本,部署到当前 GCP 环境时应升级到受支持的 Node 版本并同步升级 Apollo Server 与 graphql 依赖,同时验证 CORS 与 Playground 配置在新版本下的行为。

通过本文的完整流程,你可以把任意自定义 GraphQL 逻辑以 serverless 函数的形式部署到 Google Cloud,再无缝合并进 Hasura 的统一 GraphQL API——这也是官方提供的众多远程 Schema 样板(community/boilerplates/remote-schemas)中,Google Cloud Functions 场景下的标准做法。

【免费下载链接】graphql-engineBlazing fast, instant realtime GraphQL APIs on all your data with fine grained access control, also trigger webhooks on database events.项目地址: https://gitcode.com/gh_mirrors/gr/graphql-engine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 13:38:53

可综合的Verilog HDL设计:从RTL到门级网表的完整验证流程

简介&#xff1a;这是一份面向FPGA/ASIC初学者的Verilog HDL数字设计与综合习题解答资料&#xff0c;内容紧扣数字系统设计基础&#xff0c;覆盖编译综合流程、模块与端口概念、连续赋值与过程赋值区别、阻塞与非阻塞赋值适用场景&#xff0c;以及defparam参数传递、同步/异步清…

作者头像 李华
网站建设 2026/9/19 13:38:44

apache文件上传并获取参数获取text文本数据和上传

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 13:38:26

Safari 最近标签切换器:MRU 排序与模糊搜索实现

1. 为什么我要自己动手做一个 Safari 最近标签切换器用 Safari 的人大概都有过这种体验&#xff1a;开了十几个标签页&#xff0c;在几个页面之间来回跳&#xff0c;想切回刚才看的那一个&#xff0c;结果只能靠眼睛在标签栏里一个个找&#xff0c;或者用Control Tab一路按过去…

作者头像 李华
网站建设 2026/9/19 13:37:50

Windows 下 Node.js 安装配置全攻略:环境变量与 npm 避坑指南

1. 为什么 Node.js 在 Windows 上的安装值得单独写一篇很多人第一次接触 Node.js 都是在 Windows 上&#xff0c;下载一个 msi 安装包&#xff0c;一路 Next&#xff0c;装完之后打开命令行敲node -v能出版本号&#xff0c;就以为万事大吉了。结果真正开始跑项目的时候&#xf…

作者头像 李华