惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Spread Privacy
Spread Privacy
T
Troy Hunt's Blog
Recent Announcements
Recent Announcements
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Schneier on Security
罗磊的独立博客
T
The Exploit Database - CXSecurity.com
博客园 - 司徒正美
月光博客
月光博客
C
Cybersecurity and Infrastructure Security Agency CISA
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Project Zero
Project Zero
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Latest news
Latest news
L
Lohrmann on Cybersecurity
阮一峰的网络日志
阮一峰的网络日志
C
CERT Recently Published Vulnerability Notes
腾讯CDC
Jina AI
Jina AI
Cyberwarzone
Cyberwarzone
T
Threat Research - Cisco Blogs
T
Tenable Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - Franky
宝玉的分享
宝玉的分享
WordPress大学
WordPress大学
Attack and Defense Labs
Attack and Defense Labs
C
Cyber Attacks, Cyber Crime and Cyber Security
V
V2EX
T
Tailwind CSS Blog
有赞技术团队
有赞技术团队
Scott Helme
Scott Helme
小众软件
小众软件
L
LINUX DO - 最新话题
博客园 - 叶小钗
博客园 - 【当耐特】
PCI Perspectives
PCI Perspectives
SecWiki News
SecWiki News
S
Security Affairs
P
Palo Alto Networks Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
S
SegmentFault 最新的问题
Recent Commits to openclaw:main
Recent Commits to openclaw:main
博客园 - 聂微东
量子位
C
CXSECURITY Database RSS Feed - CXSecurity.com
Help Net Security
Help Net Security
S
Secure Thoughts
S
Securelist

f2h2h1's blog

使用yii3实现一个微框架 claw养殖技术 计算机网络基础知识 定时任务 ACME的使用经验 magento2加上varnish缓存 开发Magento2的模块 socket编程 一些开发笔记 一段CSDN文章主要内容的油猴脚本 电子邮件的不完整总结 git的笔记 在Windows下配置PHP服务器 终端,控制台和外壳 PHP各种运行方式的不完整总结 把网页导出成PDF 和颜色相关的笔记 HTTP认证方式的不完整总结 SEO的经验 密码学入门简明指南 文件的上传和下载 用纯CSS3实现的滑动按钮 在VSCode里调试PHP Linux的GUI 关于字符编码的一些坑 nc的使用和原理 在Windows下安装Magento2 对JS原型链的理解 使用docker-compose部署magento2 浏览器和服务器通讯方式的不完整总结 观察网站性能 一些关于Linux的笔记 telnet的不完整总结 在Windows下安装pear MySQL的时间类型和时间相关的函数 Windows下通过PEB读取进程的环境变量 关于 在VSCode里使用Xdebug远程调试PHP 在Windows下搭建git服务 关于环境变量的不完整总结 使用shell实现的kv数据库 如何完成以xx管理系统为选题的毕业设计 数字号码资源 各种标记语言 使用PowerShell实现的http服务器 kind相关经验 DNSSEC简介 nginx+ffmpeg+websocket实现的直播例子 使用Tesseract识别字符验证码 使用docker部署nuxt FirstData后台的设置 paypal,firtdata,支付宝的不完整接入指南 微信支付的不完整接入指南 用docker-compose部署lnmp环境 mongodb分片 练习
在magento2中使用persisted-query
2025-09-29 · via f2h2h1's blog

什么是 persisted query

Github - scandipwa/persisted-query

Packagist - scandipwa/persisted-query

scandipwa/persisted-query 是一个用于提升 magento2 graphql 响应速度的库。 大致原理是,把请求的解释缓存在 redis ,把响应的结果缓存在 full page cache (通常是 varnish) 。 只用于 query ,不用于 mutation

persisted-query 依赖

  • Redis
  • Varnish
  • PHP ext-phpredis

安装

  1. 通过 composer 安装
composer require scandipwa/persisted-query:^2.2
  1. 修改配置文件 app/etc/env.php

    • cache中加上这一段
        'persisted-query' => [
            'redis' => [
                'host' => 'localhost',
                'scheme' => 'tcp',
                'port' => '6379',
                'database' => '5'
            ]
        ],
    
    • 在 cache_types 中加上这一段
    'persisted_query_response' => 1,
    
  2. 修改配置文件 app/etc/config.php

'ScandiPWA_PersistedQuery' => 1,
  1. 安装完后记得运行构建命令。大致例子,仅供参考
php bin/magento setup:upgrade && \
php bin/magento setup:di:compile && \
php bin/magento setup:static-content:deploy -f && \
php bin/magento indexer:reindex && \
php bin/magento cache:flush;

使用

大致的使用流程

  1. 先发送一次 PUT 请求
    • url 里需要带上一个 hash 参数, hash 的值是一个随机数,这个值不能重复
    https://localhost/graphql?hash=2443957263
    
    • PUT 请求成功后会返回 201
    HTTP/1.1 201 Created
    Content-Type: application/json
    Content-Length: 55
    
    {"error":false,"code":"1","message":"Query registered"}
    
  2. 后续发送 GET 请求, GET 请求中也需要带上 hash 参数
    • 后续的 GET 请求才会有具体的数据

关键代码的位置 vendor/scandipwa/persisted-query/src/Plugin/PersistedQuery.php

可以通过这个 http 头设置过期时间 SW-cache-age ,这是设置 查询的过期时间

如果没有特别的设置,缓存在刷新时才会失效

  • 刷新查询
    bin/magento scandipwa:pq:flush
    
  • 刷新响应
    bin/magento cache:flush persisted_query_response
    

缓存无效时会返回 401

HTTP/1.1 410 Gone
Content-Type: application/json
Content-Length: 61

{"error":true,"code":"410","message":"Query hash is unknown"}

不带参数的请求

  1. 先发送一次 PUT 请求
    curl 'https://localhost/graphql?hash=2443957263' \
      -X 'PUT' \
      -H 'accept: */*' \
      -H 'content-type: application/json' \
      --data-raw '{"query":"\nquery {\n appConfig {\n all_category_cms_page_id\n app_content\n {\n id\n value\n } } }"}'
    
  2. 后续发送 GET 请求
    curl -X 'GET' 'https://localhost/graphql?hash=2443957263'
    

带参数的请求

  1. 先发送一次 PUT 请求
    curl 'https://localhost/graphql?hash=2443957282' \
    -X 'PUT' \
    -H 'accept: */*' \
    -H 'content-type: application/json' \
    -H 'Cookie: XDEBUG_SESSION=vscode;' \
    -d '{
        "query": "query GetProductsBySkus($_filter:ProductAttributeFilterInput!, $_pageSize:Int) { products(search: \"*\", filter: $_filter, pageSize: $_pageSize ) { items { id uid sku name image { url } url_key url_suffix stock_status categories { uid name } } } }"
    }'
    
  2. 后续发送 GET 请求
    curl -X 'GET' 'https://localhost/graphql?hash=2443957282&_filter=%257B%2522sku%2522%253A%257B%2522in%2522%253A%255B%2522sku1%2522%252C%2522sku2%2522%252C%2522sku3%2522%255D%257D%257D&_pageSize=1'
    

如何构造一个带参数的请求

假设这是原本的请求

curl 'https://localhost/graphql' \
  -X 'POST' \
  -H 'accept: */*' \
  -H 'content-type: application/json' \
  -H 'Cookie: XDEBUG_SESSION=vscode;' \
  -d '{
    "query": "query GetProductsBySkus($_filter:ProductAttributeFilterInput!, $_pageSize:Int) { products(search: \"*\", filter: $_filter, pageSize: $_pageSize ) { items { id uid sku name image { url } url_key url_suffix stock_status categories { uid name } } } }",
    "variables":{"_filter":{"sku":{"in":["sku1","sku2","sku3"],"_pageSize":1}}}
}'
  1. 删除请求体中的 variables
  2. 把请求的方法改成 PUT
  3. url 中加上 hash 参数
  4. 这是最后的结果
curl 'https://localhost/graphql?hash=2443957282' \
  -X 'PUT' \
  -H 'accept: */*' \
  -H 'content-type: application/json' \
  -H 'Cookie: XDEBUG_SESSION=vscode;' \
  -d '{
    "query": "query GetProductsBySkus($_filter:ProductAttributeFilterInput!, $_pageSize:Int) { products(search: \"*\", filter: $_filter, pageSize: $_pageSize ) { items { id uid sku name image { url } url_key url_suffix stock_status categories { uid name } } } }",
}'

后续的请求中,把 variables 转换为 url编码,再直接加在 url 里

curl -X 'GET' 'https://localhost/graphql?hash=2443957282&_filter=%257B%2522sku%2522%253A%257B%2522in%2522%253A%255B%2522sku1%2522%252C%2522sku2%2522%252C%2522sku3%2522%255D%257D%257D&_pageSize=1'

这是把 variables 转换为 url编码 的伪代码

$variables = '{"_filter":{"sku":{"in":["sku1","sku2","sku3"]}},"_pageSize":1}';

$variables = json_decode($variables, true);

foreach ($variables as $key => $value) {
    $variables[$key] = urlencode(json_encode($value));
}

echo http_build_query($variables);