GraphQL的踩坑之路

为了更好的支持前端能够自由组合、展示收到的数据,笔者使用graphql-go 框架开发了负责的模块,但测试过程中发现,使用GraphQL会有n+1 query的问题。经过调研发现两种解决方案:

  • 使用graphql-gophers下的graphql-go,已经支持如下特性:
    • minimal API
    • support for context.Context
    • support for the OpenTracing standard
    • schema type-checking against resolvers
    • resolvers are matched to the schema based on method sets (can resolve a GraphQL schema with a Go interface or Go struct).
    • handles panics in resolvers
    • parallel execution of resolvers
  • 在使用graphql-go的同时使用facebook开源的dataloader工具,详细例子见dataloader的issues: Example to use with graphql-go

n + 1 query解释

Scheme (simplified):

““
type Query {
orders: [Order]
}

type Order {
id: ID
client: Client
}

type Client {
id: ID
name: String
}
““

Query:

query GetOrders {
  orders {
    client {
      name
    }
  }
}

解释

为了返回100个orders,必须发送101个请求给微服务(1个请求获取批量的orders,100个获取它的client信息(每个order都需要执行一次client信息查询)。详细信息见issues: No way to get requested fields inside resolver

性能分析过程

使用vegeta工具向服务发送流量,然后使用pprof和go-torch工具对服务进行分析。

vegeta命令说明

向服务发送流量命令

 echo "POST http://localhost:8080/graphql" | vegeta attack -body /vegeta/rqst.txt -duration=30s -rate=200 > r.bin

发送流量结果分析

 vegeta vegeta report -inputs=r.bin
Requests      [total, rate]            6000, 200.03
Duration      [total, attack, wait]    29.998652838s, 29.994999868s, 3.65297ms
Latencies     [mean, 50, 95, 99, max]  3.740812ms, 3.649598ms, 4.53176ms, 5.088892ms, 22.366809ms
Bytes In      [total, mean]            222000, 37.00
Bytes Out     [total, mean]            2802000, 467.00
Success       [ratio]                  100.00%
Status Codes  [code:count]             200:6000  
Error Set:
  • 向服务发送流量命令解释: 向部署在本地的端口号为8080的服务发送POST请求,持续时间为30s,每秒发送200个请求,请求的内容存放在vegeta目录下的rqst.txt文件中。
  • 发送流量结果分析解释: 对压测的结果以报表的形式展示出来。

pprof命令说明

在使用vegeta命令压测的同时使用go tool的pprof工具分析CPU的耗时go tool pprof -seconds 25 http://localhost:8080/debug/pprof/profile,持续25s后输入web ,生成如下所示的内容:

这里写图片描述
虽然go1.9在使用pprof工具生成CPU耗时分析的时候较之前的版本已经加入了颜色,但是看起来仍不是很直观,这个时候就需要使用火焰图了。

go-torch生成火焰图

在使用vegeta命令压测的同时使用go-torch工具生成火焰图,命令go-torch -u http://192.168.189.168 -t 25 生成的火焰图如下图所示:(192.168.189.168为本地的localhost)
这里写图片描述

通过火焰图分析,graphql-go框架的占用很多的CPU耗时,查找资料发现,主要原因是graphql的Resolver函数的解析并非并发解析,所以会产生上面描述的n + 1 query的问题。

<think>嗯,用户想了解Next.js和Strapi结合使用的信息,看来是在探索全栈开发方案。从引用内容看,用户已经收集了一些基础资料,包括最佳实践、安全性和项目模板。 用户可能是个前端开发者,正在评估技术选型,或者是个全栈工程师想快速搭建项目。ta的语气比较明确,应该不需要基础概念科普,而是想要实用指南。值得注意ta特意提到“不是真正需求”,说明引用材料可能有些偏离重点。 从技术角度看,需要覆盖这几个维度:首先是架构模式,Strapi作为无头CMS提供API,Next.js处理渲染这种核心分工;然后是具体集成方式,比如Next.js里如何消费Strapi的GraphQL/REST API;最后是进阶技巧,像增量静态再生怎么配合内容更新。 用户引用的材料里有些关键点可以深化:比如引用[1]提到的博客案例,可以补充具体代码示例;引用[2]的权限控制值得展开说明JWT验证流程;引用[3]的模板项目如果能给出GitHub链接会更实用。 考虑到用户可能马上要动手开发,回复应该偏向实战:安装步骤可以简略,但环境变量配置、API端点定义这些容易的地方要强调。SEO优化那块特别重要,因为这是选择Next.js的主要优势之一。 对了,安全部分不能漏——虽然引用[2]提了权限,但还要补充Next.js端如何安全存储访问令牌。性能方面,ISR和SSG的区别应用场景可能也是用户关心的。 </think>基于Next.js与Strapi构建全栈应用的完整指南如下: --- ### 一、核心架构分工 1. **Strapi(后端)** - 无头内容管理系统,提供REST/GraphQL API接口 - 功能模块: - 内容建模(文章/用户/分类等) - 角色权限控制(引用[2]) - 媒体文件管理 - 插件扩展(如SEO优化插件) ```bash # 创建Strapi项目 npx create-strapi-app@latest my-project --quickstart ``` 2. **Next.js(前端)** - 支持SSR/SSG/ISR渲染模式 - 核心能力: - 自动API路由(`pages/api/*`) - 增量静态再生(ISR) - 内置CSS/Sass支持 --- ### 二、集成最佳实践 #### 数据获取流程 ```javascript // Next.js页面示例 (pages/blog/[slug].js) export async function getStaticProps({ params }) { // 从Strapi获取数据 const res = await fetch(`https://your-strapi-url/articles?slug=${params.slug}`); const article = await res.json(); return { props: { article }, revalidate: 60 // 启用ISR,每分钟更新 }; } ``` #### 安全增强方案 1. **API保护** ```javascript // Strapi配置 (config/middlewares.js) module.exports = [ 'strapi::security', { name: 'strapi::cors', config: { origin: ['https://your-nextjs-domain.com'] } }]; ``` 2. **前端验证** ```javascript // Next.js API路由 export default async (req, res) => { const token = req.headers.authorization?.split(' ')[1]; // JWT验证逻辑... } ``` --- ### 三、性能优化技巧 | 策略 | 实现方式 | 适用场景 | |---------------------|-----------------------------------|------------------| | 静态生成(SSG) | `getStaticProps` + `revalidate` | 文章详情页 | | 增量静态再生(ISR) | 配合Strapi webhook触发重建 | 频繁更新内容 | | 客户端渲染(CSR) | SWR/stale-while-revalidate | 用户仪表盘 | > **SEO关键配置**: > - Strapi安装`SEO Plugin`生成sitemap > - Next.js使用`next-seo`包管理meta标签 > - 动态路由结合`getStaticPaths`预渲染(引用[1]) --- ### 四、开发效率提升 1. **快速启动模板** ```bash # 使用官方模板(引用[3]) npx create-next-app -e https://github.com/strapi/nextjs-corporate-starter ``` 2. **实时内容预览** - 配置Strapi的`Preview URL`指向Next.js开发环境 - 使用`useEffect`监听内容更新(开发模式) --- ### 五、应用场景示例 **企业官网场景**: 1. Strapi管理:新闻动态/产品目录/招聘岗位 2. Next.js实现: - 首页:SSG静态化(`getStaticProps`) - 新闻页:ISR增量更新 - 后台:CSR动态渲染 + 权限验证(引用[2]) ---
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值