计算机网络实用技术:序章

Hi,我是信涛,喜欢抓包。

我打算写一个以现实应用的网络技术为主题的系列文章,姑且将其称之为「书」吧。(还从没有写过系列长篇,所以这对我来说也是一个挑战。)

这本书面向的读者

大学的网络课程,和很多计算机网络的教材,普遍存在一个问题:内容比较抽象。大部分教材都是适合对网络有所了解的人,去学习新的网络来阅读。如果是刚刚学习网络,会觉得这些抽象的内容比较难理解,会产生多问题,而这些问题大部分来自于不正确的理解。

由于内容抽象,导致阅读枯燥。我经历过这一段时间,比较喜欢学习编程,因为编程学习了就可以实践,能够看到效果;而网络的学习通常不好实践,没有实践的话,学习效果就大打折扣。所以一度认为自己与计算机网络八字不合。

但是当我在工作中遇到网络问题,没有人能够解决(或者愿意花时间去解决),然后我去抓包,分析,最后精准找到问题原因的时候,我发现网络是如此有趣!

之后的工作中,我积累了很多网络问题排查的案例,有一些记录在之前的博客中了,有一些还只存在我的笔记中。

这些案例都和网络协议等基础知识有关,又需要动手,结合实际来分析。我发现去解决实际问题很大程度上加深了我对原来学习的内容的理解。我也发现,有很多人工作多年, 竟然从没用过 Wireshark 来分析网络问题(即使他们的工作和网络相关!)。我认为原因就是,第一次太难,当你从没有用 Wireshark 来解决问题,那么遇到问题的时候,你也不会想到去分析。即使打开,面对五花八门的字段,也会感觉无从下手。我也经过这种时候。但是如果用过几次,就不一样了,在用 Wireshark 解决过一次问题之后,信心会大增,甚至遇到问题会感到兴奋——我倒要看看还能是哪里出了问题!

所以本书以让实际动手分析为主,章节大部分成对出现,第一节抛出问题,描述问题,读者可以进行自己的分析。之后发布第二节,揭晓答案,结合网络协议知识,分析相关的网络设计。

另一个问题是,教科书普遍都在介绍过时的技术。比如谈到数据链路层,必开始介绍 CDMA 如何解决冲突的,这部分内容比较枯燥,也让人困惑:为什么 Frame 要发给不需要它的机器,然后再处理冲突?事实上,这都已经是几十年前的网络了,现代的网络 Ethernet 是全双工的,交换机是只发给指定目的端口的,完全不会遇到冲突然后避让。当然学习这些技术是有用的,但是不建议一上来就讲这么枯燥、现代网络又几乎用不上的内容。

比如谈到 IP 地址,必介绍 IP 分类。然后出个问题考考你:「这个 IP 是 A 类还是 B 类?」后来,工作这么多年从没遇到一个问题需要我判断一个 IP 是几类 IP 的(倒是需要经常判断一个 IP 是不是 Private IP)。因为如今的网络掩码都是可变长度了,Classful network 那是上个世纪的东西了,没有人用这种 IP 分类划分网络了。

网络的世界中存在很多这种「过时」的设计,根本原因是,在设计之初,没有意识到今后的世界会如何发展,比如 IPv4 耗尽问题,近几年的区块链趋势,AI,等等,所以不合时宜的设计是必然会存在的。我们需要学习的是这些设计当初的考虑是什么,为什么这么设计,存在的问题有哪一些,如今的替代方案是什么。这样,才不会让自己都「学了一些没用的东西」。即使学习「过时」的技术,我们也可以从中吸取经验。

所以本书会结合现代的网络技术,介绍网络知识的同时,也介绍一下当前流行的解决方案。

本书适合阅读过一些网络教材但是感觉一身武功无处施展的读者,也适合在工作中没有思路解决实际的网络问题的读者,如果你是网络高手的话,可以拿本书来消遣,看本书抛出的问题是否能够应付自如。

如何阅读?

在问题章节,会描述问题的场景,给出一个抓包文件。读者可以根据对问题的描述,下载抓包文件进行分析,得出自己的答案。推荐重新阅读一遍问题的描述,看一下自己的答案是否能够完全解释的通场景中的问题。(就像做 leetcode 一样,有趣吧?)

读者可以在评论区发布自己的想法,和其他读者交流。我会在文末留白来和评论隔离开,避免剧透。

答案发布之后,如果读者的想法和答案一致,说明我们英雄所见略同。如果不一致,也可以将您的想法贴在评论中,说不定答案并不止一种。

问题的设计会尽量让读者有「哦!原来是这样」的感觉,而不是感觉被耍了。不然我又写成枯燥的计算机网络教材了。欢迎读者在评论中对文章质量作出反馈。

投稿?

如果您也有有意思的网络问题,欢迎通过博客右侧的邮箱联系我。说不定可以设计成一个题目。

用打赏表达您的支持!

由于是一个完整系列,需要耗费很多心血,本想做订阅制,还是觉得不合适,有人读这些东西已经很荣幸了,而且订阅制也会让自己压力变大。我还是觉得自己想写什么就写什么,才会写出让自己满意的东西来。

这里放一个赞赏码吧,如果读者感到本系列内容有所帮助,欢迎打赏。

我会坚持分享自己学到的知识。

==计算机网络实用技术 目录==

这篇文章是计算机网络实用技术系列文章中的一篇,这个系列正在连载中,我计划用这个系列的文章来分享一些网络抓包分析的实用技术。这些文章都是总结了我的工作经历中遇到的问题,经过精心构造和编写,每个文件附带抓包文件,通过实战来学习网路分析。

如果本文对您有帮助,欢迎扫博客右侧二维码打赏支持,正是订阅者的支持,让我公开写这个系列成为可能,感谢!

没有链接的目录还没有写完,敬请期待……

  1. 序章
  2. 抓包技术以及技巧
  3. 理解网络的分层模型
  4. 数据是如何路由的
  5. 网络问题排查的思路和技巧
  6. 不可以用路由器?
  7. 网工闯了什么祸?
  8. 网络中的环路和防环技术
  9. 延迟增加了多少?
  10. TCP 延迟分析
  11. 重新认识 TCP 的握手和挥手
  12. 重新认识 TCP 的握手和挥手:答案和解析
  13. TCP 下载速度为什么这么慢?
  14. TCP 长肥管道性能分析
  15. 后记:学习网络的一点经验分享
与本博客的其他页面不同,本页面使用 署名-非商业性使用-禁止演绎 4.0 国际 协议。
 

四层负载均衡分析:Google Maglev

之前的博客中,四层负载均衡漫谈 介绍和总结了四层负载均衡的相关技术。接下来的博客,会分析一些不同公司的四层负载均衡架构的设计。

今天这篇要介绍的是 Google 的 Maglev,主要的参考是这篇:Maglev: A Fast and Reliable Software Network Load Balancer,所以本文也算是一篇论文导读吧。

按照之前博文列的四层负载均衡技术选型,Maglev 在这里的选择如下。

Maglev 的技术

可以看到,其中有转发的实现(因为当时还没有 DPDK 吧),和长连接保持技术,都用了之前博客中没有介绍过的,很有创新!

Google 刚开始用的架构是硬件负载均衡,主要的问题有:

  1. 扩展性问题:硬件负载均衡是专有设备,需要购买新的设备来扩展;
  2. 高可用:基本上只有 1+1 冷备份的方案;
  3. 不可以编程扩展功能;
  4. 升级的成本高,意味着要购买新的硬件,测试和部署;

显然,用软件来替代硬件负载均衡能够解决以上的问题,只不过要复杂一些。软件意味着可以随意部署随时扩展(机房里面的服务器多的是),可以设计高可用,想要什么功能就可以实现什么功能,升级成本很低,部署新的软件就可以了。

但是软件的挑战在于:性能要高,性能如果不高,就没有意义,性能的瓶颈在哪里呢?就是网卡的速度,如果是 10G 的网卡,软件负载均衡能够用满这 10G,那就到顶了。就是在博客 四层负载均衡漫谈 中介绍过的线速(line rate)。Maglev 就能够用小包达到线速(论文中的机器规格是 10G 网卡,为什么用“小包”来做评测,因为对于负载均衡来说,评价指标是 pps, packet per second,包越小,达到线速需要的包越多,软件要处理的 pps 就越高,性能要求越高。用大包的话,达到线速比较轻松,说明不了性能有多好)。

在本文的语境中,所有的「包」指的都是 3 层 IP 协议包。

第二个挑战是,要保持连接的状态,即,保证一个连接总是到达相同的 RS(Real Server, 真实服务器)。

和硬件 LB 架构对比

转发架构设计

Maglev 使用了可以跨二层的 DSR 转发

转发架构总览

Google 的每一个服务都有一个 VIP,这个 VIP 就是对外暴露的 IP,Maglev 把这个 VIP 通过 BGP 宣告给路由器,路由器将这个 VIP 宣告给 Google 骨干网,最终会出现在公网上。

用户在访问服务的时候,通过 DNS 查询域名对应的 IP,得到的就是这个 VIP。所以用户侧发出的包,dst ip 是这个 VIP。

路由器会将这个包路由到 Maglev,此时 dst IP 依然是 VIP。

Maglev 会查找这个 VIP 对应的服务(每一个 VIP 都对应了一个服务),然后将这个包转发给此服务(就是 Real server)。因为要跨二层,所以这时候不能直接用二层路由的方式转发给服务了,Maglev 会将这个包封装在 GRE 中(就是将原来的整个二层包放到一个 IP 包里面),此时外面的 IP 包继续走正常路由,dst IP 改成真实服务器的 IP。

GRE 封装不是增加了额外的 header 字段吗?如果超过 1500 bytes 怎么办?这里我自己尝试了一下和 Google.com 建立 TCP 连接,Google 发回来的 SYN+ACK 包中,MSS 是 1412 bytes,看来是给 GRE 预留了 header 的空间。

包路由到达了真实服务器,会解开 GRE 的封装,这时候包的 dst IP 又变回了 VIP,src IP 就是客户的 IP。此时,对于真实服务器来说,这个包就好像是由客户端直接到了自己这里一样。然后它会开始处理这个请求,返回响应的时候,直接将 3 层的 src IP 设置成 VIP,dst IP 设置成客户端 IP。

响应(这里指的是反方向的 IP 包路由,包括 TCP 中发给客户端的 ACK 等等)路由给客户端,就是完全正常的 3 层路由了,从真实服务器路由给客户端,不需要任何封装了。

由于整个 DSR 过程都发生在 Google 机房内部,所以客户端对此一无所知,对客户端来说,包到了 VIP,又从 VIP 返回了响应,一切都很简单。

这里有一个小细节,我们在介绍 ECMP 的时候提到过,ECMP 是发生在一跳之间的,所有同一个路由器后面的机器都是均等路由的。Google 不想把所有的实例都放在同一个二层下面,解决方案是,Ingress 路由器发给 Maglev 这一段,也是经过 GRE 封装的,可以跨二层路由。

配置管理

Maglev 分成控制面和数据面。在网络实现方面,这是经典的做法。比如路由器中,控制面负责交换路由,计算最终的路由表,数据面负责根据路由表的高速转发。

从公网进 Maglev:

  • Controller 负责检查 Forwarder 的状态,如果健康,就将 VIP 宣告进 BGP 中;

从 Maglev 到真实服务:

  • 每一个 VIP 都对应一个 Backend Pools,这样 forwarder 根据 VIP 就知道应该向哪里转发。BP 也可以包含 BP,这样如果有 BP 被多个地方引用,就可以只在一处更新;
  • Config Manager 负责获取新的 config,验证正确性,然后执行配置变更;
  • 每一个 BP 都配置了一个或多个 health checker,heath check 会拿到 IP,去重之后再执行,减少因为 BP 重复造成的重复检查;

同一个服务有多个 VIP,部署到多个 Maglev 集群,用于做隔离,测试等。

Maglev 转发的设计和实现

这部分介绍了一个数据包进入了 Maglev 机器的网卡,处理完成,最后发出的过程。即软件实现上的架构。

Maglev 软件内部的转发实现

上图中绿色的是包经过的路径,依照此,转发链路总览如下:

  • 首先包到达网卡;
  • steering module 最先处理这个包,它的下一站有多个 Receiving Queue,steering module 的任务是计算出这个包的五元组 hash,决定这个包应该去哪一个 Queue。然后这个包来到了 Receiving Queue 等待处理;
  • 每一个 Receiving Queue 都有一个 Packet Rewrite Thread,在这里,它的主要任务是找到这个包应该去的 Real Server IP,步骤如下:
    • 查看是否有对应的 VIP,如果没有,直接丢弃;
    • 计算五元组,拿到一个 hash,查看 connection track table,找到对应的 Real Server IP;
    • 如果找不到的话,就使用 Consist Hash 算法,选择一个 Real Server IP,然后记录进入 connection track table;
    • 找到 Real Server IP 之后,封装 GRE/IP Header,放入Transmission Queue 中;
  • muxing module 会将包从 Tranmission Queue 移动到 NIC 中;
  • NIC 最终将包发出去;

这里有几个有意思的细节:

steering module 已经计算了五元组 hash,为什么在 Packet Rewrite Thread 中又要计算一遍呢?计算着两遍的值应该是一样的。这是为了减少在不同 thread 中需要的同步操作,如果计算两遍,就可以你干你的,我干我的,互不影响。真正的多线程是在 RQ 里面的 threads 开始的,所以 steering 在分配的 queue 的时候必须足够快才行。

这也是为什么每一个 thread 都有一个自己的 connection track table,而不是共用一个的原因,也是消除跨线程同步。

那么为了让 steering module 足够快,为什么不用 round robin 来分配 queue 呢?1)如果不同的 threads 都在处理同一个连接的话,很容易造成 TCP 乱序;2)因为每一个 thread 都维护了一个 connection track table,保证同一个五元组只去同一个 queue,可以减少 connection table 的大小,也可以提高效——在 connection table 直接能找到 backend,而不需要计算 hash 来选择。不过,在一个 queue 要满了的时候,steering module 就会 fallback 到 round-robin,这在相同五元组有大流量的时候很有效。

Kernel Bypass

和其他的四层负载均衡实现一样,对于 Maglev 来说,也是不需要 Kernel 协议栈的功能的,所以 bypass kernel 会带来巨大的性能提升。

Maglev 是一个运行在 userspace 的程序,使用 NIC 提供的功能,让 NIC 和程序直接共享一块内存。它在用户态实现了类似 Ring buffer 的机制。steering module 负责 Receive Queue 的指针移动,muxing module 负责 Transmission Queue 的指针移动。中间没有数据包的拷贝。

这部分还有一些细节的优化:

  • Batch 处理,等待 buffer 中有足够的 packet 再开始一起处理,效率更高;
  • Pin packet thread 到固定的 CPU,减少 context switch;

连接保持的实现

要想保持住一个 TCP 连接,本质上,就要保持五元组相同包一定要到固定的 RS 上。这里有两段需要考虑。

第一段是 Maglev 和 RS 之间的部分。这段上文已经描述过了:Maglev 在选择 RS 的时候,如果能从 connection table 找到五元组 hash 对应的 RS,就直接使用这个 RS;如果 connection table 没有五元组对应的 RS,就基于 consistent hash 选择一个并记录到 connection table 中。这样就保证 Maglev 总是能把此五元组转发给相同的 RS。

第二段是 Router 和 Maglev 之间的部分。ECMP 不会保证总是将相同五元组的包发给相同的机器,比如 Maglev 滚动升级,或者扩容,缩容等。但是这也没什么问题,以上技术方案已经覆盖这些场景了。假如一个 TCP 连接的包之前发给 Maglev A,现在转发给了 Maglev B,Maglev B 机器上不存在这个 connection table,但是经过 consistent hash,也会 hash 到同一个 RS 上。Maglev 到 RS 的包是通过 GRE 封装转发的,GRE 底层的协议是 IP 协议,无连接,所以转发到 RS 上面会被正确处理,不会被 RS 丢弃。RS 解开 GRE 封装,拿到的包的 src IP 是客户端 IP,dst IP 是 VIP,它并不知道(也不关心)是哪一个 Maglev 发过来的。所以可以说,所有的 Maglev 都能处理所有 connection 的包。

唯二可能出问题的地方是:Maglev 机器有变化,导致包去了和原先不一样的 Maglev 机器,这个机器在计算 consistent hash 选择 RS 的时候,碰巧 RS 也有变化,比如正在滚动升级,造成 consistent hash 的选择结果和之前的 Maglev 机器选择结果不一样,这时候才会出问题。

另一个可能出问题的地方是,前面提到过,connection table 是 by thread 的,如果某一个 table 遇到的 load 过高,或者遭遇了 TCP SYN flood 攻击,开始 fallback 到 round robin,那么这时候 Maglev 有变更的话,新 Maglev 机器使用 consistent hash 计算得到的 RS 就会和之前的包去的 RS 不一致。

机器的硬件配置比较高,出现这两种情况的几率其实都不高。这个方案看起来比较完美。主要归功于 consistent hash。

Consistent Hashing

Consistent Hash 在这里解决的问题是:Maglev 使用这个方法选择 RS 的时候,每次计算,只要是连接的五元组一样,就需要选择出一样的 RS。

并且,它还要保证两点:

  1. 选择 RS 要是均匀的,这样才能保证 RS 之间的负载均衡;
  2. 当 RS 发生升级和替换的时候,要尽可能减少 rehash 带来的选路变化;

举个例子,现在有 1000 个五元组(src ip, dst ip, portocol, src port, dst port),有 100 个 RS,hash 算法要保证,对于每一个五元组都选择一个 RS,并且相同的五元组选择的 RS 也相同,所有的 RS 被选择的次数几乎是一样的(负载均衡)。当其中有一个 RS 出现问题被删除的时候,1000 个五元组 hash 的结果中,只有 10 个需要改变(hash 到出现问题的 RS 的这 10 个),其余的都不需要改变,以减少 RS 变化带来的连接迁移变动。

论文的原文里有介绍具体的 hash 算法实现,但是本文就不展开介绍了,先介绍到这个算法的作用。

运维经验分享

论文中有这么一小节,看似收尾实则非常精彩。

架构演进

主要有两点:一开始是 Active-backup 的模式部署的,这样有点浪费资源。现在改成用健康检查 + BGP 宣告 VIP 的方式,这样坏了随时立即下线,平时都跑着;另外就是一开始用的 Kernel 的协议栈,用 socket 编程实现的。后来换成了 bypass kernel,这部分难点就是要找一个 GRE 封装实现,去在用户态做 GRE 的事情。Kernel bypass 之后得到了 5 倍的性能提升。

我原本以为 consistent hashing 选择后段的 RS 也是后来加上的,没想到自设计之初就有了,这个 feature 简直太厉害了,解决了许多问题。

VIP Matching

这个设计太有意思了。

在某些紧急的时候,一个 cluster 的 Maglev 需要将流量全部转发到另一个 cluster。比如 cluster-A 的 Maglev发现,本 cluster 的服务 X 的实例都不健康了,需要将 cluster-A 收到的流量全部发送到 cluster-B 来处理。cluster-B 有服务 X,Y,Z,怎么能让服务 X 的流量从 cluster-A 全部转发到 cluster-B 的服务 X 呢?

这里有两种方法:一种是在不同的 cluster 之间同步服务发现数据,即 cluster-A 知道 cluster-B 的服务 X 有哪些 VIP;另一种是让 cluster-B 的所有 VIP 都能处理 X,Y,Z 的流量,这样只要收到流量就能处理。

但是这两种方法在规模很大的时候都会有问题,复杂度也比较高。Google 用很简单的一种设计解决了这个问题:同一个服务在不同的地区的 VIP 后缀(即 IP 的最后几个 bit)是一样的。因为像 Google 这样的公司申请 IP 都是按段分配,所以可以做到这一点。比如在一个地区拿到的公网 IP 是 3.3.3.0/24, 另一个地区拿到的公网 IP 是 4.4.4.0/24,那么一个服务的 VIP 就分别用 3.3.3.14.4.4.1。当 3.3.3.1 出现问题的时候,全部将流量转发到 4.4.4.1。再比如当 3.3.3.2 服务出现问题的时候,将流量全部转发到 4.4.4.2

这样,既不需要在不同的集群之间同步状态,也能在不同的集群之间准确路由不同服务的数据。

举个例子,我们可以用 DNS Checker 这个网站来查看 accounts.google.com 在世界各地的解析结果。

accounts.google.com 在世界各地的解析结果

可以看到,虽然这个域名在世界各地解析出来的 IP 前缀不同,但是最后都是以 .84 结尾的。(也有一些域名不是这种形式,这篇论文是很久之前发布的,可能不是所有的站点都用了论文中描述的技术。)

Fragmentation

如果客户端发来的 IP 有 Fragmentation 怎么办?这里的难点是,如果发生 Fragmentation,是在 3 层做的,也就是一个 TCP segment 拆到了多个 IP 包里面发送,只有第一个 IP 包会存在 TCP header,剩余的分片不会带有 TCP header。

我们之前提到的 consistent hashing 是基于五元组的,少了 TCP port,Maglev 怎么知道应该发送给谁呢?

方法是这样的:现在只有三元组了,那就按照三元组来,根据三元组得到一个 Hash,然后用这个 Hash 不是选择一个 RS,而是在当前集群中选择一个 Maglev,把这个 IP Fragment 发到选中的 Maglev 上面。这样,无论是哪一个 Maglev 收到这种 IP 分片,它们总是会到达同一个 Maglev 实例上。

这台身负重任 Maglev 要负责始终转发到同一个 RS 上。方法是,IP 分片的第一个,按照老样子挑选一个 RS 转发,并在一个特殊的 fragment table 中记录对应的 RS,后续进来的 IP 分片都朝这个 RS 转发。那么如果发生了乱序,分片2 比分片1 先到了,怎么办?这种情况下 Maglev 会等待一段时间,等分片1到了,那么先发分片1,再发分片2。如果等了一段时间还没等到,就放弃了,直接丢弃。

IP Fragment 的支持

这样能保证正确性,但是还有两个问题。(其实这些问题在博文 有关 MTU 和 MSS 的一切 中我们详细讨论过。

一个问题是,因为多一个 hop,可能造成乱序,比如分片 3 直接命中,一跳就成功,分片 2 要 2 跳才到正确的 RS。这种情况要依赖对端来处理了。比如 TCP 本身就保证顺序,如果是 UDP,那么应用要自己处理乱序。

另一个问题是,这个实现引入 buffer,可能有安全问题。现实是分片不应该很多,Google 只对部分 VIP 开启允许 Fragmentation 功能,其他禁用,所以内存也就足够了。

监控和 Debug

这部分值得一说的是 Google 实现了一个 Debug 工具:packet-tracer。核心原理是,这个工具作为客户端发给 VIP 请求,其中 L3/L4 中加入了特殊的 header,Maglev 认识这些 header,Maglev 会正常处理这些请求,但是会从 header 中读出来一个 debug 信息上报用的 IP,然后把自己的名字,选择的 RS 上报到这个 IP。我目前的工作是 service meshing 领域,所以深知这个能够追踪整个链路的工具的价值。

论文的最后一节是性能评测部分,结论就是很牛就对了,能小包到线速。这部分的详情笔者想省略了。以上就是论文的技术实现部分的详细分享,欢迎留言交流。

附录:

四层负载均衡系列文章

版权说明:本文中的图片,如果带有 Figture n: 字样,说明截图自论文,版权属于论文。其余文字和图片内容为原创,发布即进入公有领域,任何人可以随意使用。

 

厨艺见长

最近感觉厨艺见长,但是仔细想想又说不出来“长”在哪里,好像炒菜还是和以前一样炒法,也没有悟到什么窍门,就觉得炒的菜越来越好吃了。以前在做饭有两个不自信的方面,一个是做鱼,一个是面点。这几个月也逐渐克服心理阴影了。馒头,包子,锅贴,越做越得心应手。妻跟我算是老乡,口味相同,这些山东的面点她也爱吃。

鱼还有一些困难,因为新加坡的鱼我都不认识。决定第二天做鱼之前,还在网上学了各种本地鱼的名字,第二天到了湿巴沙有点底气了。结果跟老板娘问了几条鱼的名字,完全和我在网上学习的不一样,功课白做了。最后买了一条“红狮子头”回家,看着像红石斑鱼,就按照石斑鱼的方法红烧,味道也还可以。鱼也至少算是做过一次了。

妻夸我做的好吃,我便接茬夸下海口,说“只要是我吃过的东西,都能做出来”。去 Fun Toast 吃早点,点了一种裹着鸡蛋液煎的吐司面包,感觉不难。回头买来吐司和鸡蛋做了一次,居然味道也是类似,把“海口“给糊弄过去了。

最近在认真学习摄影。我觉得摄影就像炒菜:菜谱常说盐适量,油少许,加酱油和加盐可能咸度都能调的差不多,拍照的光圈大点或者快门长一点,最后曝光也可能差不多,在网上问别人光圈快门参数的,和德国人做中国菜用天平量盐放多少克一样;炒菜时间长了,菜会好吃,摄影时间长了,拍照会好看,但是都可能说不上来哪里提高了,美感和手艺一样玄乎;学习的过程也很像,吃别人炒的菜,思考是怎么炒出来的,看别人的照片,思考是怎么拍出来的;看王刚教做菜,看 Youtuber 教我拍照片;猛火爆炒就是高速快门,小火慢蒸就是延迟摄影;菜式有很多,川菜鲁菜和东北菜,甚至法餐,日本料理,摄影门类也很多,风光肖像,街拍。

唯一不同的是,很多「摄影人」热衷于摄影装备,镜头,但是很少见「炒菜人」大谈特谈自己用的锅的。这么一想,治好了我的装备焦虑。

 

去伊豆

在高楼林立的东京呆够了,我们去了南边的伊豆半岛。

一如东京城市的交通一样,去伊豆的路线也有很多,也很复杂。为了省点脑筋,我们在一个 JR 车站,在一个热心的工作人员帮助下,买了舞女号列车的票(也叫踊子号,日语:踊り子/おどりこ Odoriko),这个列车的名字可能也是从川端康成的小说,《伊豆的舞娘》里面取来的吧。价钱不便宜,折合 230 多人民币一个人,好处是换乘少,速度快一些。

在列车上时而能看到一些海景。大约 2 个小时就到了伊豆高原。我们这一天的终点是下田市。所以在等待下一班列车的时间,打算去填饱肚子。

伊豆的特产是金目鲷鱼,我们在附近找了一家饭店,走路过去。

一路上非常安静,出了偶尔路过的汽车,一点声音都没有。天很蓝,植物绿油油的。

伊豆高原的路

一会就到了我们找的饭店。店家看起来很忙,门口已经排了很多人。等到一个服务员,我说我们想在这里吃饭,他拿出来记录排队的板子问我们,几个人?我说 2 个。他又问,几条狗?我惊讶,我说我没有狗。他说,哦不好意思,我们这家是和狗一起吃的饭店,如果没有狗请去隔壁那一家。这时候我才发现在外面排队的食客都带着狗。

有狗才能来吃的饭店

不过也好,隔壁这家没有人在排队。

欣点了鲷鱼的套餐,我点了一份带刺身的套餐。鲷鱼有一些甜,挺好吃。

鲷鱼定食

回到车站的路上,碰到了另一辆舞女号。

我们接下来乘坐的电车是伊豆急行线,这条线路的电车有两辆是特殊装饰的列车。一辆叫做金目绸鱼号,另一辆叫黑船电车。代表了伊豆的特色。鲷鱼是伊豆的特产,比较好理解。黑船电车呢?查了一下,发现特别有意思。我甚至不能理解。

简单来说,江户时代的日本和清朝一样,也是闭关锁国的政策。美国为了发展亚洲捕鲸事业,想要日本开放国门,德川幕府不同意。后来,美国人又来了,开着四艘涂成黑色船舰,载 63 门大炮,要求德川幕府打开国门,一直闭关锁国的日本国明都吓傻了,无计可施,只能签下屈辱的、不平等的《神奈川条约》。但是这个黑船事件,给日本埋下了希望改变的种子,最终促使了明治维新。今天,下田市将这个黑船事件看作是值得纪念的,自豪的事情。所以在下田可以看到非常多黑船事件的影子,黑船电车就是其一。

所以说,就是被迫打开国门,但是下田市将其看作是自豪的事情,大办黑船电车,黑船游览,黑船祭,必须要让世界知道这段历史!?

黑船电车是观海列车,座位不是朝向列车行进的方向,而是朝向窗户。景致非常特别。

观海列车
站台的一位老人

来到下田市,一出站台就看到满大街的日本国旗和美国国旗并肩挂在路边。非常奇特。

街上的美国国旗和日本国旗

在街上逛了一会,我们打算租自行车骑一骑。找到了一家店,里面是一位年纪很大的老爷爷。一点英文都不懂。我拿出 Google 翻译,他拿着放大镜,我一句他一句的,沟通起来,障碍竟然不是很大。

我说,我想租自行车。

他笑着说,你想去哪里?

海边吧。

我的自行车没有电,海边的路上上下下,不好骑。(说的也是,伊豆半岛是个高原,起起伏伏。)

我说,那去下田公园吧。

他笑着说,那里没什么可看的。

那去哪里呢?

就在城市转转吧。

于是老爷爷帮我们两个人挑好了自行车,还扶住车让我们上去试试高度,没问题了之后,我付给他钱,他说,回来再给钱。

骑上车之后,我们随便在地图上找了一个看起来是海港的地方,超那里骑过去。歪打正着,一路上风景非常美,而且很安静,除了鸟叫什么声音都听不到。

在路上看到了黑船。黑船游览在下田市已经成了一项观光活动
骑行的路上看到的海边

骑到尽头,发现这个位置是一个海洋馆。于是开始折返。

回到自行车的店,店里只有一个日本老奶奶了,这次不需要用 Google 翻译,她就明白我们是还车的。出门的时候,我用仅回的几句日语说谢谢,老奶奶回谢谢并且鞠躬,我说谢谢,她又鞠躬说谢谢。(出来之后,欣说你说谢谢她就鞠躬,直到你不说了。我这时才发现,早知道就不说那么多了)

归还自行车之后,我们打算去坐公交车去海滩。伊豆的公交车很少,一个小时一趟,有的甚至要两个小时。

不过等待是值得的,到了海边之后,发现这里的海滩好美。

白浜神社
去冲浪的人
另一个一千多年历史的神社

晚上住的民宿比较偏僻,所以打算在附近吃了晚饭再回去。找餐厅费了一番劲,好像很多餐厅都没有什么人,有一些甚至门都没开,像是倒闭了,很冷清。最后找到一个像是家庭餐厅的地方吃了拉面,味道不错,很温馨的馆子。

吃饱之后,坐火车去民宿。从车站出来,发现周围居然黑的伸手不见五指!连一个路灯都没有,非常吓人。开着手电筒一路小跑到了民宿。

这晚住的民宿是日本传统的房间,跟多啦A梦里面的一样。

住的民宿

睡了一个好觉,第二天的天气不是很好,我们趁着雨还没下下来,先去了大室山。

大室山是传说中新海诚《你的名字》里面那个山的取景地,很漂亮,和富士山一样是一个近乎完美的圆锥形。

大室山上

然后去了山脚下的仙人掌动物园。

这个动物园很赞,之前去过的动物园,动物们都在睡觉,要么就是懒洋洋的。这个动物园很多动物就在路上走,甚至可以伸手摸。

细尾獴
水豚

水豚可太可爱了,在路上走着走着就自己定住了,心事重重的样子。

可爱的水豚吓得小孩哇哇哭

动物园地图有一条路上画着孔雀,这孔雀可太有意思了,它就在地图画的这条路上来回走。见人多的时候,就从容地走到人群中间开屏,还会转几圈让所有人都看到,真像一个专业的艺术家!

孔雀

逛到一半开始下大雨了,雨比天气预报的还要大。我们算准了下一班公交车,坐车回到了伊豆高原,然后搭舞女号回到了东京。

 

去东京

一直想去日本旅行, 这一次终于成行了。日本的第一站是首都东京。

东京!(其实是在介绍皇居历史啦,但是放在这里可以搞笑)

签证办的非常顺利,在网上预约好时间,然后携带指定的资料去大使馆就可以了,不用事先在网上填写表格。比澳大利亚简单太多。费用是 60 新币一人,五年有效,相比于澳大利亚 220 新币一年,简直便宜太多。

去东京还发生了一件有趣的事。我们下了飞机第一站去筑地市场吃早饭,结果在那里居然遇到了飞机上坐在我旁边小哥。我跟他打招呼,他也认出来我,然后他旁边的朋友惊掉了下巴——what?(你在东京居然有熟人?)

东京给我们的第一印象是干净。大街上一尘不染,几乎看不到垃圾。(在游客聚集的地方,比如筑地市场,还是有一些垃圾的。)而且很神奇的是,我在整个城市都没见过垃圾桶,只有在某些商业场所,商家自己安置的垃圾桶,所有人都自己拿着垃圾。没有垃圾桶,城市不是应该更脏吗?不知道为何东京反而这么干净。有天早上买了一杯咖啡,结果一直没见到垃圾桶,拿着喝完的纸杯拿了一整天。

我发现我的博客宽度太小,导致我自豪的很多照片贴在这里显得小气。读者如果碰到喜欢的照片可以点击打开大图慢慢欣赏。(也许改换一个博客主题了?)

东京地铁

东京的市民总是行色匆匆,在地铁站总是能看到人们在着急赶着什么。在工作日,地铁里面的上班族打扮都非常精致,男士都穿着西装,女士都妆容精致。

我们第一站去了新宿,新宿站有超过200个出口,可能是世界上最大的地铁站。

东京的地铁可太值得一说了。这是下飞机之后带给我们的第一个冲击。东京的地铁非常复杂:

出口多而且不连通。像上海和新加坡这种城市,地铁网也很发达,很多换乘站有好几条线。在换乘站,你只要从任何一个入口进入地铁站,就可以根据指示去任何一条线路。我们以为东京也是这样,结果在秋叶原站从一个入口进去,找日比谷线,转了好半天,才意识到不同线路之间的地铁站是不连通的!即使它们都叫做秋叶原站。有时候甚至同站换乘都要刷卡出去,然后再从另一个入口进。所以,后面还是乖乖按照 Google 地图来走吧,如果 Google 让你去一个入口,即使在途中遇到了更近的入口,也不要选择这个近的入口。究其原因,是因为东京的铁路是由不同公司运营的,同一家公司的线路可能共享入口。

地铁站设计复杂。很多列车的两个反方向站台是只有一条路过去的,很容易坐反方向。不过我摸索出一个窍门,东京的地铁每一个线路都有编号,比如 G,JR,JT,等等,每一个站都有标号,比如 G9,G10,G11. 如果你要去一个地方,先查看目的地的编号,比如 G8,然后看当前位置,比如是 G4,那么找到站台之后,确认方向是数字变大的方向,就对了。

计价方式复杂。东京铁路有各种 Pass,即周游券,通票。但是简单算了一下,就放弃了。因为 Pass 的种类繁多,有的不包括这家公司,有的不包括那家公司。而且正常坐地铁,买 Pass 的话很难回本,如果能回本,很可能旅行计划做的有问题,哈哈。我们是全程刷西瓜卡。

铁路系统和地铁系统。如果去周边城市,就要用到铁路系统,这个又很复杂了,分成 Local train,急行线,特急线,票价区分度很高,可能快 20min 就贵出来好多。票可能要买两种,一种乘车券和一种指定席券。我们去机场的时候只刷了西瓜卡,结果上车发现全是指定席,只好在车上补票。还有一个有趣的事情,是我们去东京站坐火车,火车站和地铁站都是东京站。我们从地铁到了之后,按照指示找到了我们要找的站台(非常难找,问了工作人员才找到),等火车的时候,欣突然意识到,我们根本没用到购买的火车票,一定是哪里不对。于是又找了一个工作人员问了一下,才明白,我们需要找一个出口,刷西瓜卡出去,然后再刷火车票进入。晕!

电梯很少。这一点也很不好,虽然可能是有电梯的,但是我们 90% 的时间都在走楼梯,因为指示牌都是指向楼梯路线的,找直梯无疑是给自己增加难度。上海,新加坡的地铁就很少需要人走楼梯,扶梯和直梯都在显眼的位置。说起来,在东京没有见过轮椅,可能东京的无障碍设施也不是很好。

东京市区

日本的相机行业非常发达,目前单反微单头部三家,佳能,尼康,索尼都是日本企业(网上看到有人说日本二战点错了技能树,研究瞄具去了,不知真假,但是挺有趣)。日本人对相机使用又比较爱惜(无从考证,个人认为所有的摄影师都对相机比较爱惜)。所以在日本能看到很多中古(二手)相机店。折合汇率,日本可能是购买相机最好的地方,而且很多热门款式,在中国可能都买不到了,日本还有货。

北村写真就是一整栋大楼,一层是二手镜头,一层是机身设备。还有一层很有趣,都是过时的 CCD 和胶片机,花 5 新币就能买到一台还能工作的相机。很多镜头由于缺陷,也买几十新币的。

北村写真店
街头的咖啡店,但是没什么人光顾,我觉得如果能提供一个垃圾桶,顾客肯定会很多!
筑地市场的一个店,不知道为什么要放两只蛙蛙
筑地市场的一家寿司店
东京的街道,琳琅满目的广告牌是东京的签名
东京塔上的夜景

哈哈,不要小看了这张照片,这是我在东京塔上没有三脚架的情况下,手持 4s,才得到的这张图片。其实是发现了一个绝妙的方法,只要把镜头按在玻璃上,即能克服反光,又能保持稳定。

皇居

皇居的导览很赞,有中文,需要提前一个月预约,当天去排队也可以,我去的时候发现大部分人好像是当天排队进来的。导览团队非常专业,介绍的内容也很有趣。

我们的导览,很有趣,讲很多笑话,中文说的很好
皇居
皇居

新宿

歌舞伎町一番街,白天路过了一下
新宿御苑,蒲公英
新宿御苑
新宿御苑
新宿御苑

涩谷 – 原宿

涩谷这天可太有趣了。先是早上,在明治神宫,遇到了有人结婚,于是观摩了日本的传统婚礼。然后在原宿的大街上,见到了很多警察,整条街都是警察,阵势很大的样子,往前走,看到了貌似是某种日本右翼势力在抗议(真是可恶)。

涩谷 sky 上面的景色
涩谷 sky
Google 气派的办公室

涩谷 sky 也挺有趣,就是一个很高的办公楼顶楼的景观,上面很漂亮。有意思的是它的售票,官网提前一个月开卖,在涩谷 sky 看日落很美,但是一定要提前一个月抢票,这个时段的票基本上放出来就没了。日落时段的票,官方推荐的购票渠道,比如 Klook,booking等,都没有了,但是——淘宝居然可以买得到?是的,淘宝无良商家在官方一开卖就全买下来了,然后用 2-3 倍的价格再卖给我们。简直太可恶了!

其实官方的角度讲,票卖光了是好事,对吧?但是他们居然没有坐视不管。他们会检查票是不是官方发送的邮件,是不是二次转发或者截图,一个账号购买的5张票如果分开入场会被拒绝,等等,以此来打击黄牛。

其实购票实名认证不就好了?

明治神宫
明治神宫的大树
明治神宫的婚礼
严阵以待的警察

上野

上野公园,「环游世界第一站」,不知道现在到哪里了?
鸭子船,本来没计划做,偶尔看到了,居然才 7 新币,就当上去休息一下了。 (结果因为要炫耀一下速度蹬的腿都酸了)
某种会飞又会游泳可能也会走路的三栖鸟儿
上野区域有很多鞋店
晴空塔
虽然垃圾桶没有,但是这种自动售卖机倒是随处可见。口渴了,只要随便找一个看起来会有售卖机的胡同,就能发现售卖机。
仲见世商店街
浅草寺
浅草寺

富士山

这一天在飞猪上买了一个一天的包车团,从东京出发,去了很多网红景点,一路比较赶,我很痛苦。团上的姑娘都是下车拍照,上车修图,乐此不疲。事实证明我报错团(选错路线)了。

其中,日川时计店就是一个卖表的店,店门口的街道能看到富士山而已。lawson 就是一个便利店,店后面是富士山。我不理解为什么要来打卡,可能是被小红书忽悠过来的?来的大部分是中国人。看富士山的话,去一个公园(我觉得大石公园比较好)就够了,真没必要去这些“网红”景点打卡奔波。

东京站
下吉田,富士山下的小村子
下吉田的火车道
新仓山浅间公园在山上,要爬上去。这是爬到半山腰拍的。
Arakurayama Sengen Park 新仓山浅间公园,网红景点
富士山
lawson 便利店,著名打卡景点。但是这个 lawson 据说要拆了,因为游客在马路上拍照,挺危险的。lawson估计也没有怨言,因为大家都是在这里拍照,不进去消费,关了就关了。
日川时计店旁边的一条小溪

日川时计店的照片就不放了,很多游客在马路上拍照,特别安置了一个工作人员维持秩序,场面很混乱。

忍野八海

忍野是富士山下的一个小村子,八海就是八个池子。类似于中国的古镇景点。

但是其中这个池子真值得说一说,拍照又拍不出来当时的效果。照片的水看起来很浅,其实有 8 米深,但是水非常清澈,比游泳池还清。除了波纹,几乎看不到水的存在,只有鱼和鱼的影子,鱼就像在这里飞翔一样。有一种恐怖的幽静。非常震撼。我觉得现在的数码设备记录不下来这种感觉,得亲身看了才知道。

忍野村
大石公园

我们这一天运气不错,能看到富士山。富士山很多时候是被云遮挡住的,如果不是晴天,那么云都见不到,都是雾。这个网站可以查看富士山能见度的预报:什么时候去看富士山?

镰仓

镰仓高校前,又是一个我不理解的景点,普普通通的电车,普普通通的学校。可能是因为我不看灌篮高手吧。
镰仓的海
海边钓鱼的父子
还是大海
在镰仓拍到的 1969 年 GTO
狗(很显然)
街道
在去江之岛的桥上拍到的,天气好的时候应该能看到富士山

热海花火大会

这次的旅行以花火大会结尾,非常完美。举办方做的很好,活动的信息非常周全,甚至烟花放 5000 发都标记清楚。新闻上说现场人很多,但是我感觉不至于能到上新闻的程度。我们的司机很专业,让我们去人流少的地方上车,全程安排很好。

花火大会的场面很震撼,居然有笑脸烟花,地球仪烟花这种东西,不知道怎么做到的。最后的节目空中尼加拉瓜大瀑布,非常震撼。只可惜我第一次使用相机的 B 门,很不熟练,以及没有三脚架,只能拍出下面的样子了。

购物

现在的东京是购物天堂。一个是日元汇率大跌,相当于是全国物价对于外国人来说都便宜了。另一个是退税方便,一般的城市是机场退税,但是东京大部分商店可以直接用退税价格购物,甚至超市都可以退税,相当于全国都是免税店,只要拿出护照就可以了。但是消耗品用退税价格购买的话,不能在日本消费。退税购买之后,电源会用一个专用的透明袋子封起来,不能拆开使用。东京的商业很发达,商场林立,像优衣库,MUJI,这种商场都是整栋楼整栋楼开,很好逛。

优衣库

东京的食堂

可能是因为寸土寸金,我们去过的食堂都非常小。很多食堂的设计,都是开放式厨房,食客围着厨房而坐,可以边吃边看厨师的制作过程。有种温馨的感觉。

不过也是因为都比较小吧,大部分的食堂都需要排队的,甚至有很多,如果不是提前预约,都吃不上。幸运的是,我们是在五一之前去的,所以在工作日的非午餐饭餐高峰时间去,不排队也能吃到很多不错的。很多餐厅午餐和晚餐是不一样的价格,相同的餐厅相同的食物,晚餐的价格可能是午餐的两倍。

一些有趣的餐厅和图片。

这家是在涩谷玩的时候在附近随便找的一家牛肉饭。菜单基本上只有牛肉一种,只是你要选择多少肉而已,类似于食其家。厨师的主要工作就是烤肉和切肉。

ステーキライスの店 センタービーフ渋谷宮益坂店

地址:Japan, 〒150-0002 Tokyo, Shibuya City, Shibuya, 1 Chome−12−24, 707 Shibuya, 1階

围着厨房而坐
我点的 mega size 正在制作中
开吃。很自不量力的点了最大份 Mega size,结果吃撑了。

下面这家是在神田的一番街随便找的一家,因为住在附近,回去的时间玩了,就在这里吃了。这是一家烧鸟店,也是厨师在中间烤,食客围坐,但是很干净,餐厅有合理的排烟系统,食客和厨师之间也有一层玻璃,所以完全没有烧烤的烟。厨师会时不时看你吃的进度,等你快吃完的时候马上烤下一串,让你吃到的都是新鲜的刚烤好的。

烤的很嫩,一点烤黑的地方都没有,像是水浴烹调的牛排一样,非常鲜美。新加坡也有烧鸟,但是新加坡的是事先烤好的,完全比不上现烤的。我们点的套餐,有鸡肉,鸡肝等等,非常下酒。

店名:Tori no Kakehashi

地址:Japan, 〒101-0044 Tokyo, Chiyoda City, Kajicho, 2 Chome−11−19 神田日新ビル1B

随便拍了一张前菜

后来又在附近找了一家居酒屋。这家更有意思,自己加装了楼梯,将一个小餐厅隔成两层。我们就坐着二楼很小的一个地方边喝边吃。这家的烧鸟不贵,店名就叫做 50,所以每一串只有 50yen,折合人民币 2.3元。

居酒屋的二楼小桌子

但是居酒屋有一套 system,(我发现之前去过的也都是一样的套路):

  • 每个人至少点一杯饮料;
  • 是有餐位费的,但是也会有免费小菜,叫做 Otoshi;
  • 23点之后加收 10%;
  • 小费加收 10%;

可能是因为店小,要通过这种系统来提高翻桌率吧。不然遇到点一杯酒喝一晚上的酒鬼怎么办。

下面这一家是烤肉。叫做俺の肉。

地址是:神田(東京都) JR 神田站 西口 步行1分鐘,3-15-10, Uchikanda, Chiyoda-ku, Tokyo, 101-0047

空间依然非常局促,像是飞机的经济舱座位。但是肉非常好吃。非常鲜嫩,像果冻一样。老板是一个五大三粗的汉子,但是总是笑眯眯的。

治愈的烤肉
买的一个套餐,非常好吃。尤其是最上面两块。

下面一家是鳗鱼饭。叫做:鰻の成瀬。也很好吃,服务员会给一个牌子,上面写的鳗鱼的不同吃法。

心心念念的鳗鱼饭

最后一个随便找的一家家庭料理。都是 1300yen 的定食,便宜又好吃。

家庭料理的定食

这次旅行我们还去了伊豆,伊豆游记请见这里