#763 HTTP 超时相关的疑问
Linux HTTP 2022-02-25今天发现一个奇怪的现象,相同的代码在 CentOS 7 服务器上发起 HTTP 请求 3 秒之后超时,报 “TimeoutError: [Errno 110] Connection timed out”。
在我本地就按我们的定义的超时时间 5 秒超时,报 “tornado.simple_httpclient.HTTPTimeoutError: Timeout while connecting”。
coding in a complicated world
今天发现一个奇怪的现象,相同的代码在 CentOS 7 服务器上发起 HTTP 请求 3 秒之后超时,报 “TimeoutError: [Errno 110] Connection timed out”。
在我本地就按我们的定义的超时时间 5 秒超时,报 “tornado.simple_httpclient.HTTPTimeoutError: Timeout while connecting”。
线上环境 HTTP 服务有报获取不到 Host 信息。应该是域名,但是拿到的是 backend 这样的名字。
我第一反应肯定是 Nginx 的配置问题,我印象中 Nginx 给 upstream 转发的请求就会设置 Host 为 upstream 名称。
但是我检查了 Nginx 的配置 (nginx.conf), 在 http 这一层的配置中有 proxy_set_header Host $http_host;
。
不过搜索 proxy_set_header 的时候发现,在 server 这一层设置了 proxy_set_header X-Forwarded-For $remote_addr;
, 这个头在 http 这一层也设置了,没必要在设置的。
我就想到,会不会下层设置头会覆盖上一层的所有头设置。
在 Nginx 文档 (proxy_set_header) 中查到:
Allows redefining or appending fields to the request header passed to the proxied server.
The value can contain text, variables, and their combinations.
These directives are inherited from the previous configuration level if and only if there are no proxy_set_header directives defined on the current level.
当本层没有 proxy_set_header 指令的时候,才会继承上一级的 proxy_set_header 指令。
将 server 层重复的这个设置拿掉,果然就好了。
已经 30 几了,生活一团糟。
如果能有些事业,好歹有一个方面可以让我感受到自己的价值,至少可以分散一下注意力。可是,也没有,反而也是个令人糟心的事,让我常有髀肉复生之叹,感觉人生就要荒废。
我感觉我在一个漩涡中无法自拔,想逃离却又不能逃离。我不知道该怎么做。我时常想起《阿甘正传》中珍妮的祈祷。
这个可能就是中年危机的前兆吧!
公共库 CDN,也叫静态资源库。
我想了一下,国内公共库 CDN 全面挂了可能是由于监管压力。
在国内,如果 CDN 提供的静态资源被一些恶意网站引用,会被问责。如果要全面审核使用 CDN 的网站,肯定是会增加太多的管理成本。
感觉这真是太不合理了!
如果是线上项目,不要用公共库 CDN。
小项目自己管理静态资源,大项目可以用付费的 CDN 服务。
我之前用的最多的 CDN,但是总是挂,心累。现在开始用字节跳动 CDN 了。
已经挂了。
打不开。
只有很少的资源。
只有很少的资源。
感觉很久没有维护了。一些常用库都非常老了。
https://db-engines.com/en/ranking
https://db-engines.com/en/ranking_trend
https://db-engines.com/en/ranking/relational+dbms
这几种大型商用数据库就不提了,除了 Access 和 SQL Server 稍微熟悉一点点之外,其他几个碰都没碰过。
开源:
MongoDB 遥遥领先。
排除两个商业服务 Splunk, Algolia。
Elasticsearch 和 Solr 都基于 Apache Lucene
熟悉的 RDB 基本上都是行式存储。
Cassandra 遥遥领先, 第二是 HBase。
set file capabilities, 设置文件权限
setcap
usage: setcap [-q] [-v] [-n <rootid>] (-r|-|<caps>) <filename> [ ... (-r|-|<capsN>) <filenameN> ]
Note <filename> must be a regular (non-symlink) file.
编程语言中一般都有枚举类型。可以用来替换代码中的那些有一定范围的常量,减少幻数的使用,提升代码可读性。
有些语言的枚举支持遍历等操作,有一些语言的枚举还支持枚举值和枚举名字的映射。
Go 没有在语言层面实现枚举,只能通过定义一组变量。
比如(src/runtime/time.go
):
const (
timerNoStatus = iota
timerWaiting
timerRunning
timerDeleted
timerRemoving
timerRemoved
timerModifying
timerModifiedEarlier
timerModifiedLater
timerMoving
)
官方代码(src/time/time.go
)中有些地方会给这些变量加一个自定义类型:
// A Weekday specifies a day of the week (Sunday = 0, ...).
type Weekday int
const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
Linksys WRT54G 系列路由器(2002 年 12 月首次发布)的操作系统是基于 Linux 内核开发。
2003 年,思科旗下的 Linksys 公司面对各方面压力,开源了 WRT54G 源代码。
PS: Linksys 是美国加州的台湾移民创建, 2003 年被思科收购, 2013 年又被 Belkin 收购。2018 年 Belkin 被台湾的富士康收购。
2014 年,作为 Linux 嵌入式发行版发行。
2015 年,与 LibreWRT 项目(研究项目)合并。
2017 年,基于 LEDE 17。
2020 年,基于 OpenWrt 19。
iKuai / iKuic (海外)
北京丰台一家网络设备厂商的闭源路由器系统,有商业版和免费版。
https://www.ikuai8.com/component/download
之前的文章:Golang HTTP 以及 HTML/XML 解析
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
resp, err := http.Get("https://www.baidu.com")
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
fmt.Printf("%#v\n", resp.Status) // string, "200 OK"
fmt.Printf("%#v\n", resp.StatusCode) // int, 200
fmt.Printf("%#v\n", resp.Header) // http.Header, map[string][]string
fmt.Printf("%#v\n", resp.Request) // *http.Request
fmt.Printf("%#v\n", resp.ContentLength) // int64
fmt.Printf("%#v\n", resp.TransferEncoding) // []string(nil)
fmt.Printf("%#v\n", resp.Trailer) // http.Header(nil)
fmt.Printf("%#v\n", resp.Uncompressed) // bool
fmt.Printf("%#v\n", resp.TLS) // *tls.ConnectionState
fmt.Printf("%#v\n", resp.Body) // *http.bodyEOFSignal => io.ReadCloser => io.Reader
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
admin@victus:~$ cd /C/Program\ Files/Go/src/mime/multipart
nosch@victus:/C/Program Files/Go/src/mime/multipart$ grep -ER 'func.+\) [A-Z]\w+' .
./formdata.go:func (r *Reader) ReadForm(maxMemory int64) (*Form, error) {
./formdata.go:func (f *Form) RemoveAll() error {
./formdata.go:func (fh *FileHeader) Open() (File, error) {
./formdata.go:func (rc sectionReadCloser) Close() error {
./formdata_test.go:func testFile(t *testing.T, fh *FileHeader, efn, econtent string) File {
./formdata_test.go:func (r *failOnReadAfterErrorReader) Read(p []byte) (n int, err error) {
./multipart.go:func (p *Part) FormName() string {
./multipart.go:func (p *Part) FileName() string {
./multipart.go:func (r *stickyErrorReader) Read(p []byte) (n int, _ error) {
./multipart.go:func (p *Part) Read(d []byte) (n int, err error) {
./multipart.go:func (pr partReader) Read(d []byte) (int, error) {
./multipart.go:func (p *Part) Close() error {
./multipart.go:func (r *Reader) NextPart() (*Part, error) {
./multipart.go:func (r *Reader) NextRawPart() (*Part, error) {
./multipart_test.go:func (mr *maliciousReader) Read(b []byte) (n int, err error) {
./multipart_test.go:func (s *slowReader) Read(p []byte) (int, error) {
./multipart_test.go:func (s *sentinelReader) Read([]byte) (int, error) {
./writer.go:func (w *Writer) Boundary() string {
./writer.go:func (w *Writer) SetBoundary(boundary string) error {
./writer.go:func (w *Writer) FormDataContentType() string {
./writer.go:func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error) {
./writer.go:func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error) {
./writer.go:func (w *Writer) CreateFormField(fieldname string) (io.Writer, error) {
./writer.go:func (w *Writer) WriteField(fieldname, value string) error {
./writer.go:func (w *Writer) Close() error {
./writer.go:func (p *part) Write(d []byte) (n int, err error) {
GitHub: http client stars:>1000
简单的了解:
前些天应该都看过微软 Exchange Server 开发者跨年改 BUG 的新闻了吧 (相关链接)。
Exchange Server 的邮件过滤器采用了 yymmddHHMM
格式的时间,存储在 long
类型字段中。
PS: 微软的 C++ Compiler 会将 long 当做 32 位 int。
32 位有符号整形能够表达的范围:[$-2^{31}$, $2^{31} - 1$],也就是 [-2147483648, 2147483647]。
到了 2022 年,就会超出范围,比如 2022-01-01 12:00:00
, 会被存储为 2201011200
,会超出 signed int 的表达范围。
2147483647
2201011200 # 超出
可能有一些系统采用 int 类型存储 yymmdd + 4 位数字做编号的方式,比如 2101011234。
相同的原因,到了 2022 年,就行不通了。
2147483647
2201011234 # 超出
最好的办法是改成 long long
, 或者 unsigned int
。
PS: Linux 下的 C/C++ 编译器——GCC、CLang/LLVM 都是将 long 当做是 64 位。