Eric 发布的文章

HTTP post/put 的 payload 的内容(content-type)类型

虽然看过几遍 HTTP 权威指南, 可是每次遇到 post 上传文件或者看到 Postman 的 form-data, x-www-form-urlencoded 的时候, 还是有点迷糊. 今天看 everything about curl 的时候, 又谈到了 post 的 payload 内容类型. 索性把它理清楚, 方便自己以后查找.

关于 POST 和 PUT 区别

有 ID, 每次根据 ID 去创建/更新, 就用 PUT, 具有幂等性, 多次提交不影响结果.
没有 ID, 每次都创建, 就用 POST, 不具有幂等性, 多次提交产生多次内容.

网页表单(FORM)提交

网页表单提交时, 若 method 为 POST, 表单的 enctype 属性决定了提交的负载内容(payload)的 MIME(网络多媒体类型)类型. enctype 是 encoding type 的缩写, 表示了内容的编码类型, 相当于告诉接受请求的服务器: 我这边把发送的内容经过了某种编码类型A 编码, 你收到之后也用同样的类型解码一下. 现在(20220102)enctype 可能的值(反映到 Content-Type)只有3种:

  1. application/x-www-form-urlencoded 只支持键值对,键值对中间用&分隔开, 比如 name=eric&gender=1&age=50
  2. multipart/form-data 如果表单的某个值为文件时(上传文件), 使用这种方式, 否则使用上面编码方式(简单).
  3. text/plain HTML5 新加的, 主要用于调试.

除去第三种调试用的, 我们在网页上看到的基本就是上面2种, 如果没有文件上传, 基本是第一种, 因为它最简单, 基本就是把 form 的内容根据键值对使用&连接到一起.
multipart/form-data 要对表单内容的每个项目使用分隔符分开, 它的分隔符比较长, 中间还有空行. 比如我上传一个图片文件(sni.png)和另外一个字段(key1=value1), 它的负载的内容是:

------WebKitFormBoundarycsbFnSl9t4kuAjfv
Content-Disposition: form-data; name="a"; filename="sni.png"
Content-Type: image/png

.PNG
.
...
IHDR................e....sRGB........leXIfMM.*.
<<中间省略 png 里面的1000多行二进制内容>>
...adfas
------WebKitFormBoundarycsbFnSl9t4kuAjfv
Content-Disposition: form-data; name="key1"

value1
------WebKitFormBoundarycsbFnSl9t4kuAjfv--

Ajax 请求表单/代码(微服务)提交表单

这种情况下, Content-type 可以是其它类型: application/xml, application/json

查看 DNS 查询记录

要使用外部服务, 就要连接外部 endpoint, 通常我们都是用 FQDN 去连接外部, 偶尔直接使用 IP 地址. 如果使用 FQDN, 那么就涉及 DNS 查询. 通常 DNS 记录都有 TTL (time to live)时限, 时限一过, 就要重新 DNS 查询.
使用 dig 命令可以查看一条 DNS 记录的 ttl:

$ dig +nocmd +noall +answer +ttlid a www.tianxiaohui.com
www.tianxiaohui.com.    389    IN    A    103.144.218.
$ dig +nocmd +noall +answer +ttlid a www.baidu.com
www.baidu.com.        1200    IN    CNAME    www.a.shifen.com.
www.a.shifen.com.    239    IN    CNAME    www.wshifen.com.
www.wshifen.com.    239    IN    A    45.113.192.102
www.wshifen.com.    239    IN    A    45.113.192.101

上面结果第二列就是 ttl, 单位是秒.

如何查看 Linux 上的 DNS 查询

使用 tcpdump 查看 53 端口的流量, 就能查看 DNS 查询记录 (

$ sudo tcpdump -l port 53  # -l 表示使用 buffer
06:29:08.312928 IP 10.226.197.72.40898 > sin-dns.tianxiaohui.com.domain: 42885+ A? firestore.googleapis.com. (42)
06:29:08.422806 IP sin-dns.tianxiaohui.com.domain > 10.226.197.72.40898: 42885 1/0/0 A 142.250.4.95 (58)
06:29:45.507982 IP 10.226.197.72.5013 > sin-dns.tianxiaohui.com.domain: 2509+ A? github.com. (28)
06:29:45.575657 IP sin-dns.tianxiaohui.com.domain > 10.226.197.72.5013: 2509 1/0/0 A 20.205.243.166 (44)
06:29:45.576415 IP 10.226.197.72.42090 > sin-dns.tianxiaohui.com.domain: 64400+ A? github.com. (28)
06:29:45.640234 IP sin-dns.tianxiaohui.com.domain > 10.226.197.72.42090: 64400 1/0/0 A 20.205.243.166 (44)
06:30:05.738311 IP 10.226.197.72.54902 > sin-dns.tianxiaohui.com.domain: 51140+ A? translate.google.com. (38)

如何查看一个 Java 应用程序的 DNS 查询

Java 应用程序的 DNS 最近的查询记录都记录在 InetAddress 类的某个字段中, 所以对这个字段读, 或者你有一个 heap dump, 查看这个字段, 就能查看到最近的 DNS 记录. 详细的方法, 可以查看这段代码:
https://github.com/manecocomph/myJavaAgent/blob/master/src/com/tianxiaohui/java/agent/SampleAgent.java#L191

google search Operators 谷歌搜索操作符

  1. 限定搜索结果在某个或某些站点 -> 使用 site:

    site:github.com  
    site:*.edu
  2. 完全匹配多个字符 -> 使用双引号 ""

    "Steve Jobs"
  3. 结果不包含某些字符 -> 使用减号 -

    Socket -network
  4. 模糊匹配 -> 使用星号 *

    steve * apple
  5. 或者 -> 使用 or 或 |

    steve or gates
  6. 词典 翻译 -> 使用 define:

    define:star
  7. 返回最新缓存的 -> 使用cache:

    cache:ebay.com
  8. 特定文件类型 -> 使用 filetype: 或 ext:

    Distributed Systems, 3rd Edition filetype:pdf
  9. 搜索相关站点 -> 使用 related:

    related:github.com
  10. 搜索关键字在标题, url, 文本, 超链接 -> intitle: inurl: intext: inanchor:

    intitle:star
    inurl:star
    intext:star
  11. 搜索关键字全在标题, url, 文本, 超链接 -> allintitle: allinurl: allintext: allinanchor:

    allintitle:star life water
    allinurl:star life water
    allintext:star life water
  12. 多个条件组合 -> 使用括号

    (steve or jobs) rich

Redis 学习笔记

工作中从来没用到过 Redis, 偶尔看过文档, 这次在学习数据库的理论一本书的过程中, 又萌发了要学习一边 Redis 的兴趣.
主要文档: https://redis.io/documentation
主要书籍:

  1. Mastering Redis (Packt, 2016) by Jeremy Nelson.
  2. Redis Essentials (Packt, 2015) by Maxwell Da Silva and Hugo Tavares
    实践: docker 安装 https://hub.docker.com/_/redis
$ docker network create redis-network
$ sudo docker run --network redis-network --restart always --volume /home/supra/work/data/redis/data:/data --name redis -p 6379:6379 -d redis redis-server --save 60 1 --loglevel warning
$ docker run -it --network redis-network --rm redis redis-cli -h redis

Redis Essentials 笔记:

如何搜索 grafana 的所有仪表盘(dashboard) 和面板(panel)的标题(title)

Grafana 提供了很多各种各样的图表, 被广泛用在各种需要仪表盘(dashboard)的场合. 它默认提供的搜索, 可以搜所有的文件夹名字和 dashboard 的名字. 可是有时候我们只看到别人给了一个 panel 的截图, 如何根据 panel的名字找到对应的 dashboard 呢? 当你有上千个 dashboard 的时候, 这种情况变得很困难.


最好的方式是 Grafana 提供这样一个插件, 可以搜索所有的文件夹(folder)/仪表盘(dashboard)/面板(panel)的名字, 但是我们现在没有找到.
其次, 这些文件夹(folder)/仪表盘(dashboard)/面板(panel)都定义在 grafana 背后的一个数据库中, 如果这个数据库的表提供了全文索引, 也能方便我们搜索. 但是现在也没有.

那么有没有可能我们把所有的 文件夹(folder)/仪表盘(dashboard)/面板(panel) 的标题放到一个支持全文索引的产品里面, 然后提供一个索引搜索的可能呢?

这种方式是可行的. 首先, Grafana 提供了一整套的 API, 我们可以通过 API 列出所有的文件夹, 然后列出每个文件夹下的所有 dashboard, 然后查询每个 dashboard 的每个 panel , 这样我们就能获得 文件夹(folder)/仪表盘(dashboard)/面板(panel) 的所有标题了. 接着, 我们把获得的标题放到一个支持全文索引的产品, 就能支持全面搜索了.

这里我们给出一个 JavaScript 的脚本, 当你打开你的 Grafana 之后, 然后登录, 然后打开开发者工具, 选择 Console tab, 然后运行这个脚本. 当脚本运行完之后, 在运行导出脚本, 它会打印所有要导出的 json 内容, 然后把这些 json 内容复制到文本编辑器, 然后保存到本地.

获得所有标题的内容

使用这个脚本
https://github.com/manecocomph/scripts/blob/main/JavaScript/grafana/exportAllTitles.js
当上面的脚本运行完之后, 可以看到上面的文件结尾处在注释的地方有个导出脚本, 运行导出脚本. 导出完之后, 复制保存到本地.
export.png

导入到 MongoDB, 并设置全文索引

安装 MongoDB 和 webUI. 更改下面的 volume 到你的本地文件夹

sudo docker network create mongo-network
sudo docker run --network mongo-network --restart always -p 27017:27017 --volume /home/supra/work/data/mongo/grafana:/data/db --name mongodb -d mongo
sudo docker run --network mongo-network --restart always -e ME_CONFIG_MONGODB_SERVER=mongodb -p 8081:8081 --name mongoui mongo-express

可以选择 webUI 导入, 或者使用下面的命令行在 docker 容器内导入(更改 db 名字和 collection 名字, 以及文件名)

mongoimport --db dbName --collection collectionName --file fileName.json 

设置全文索引, 如何查询

db.grafana.createIndex({title: "text", folder: "text", panels: "text", });
db.grafana.find({$text: {$search: "EricTian"}});

导入 ElasticSearch & Kibana

安装 ES & Kibana

sudo docker network create elastic-network
sudo docker run --restart always --name es01 --network elastic-network -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -d docker.elastic.co/elasticsearch/elasticsearch:7.15.2
sudo docker run --restart always --name kib01 --network elastic-network -p 5601:5601 -e "ELASTICSEARCH_HOSTS=http://es01:9200" -d docker.elastic.co/kibana/kibana:7.15.2

打开 http://host:5601/ 然后导入数据文件, 然后查询

导入 Splunk (最方便)

安装 Splunk

sudo docker run --rm -p 8000:8000 -e "SPLUNK_START_ARGS=--accept-license"  -e "SPLUNK_PASSWORD=admin" --name splunk splunk/splunk

打开 http://host:8000/ 输入用户名/密码 admin/admin 然后选择导入数据文件, 然后查询