#539 基于 CentOS Stream 的桌面环境

2021-12-15

CentOS Stream 9 已于月初发布,基于 Fedora 34,这就是 RHEL 9 未来的发展方向。
CentOS Stream 的稳定性应该是比 Fedora 更好,如果我想选择改用 Fedora 当桌面环境,为什么不试试 CentOS Stream 呢?
这里就开始调研一下。

#537 DNS_PROBE_FINISHED_NXDOMAIN

2021-12-14
  1. 浏览器突然打不开 zhihu.com, 报 DNS_PROBE_FINISHED_NXDOMAIN
  2. Windows 网络诊断之后说是 DNS 不可用。
  3. 经过检查,使用 DHCP 获取到的 DNS 172.16.0.1
  4. 改成 AliDNS: 223.5.5.5, 223.6.6.6 之后就好了。
  5. 然后再改回默认的 DNS 发现也能正常访问了。

我应该在出现问题的时候先尝试 nslookup 一下,看看 DNS 解析出来的到底是个什么结果。
下次遇到再继续更新。

C:\Users\Administrator>ipconfig /all | findstr DNS
   主 DNS 后缀 . . . . . . . . . . . :
   连接特定的 DNS 后缀 . . . . . . . :
   DNS 服务器  . . . . . . . . . . . : 172.16.0.1
   连接特定的 DNS 后缀 . . . . . . . :
   DNS 服务器  . . . . . . . . . . . : fec0:0:0:ffff::1%1
   连接特定的 DNS 后缀 . . . . . . . :
   连接特定的 DNS 后缀 . . . . . . . :
   连接特定的 DNS 后缀 . . . . . . . :
   连接特定的 DNS 后缀 . . . . . . . :

C:\Users\Administrator>nslookup zhihu.com
服务器:  UnKnown
Address:  172.16.0.1

非权威应答:
名称:    zhihu.com
Address:  103.41.167.234

#536 Tornado HTTP 服务的 “ACK”

2021-12-13
  1. 一个请求会先到 A 服务,然后通过 HTTP 调用的方式传到 B 服务 (基于 Tornado)
  2. 面对突然涌来的大量请求,B 服务负载迅速升高,响应时间拉长
  3. A 服务的部分请求因为超时断开,然后重发

也就是说,在负载较高的时候,B 会收到一些重复请求。因为负载高的时候,B 其实已经接收过一遍,只是没有响应。
B 服务处理任务结束之后,会将请求加入幂等。但是在 B 服务正在处理的时候,还是会有重复处理的可能性。
如果是一些对数据可靠性有一定要求的场景,这样重复的处理就不能接受。

比较合适的设计应该是 A 和 B 之间通过 MQ 通讯,根本不可能有这样的情况发生,哪怕请求再多也可以按照自己的速度消费,使系统保持最佳状态运行。而且,服务之间解耦之后,可以避免相互影响。

但是,如果不能改变 A B 两个服务的现有设计(调用关系),可以做的事情:

  1. 通过请求的正常返回来当 ACK 机制 (本文原本想重点说的内容)
    1. 将请求的接收和处理拆开
    2. 请求收到,加入队列,然后就可以返回了,这个时间非常短,这个过程出现问题的可能性非常低
    3. 如果在处理请求之前,连接断开,那就结束流程,抛弃任务
  2. A 服务的重试机制延迟一个合适的时间(比如 3 分钟)处理,可以通过 MQ, DB, Redis 实现

两个方案都应该能大幅减小出现重复请求的情况,双管齐下效果会更好。
方案一, 如果引入 MQ 或 DB 的话,就会觉得为什么不在 A 服务做;如果不引入新组件的化,复杂是需要保证服务突然挂掉之后,队列数据的恢复。只能在启动服务时通过扫描日志来恢复数据。
方案二,无论是业务还是代码,影响范围比较小,易于实现。

Tornado 实现 ACK 机制

客户端在正常流程处理完成之前,断开连接,会触发 on_connection_close 调用,可以在这个里面做手脚。

class MainHandler(tornado.web.RequestHandler):
    def post(self):
        if self._finished:
            return
        # do something

    def on_connection_close(self):
        LOG.debug('connection closed')
        self._finished = True
        super().on_connection_close()

#532 程序员的 10 个习惯

2021-12-08

公众号四猿外的文章《这 10 个程序员的好习惯,让我变强了》,很有同感,这里总结一下:

  1. 要看官方文档,网上的资料鱼龙混杂
  2. 开发者的可靠性:自测没有问题了再交付
  3. 日志设计合理,保证调试时,有恰当的信息来定位问题
  4. 精通 Git
  5. 优先功能实现,别急着优化
    过早优化是魔鬼,应该根据实际运行的情况来优化
  6. 先做明确的需求,不确定或者模糊的需求先往后放
  7. 积极主动:发现问题,提出方案,解决问题
  8. 开发时间评估,保证有冗余时间,以处理可能的意外
  9. 学习编程主要靠上手写代码,不要光看文档
  10. 英语。不需要很好,能看懂英文文档就行

#530 转载:云原生时代,Java 的危与机

2021-12-03

今天,25 岁的 Java 仍然是最具有统治力的编程语言,长期占据编程语言排行榜的首位,拥有一千二百万的庞大开发者群体,全世界有四百五十亿部物理设备使用着 Java 技术,同时,在云端数据中心的虚拟化环境里,还运行着超过两百五十亿个 Java 虚拟机的进程实例 (数据来自Oracle的WebCast)。
以上这些数据是 Java 过去 25 年巨大成就的功勋佐证,更是 Java 技术体系维持自己“天下第一”编程语言的坚实壁垒。Java 与其他语言竞争,底气从来不在于语法、类库有多么先进好用,而是来自它庞大的用户群和极其成熟的软件生态,这在朝夕之间难以撼动。然而,这个现在看起来仍然坚不可摧的 Java 帝国,其统治地位的稳固程度不仅没有高枕无忧,反而说是危机四伏也不为过。目前已经有了可预见的、足以威胁动摇其根基的潜在可能性正在酝酿,并随云原生时代而降临。

#529 curl: 通过 SSH 隧道执行

2021-12-03
ssh user@host curl http://anyurl

先建立 SSH 代理,在 curl:

ssh -D 19888 -CNfq user@host
curl -x socks5h://localhost:19888 http://anyurl

后面的 CNfq 也是非常好记的,懂的懂。
至于什么含义,可以 man ssh

#528 Nginx 缓存导致的问题

2021-12-03

背景:公司有两套环境,其中有一个 Web 服务,包含一个比较耗时的接口。

今天收到反馈说环境 B 中的接口每次都是半天没有反应,等执行完一次性输出,A 环境中则是流式的,一点一点输出。
然后相关同事希望 A 环境体验好一些,希望 B 环境能和 A 环境保持一致。

经过检查,发现其中一遍经过了 Nginx 的代理,马上就想到了代理缓存的问题。

联系运维修改配置,在相关 server 中添加 proxy_buffering off;,问题果然解决。

#527 Susam Pal:Curl 计时

2021-11-28

Here is a command I use often while measuring why an HTTP request is taking too long:

curl -L -w "time_namelookup: %{time_namelookup}
time_connect: %{time_connect}
time_appconnect: %{time_appconnect}
time_pretransfer: %{time_pretransfer}
time_redirect: %{time_redirect}
time_starttransfer: %{time_starttransfer}
time_total: %{time_total}
" https://example.com/

Here is the same command written as a one-liner, so that I can copy it easily from this page with a triple-click whenever I need it in future:

curl -L -w "time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_pretransfer: %{time_pretransfer}\ntime_redirect: %{time_redirect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" https://example.com/

Here is how the output of the above command typically looks:

$ curl -L -w "namelookup: %{time_namelookup}\nconnect: %{time_connect}\nappconnect: %{time_appconnect}\npretransfer: %{time_pretransfer}\nstarttransfer: %{time_starttransfer}\ntotal: %{time_total}\n" https://example.com/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
...
</html>
time_namelookup: 0.001403
time_connect: 0.245464
time_appconnect: 0.757656
time_pretransfer: 0.757823
time_redirect: 0.000000
time_starttransfer: 0.982111
time_total: 0.982326

In the output above, I have omitted most of the HTML output and replaced the omitted part with ellipsis for the sake of brevity.

The list below provides a description of each number in the output above. This information is picked straight from the manual page of curl 7.20.0. Here are the details:

  • time_namelookup: The time, in seconds, it took from the start until the name resolving was completed.
  • time_connect: The time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed.
  • time_appconnect: The time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed. (Added in 7.19.0)
  • time_pretransfer: The time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.
  • time_redirect: The time, in seconds, it took for all redirection steps include name lookup, connect, pretransfer and transfer before the final transaction was started. time_redirect shows the complete execution time for multiple redirections. (Added in 7.12.3)
  • time_starttransfer: The time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the time the server needed to calculate the result.
  • time_total: The total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution.

An important thing worth noting here is that the difference in the numbers for time_appconnect and time_connect time tells us how much time is spent in SSL/TLS handshake. For a cleartext connection without SSL/TLS, this number is reported as zero. Here is an example output that demonstrates this:

$ curl -L -w "time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_pretransfer: %{time_pretransfer}\ntime_redirect: %{time_redirect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" http://example.com/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
...
</html>
time_namelookup: 0.001507
time_connect: 0.247032
time_appconnect: 0.000000
time_pretransfer: 0.247122
time_redirect: 0.000000
time_starttransfer: 0.512645
time_total: 0.512853

Also note that time_redirect is zero in both outputs above. That is because no redirection occurs while visiting example.com. Here is another example that shows how the output looks when a redirection occurs:

$ curl -L -w "time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_pretransfer: %{time_pretransfer}\ntime_redirect: %{time_redirect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" https://susam.in/blog
<!DOCTYPE HTML>
<html>
...
</html>
time_namelookup: 0.001886
time_connect: 0.152445
time_appconnect: 0.465326
time_pretransfer: 0.465413
time_redirect: 0.614289
time_starttransfer: 0.763997
time_total: 0.765413

When faced with a potential latency issue in web services, this is often one of the first commands I run several times from multiple clients because the results form this command help to get a quick sense of the layer that might be responsible for the latency issue.

#526 转载:是谁拉黑了你的IP

2021-11-24

邮件无法送达的原因有很多,例如 取消订阅、服务器不可达、地址格式错误或不存在、被判定为垃圾邮件、发信人/收信人被拒等等等等…今天,我们来聊一下 IP、域名被拒。