0%

Message Queue

message queue

要素

  • 生产者(producer/publisher)
  • 消费者(consumer/subscriber)
  • 队列

作用

  • 解耦生产者和消费者
  • 缓存瞬时大量数据,提升处理吞吐量

SQS

一种高可用,弹性、分布式的Message Queue

模型

sqs modal

生命周期

sqs lifecycle

  1. 生产者1入队消息A,此时启动 Retention Period Timout(默认4天,最大14天)计时;
  2. 消费者1poll消息A,此时启动Visibility Timeout(默认30秒,最大12小时)计时,Visibility Timeout前,A不被其他消费者可见, 同时其Receive count计数加1;
  3. 消费者1处理完消息A,主动删除消息A;
  4. 如果该SQS配置了死信队列,当Receive count计数达到maxReceiveCount,A会被系统移动到死信队列
  5. 消息A在队列中的时间达到Retention Period Timeout后,系统将会将A删除;

SQS的分类

分类

standard vs fifo

  • Message Order
    Standard queues 提供最大限度保证顺序能力(best-effort ordering),但顺序也可能不一致
    FIFO queues 提供绝对保证顺序能力(first-in-first-out delivery)
  • Delivery
    Standard queues 保证消息至少可以被获取一次,但也可能被获取多次
    FIFO queues 保证消息有且只能被获取一次
  • Throughput
    Standard queues 提供无TPS(transactions per second)限制的收发能力
    FIFO queues 提供最大300TPS的收发能力,如果使用batch,最大可以到3000TPS
  • Availability
    Standard queues 在所有region可用
    FIFO queues 仅部分region可用,比如 the US West (Oregon), US East (Ohio), US East (N. Virginia), and EU (Ireland)

我们项目使用Dropwizard框架构建了一个API服务,服务运行在AWS的ECS上,该ECS服务关联了CloudWatch的一个LogGroup。

最近在定位问题的时候,发现日志中存在这样的现象,当服务打印的一条日志有多行文本,那么在Loggroup里会将该条日志截断为多个LogEvent,每一行生成一个LogEvent。

Read more »

计算机网络基础

网络分层模型

协议分层模型
tcp_ip_model

包封装/解封装模型
encap

IP地址

IP地址 = 网络号 + 主机号

分类

根据网络号的区域划分位ABCDE五类IP地址

私有IP地址

有一些ip地址预留在局域网内部使用,不能在Internet上被识别

CIDR

由于ABC三类IP地址过于粗旷,为了方便路由,需要更精细划分网络地址段,便有了CIDR(Classless inter-domain routing)

路由

目的IP地址和当前处于的网络不在同一个网段,根据目的IP地址找下一跳IP的过程

NAT

公网IP很珍贵,私网地址的机器也想访问Internet,就诞生NAT(Network Address Translation)

VPC

VPC(Virtual Private Cloud)是AWS提供的虚拟网络基础设施服务。
一个VPC只能限定在一个Region下,同时可以跨越该Region下所有的AZ(Availability Zone)。同一个Region下可以有多个VPC,多个VPC的私有地址可以重叠。

Subnet

subnet是将VPC划分为更小的网络单元,AWS要求一个subnet必须位于一个AZ下。同时一个AZ可以有多个subnet。
subnet有五个特殊ip地址不能被使用

ip 用途
x.x.x.0 网络号
x.x.x.1 Gateway
x.x.x.2 DNS Sever
x.x.x.3 Reserved
x.x.x.255 广播地址

subnet内的资源默认可以相互被访问
根据subnet内的资源是否能被外部访问,将subnet分为Public subnetPrivate subnet

Public Subnet

公有ip子网内的Instance除了有一个私有IP地址外,可以再分配一个或者多个公有IP地址。他们既可以访问子网内的资源,也可以访问Internet上的资源,同时也可以被Internet访问。
Internet的路由直接去往IGW(Internet Gateway)

Private Subnet

私有IP子网的Instance只能被分配私有IP地址,通常只能访问私有IP子网的资源,或者主动访问Internet,不能够被Internet访问。
如果需要访问Internet,需要在公有子网内部署NAT设备,然后将访问Internet的Gateway指向这个NAT设备(NGW, NAT Gateway)

Route Table

VPC或者Subnet需要关联路由表,且只能关联一个。
路由表的每一条入口由destination CIDR和target组成,表示去destination需要经过target。

内置VPC网络拓扑模型

  • public subnet only
  • public & private subnet
  • public & private & vpn subnet
  • private & vpn subnet

Security

Security Group

  • Instance 级别的Firewell,包含一个或者多个上下行的Rules(最多50个)。

  • 一个Instance可以关联多个Security Group(一个Network Interface最多关联5个Security Group), 一个Security Group 也可以被多个Instance共用。

  • 一个Instance至少要关联一个Security Group,如果没有显式指定,使用默认的Security Group,这个Group的上行规则是允许所有的traffic出去,下行规则是不允许任何traffic进来

  • 只包含Allow comunication rule,无法显式指定Deny comunication rule

  • Rule是有状态的(stateful),如果指定允许从某个IP:Port来的traffic,则去到该IP:Port的traffic也是被Allow的,反之是不成立

  • Security Group的Rules叠加权限取最宽的权限。

    eg: 一条Rule允许来自ip1:23的traffic,另外一条Rule允许来自0.0.0.0:23的traffic,则叠加后,最终允许0.0.0.0:23的traffic

Network ACL

  • Subnet 级别的firewell,包含一个或者多个上下行的Rules(最多32766个),不同Rule有不同的编号,编号越小,优先级越高
  • 一个Subnet只能关联一个NACL, 一个NACL可以被多个Subnet公用
  • 一个Subnet必须要关联一个NACL,如果没有显式指定,则使用默认的NACL,其中包含一条编号为*的默认规则,拒绝所有上下行的traffic
  • Rule可以显式Allow或者Deny任何traffic
  • Rule是无状态的(stateless), 上下行的traffic过滤规则相互独立

Security Group 和 Network ACL的对比如下

flow logs

一种监控traffic的技术,可以分别配置在ENI/Subnet/VPC级别, 日志可以存到Cloud watch或者S3

VPC Peering

两个VPC资源相互访问的技术

VPC endpoints

直接内网访AWS自家服务的技术,可以省内网通过NAT或者IGW去访问AWS服务的公网地址

访问AWS EC2-Classic(2013年12月4日之后官方不允许新建)类型网的技术

Database.Stateful是Salesforce内置的一个接口类,batchable job默认是无状态的,也就是说即使在batchable job类中定义了实例变量,这些变量在start/excute/finish函数执行时, 会被重新初始化,并不能保持运行过程中的状态。请看示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
global class TestBatchable implements Database.Batchable<SObject> {
private Integer idx = 1;

global List<SObject> start(Database.BatchableContext bc) {
System.debug('start exec, idx:' + idx);
Contact c1 = new Contact();
Contact c2 = new Contact();
List<Contact> l = new List<Contact>();
l.add(c1);
l.add(c2);
return l;
}

global void execute(Database.BatchableContext bc, List<SObject> records) {
idx += 1;
System.debug('execing, idx:' + idx);
}

global void finish(Database.BatchableContext bc) {
System.debug('finish exec, idx:'+ idx);
}
}

以上batchable job分两个batch运行后,

1
2
TestBatchable testBatchable = new TestBatchable();
Database.executeBatch(testBatchable, 1);

执行结果为:

start exec, idx:1
execing, idx:2
execing, idx:2
finish exec, idx:1

如果需要保持运行过程中的状态,需要batchable job实现Database.stateful接口,请看对比例子:

1
2
3
global class TestBatchable implements Database.Batchable<SObject>, Database.Stateful {
private Integer idx = 1;
...(和上面的代码相同)

同样将这个batchable job分两个batch运行后,执行结果为:

start exec, idx:1
execing, idx:2
execing, idx:3
finish exec, idx:3

可以看到,batchable job的excute接口串行运行,同时idx变量的状态得到保持。

另外值得一提的是,Database.stateful接口中并没有定义任何函数需要实例实现,这个比较少见,但是值得学习。此处stateful仅仅表述batchable实例的一个状态,通常我们设计类的时候,会将该状态设计成类的一个成员变量,在构造函数或者setter中配置这个状态。这样的坏处是,如果这样的状态位太多,会使得类很累赘。如果把这样的状态位设计成接口,由用户选择是否需要实现这些接口,设计可以变得更加优雅、简介。