在制作Ubuntu的Docker镜像时,安装tzdata库会弹出交互提示,中断了镜像文件制作。

解决方法,采用静默安装的方式:

ENV DEBIAN_FRONTEND=non-interactive
RUN apt-get update && apt-get -y install tzdata

如果代码中使用了线程池,一种优雅停机的方式就是注册一个JVM钩子函数,在JVM进程关闭之前,先将线程池关闭,及时释放资源。

public static NamesrvController start(final NamesrvController controller) throws Exception {

        if (null == controller) {
            throw new IllegalArgumentException("NamesrvController is null");
        }

        boolean initResult = controller.initialize();
        if (!initResult) {
            controller.shutdown();
            System.exit(-3);
        }

        Runtime.getRuntime().addShutdownHook(new ShutdownHookThread(log, new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                controller.shutdown();
                return null;
            }
        }));

        controller.start();

        return controller;
    }

link: https://github.com/apache/rocketmq/blob/master/namesrv/src/main/java/org/apache/rocketmq/namesrv/NamesrvStartup.java

1. RocketMQ消息写入磁盘的方式:同步刷盘和异步刷盘

❑ 异步刷盘方式:在返回写成功状态时,消息可能只是被写入了内存的PAGECACHE,写操作的返回快,吞吐量大;当内存里的消息量积累到一定程度时,统一触发写磁盘动作,快速写入。

❑ 同步刷盘方式:在返回写成功状态时,消息已经被写入磁盘。具体流程是,消息写入内存的PAGECACHE后,立刻通知刷盘线程刷盘,然后等待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写成功的状态。

同步刷盘还是异步刷盘,是通过Broker配置文件里的flushDiskType参数设置的,这个参数被配置成SYNC_FLUSH、ASYNC_FLUSH中的一个。

2. RocketMQ主从同步方式:同步复制和异步复制

如果一个Broker组有Master和Slave,消息需要从Master复制到Slave上,有同步和异步两种复制方式。

同步复制方式是等Master和Slave均写成功后才反馈给客户端写成功状态;

异步复制方式是只要Master写成功即可反馈给客户端写成功状态。

这两种复制方式各有优劣,在异步复制方式下,系统拥有较低的延迟和较高的吞吐量,但是如果Master出了故障,有些数据因为没有被写入Slave,有可能会丢失;在同步复制方式下,如果Master出故障,Slave上有全部的备份数据,容易恢复,但是同步复制会增大数据写入延迟,降低系统吞吐量。

同步复制和异步复制是通过Broker配置文件里的brokerRole参数进行设置的,这个参数可以被设置成ASYNC_MASTER、SYNC_MASTER、SLAVE三个值中的一个。

实际应用中要结合业务场景,合理设置刷盘方式和主从复制方式,尤其是SYNC_FLUSH方式,由于频繁地触发磁盘写动作,会明显降低性能。

通常情况下,应该把Master和Save配置成ASYNC_FLUSH的刷盘方式,主从之间配置成SYNC_MASTER的复制方式,这样即使有一台机器出故障,仍然能保证数据不丢,是个不错的选择。

3. 部分顺序消息

要保证部分消息有序,需要发送端和消费端配合处理。在发送端,要做到把同一业务ID的消息发送到同一个Message Queue;在消费过程中,要做到从同一个Message Queue读取的消息不被并发处理,这样才能达到部分有序。

4. 消息的Tag和Key

对一个应用来说,尽可能只用一个Topic,不同的消息子类型用Tag来标识(每条消息只能有一个Tag),服务器端基于Tag进行过滤,并不需要读取消息体的内容,所以效率很高。发送消息设置了Tag以后,消费方在订阅消息时,才可以利用Tag在Broker端做消息过滤。

其次是消息的Key。对发送的消息设置好Key,以后可以根据这个Key来查找消息。所以这个Key一般用消息在业务层面的唯一标识码来表示,这样后续查询消息异常,消息丢失等都很方便。Broker会创建专门的索引文件,来存储Key到消息的映射,由于是哈希索引,应尽量使Key唯一,避免潜在的哈希冲突。

Tag和Key的主要差别是使用场景不同,Tag用在Consumer的代码中,用来进行服务端消息过滤,Key主要用于通过命令行查询消息。

5. Consumer的负载均衡

  • DefaultMQPushConsumer的负载均衡

DefaultMQPushConsumer的负载均衡过程不需要使用者操心,客户端程序会自动处理,每个DefaultMQPushConsumer启动后,会马上会触发一个doRebalance动作;而且在同一个ConsumerGroup里加入新的DefaultMQPushConsumer时,各个Consumer都会被触发doRebalance动作。

以AllocateMessageQueueAveragely策略为例,如果创建Topic的时候,把Message Queue数设为3,当Consumer数量为2的时候,有一个Consumer需要处理Topic三分之二的消息,另一个处理三分之一的消息;当Consumer数量为4的时候,有一个Consumer无法收到消息,其他3个Consumer各处理Topic三分之一的消息。可见Message Queue数量设置过小不利于做负载均衡,通常情况下,应把一个Topic的Message Queue数设置为16。

  • DefaultMQPullConsumer的负载均衡

Pull Consumer可以看到所有的Message Queue,而且从哪个Message Queue读取消息,读消息时的Offset都由使用者控制,使用者可以实现任何特殊方式的负载均衡。

DefaultMQPullConsumer有两个辅助方法可以帮助实现负载均衡,一个是registerMessageQueueListener函数,registerMessageQueueListener函数在有新的Consumer加入或退出时被触发。另一个辅助工具是MQPullConsumerScheduleService类,使用这个Class类似使用DefaultMQPushConsumer,但是它把Pull消息的主动性留给了使用者。

6. 配置文件

Property NameDefault valueDetails
listenPort10911listen port for client
namesrvAddrnullname server address
brokerIP1InetAddress for network interfaceShould be configured if having multiple addresses
brokerNamenullbroker name
brokerClusterNameDefaultClusterthis broker belongs to which cluster
brokerId0broker id, 0 means master, positive integers mean slave
storePathCommitLog$HOME/store/commitlog/file path for commit log
storePathConsumerQueue$HOME/store/consumequeue/file path for consume queue
mapedFileSizeCommitLog1024 * 1024 * 1024(1G)mapped file size for commit log
deleteWhen04When to delete the commitlog which is out of the reserve time
fileReserverdTime72The number of hours to keep a commitlog before deleting it
brokerRoleASYNC_MASTERSYNC_MASTER/ASYNC_MASTER/SLAVE
flushDiskTypeASYNC_FLUSH{SYNC_FLUSH/ASYNC_FLUSH}. Broker of SYNC_FLUSH mode flushes each message onto disk before acknowledging producer. Broker of ASYNC_FLUSH mode, on the other hand, takes advantage of group-committing, achieving better performance.
配置文件详情

参考文献:

  1. 杨开元 2018 《RocketMQ实战与原理解析》 机械工业出版社 ISBN:9787111600251
  2. https://rocketmq.apache.org/docs/rmq-deployment/

打开Charles,点击”help > ssl proxying” 中的 “install Charles root certificale”,进行安装本机证书,如图1:

安装本机Charles root证书

打开钥匙串将Charles证书设置为信任,如图2:

信任证书

配置好Charles的http代理,并在iOS设备上配置wifi代理之后,打开Safari浏览器,输入: https://chls.pro/ssl. 浏览器将自动弹出下载和安装证书,安装成功后。打开“设置”,找到“通用>关于本机>证书信任设置”,并将Charles正式的信任开关打开,如图3:

iOS设备信任证书

Charles打开SSL代理设置(“Proxy>SSL Proxy Settins”):

Charles的SSL设置

The host has a changing IP address (or none if you have no network access). From 18.03 onwards our recommendation is to connect to the special DNS name host.docker.internal, which resolves to the internal IP address used by the host. This is for development purpose and will not work in a production environment outside of Docker Desktop for Mac.

The gateway is also reachable as gateway.docker.internal.

link: https://docs.docker.com/docker-for-mac/networking/

docker在制作镜像时,抛出异常:

debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin:

原因是因为在使用apt-get安装依赖时并非静默安装,需要交互,所以无法正常通过。

解决方法,在docker file中增加一句:

ENV DEBIAN_FRONTEND noninteractive

link: https://blog.csdn.net/a19891024/article/details/78250967

Additional completion definitions for Zsh

brew install zsh-completions

To activate these completions, add the following to your .zshrc:

fpath=(/usr/local/share/zsh-completions $fpath)
plugins=(… zsh-completions)
autoload -U compinit && compinit

You may also need to force rebuild `zcompdump`:

  rm -f ~/.zcompdump; compinit

Additionally, if you receive “zsh compinit: insecure directories” warnings when attempting to load these completions, you may need to run this:

chmod go-w '/usr/local/share'

在腾讯云服务器中使用腾讯的容器服务,拉取腾讯云仓库中的镜像时,会出现如下的报错:

docker pull ccr.ccs.tencentyun.com/qcloud/nginx:1.9
Trying to pull repository ccr.ccs.tencentyun.com/qcloud/nginx ... 
1.9: Pulling from ccr.ccs.tencentyun.com/qcloud/nginx
51f5c6a04d83: Pulling fs layer 
a3ed95caeb02: Pulling fs layer 
640c8f3d0eb2: Downloading 
a4335300aa89: Waiting 
unknown blob

出现这种问题一般是dns解析问题或者https认证等问题。

dns的问题手动添加hosts即可,https问题添加如下配置到/etc/default/docker 即可:

DOCKER_OPTS="--insecure-registry ccr.ccs.tencentyun.com"

重启docker服务

systemctl restart  docker.service

重启完之后,即可正常拉取。

docker pull ccr.ccs.tencentyun.com/qcloud/nginx:1.9
Trying to pull repository ccr.ccs.tencentyun.com/qcloud/nginx ... 
1.9: Pulling from ccr.ccs.tencentyun.com/qcloud/nginx
51f5c6a04d83: Pull complete 
a3ed95caeb02: Pull complete 
640c8f3d0eb2: Pull complete 
a4335300aa89: Pull complete 
Digest: sha256:311e9840c68d889e74eefa18227d0a6f995bc7a74f5453fdcd49fe3c334feb24
Status: Downloaded newer image for ccr.ccs.tencentyun.com/qcloud/nginx:1.9

一、OSI模型和TCP/IP模型

  • OSI(Open System Interconnect),即开放式系统互联。 一般都叫OSI参考模型,是ISO(国际标准化组织)组织在1985年研究的网络互连模型
  • TCP/IP协议族是一个四层协议系统,自底而上分别是数据链路层、网络层、传输层和应用层。每一层完成不同的功能,且通过若干协议来实现,上层协议使用下层协议提供的服务
OSI模型和TCP/IP模型
  • OSI模型
    • 应用层:是为计算机用户提供应用接口,也为用户直接提供各种网络服务。我们常见应用层的网络服务协议有:HTTP,HTTPS,FTP,POP3、SMTP等
    • 表示层:提供各种用于应用层数据的编码和转换功能,确保一个系统的应用层发送的数据能被另一个系统的应用层识别。如果必要,该层可提供一种标准表示形式,用于将计算机内部的多种数据格式转换成通信中采用的标准表示形式。数据压缩和加密也是表示层可提供的转换功能之一
    • 会话层:负责建立、管理和终止表示层实体之间的通信会话
    • 传输层:建立了主机端到端的链接,传输层的作用是为上层协议提供端到端的可靠和透明的数据传输服务,包括处理差错控制和流量控制等问题。该层向高层屏蔽了下层数据通信的细节,使高层用户看到的只是在两个传输实体间的一条主机到主机的、可由用户控制和设定的、可靠的数据通路。我们通常说的,TCP UDP就是在这一层
    • 网络层:通过IP寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换节点,正确无误地按照地址传送给目的端的运输层。就是通常说的IP层。这一层就是我们经常说的IP协议层
    • 数据链路层:将比特组合成字节,再将字节组合成帧,使用链路层地址 (以太网使用MAC地址)来访问介质,并进行差错检测
    • 物理层:实际最终信号的传输是通过物理层实现的。通过物理介质传输比特流。规定了电平、速度和电缆针脚。常用设备有(各种物理设备)集线器、中继器、调制解调器、网线、双绞线、同轴电缆。这些都是物理层的传输介质
  • TCP/IP模型
    • 应用层:负责处理特定的应用程序细节。简单网络管理SNMP协议,简单网络传输SMTP,域名解析DNS,文件下载FTP协议,远程协助Telnet协议,超文本传输HTTP等等
    • 传输层:主要为两台主机上的应用提供端到端的通信。TCP协议和UDP协议
    • 网络层:处理分组在网络中的活动,比如分组的选路。IP协议等
    • 网络接口层:包括操作系统中的设备驱动程序、计算机中对应的网络接口卡

二、HTTP与TCP/IP

HTTP通信是由TCP/IP协议承载的,因此HTTP协议的需要进行三次握手才能建立连接,经过四次挥手才能断开连接。

2.1 建立连接

  • 第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认
  • 第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态
  • 第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了
TCP/IP建立连接

2.2 断开连接

  • 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态
  • 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态
  • 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态
  • 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手
TCP/IP断开连接

2.3 浏览器对同一域名下的并发限制

各版本浏览器对同一域名下的并发连接数有一定限制,具体详情如下:

浏览器 HTTP/1.1 HTTP/1.0
IE 11 6 6
IE 10 6 6
IE 9 10 10
IE 8 6 6
IE 6, 7 2 4
Firefox 6 6
Safari 3,4 4 4
Chrome 4+ 6 6

http协议目前有如下几个版本:

  • HTTP/0.9    HTTP的1991原型版本。这个版本的设计有许多严重的缺陷,几乎没有人在使用了
  • HTTP/1.0    第一个得到广泛应有的HTTP协议,详情见https://tools.ietf.org/html/rfc1945
  • HTTP/1.0+  在1.0版本基础上增加Keep Alive连接,虚拟机支持已经代理连接支持等特性。也称之为1.1的非正式版本,详情见https://tools.ietf.org/html/rfc2068
  • HTTP/1.1    当前比较流行的HTTP协议版本,该版本校正了之前版本的结构设计缺陷,明确了语义,引入了性能优化特性,删除了一些不友好的特性,详情见https://tools.ietf.org/html/rfc2616
  • HTTP/NG    又称HTTP/2.0,该版本重点关注性能的优化,具有二进制分帧,首部压缩,多路复用,服务器推送等新特性。详情见https://tools.ietf.org/html/rfc7540

发展历史图如下:

HTTP发展历史

注:

Google在2012年时推出了自己SPDY协议,该协议优化了HTTP/1.x中的请求延迟,解决了安全性等问题,大部分特性在HTTP/2.0中均已包含进去了

一、HTTP1.0和HTTP1.1的常见区别

HTTP/1.1是目前最广泛应用的协议,它与HTTP/1.0的几个明显在应用上差异如下:

  • 长连接与短连接
    • HTTP/1.0仅支持短连接,即每次请求都要经历一次建立连接(三次握手)的过程,效率很低,有些时候我们看到有些基于HTTP/1.0的协议,使用Connection: keep-alive来打开长连接,这里的HTTP/1.0是通常指HTTP/1.0+,真正的HTTP/1.0协议是没有这个特性的
    • HTTP/1.1默认就是长连接,只要在Keep Alive的时间内,再次发起请求不需要再重新建立一个连接,直接使用上一次建立好的连接进行传输,减少了建立和关闭连接的资源消耗和延迟
  • 缓存控制
    • HTTP/1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准
    • HTTP/1.1引入了更多的缓存控制策略例如ETag,If-Unmodified-Since, If-Match, If-None-Match,Cache-Control等更多可供选择的HEAD头来控制缓存策略
  • 错误通知
    • 在HTTP/1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除
  • Host头
    • 在HTTP/1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP/1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)
  • 断点续传
    • HTTP/1.1在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content)

总结图:

HTTP/1.0与HTTP/1.1的区别

二、URL

  • URI:统一资源标识符(Uniform Resource Identifier)
  • URL: 统一资源定位符(Uniform Resource Locator)
  • URN: 统一资源名(Uniform Resource Name)

URI = URL + URN

  • URL完整定义:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>

举例:

mailto: president@example.com
ftp://ftp.example.com/pub/books.xls
rtsp://www.example.com:554/videos/cook.rmvb
ftp://joe:joepassword@www.joes.com:23/pub/gun;type=5;graphic=6?item=123&mode=test#dog 
  • URL 字符集与转义

由于 URL 常常会包含 ASCII 集合之外的字符,URL 必须转换为有效的 ASCII 格式。URL 编码使用 “%” 其后跟随两位的十六进制数来替换非 ASCII 字符。URL 不能包含空格。URL 编码通常使用 + 来替换空格

  • URL的最大长度

在HTTP协议中并没规定URL的长度限制,但各个浏览器厂商及Web服务软件是有这个限制的,具体如下:

浏览器最大长度(字节)
IE浏览器 2,083
Firefox65,536
Chrome8,182
Safari80,000

Web服务软件:

Web Service最大长度(字节)备注
Apache8,192
IIS16,384configuration/system.webServer/security/requestFiltering/requestLimits@maxQueryStringsetting.
Nginx1,000client_header_buffer_size 1k
large_client_header_buffers 4 4k/8k

三、常见状态码

  • 100 – 199 信息性状态码
  • 200 – 299 成功状态码
  • 300 – 399 重定向状态码
  • 400 – 499 客户端错误状态码
  • 500 – 599 服务器错误状态码

常见状态码列表:

状态码含义HTTP/1.0是否支持HTTP/1.1是否支持
200OK
206Partial Content
301Moved Permanently
304Not Modified
400Bad Request
403Forbidden
404Not Found
500Internal Server Error
502Bad Gateway
503Service Unavailable
504Gateway Timeout

四、METHOD

HTTP协议定义了一组安全的方法:GET方法和HEAD方法,即这两个方法不会让服务产生新的内容或影响。

常见METHOD列表:

方法名含义HTTP/1.0是否支持HTTP/1.1是否支持
GET获取资源
HEAD获取报文HEAD
POST向服务器提交数据
PUT向服务器提交资源
DELETE请求服务器删除资源
TRACE网络跟踪
CONNECT与PROXY之间的连接管理
OPTIONS查询能力

五、HEAD

HEAD头分为通用HEAD, 请求HEAD, 响应HEAD和实体HEAD四个部分

  • 通用HEAD
HEAD字段 描述 备注
Connection 允许客户端和服务器指定与请求/响应连接有关的选项 HTTP/1.1
Date 创建报文的日期时间 HTTP/1.0、HTTP/1.1
Transfer-Encoding 指定报文主体的传输编码方式 HTTP/1.1
Via 代理服务器的相关信息 HTTP/1.1
Cache-Control 控制缓存的行为 HTTP/1.1
  • 请求HEAD
HEAD字段 描述 备注
From 客户端用户的E-Mail地址 HTTP/1.0、HTTP/1.1
Host 接收请求的服务器的主机名和端口号 HTTP/1.1
Referer 当前请求URI的文档的URL HTTP/1.0、HTTP/1.1
User-Agent HTTP客户端程序的信息 HTTP/1.0、HTTP/1.1
Accept 告诉服务器客户端能接收哪些媒体类型 HTTP/1.1
Accept-Charset 告诉服务器客户端能接收哪些字符集 HTTP/1.1
Accept-Encoding 告诉服务器客户端能接收哪些内容编码 HTTP/1.1
Accept-Language 告诉服务器客户端能接收哪些语言 HTTP/1.1
Authorization Web 认证信息 HTTP/1.0、HTTP/1.1
If-Match 比较实体标记(ETag) HTTP/1.1
If-Modified-Since 比较资源的更新时间 HTTP/1.0、HTTP/1.1
If-None-Match 比较实体标记(与 If-Match 相反) HTTP/1.1
Range 实体的字节范围请求 HTTP/1.1
  • 响应HEAD
HEAD字段 描述 备注
Age 响应持续时间 HTTP/1.1
Server Web Service的名称和版本 HTTP/1.0、HTTP/1.1
Location 客户端重定向至指定 URI HTTP/1.0、HTTP/1.1
Accept-Ranges 服务器可接受的范围类型 HTTP/1.1
Vary 代理服务器缓存的管理信息 HTTP/1.1
WWW-Authenticate 服务器对客户端的认证信息 HTTP/1.0、HTTP/1.1
  • 实体HEAD
HEAD字段 描述 备注
Content-Encoding 对Body执行的编码方式 HTTP/1.0、HTTP/1.1
Content-Language 对Body执行的自然语言 HTTP/1.0、HTTP/1.1
Content-Length Body的长度 HTTP/1.0、HTTP/1.1
Content-Range Body的位置范围 HTTP/1.1
Content-Type Body的媒体类型 HTTP/1.0、HTTP/1.1
Expires Body的过期日期时间 HTTP/1.0、HTTP/1.1
Last-Modified Body的最后一次修改的日期和时间 HTTP/1.0、HTTP/1.1
ETag Body的标记 HTTP/1.1

六、参考文献