《HTTP/2 in Action》阅读笔记(二)

要开始步入 HTTP/2 的,https://httparchive.org/reports/state-of-the-web#h2 显示了使用 HTTP/2 的趋势,和其他数据,如 HTTP/3 的应用趋势。随着互联网的发展,展示一个网页请求的资源越来越多,传输的总字节数在变大,平均近几M - https://www.speedcurve.com/blog/web-performance-page-bloat/

https://www.webpagetest.org 可以用测试网页中所有资源加载的瀑布图,包括 DNS 的查询,网络连接,SSL 协商及 CPU, 带宽使用情况。

HTTP/1.1 效率较低下,只能同步发送处理请求,即请求,得到响应后才能发下一个请求,一个网会加载许多的资源,如图片, js, css 等。

HTTP/1.1 的 Pipeling 像 Redis 那样的 pipeline, 通过一个连接传递多个 HTTP 请求,再依次返回结果,但这种方案并未得到支持与应用。 阅读全文 >>

Python 实现 RSA 非对称加解密

在阅读《HTTP/2 in Action》的 HTTPS 一节后,不觉一脚踏入到非对称加密这一领地而不能自拔。与非对称加密相对应的是对称加密,有点像是由一把钥匙反锁的门,只能用同一把钥匙打开; 而非对称加密是用一把钥匙反锁门,但只能用另一把特定的钥匙才能打开它,锁门的叫做公钥,开门的叫做私钥。

在此之前我理解的非对称加密以为是像 MD5 那种摘要(Digest), 由明文生成的 MD5 摘要信息是无法还原出原始数据的,谬以为那就是所谓的非对称。

1976 年,两位美国计算机学家 Whitefield Diffie 和 Martin Hellman 提出了非对称加解密的的构思。1977 年三位数学家 Ron Rivest, Adi Shamir 和 Leonard Adleman 实现了非对称加密算法,即 RSA,取自这三个的姓的首字母

具体的 RSA 算法原理可参考阮一峰的两篇网络日志:RSA算法原理 (一)RSA算法原理 (二), 大致就是通过互质的两个数,计算欧拉函数, 模反元素,最终算法公钥和私钥,公钥加密的数据只能用用私钥解密,以当前的算力,只要 RSA 的密钥足够长,如 1024 位以上,私钥是无法通过公钥推断出来的。 阅读全文 >>

《HTTP/2 in Action》阅读笔记(一)

本书买来有一段时日了,一直还未开始阅读,关于网络上 HTTP/2 的真实使用状态查到以下信息

  1. 截止 2021 年 1 月 8 日,有 50% 的网站正在使用 HTTP/2,参见 Usage statistics of HTTP/2 for websites
  2. 另一篇介绍 HTTP/2 Adoption 说 2020 年就有 64% Web 请求是基于 HTTP/2 的

得看看我们自己的网站对 HTTP/2 的支持以及使用状况

于此同时,HTTP/3(gQUIC) 也上了议程,作为 HTTP/3 的提议标准的 RFC9114 也于 2022 年 6 月 6 日由 IETF 发布。

本书首先介绍的是关于 HTTP 协议从 0.9 到 1.0, 再到 1.1 的变迁史。

关于 IPv4 和 IPv6

IP 报文的前四位表示协议版本,所以 0100 就是 4。版本 0 ~ 3 是留给实验用的,5 设计为 Intenet 流协议的,例如实时音视频,像 VoIP, 实际上也因为地址数量的限制没被使用。所以就跳到了 IPv6,字节为  0110。后续的 IP 协议版本 7, 8, 9 都被预定了(比如中国的 IPv9 - 冷),所以再有新的 IP 协议版本的放丈是 IPv10 阅读全文 >>

Spring Boot 如何选择 Cache 实现的

写作此篇是作为对 Spring 使用 Cache 解析及使用不同类型的 Cache 一文的补充,该文中提到了自定 CacheManager 及配置 spring.cache.type 来选择自己的 Cache 实例,但对 Spring 是如何确定具体 Cache 实现未作展开。本文将介绍选择 Cache 实现的几种方式

  1. 默认选择 Cache
  2. 声明 Spring Bean Cache
  3. 声明 Spring Bean CacheManager
  4. 通过 spring.cache.type 属性选择
  5. 引入相应的 Cache 实现依赖

阅读全文 >>

学习 Airflow 第一篇章

Airflow 起初是由 Airbnb 开发的, 用于调度和监控工作流的平台,后来开源了, 并于 2019 年 1 月成为了 Apache 的顶级项目。它是用 Python 编写的,管理的工作流是有向无环图(DAG - Directed Acyclic Graph), 这能满足绝大多数情况下的需求。

顺带插一句,Airflow 用了与 Google Photos 极其相似的 Logo,不知算不算侵权。

说到工作调度,头脑中很快会掠过 Cron, 计划任务, Quartz, Spring Schedule, 和 Control-M。除了商业的 Control-M 有调度和监控工作流的功能外,其他的基本只用来调度任务,监控全靠自己的日志。

还有一个类似的工具是由易观贡献给 Apache 的 DolphinScheduler, 它处理的也是 DAG 工作流,用 Java 实现的,所以体量大,硬件要求会高些。它的工作流的创建是通过 Web UI 可视化界面完成的,对程序员来说不那么友好。奇怪的是, 作为 Apache 旗下的项目,项目首页面是中文的,启动后控制台默认界面也是中文的。

而 Airflow 功能就厉害了, 它可动态管理工作流,易于扩展,可集群化进行伸缩,更有一个漂亮的 UI 用于实时监控任务。基于以上特性 Airflow 是很适于执行数据的 ETL(Extract, Transform, Load) 操作的。

这么好的开源产品, 免不了又被 AWS 盯上了, 以 Amazon Managed Workflows for Apache Airflow(MWAA) 服务进行出售,费用还真不菲。AWS 创造性的以 vCPU 数量,DAG 数量限制进行分层次进行收费,远比自己启动一两个 EC2 实例部署 Airflow 贵的多。但 MWAA 有个方便的特性就是 DAG 文件可以放到 S3 中自动部署,相信自己部署的 Airflow 也能进行扩展而从 S3 加载 DAG。 阅读全文 >>

Spring 使用 Cache 解析及使用不同类型的 Cache

要在一个 Spring 应用中开启缓存方法返回结果的功能很简单,不需要额外的依赖,相关的的注解  @Cacheable, @CacheConfig, @CachePut, @CacheEvict, @EnableCache 等来自 spring-context 包。默认的的 Cache 实现是把数据存入到 ConcurrentMap 中,所以数据一直在内存中,除非显式的调用被 @CacheEvict 的方法来清理。实际进行数据缓存时会有更复杂的策略,如元素个数,占用内存,过期时间,何时使用磁盘等,而且不同的数据类型应有不同的缓存策略。

因此,除了使用默认的 ConcurrentMap 作为缓存外,还可通过配置属性 spring.cache.type 来使用其他类型的缓存,如 Caffeine, Couchbase, EhCache, INfinispan, JCache, Redis 等,或自定义 CacheManager 来使用 Guava Cache。 阅读全文 >>

理解 Spring Boot Security + JWT Token 的简单应用

项目中有用到 Spring Security 来控制 API 的访问权限,但对于配置应用它基本上是照葫芦画瓢。至于为什么要调用方法

SecurityContextHolder.getContext().setAuthentication()

并且能从 HttpServletRequest 中得到 Authentication。还有,只要在 Controller 的方法中添加一个带 @AuthenticationPrincipal 注解的参数

public String sampleApi(@AuthenticationPrincipal DecodedJWT decodedJWT) {...}

之后,decodedJWT 便自动有了值,诸如此类的,此前一概模糊不清。

早先配置 spring-security-config 是通过继承 WebSecurityConfigurerAdapter, 覆盖它的 configure(HttpSecurity http) 来配置访问规则等。在 spring-security-config 5.7.x 开始不建议用 WebSecurityConfigurerAdapter, 而是借由 SecurityFilterChain 来配置 HttpSecurity 中的规则 ,或者通过 WebSecurityCustomizer 完成定制。 阅读全文 >>

构建 AWS AMI 镜像(EC2 Image Builder + Terraform)

使用到 AWS 的 EC2 服务时,选择一个基础镜像后,要定制的话需要在 userdata 中写上一堆脚本。如果不想每次重复 userdata,或者要更快速的初始化一个虚拟机,就应该定制自己的 AMI,特别是在 Batch, ECS, EKS 选择的基础镜像还不方便使用 userdata。

定制一个 AMI, 我们可以用 aws create-image 命令,或是 HashiCorp 提供的 Packer(它不仅支持 AWS, 还能为 阿里云,Azure, Google 云,vmware, docker, Vagrant 等定制镜像)。而我们这里将要介绍的仍然是 HashiCorp 公司的 Terraform 并结合 AWS 的 EC2 Image Builder 服务来构建 AMI 镜像。

EC2 Image Builder 是 2019 年 12 月 1 日推出来的服务,见 Introducing EC2 Image Builder

构建一个镜像的基本过程是选择一个基础镜像来启动一个实例,然后在该实例中做一系列的操作,再保存操作后的状态为自己的镜像。这和用 Dockerfile 定制自己的 Docker 镜像是类似的。 阅读全文 >>

macOS 如何定位 JAVA_HOME

多数的 Java 入门教程都是要求同时设置 JAVA_HOME 和 PATH(包含 $JAVA_HOME/bin) 两个环境变量,反正两个都有了就保险。其实一般情况下系统能在 PATH 中找到 java 程序时就知道 JAVA_HOME, 基本上只要配置 PATH 就行,而 JAVA_HOME 环境变量是可选的。但也有例外,比如 TOMCAT 就可能要求有 JAVA_HOME 环境变量。

在 macOS 下,JAVA_HOME 与 PATH 的关系又显得有点微妙了。一个新的 macOS 系统,它自带有 java 命令

$ which java
/usr/bin/java

你要直接执行它的话

$ java
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.

所以它实际上只是执行 java 的辅助入口,没有实际的 JDK 或 JRE 是没用的。 阅读全文 >>

使用原生的 Windows Docker 容器

一谈到 Docker 容器,按照以往的惯性思维,那就是 Linux 容器(LXC),和 Windows 没多大关系,顶多也就是在 Windows 的 Linux 虚拟机中跑 Docker 容器。

不过自从 Windows Server 2016 开始,出现了 Windows 原生的 Docker 容器,它再也不只是 Linux 下的专利了。Docker 容器中可以运行 Windows 系统了, 每个 Windows 容器共享宿主机的 Windows 内核(--isolation=process,),或使用一个高度优化虚拟机中的 Windows 内核(--isolation=hyperv)。

我们说自 Windows Server 2016 开始,包括现在的 Windows Server 2019, Windows Server 2022, 还有桌面系统的 Windows 10 和  11 上 借助于 Docker Desktop 也能跑 Windows 容器。

原本在 Windows 桌面版上安装 Docker Desktop 就能用来运行 Linux 容器,由此可知在 Windows 桌面版上(如 Windows 7, 10, 11) 可运行两种类型的容器

  1. Linux 容器: 每个容器运行的是 Linux 实例,用 cgcroups 命名空间隔离资源。默认的,使用 Docker Desktop 的 LinuxEngine
  2. Windows 容器:容器中运行的是 Windows 实例,进程隔离模式是容器共享主 机的 Windows 内核,Hyper-V 隔离模式是容器使用高度优化虚拟机的内核。需启用 Windows 的 Hyper-V 特性,并切换 Docker Desktop 使用 WindowsEngine

阅读全文 >>