后端API网关【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址https://gitcode.com/gh_mirrors/cry/crystal点击查看免费下载本指南基于 PostGraphile v4 官方文档讲解如何在本地用 Docker Compose 编排一组容器——一个 PostgreSQL 数据库容器加一个以 Node.js 库形式运行 PostGraphile 的 GraphQL 容器。读完本文你将掌握把 PostGraphile 当作 Node 模块嵌入自有 HTTP 服务器、通过环境变量注入数据库连接、编写 Dockerfile 与 docker-compose.yml以及用docker-compose up一键拉起整套 API 服务。与 CLI 方式相比以库方式运行 PostGraphile 打开了更大的定制空间你可以在 PostGraphile 前后自由挂载自己的中间件、按需加载插件并把 GraphQL 服务无缝整合进已有的 Node.js 应用中。本文对应仓库中的 v4 文档 running-postgraphile-as-a-library-in-docker.md。文中代码以postgraphile^4.5.5为准。为什么选择库而不是 CLIPostGraphile 整体分为三层详见 v4 文档 usage.mdPostGraphile CLI最易上手负责接收命令行参数、启动 HTTP 服务器并挂载中间件多数用户从这里起步PostGraphile 库中间件本主题适合挂载到 Node.js HTTP、Connect、Express、Koa 等应用中文档指出约有 70% 的用户最终会使用这一层。理由包括可以在 PostGraphile 之前加入自己的 Express 中间件如限流、会话、自定义日志、自定义认证并对 PostGraphile 系统拥有更强的控制力GraphQL schemaschema-only最底层绝大多数用户不会用到。本教程与姊妹篇 Running PostGraphile in Docker 的场景完全一致唯一区别是CLI 方式在容器内全局安装postgraphile命令而本文用Node.js 应用以库方式引用 PostGraphile。前置条件先完成 PostgreSQL 容器部分本指南默认你已经按 running-postgraphile-in-docker.md 的步骤完成了以下工作仓库目前应呈现如下结构/ ├─ db/ │ ├─ init/ │ │ ├─ 00-database.sql │ │ └─ 01-data.sql │ └─ Dockerfile ├─ .env └─ docker-compose.yml其中.env已包含数据库相关变量# DB # Parameters used by db container POSTGRES_DBforum_example POSTGRES_USERpostgres POSTGRES_PASSWORDchange_medocker-compose.yml中已定义db服务、network网络与db卷。下面的步骤全部围绕新增graphql服务展开。更新环境变量为 GraphQL 容器补充连接参数编辑仓库根目录的.env文件追加PORT与DATABASE_URL[...] # GRAPHQL # Parameters used by graphql container DATABASE_URLpostgres://postgres:change_medb:5432/forum_example PORT5433两个关键点DATABASE_URL遵循postgres://user:passworddb:5432/db_name语法。注意主机名是db而不是localhost——这是 Docker Compose 网络内的服务名graphql容器正是通过它解析到数据库容器的地址PORT5433供 Node.js 应用监听与下文 docker-compose 中5433:5433的端口映射保持一致。创建 Node.js 应用把 PostGraphile 作为库使用package.json在仓库根目录新建graphql文件夹并在其中创建src子文件夹。首先在graphql/src中放入package.json{ name: postgraphile-as-library, version: 0.0.1, description: PostGraphile as a library in a dockerized Node.js application., author: Alexis ROLLAND, license: Apache-2.0, main: server.js, keywords: [nodejs, postgraphile], dependencies: { postgraphile: ^4.5.5, postgraphile-plugin-connection-filter: ^1.1.3 } }NPM 将依据此文件在容器内安装依赖其中postgraphile是核心包postgraphile-plugin-connection-filter是官方推荐的连接过滤插件用于给连接查询添加filter参数。插件也可以之后通过appendPlugins选项以代码方式加载这一点我们稍后说明。server.js在graphql/src中创建server.jsconst http require(http); const { postgraphile } require(postgraphile); http .createServer( postgraphile(process.env.DATABASE_URL, public, { watchPg: true, graphiql: true, enhanceGraphiql: true, }), ) .listen(process.env.PORT);这就是以库方式运行的核心。它使用 Node.js 内置http模块创建服务器将postgraphile(...)返回的中间件直接作为请求处理器并监听process.env.PORT即我们刚在.env中定义的5433。从 v4 的 API 签名看postgraphile(pgConfig, schemaName, options)三个参数均为可选pgConfigPostgreSQL 连接信息可以是连接字符串、传给pg.Pool的配置对象或一个pg.Pool实例。这里直接使用DATABASE_URL连接字符串schemaName要暴露的 PostgreSQL schema字符串或字符串数组默认public这里显式传入publicoptions其他杂项配置。本示例用到的三个选项watchPg: true监听数据库 schema 变化并自动更新 GraphQL API。该特性需要在数据库安装postgraphile_watchschemaPostGraphile 会尝试自动创建但需要超级用户权限失败时可手动安装移除时执行DROP SCHEMA postgraphile_watch CASCADE;graphiql: true启用 GraphiQL 交互式查询界面enhanceGraphiql: true为 GraphiQL 增加增强功能仅建议开发环境使用开启subscriptions与live时会自动启用。编写 PostGraphile Dockerfile在graphql文件夹注意不是src子文件夹中创建DockerfileFROM node:alpine LABEL descriptionInstant high-performance GraphQL API for your PostgreSQL database https://github.com/graphile/postgraphile # Set Node.js app folder RUN mkdir -p /home/node/app/node_modules WORKDIR /home/node/app # Copy dependencies COPY ./src/package*.json . RUN chown -R node:node /home/node/app # Install dependencies USER node RUN npm install # Copy application files COPY --chownnode:node ./src . EXPOSE 8080 CMD [ node, server.js ]要点拆解FROM node:alpine以官方 Node.js Alpine 镜像为基础镜像体积小适合生产WORKDIR /home/node/app设置应用工作目录USER node切换为非 root 用户运行避免以 root 身份启动 Node 服务COPY ./src/package*.json .先只复制清单文件再执行npm install这样当应用源码变化而依赖未变时Docker 可以复用依赖层缓存显著加快重复构建COPY --chownnode:node ./src .复制src下的server.js与package.json到工作目录并确保属主为node用户EXPOSE 8080声明容器监听端口仅为文档性声明实际端口映射由 docker-compose 控制CMD [ node, server.js ]容器启动时执行node server.js即启动我们上面用库方式编写的 HTTP 服务。更新 Docker Compose注册 graphql 服务编辑根目录的docker-compose.yml在services下追加graphql服务version: 3.3 services: db: [...] graphql: container_name: forum-example-graphql restart: always image: forum-example-graphql build: context: ./graphql env_file: - ./.env depends_on: - db networks: - network ports: - 5433:5433 [...]与db服务逐项对照各参数含义如下完整参数表见 running-postgraphile-in-docker.md参数说明container_name容器名称此处为forum-example-graphqlrestart: always容器退出如崩溃后自动重启image构建产物镜像名forum-example-graphqlbuild.context: ./graphql使用./graphql目录下的 Dockerfile 构建镜像env_file: ./.env将.env中的变量注入容器环境DATABASE_URL与PORT由此进入server.jsdepends_on: db声明依赖数据库服务db先启动networks: network加入与db相同的自定义网络从而可通过服务名db互访ports: 5433:5433将宿主机 5433 端口映射到容器 5433 端口此时仓库结构应为/ ├─ db/ │ ├─ init/ │ │ ├─ 00-database.sql │ │ └─ 01-data.sql │ └─ Dockerfile ├─ graphql/ │ ├─ src/ │ │ ├─ package.json │ │ └─ server.js │ └─ Dockerfile ├─ .env └─ docker-compose.yml构建镜像并启动容器构建镜像在仓库根目录执行# Build images for all services in docker-compose.yml docker-compose build # You can also build images one by one # For instance you can build the database image like this docker-compose build db # And build the graphql image like this docker-compose build graphql启动容器# Run containers for all services in docker-compose.yml docker-compose up # Run containers as daemon (in background) docker-compose up -d # Run only the database container as daemon docker-compose up -d db # Run only the GraphQL container as daemon docker-compose up -d graphql注意首次运行数据库容器时Docker 会自动创建用于持久化数据的卷卷名自动生成为your_repository_name_db。启动后各服务访问地址如下容器Docker on Linux / Windows ProDocker on Windows HomeGraphQL API Documentationhttp://localhost:5433/graphiqlhttp://your_docker_machine_ip:5433/graphiqlGraphQL APIhttp://localhost:5433/graphqlhttp://your_docker_machine_ip:5433/graphqlPostgreSQL Databasehost:localhost, port:5432host:your_docker_machine_ip, port:5432如果你在 Windows Home 上使用 Docker Toolbox可通过docker-machine ip default获取 Docker 机器的 IP 地址替换上面的your_docker_machine_ip。重新初始化数据库当修改/db/init下的 SQL 文件后需要删除卷与数据库镜像并重建才能让新 schema 生效# Stop running containers docker-compose down # List Docker volumes docker volume ls # Delete volume docker volume rm your_repository_name_db # Delete database image to force rebuild docker rmi db # Run containers (will automatically rebuild the image) docker-compose up因为db镜像已被删除docker-compose up会先自动重建镜像同时由于卷已删除/docker-entrypoint-initdb.d/中的初始化 SQL 会重新执行。在库方式下加载插件CLI 方式通过--append-plugins加载插件而库方式则把插件以数组形式传给appendPlugins选项见 v4 文档 extending.mdxconst ConnectionFilterPlugin require(postgraphile-plugin-connection-filter); //... app.use( postgraphile(process.env.DATABASE_URL, public, { appendPlugins: [ ConnectionFilterPlugin, /* add any more plugins you need here */ ], graphiql: true, }), );示例server.js中虽然没有显式加载postgraphile-plugin-connection-filter但package.json已经声明了该依赖你可以随时通过appendPlugins启用它。PostGraphile 的 schema 生成器由一系列 Graphile Engine 插件构成appendPlugins在默认插件之后加载、prependPlugins在默认插件之前加载、skipPlugins用于跳过指定插件。自定义插件实战包装 Mutation 解析器库方式最大的价值在于可以把 PostGraphile 生成的能力与自己的代码深度组合。v4 文档 running-postgraphile-in-docker.md 中的Add Custom Plugin章节给出了一个典型例子用graphile-utils提供的makeWrapResolversPlugin包装createUser变更解析器在解析器执行前后插入日志。const { makeWrapResolversPlugin } require(graphile-utils); // Create custom wrapper for resolver createUser const createUserResolverWrapper () { return async (resolve, source, args, context, resolveInfo) { // You can do something before the resolver executes console.info(Hello world!); console.info(args); // Let resolver execute against database const result await resolve(); // You can do something after the resolver executes console.info(Hello again!); console.info(result); return result; }; }; // Register custom resolvers module.exports makeWrapResolversPlugin({ Mutation: { createUser: createUserResolverWrapper(), }, });包装函数比普通 GraphQL resolver 多一个开头的resolve参数它用于委托给被包装的原始解析器不传参调用resolve()即原样透传也可传source, args, context, resolveInfo覆盖原值详见 make-wrap-resolvers-plugin.md。注意由于 PostGraphile 使用 Graphile Engine 的 look-ahead前瞻特性覆盖 resolver 不一定会影响生成的 SQL。若想影响系统执行方式应只对根级 resolver 使用包装而用包装来增强返回值如脱敏、规范化则对所有字段都安全。在库方式下将该插件文件通过require引入后放进appendPlugins数组即可无需像 CLI 方式那样在 Dockerfile 里npm pack打包插件再经--append-plugins指定。验证效果查询与变更示例数据库初始化脚本db/init创建了user与post两张表一对多关系post.author_id外键引用user.id并预置了三条用户与三条帖子。容器启动后即可在http://localhost:5433/graphiql中验证query { allPosts { nodes { id title body userByAuthorId { username } } } }mutation { createUser(input: { user: { username: Bob } }) { user { id username createdDate } } }执行createUser变更时如果你已按上文加载了makeWrapResolversPlugin包装插件终端会打印Hello world!/Hello again!及其前后的参数与结果日志。生产化建议v4 文档 usage-library.mdx 为库方式提供了生产环境选项集结合本主题可归纳为const postgraphileOptions { subscriptions: true, retryOnInitFail: true, // schema 构建失败时按指数退避重试100ms 起上限 30s dynamicJson: true, // JSON/JSONB 字段以原生 JSON 输入输出 setofFunctionsContainNulls: false, ignoreRBAC: false, extendedErrors: [errcode], graphiql: false, // 生产环境关闭 GraphiQL enableQueryBatching: true, disableQueryLog: true, // 关闭默认查询日志务必自行接入日志系统 legacyRelations: omit, };几点与 Docker 部署直接相关的提醒watchPg依赖数据库超级用户权限安装postgraphile_watchschema且会随 schema 变化重建 GraphQL schema适合开发环境生产环境更推荐在构建流程中导出 schemaexportGqlSchemaPath并关闭 watch生产环境建议关闭graphiql与enhanceGraphiql二者专为开发设计retryOnInitFail在容器化场景尤其有用数据库容器启动需要时间设为true可避免 GraphQL 容器因数据库尚未就绪而在初始化时直接退出。从源码看 PostGraphile 库的形态演进本仓库当前版本v5中postgraphile包的库接口已经从 v4 的postgraphile(pgConfig, schemaName, options)演进为预设preset驱动的工厂函数。在 postgraphile/src/index.ts 中可以看到export function postgraphile( preset: GraphileConfig.Preset, ): PostGraphileInstance { const resolvedPreset resolvePreset(preset); // 若启用 watch则通过 watchSchema 监听 schema 变化并热更新 // ... return { createServ(grafserv) { /* 创建 grafserv 服务器实例 */ }, async getSchemaResult() { /* 获取 schema 构建结果 */ }, async getSchema() { /* 获取 GraphQLSchema */ }, getResolvedPreset() { return resolvedPreset; }, async release() { /* 释放资源、停止 watch */ }, }; }从源码结构可以推断v5 的postgraphile()返回的不再是可直接app.use的中间件而是一个PostGraphileInstance对象需要通过createServ与底层 Grafserv 服务器结合使用连接串、schema、watchPg/graphiql等配置全部并入preset中。本文所讲的 v4 库方式 APIpostgraphile(connectionString, schemaName, options)三参签名与直接作为 HTTP 中间件挂载仍是理解 PostGraphile 库用法的基石v5 文档可参考仓库中 version-5 的对应教程 与 deploying-docker.md。小结至此你已经完成了一套完整的容器化 PostGraphile 库方式部署PostgreSQL 容器负责数据Node.js 容器内嵌postgraphile库提供 GraphQL API二者通过 Docker Compose 网络互联、通过.env共享配置。相比 CLI 方式库方式让你得以在 GraphQL 服务前后自由组合 Node.js 生态的中间件与自定义插件为认证、限流、日志与业务逻辑集成打开了更大的空间。动手修改db/init下的 SQL 并重建卷再在 GraphiQL 中跑一遍查询与变更即可直观感受这套架构的完整工作流。赞分享后端API网关【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址https://gitcode.com/gh_mirrors/cry/crystal点击查看免费下载相关推荐在 Docker 中以 Library 模式运行 PostGraphile V5构建 Node.js 驱动的 GraphQL 容器在 Docker 中以 Library 模式运行 PostGraphile V5构建 Node.js 驱动的 GraphQL 容器 本指南基于 PostGra后端API网关WVP-GB28181-Pro一个开箱即用的 GB28181 国标视频监控平台WVP GB28181 Pro一个开箱即用的 GB28181 国标视频监控平台 当手里的摄像头有海康的、大华的还有早年 RTSP 拉流的老设备想统一纳管或后端音视频前端Squirrel中的容器化在Docker中运行Go数据库应用Squirrel中的容器化在Docker中运行Go数据库应用 为什么需要容器化Go数据库应用 传统Go数据库应用部署常面临环境依赖复杂、版本冲突、部署流程繁琐后端数据库上一篇EntityFramework6三种开发模式深度解析Code First vs Model First vs Database First下一篇WinFsp数据恢复文件系统故障恢复工具全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考