雨中思绪
雨加快了步伐 而我却停住了脚步 看着行人紧张的神情 自己却有丝丝地喜悦 也许是久违的笑容 让我变得如此轻松 雨拍着我的肩 萌生出前所未有的鼓励 这是我多年的期盼 雨抚过我的心 那种无可言状的激情 复活了那曾经枯萎的心 雨轻吻着我的脸 一种莫名的快感 给了我多少勇气 也许时光没有风化掉的那段记忆 雨水可以冲淡 我在雨中徘徊 任凭风吹雨打 任凭痛消愁灭 雨滋润了我的心 我驻足在雨中 从未有过的舒适
雨加快了步伐 而我却停住了脚步 看着行人紧张的神情 自己却有丝丝地喜悦 也许是久违的笑容 让我变得如此轻松 雨拍着我的肩 萌生出前所未有的鼓励 这是我多年的期盼 雨抚过我的心 那种无可言状的激情 复活了那曾经枯萎的心 雨轻吻着我的脸 一种莫名的快感 给了我多少勇气 也许时光没有风化掉的那段记忆 雨水可以冲淡 我在雨中徘徊 任凭风吹雨打 任凭痛消愁灭 雨滋润了我的心 我驻足在雨中 从未有过的舒适
一些概念 领域(核心域,子域) 实体 仓库responsity 聚合根 限定上下文 防腐层 为什么要使用ddd https://www.infoq.cn/article/alibaba-freshhema-ddd-practice https://tech.meituan.com/2017/12/22/ddd-in-practice.html https://insights.thoughtworks.cn/architecture-from-sandwich-to-hexagon/
我以 K8s 极简实战模块的示例应用为例,看看如何配置自动构建示例应用的前后端镜像工作流。在这个例子中,我们创建的工作流将实现以下这些步骤。 当 main 分支有新的提交时,触发工作流。 克隆代码。 初始化 Docker 构建工具链。 登录 Docker Hub。 构建前后端应用镜像,并使用 commit id 作为镜像的 tag。 推送到 Docker Hub 镜像仓库。
https://mp.weixin.qq.com/s/YhpxoPbJNMGPhUfj9PCTZg es基于什么建立的? es是基于开源的Lucene库写的一个搜索引擎,Elasticsearch 把操作都封装成了 HTTP 的 API,我们可以通过api快速操作es 概念 索引 用于存放数据的地方,对应mysql的库 类型 用于定义数据结构的,对应mysql的表 keyword类型与text类型的区别 Keyword 类型是不会分词的,直接根据字符串内容建立反向索引,Text 类型在存入 Elasticsearch 的时候,会先分词, 然后根据分词后的内容建立反向索引。 文档 最终的数据,相当于mysql表里的一条记录 分布式原理 Elasticsearch 会对数据进行切分,同时每一个分片会保存多个副本,为了保证分布式环境下的高可用。 倒排索引的原理 正排索引:通过id查找一条记录,通过某个字段查找一条记录,mysql的索引都属于正排索引,与倒排索引正好相反 倒排索引:一般用于全文搜索,首先会将我们的内容进行分词处理,拆分成单独的词(一般会去掉助词这些,我们称为词条或term),然后每个分词,我们都可以直接索引到对应的文档,这就叫倒排索引 词条(term) 索引里最小的存储与查询单元,英文一般来说是一个单词,中文一般是内容用分词后的词 词典 (term dictionary) 是词条的集合,单词词典是指由文档集合中出现过的所有单词构成的字符串集合。单词词典内每条索引项记载单词本身的一些信息以及指向倒排列表的指针 ES 为了能快速查找到 term,将所有的 term 排了一个序,二分法查找。 倒排表(posting list) 一个文档通常是由多个词组成,倒排表记录的是某个词在哪些文档里出现过以及出现的位置。倒排表记录的不仅是文档编号,还存储了词频等信息。 postings list 如果不进行压缩,会非常占用磁盘空间。 联合查询下,如何快速求交并集(intersections and unions)。 ①压缩 Frame of Reference:在 lucene 中,要求 postings lists 都要是有序的整形数组。 这样就带来了一个很好的好处,可以通过 增量编码(delta-encode)这种方式进行压缩。 比如现在有 id 列表 [73, 300, 302, 332, 343, 372],转化成每一个 id 相对于前一个 id 的增量值(第一个 id 的前一个 id 默认是 0,增量就是它自己)列表是 [73, 227, 2, 30, 11, 29]。...
logstash 的问题 Logstash 致命的问题是它的性能以及资源消耗(默认的堆大小是 1GB)。 尽管它的性能在近几年已经有很大提升,与它的替代者们相比还是要慢很多的。 因为 Logstash 自身的灵活性以及网络上丰富的资料,Logstash 适用于原型验证阶段使用,或者解析非常的复杂的时候。在不考虑服务器资源的情况下,如果服务器的性能足够好,我们也可以为每台服务器安装 Logstash 。我们也不需要使用缓冲,因为文件自身就有缓冲的行为,而 Logstash 也会记住上次处理的位置。 如果服务器性能较差,并不推荐为每个服务器安装 Logstash ,这样就需要一个轻量的日志传输工具,将数据从服务器端经由一个或多个 Logstash 中心服务器传输到 Elasticsearch: filebeat 在版本 5.x 中,Elasticsearch 具有解析的能力(像 Logstash 过滤器)— Ingest。这也就意味着可以将数据直接用 Filebeat 推送到 Elasticsearch,并让 Elasticsearch 既做解析的事情,又做存储的事情。 Filebeat 也会和 Logstash 一样记住上次读取的偏移,如果需要缓冲(例如,不希望将日志服务器的文件系统填满),可以使用 Redis/Kafka,因为 Filebeat 可以与它们进行通信。 Filebeat 只是一个二进制文件没有任何依赖。它占用资源极少,尽管它还十分年轻,正式因为它简单,所以几乎没有什么可以出错的地方,所以它的可靠性还是很高的。 Fluentd Fluentd 创建的初衷主要是尽可能的使用 JSON 作为日志输出,所以传输工具及其下游的传输线不需要猜测子字符串里面各个字段的类型。 这样,它为几乎所有的语言都提供库,这也意味着,我们可以将它插入到我们自定义的程序中。 因为在多数应用场景下,我们会通过 Fluentd 得到结构化的数据。 它的灵活性并不好。但是我们仍然可以通过正则表达式,来解析非结构化的数据。 三者区别 可以看出 Filebeats 功能比较单一,它仅仅只能收集本地的 log,但并不能对收集到的 Log 做什么处理, 所以通常 Filebeats 通常需要将收集到的 log 发送到 Logstash 做进一步的处理。 Logstash 和 Fluentd 都具有收集并处理 log 的能力,网上有很多关于二者的对比,提供一个写得比较好的文章链接如下。 功能上二者旗鼓相当,但 Logstash 消耗更多的 memory,对此 Logstash 的解决方案是使用 Filebeats 从各个叶子节点上收集 log,当然 Fluentd 也有对应的 Fluent Bit....
go struct 能不能比较 需要具体情况具体分析,如果struct中含有不能被比较的字段类型,就不能被比较,如果struct中所有的字段类型都支持比较,那么就可以被比较。 不可被比较的类型: ① slice,因为slice是引用类型,除非是和nil比较 ② map,和slice同理,如果要比较两个map只能通过循环遍历实现 ③ 函数类型 其他的类型都可以比较。 还有两点值得注意: 结构体之间只能比较它们是否相等,而不能比较它们的大小。 只有所有属性都相等而属性顺序都一致的结构体才能进行比较。
https://www.itzhai.com/articles/deep-understanding-of-kafka.html 基本概念 Kafka基本概念: Broker:Kafka以Broker集群的方式运行,一个Kafka节点就是一个Broker。理论上可以跨越多个数据中心。Broker负责数据复制,管理主题、分区、消费偏移量等。如果要跨越多个数据中心,数据中心之间的网络延迟需要非常低,因为Kafka Broker之间以及Broker和Zookeeper服务器之间有大量的通信。 在上图中,Kafka集群中包含3个Broker。 Topic:即主题,与RocketMQ的Topic类似,使用Topic对消息进行分类,Kafka接收到的每条消息都会放入到一个Topic中。 Topic代表发布和消费记录的端点。生产者向主题发布消息,消费者订阅主题进行消费消息; 每条记录有一个键,一个值,一个时间戳和一些元数据组成; 在未指定分区的情况下发布消息时,将使用键的散列选择分区。 Producer:消息生产者,负责向Broker发送消息; Consumer:消息消费者,从负责Broker读取并消费消息; ConsumerGroup:消费分组,对于同一个主题,可以被多个消费分组分别消费,每个消费分组有自己的消费偏移量,互不影响; Partition:分区,对Topic的数据进行分布式存储的最小单位。 存储架构 Kafka是以分区为维度进行存储的 每个Partition分区下面是由多个Segment(段)组成的,Segment是逻辑概念,实际上会对应到上面的三个文件 log:数据文件,存储实际的消息数据; index:索引文件,存储消息数据的索引; timeindex:索引文件,提供时间维度的检索。 Segment文件的命名规则:Partition的第一个Segment文件从0开始,后续每生成一个新的Segment文件的时候,文件名以当前Partition的最大offset为基准,文件名长度为64位long类型。 Segment生成相关配置: log.segment.bytes: 每个segment的大小,达到这个大小后会创建一个新的segment,默认是1G; log.segment.ms: 配置每隔多少毫秒产生一个新的segment,默认是7天。 kafka 集群特性 每个Topic可以配置为多个分区,每个分区可以有多个副本,副本称为Replica,在副本集合中会存在一个Leader副本, Leader负责所有的读写请求,其余副本只负责从Leader同步备份数据。 Isr(In-Sync Replica):是Replicas的一个子集,列出当前还存活着,并且已经同步备份了该分区的节点。 Isr中包括Leader副本,以及与Leader副本保持同步的Follower副本。 Rebalance机制 Rebalance机制是Kafka消费机制的核心。 当消费组消费者数量发生变化、或者消费组消费主题数量变化、主题分区数量变化等的时候,Kafka会重新分配消费者和分区的关系,也就是做一次Rebalance。 **Kafka保证一个Topic分区只会配给一个组内的消费者,**而一个消费者可以消费多个分区。 Rebalance策略主要有三种:Range、RoundRobin、StickyAssignor(粘性分配器) Range:分区数除于消费者总数 RangeAssignor有何缺点? 消费组中的消费者数量多于主题的分区数量,并没有尽可能地使用到所有的消费者 轮循: RoundRobin有何缺点? 虽然RoundRobin尽可能的利用所有的消费者,但是一旦消费者数量发生变化触发Rebalance时,会导致更多的分区重分配。 StickyAssignor:分区尽可能保证分布均匀,分区分配尽可能保持不变更 Kafka是如何保证数据的可靠性? 生产者:acks=all,并且使用同步阻塞的方式发送消息; Topic:replication.factor >= 3,min.insync.replicas >= 2; Broker:unclean.leader.election.enable=false,确保ISR集合中没有可用的在线副本时,不会去选举ISR之外的副本作为新的Leader。 消费端:为了避免丢失未处理完的消息,需要设置为手动提交 Kafka为啥性能这么高? 大家知道RocketMQ是基于Kafka改造而来的,因此Kafka的高性能原因与RocketMQ类似,以下是Kafka高性能的原因: 磁盘顺序读写:Kafka写消息都是直接追加到文件末尾的,不会有随机写的情况,另外,不会随机删除日志,只会按照删除策略删除一整段的历史消息。 与RocketMQ不同的是,kafka不会像RocketMQ那样预分配一个很大的文件来存储消息,Kafka的顺序写可以理解为分段顺序写的,一般一台服务器只部署Kafka就更接近与完全顺序; 批量读写数据,以及压缩传输: Rocket发送消息底层是分批发送的,提高了传输和存储的效率; 数据零拷贝技术:通过mmap内存映射,以及sendfile,减少了数据拷贝次数,提高了数据发送效率。 消息顺序性如何保证 发送端设置同步发送,避免异步发送导致乱序; 消费端消息统一发到同一个分区,通过一个消费者去消费消息。
https://juejin.cn/post/6844903805453074446 一些概念 ConnectionFactory(连接管理器):应用程序与Rabbit之间建立连接的管理器,程序代码中使用。 Channel(信道):消息推送使用的通道,在客户端的每个连接里,可建立多个channel。 Exchange(交换器):消息交换机,指定消息按什么规则,路由到哪个队列。 Queue(队列):消息的载体,每个消息都会被投到一个或多个队列。 RoutingKey(路由键):exchange根据这个关键字进行消息投递。 Binding(绑定键):把exchange和queue按照路由规则绑定起来 Consumer:消息消费者,接受消息的程序 Producer:消息生产者,投递消息的程序 exchange direct exchange:直接匹配,通过exchange名称 + routingKey来发送与接收消息 fanout exchange:广播订阅,向所有的消费者发布消息,但是只有消费者将队列绑定到该路由器才能收到消息 topic exchange:主题匹配订阅,这里的主题指的是routingKey,routingKey可以采用通配符 默认的exchange:如果使用空字符串去声明一个exchange,系统就会使用amq.direct这个exchange,我们创建一个queue时,默认的都会有一个和新建queue同名的routingKey绑定到这个默认的exchange上去 rabbitmq 中 vhost 的作用是什么? vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。 其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。 当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。 rabbitmq 怎么实现延迟消息队列? 通过消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能; 使用 RabbitMQ-delayed-message-exchange 插件实现延迟功能。 使用插件rabbitmq_delayed_message_exchange 该插件需要手动下载并安装到RabbitMQ中,安装方法可以参考官方文档。安装完成后,需要在RabbitMQ管理界面中创建一个新的Exchange,并将Exchange的类型设置为“x-delayed-message”。然后在发送消息时,需要将消息的header中添加一个“x-delay”属性,该属性的值表示消息需要延迟的时间(单位为毫秒)。例如,如果要将消息延迟10秒发送,则需要将“x-delay”属性设置为10000。这样,消息就会被发送到延迟队列中,并在指定的延迟时间后再被重新路由到目标队列中。 使用TTL和死信队列 在RabbitMQ中,可以为队列设置TTL(Time To Live)属性,来控制消息在队列中的存活时间。当消息的TTL过期时,消息会被自动从队列中删除,并发送到一个死信队列中。因此,可以通过设置队列的TTL属性和死信队列来实现延迟消息的功能。具体来说,需要创建一个专门用于接收延迟消息的队列,并设置该队列的TTL属性。然后,当需要发送延迟消息时,将消息发送到该队列中。当消息的TTL过期时,消息就会被路由到死信队列中,然后从死信队列中重新路由到目标队列中。 需要注意的是,在使用TTL和死信队列的方式时,需要确保队列中的消息TTL比死信队列中的TTL大,以确保消息能够被正确地路由到目标队列中。同时,由于死信队列可能会被多个队列共享,因此需要在消息的header中添加一个“x-death”属性,以便识别该消息的原始队列和原始路由键。 消息确认 消息确认 消费者应用(Consumer applications) - 用来接受和处理消息的应用 - 在处理消息的时候偶尔会失败或者有时会直接崩溃掉。而且网络原因也有可能引起各种问题。这就给我们出了个难题,AMQP代理在什么时候删除消息才是正确的?AMQP 0-9-1 规范给我们两种建议: 当消息代理(broker)将消息发送给应用后立即删除。(使用AMQP方法:basic.deliver或basic.get-ok) 待应用(application)发送一个确认回执(acknowledgement)后再删除消息。(使用AMQP方法:basic.ack) 前者被称作自动确认模式(automatic acknowledgement model),后者被称作显式确认模式(explicit acknowledgement model)。在显式模式下,由消费者应用来选择什么时候发送确认回执(acknowledgement)。应用可以在收到消息后立即发送,或将未处理的消息存储后发送,或等到消息被处理完毕后再发送确认回执(例如,成功获取一个网页内容并将其存储之后)。...