guoshaomin

guoshaomin 查看完整档案

北京编辑烟台大学  |  计算机科学与技术 编辑北京嘀嘀无限科技有限公司  |  高级开发工程师 编辑 martinguo.github.io 编辑
编辑

hey

个人动态

guoshaomin 收藏了文章 · 2月26日

带你涨姿势的认识一下 Kafka Consumer

之前我们介绍过了 Kafka 整体架构,Kafka 生产者,Kafka 生产的消息最终流向哪里呢?当然是需要消费了,要不只产生一系列数据没有任何作用啊,如果把 Kafka 比作餐厅的话,那么生产者就是厨师的角色,消费者就是客人,只有厨师的话,那么炒出来的菜没有人吃也没有意义,如果只有客人没有厨师的话,谁会去这个店吃饭呢?!所以如果你看完前面的文章意犹未尽的话,可以继续让你爽一爽。如果你没看过前面的文章,那就从现在开始让你爽。

Kafka 消费者概念

应用程序使用 KafkaConsumer 从 Kafka 中订阅主题并接收来自这些主题的消息,然后再把他们保存起来。应用程序首先需要创建一个 KafkaConsumer 对象,订阅主题并开始接受消息,验证消息并保存结果。一段时间后,生产者往主题写入的速度超过了应用程序验证数据的速度,这时候该如何处理?如果只使用单个消费者的话,应用程序会跟不上消息生成的速度,就像多个生产者像相同的主题写入消息一样,这时候就需要多个消费者共同参与消费主题中的消息,对消息进行分流处理。

Kafka 消费者从属于消费者群组。一个群组中的消费者订阅的都是相同的主题,每个消费者接收主题一部分分区的消息。下面是一个 Kafka 分区消费示意图

image.png

上图中的主题 T1 有四个分区,分别是分区0、分区1、分区2、分区3,我们创建一个消费者群组1,消费者群组中只有一个消费者,它订阅主题T1,接收到 T1 中的全部消息。由于一个消费者处理四个生产者发送到分区的消息,压力有些大,需要帮手来帮忙分担任务,于是就演变为下图

image.png

这样一来,消费者的消费能力就大大提高了,但是在某些环境下比如用户产生消息特别多的时候,生产者产生的消息仍旧让消费者吃不消,那就继续增加消费者。

image.png

如上图所示,每个分区所产生的消息能够被每个消费者群组中的消费者消费,如果向消费者群组中增加更多的消费者,那么多余的消费者将会闲置,如下图所示

image.png

向群组中增加消费者是横向伸缩消费能力的主要方式。总而言之,我们可以通过增加消费组的消费者来进行水平扩展提升消费能力。这也是为什么建议创建主题时使用比较多的分区数,这样可以在消费负载高的情况下增加消费者来提升性能。另外,消费者的数量不应该比分区数多,因为多出来的消费者是空闲的,没有任何帮助。

Kafka 一个很重要的特性就是,只需写入一次消息,可以支持任意多的应用读取这个消息。换句话说,每个应用都可以读到全量的消息。为了使得每个应用都能读到全量消息,应用需要有不同的消费组。对于上面的例子,假如我们新增了一个新的消费组 G2,而这个消费组有两个消费者,那么就演变为下图这样

image.png

在这个场景中,消费组 G1 和消费组 G2 都能收到 T1 主题的全量消息,在逻辑意义上来说它们属于不同的应用。

总结起来就是如果应用需要读取全量消息,那么请为该应用设置一个消费组;如果该应用消费能力不足,那么可以考虑在这个消费组里增加消费者

消费者组和分区重平衡

消费者组是什么

消费者组(Consumer Group)是由一个或多个消费者实例(Consumer Instance)组成的群组,具有可扩展性和可容错性的一种机制。消费者组内的消费者共享一个消费者组ID,这个ID 也叫做 Group ID,组内的消费者共同对一个主题进行订阅和消费,同一个组中的消费者只能消费一个分区的消息,多余的消费者会闲置,派不上用场。

我们在上面提到了两种消费方式

  • 一个消费者群组消费一个主题中的消息,这种消费模式又称为点对点的消费方式,点对点的消费方式又被称为消息队列
  • 一个主题中的消息被多个消费者群组共同消费,这种消费模式又称为发布-订阅模式

消费者重平衡

我们从上面的消费者演变图中可以知道这么一个过程:最初是一个消费者订阅一个主题并消费其全部分区的消息,后来有一个消费者加入群组,随后又有更多的消费者加入群组,而新加入的消费者实例分摊了最初消费者的部分消息,这种把分区的所有权通过一个消费者转到其他消费者的行为称为重平衡,英文名也叫做 Rebalance 。如下图所示

image.png

重平衡非常重要,它为消费者群组带来了高可用性伸缩性,我们可以放心的添加消费者或移除消费者,不过在正常情况下我们并不希望发生这样的行为。在重平衡期间,消费者无法读取消息,造成整个消费者组在重平衡的期间都不可用。另外,当分区被重新分配给另一个消费者时,消息当前的读取状态会丢失,它有可能还需要去刷新缓存,在它重新恢复状态之前会拖慢应用程序。

消费者通过向组织协调者(Kafka Broker)发送心跳来维护自己是消费者组的一员并确认其拥有的分区。对于不同不的消费群体来说,其组织协调者可以是不同的。只要消费者定期发送心跳,就会认为消费者是存活的并处理其分区中的消息。当消费者检索记录或者提交它所消费的记录时就会发送心跳。

如果过了一段时间 Kafka 停止发送心跳了,会话(Session)就会过期,组织协调者就会认为这个 Consumer 已经死亡,就会触发一次重平衡。如果消费者宕机并且停止发送消息,组织协调者会等待几秒钟,确认它死亡了才会触发重平衡。在这段时间里,死亡的消费者将不处理任何消息。在清理消费者时,消费者将通知协调者它要离开群组,组织协调者会触发一次重平衡,尽量降低处理停顿。

重平衡是一把双刃剑,它为消费者群组带来高可用性和伸缩性的同时,还有有一些明显的缺点(bug),而这些 bug 到现在社区还无法修改。

重平衡的过程对消费者组有极大的影响。因为每次重平衡过程中都会导致万物静止,参考 JVM 中的垃圾回收机制,也就是 Stop The World ,STW,(引用自《深入理解 Java 虚拟机》中 p76 关于 Serial 收集器的描述):

更重要的是它在进行垃圾收集时,必须暂停其他所有的工作线程。直到它收集结束。Stop The World 这个名字听起来很帅,但这项工作实际上是由虚拟机在后台自动发起并完成的,在用户不可见的情况下把用户正常工作的线程全部停掉,这对很多应用来说都是难以接受的。

也就是说,在重平衡期间,消费者组中的消费者实例都会停止消费,等待重平衡的完成。而且重平衡这个过程很慢......

创建消费者

上面的理论说的有点多,下面就通过代码来讲解一下消费者是如何消费的

在读取消息之前,需要先创建一个 KafkaConsumer 对象。创建 KafkaConsumer 对象与创建 KafkaProducer 对象十分相似 --- 把需要传递给消费者的属性放在 properties 对象中,后面我们会着重讨论 Kafka 的一些配置,这里我们先简单的创建一下,使用3个属性就足矣,分别是 bootstrap.serverkey.deserializervalue.deserializer

这三个属性我们已经用过很多次了,如果你还不是很清楚的话,可以参考 带你涨姿势是认识一下Kafka Producer

还有一个属性是 group.id 这个属性不是必须的,它指定了 KafkaConsumer 是属于哪个消费者群组。创建不属于任何一个群组的消费者也是可以的

Properties properties = new Properties();
        properties.put("bootstrap.server","192.168.1.9:9092");     properties.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");   properties.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");
KafkaConsumer<String,String> consumer = new KafkaConsumer<>(properties);

主题订阅

创建好消费者之后,下一步就开始订阅主题了。subscribe() 方法接受一个主题列表作为参数,使用起来比较简单

consumer.subscribe(Collections.singletonList("customerTopic"));

为了简单我们只订阅了一个主题 customerTopic,参数传入的是一个正则表达式,正则表达式可以匹配多个主题,如果有人创建了新的主题,并且主题的名字与正则表达式相匹配,那么会立即触发一次重平衡,消费者就可以读取新的主题。

要订阅所有与 test 相关的主题,可以这样做

consumer.subscribe("test.*");

轮询

我们知道,Kafka 是支持订阅/发布模式的,生产者发送数据给 Kafka Broker,那么消费者是如何知道生产者发送了数据呢?其实生产者产生的数据消费者是不知道的,KafkaConsumer 采用轮询的方式定期去 Kafka Broker 中进行数据的检索,如果有数据就用来消费,如果没有就再继续轮询等待,下面是轮询等待的具体实现

try {
  while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(100));
    for (ConsumerRecord<String, String> record : records) {
      int updateCount = 1;
      if (map.containsKey(record.value())) {
        updateCount = (int) map.get(record.value() + 1);
      }
      map.put(record.value(), updateCount);
    }
  }
}finally {
  consumer.close();
}
  • 这是一个无限循环。消费者实际上是一个长期运行的应用程序,它通过轮询的方式向 Kafka 请求数据。
  • 第三行代码非常重要,Kafka 必须定期循环请求数据,否则就会认为该 Consumer 已经挂了,会触发重平衡,它的分区会移交给群组中的其它消费者。传给 poll() 方法的是一个超市时间,用 java.time.Duration 类来表示,如果该参数被设置为 0 ,poll() 方法会立刻返回,否则就会在指定的毫秒数内一直等待 broker 返回数据。
  • poll() 方法会返回一个记录列表。每条记录都包含了记录所属主题的信息,记录所在分区的信息、记录在分区中的偏移量,以及记录的键值对。我们一般会遍历这个列表,逐条处理每条记录。
  • 在退出应用程序之前使用 close() 方法关闭消费者。网络连接和 socket 也会随之关闭,并立即触发一次重平衡,而不是等待群组协调器发现它不再发送心跳并认定它已经死亡。
线程安全性

在同一个群组中,我们无法让一个线程运行多个消费者,也无法让多个线程安全的共享一个消费者。按照规则,一个消费者使用一个线程,如果一个消费者群组中多个消费者都想要运行的话,那么必须让每个消费者在自己的线程中运行,可以使用 Java 中的 ExecutorService 启动多个消费者进行进行处理。

消费者配置

到目前为止,我们学习了如何使用消费者 API,不过只介绍了几个最基本的属性,Kafka 文档列出了所有与消费者相关的配置说明。大部分参数都有合理的默认值,一般不需要修改它们,下面我们就来介绍一下这些参数。

  • fetch.min.bytes

该属性指定了消费者从服务器获取记录的最小字节数。broker 在收到消费者的数据请求时,如果可用的数据量小于 fetch.min.bytes 指定的大小,那么它会等到有足够的可用数据时才把它返回给消费者。这样可以降低消费者和 broker 的工作负载,因为它们在主题使用频率不是很高的时候就不用来回处理消息。如果没有很多可用数据,但消费者的 CPU 使用率很高,那么就需要把该属性的值设得比默认值大。如果消费者的数量比较多,把该属性的值调大可以降低 broker 的工作负载。

  • fetch.max.wait.ms

我们通过上面的 fetch.min.bytes 告诉 Kafka,等到有足够的数据时才会把它返回给消费者。而 fetch.max.wait.ms 则用于指定 broker 的等待时间,默认是 500 毫秒。如果没有足够的数据流入 kafka 的话,消费者获取的最小数据量要求就得不到满足,最终导致 500 毫秒的延迟。如果要降低潜在的延迟,就可以把参数值设置的小一些。如果 fetch.max.wait.ms 被设置为 100 毫秒的延迟,而 fetch.min.bytes 的值设置为 1MB,那么 Kafka 在收到消费者请求后,要么返回 1MB 的数据,要么在 100 ms 后返回所有可用的数据。就看哪个条件首先被满足。

  • max.partition.fetch.bytes

该属性指定了服务器从每个分区里返回给消费者的最大字节数。它的默认值时 1MB,也就是说,KafkaConsumer.poll() 方法从每个分区里返回的记录最多不超过 max.partition.fetch.bytes 指定的字节。如果一个主题有20个分区和5个消费者,那么每个消费者需要至少4 MB的可用内存来接收记录。在为消费者分配内存时,可以给它们多分配一些,因为如果群组里有消费者发生崩溃,剩下的消费者需要处理更多的分区。max.partition.fetch.bytes 的值必须比 broker 能够接收的最大消息的字节数(通过 max.message.size 属性配置大),否则消费者可能无法读取这些消息,导致消费者一直挂起重试。 在设置该属性时,另外一个考量的因素是消费者处理数据的时间。消费者需要频繁的调用 poll() 方法来避免会话过期和发生分区再平衡,如果单次调用poll() 返回的数据太多,消费者需要更多的时间进行处理,可能无法及时进行下一个轮询来避免会话过期。如果出现这种情况,可以把 max.partition.fetch.bytes 值改小,或者延长会话过期时间。

  • session.timeout.ms

这个属性指定了消费者在被认为死亡之前可以与服务器断开连接的时间,默认是 3s。如果消费者没有在 session.timeout.ms 指定的时间内发送心跳给群组协调器,就会被认定为死亡,协调器就会触发重平衡。把它的分区分配给消费者群组中的其它消费者,此属性与 heartbeat.interval.ms 紧密相关。heartbeat.interval.ms 指定了 poll() 方法向群组协调器发送心跳的频率,session.timeout.ms 则指定了消费者可以多久不发送心跳。所以,这两个属性一般需要同时修改,heartbeat.interval.ms 必须比 session.timeout.ms 小,一般是 session.timeout.ms 的三分之一。如果 session.timeout.ms 是 3s,那么 heartbeat.interval.ms 应该是 1s。把 session.timeout.ms 值设置的比默认值小,可以更快地检测和恢复崩愤的节点,不过长时间的轮询或垃圾收集可能导致非预期的重平衡。把该属性的值设置得大一些,可以减少意外的重平衡,不过检测节点崩溃需要更长的时间。

  • auto.offset.reset

该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下的该如何处理。它的默认值是 latest,意思指的是,在偏移量无效的情况下,消费者将从最新的记录开始读取数据。另一个值是 earliest,意思指的是在偏移量无效的情况下,消费者将从起始位置处开始读取分区的记录。

  • enable.auto.commit

我们稍后将介绍几种不同的提交偏移量的方式。该属性指定了消费者是否自动提交偏移量,默认值是 true,为了尽量避免出现重复数据和数据丢失,可以把它设置为 false,由自己控制何时提交偏移量。如果把它设置为 true,还可以通过 auto.commit.interval.ms 属性来控制提交的频率

  • partition.assignment.strategy

我们知道,分区会分配给群组中的消费者。PartitionAssignor 会根据给定的消费者和主题,决定哪些分区应该被分配给哪个消费者,Kafka 有两个默认的分配策略RangeRoundRobin

  • client.id

该属性可以是任意字符串,broker 用他来标识从客户端发送过来的消息,通常被用在日志、度量指标和配额中

  • max.poll.records

该属性用于控制单次调用 call() 方法能够返回的记录数量,可以帮你控制在轮询中需要处理的数据量。

  • receive.buffer.bytes 和 send.buffer.bytes

socket 在读写数据时用到的 TCP 缓冲区也可以设置大小。如果它们被设置为 -1,就使用操作系统默认值。如果生产者或消费者与 broker 处于不同的数据中心内,可以适当增大这些值,因为跨数据中心的网络一般都有比较高的延迟和比较低的带宽。

提交和偏移量的概念

特殊偏移

我们上面提到,消费者在每次调用poll() 方法进行定时轮询的时候,会返回由生产者写入 Kafka 但是还没有被消费者消费的记录,因此我们可以追踪到哪些记录是被群组里的哪个消费者读取的。消费者可以使用 Kafka 来追踪消息在分区中的位置(偏移量)

消费者会向一个叫做 _consumer_offset 的特殊主题中发送消息,这个主题会保存每次所发送消息中的分区偏移量,这个主题的主要作用就是消费者触发重平衡后记录偏移使用的,消费者每次向这个主题发送消息,正常情况下不触发重平衡,这个主题是不起作用的,当触发重平衡后,消费者停止工作,每个消费者可能会分到对应的分区,这个主题就是让消费者能够继续处理消息所设置的。

如果提交的偏移量小于客户端最后一次处理的偏移量,那么位于两个偏移量之间的消息就会被重复处理

image.png

如果提交的偏移量大于最后一次消费时的偏移量,那么处于两个偏移量中间的消息将会丢失

image.png

既然_consumer_offset 如此重要,那么它的提交方式是怎样的呢?下面我们就来说一下

提交方式

KafkaConsumer API 提供了多种方式来提交偏移量

自动提交

最简单的方式就是让消费者自动提交偏移量。如果 enable.auto.commit 被设置为true,那么每过 5s,消费者会自动把从 poll() 方法轮询到的最大偏移量提交上去。提交时间间隔由 auto.commit.interval.ms 控制,默认是 5s。与消费者里的其他东西一样,自动提交也是在轮询中进行的。消费者在每次轮询中会检查是否提交该偏移量了,如果是,那么就会提交从上一次轮询中返回的偏移量。

提交当前偏移量

auto.commit.offset 设置为 false,可以让应用程序决定何时提交偏移量。使用 commitSync() 提交偏移量。这个 API 会提交由 poll() 方法返回的最新偏移量,提交成功后马上返回,如果提交失败就抛出异常。

commitSync() 将会提交由 poll() 返回的最新偏移量,如果处理完所有记录后要确保调用了 commitSync(),否则还是会有丢失消息的风险,如果发生了在均衡,从最近一批消息到发生在均衡之间的所有消息都将被重复处理。

异步提交

异步提交 commitAsync() 与同步提交 commitSync() 最大的区别在于异步提交不会进行重试,同步提交会一致进行重试。

同步和异步组合提交

一般情况下,针对偶尔出现的提交失败,不进行重试不会有太大的问题,因为如果提交失败是因为临时问题导致的,那么后续的提交总会有成功的。但是如果在关闭消费者或再均衡前的最后一次提交,就要确保提交成功。

因此,在消费者关闭之前一般会组合使用commitAsync和commitSync提交偏移量

提交特定的偏移量

消费者API允许调用 commitSync() 和 commitAsync() 方法时传入希望提交的 partition 和 offset 的 map,即提交特定的偏移量。

文章参考:

Kafka 消费者解读

《Kafka-the-definitive》

《极客时间-Kafka核心技术与实战》

《Kafka 权威指南》

https://docs.confluent.io/cur...

KafkaConsumer

查看原文

guoshaomin 关注了专栏 · 2020-11-24

民工哥技术之路

公众号:民工哥技术之路、《Linux系统运维指南 从入门到企业实战》作者。专注系统架构、高可用、高性能、高并发,数据库、大数据、数据分析、Python技术、集群中间件、后端等开源技术分享。

关注 27645

guoshaomin 收藏了文章 · 2020-11-24

Linux三剑客Awk、Sed、Grep 命令详解

Linux三剑客Awk命令详解

命令名称

Awk  pattern scanning and processing language

命令作用

对文本和数据进行处理

详细说明

awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输(stdin)、一个或多个文件,或其它命令的输出。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。

语法格式

awk [options] 'scripts' var=value filename

常用参数

  • -F 指定分隔符(可以是字符串或正则表达式)
  • -f 从脚本文件中读取awk命令
  • -v var=value 赋值变量,将外部变量传递给awk

脚本基本结构

 awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' filename

一个awk脚本通常由BEGIN语句+模式匹配+END语句三部分组成,这三部分都是可选项

工作原理:

  • 第一步执行BEGIN 语句
  • 第二步从文件或标准输入读取一行,然后再执行pattern语句,逐行扫描文件到文件全部被读取
  • 第三步执行END语句

实例展示:

echo "hello " | awk 'BEGIN{ print "welcome" } END{ print "2017-08-08" }'
welcome
2017-08-08

echo -e "hello" | awk 'BEGIN{ print "welcome" } {print} END{ print "2017-08-08" }'
welcome
hello
2017-08-08
#不加print参数时默认只打印当前的行

echo|awk '{ a="hello"; b="nihao"; c="mingongge"; print a,b,c; }'
hello nihao mingongge
#使用print以逗号分隔时,打印则是以空格分界

echo|awk '{ a="mgg"; b="mingg"; c="mingongge"; print a" is "b" or "c; }'
mgg is mingg or mingongge
#awk的print语句中双引号其实就是个拼接作用

Awk的变量

内置变量

$0   #当前记录
$1~$n #当前记录的第N个字段
FS   #输入字段分隔符(-F相同作用)默认空格
RS   #输入记录分割符,默认换行符
NF   #字段个数就是列
NR   #记录数,就是行号,默认从1开始
OFS  #输出字段分隔符,默认空格
ORS  #输出记录分割符,默认换行符  

外部变量

[mingongge@ ~]#a=100
[mingongge@ ~]#b=100
[mingongge@ ~]#echo |awk '{print v1*v2 }' v1=$a v2=$b
10000

Awk运算与判断

算术运算符

      •  加减
    • / & 乘 除 求余
  • ^ *  求幂
  • ++ -- 增加或减少,作为前缀或后缀
[mingongge@ ~]#awk 'BEGIN{a="b";print a,a++,a--,++a;}'
b 0 1 1

[mingongge@ ~]#awk 'BEGIN{a="0";print a,a++,a--,++a;}'
0 0 1 1

[mingongge@ ~]#awk 'BEGIN{a="0";print a,a++,--a,++a;}'
0 0 0 1

#和其它编程语言一样,所有用作算术运算符进行操作,操作数自动转为数值,所有非数值都变为0

赋值运算符

= += -= *= /= %= ^= **=

正则运算符

~ !~  匹配正则表达式/不匹配正则表达式

逻辑运算符

||  &&  逻辑或  逻辑与

关系运算符

< <= > >= != = 

其它运算符

$     #字段引用 
空格  #字符串链接符
?:    #三目运算符
ln    #数组中是否存在某键值

Awk正则

^    行首定位符
$    行尾定位符
.    匹配任意单个字符
*    匹配0个或多个前导字符(包括回车)
+    匹配1个或多个前导字符
?    匹配0个或1个前导字符 
[]   匹配指定字符组内的任意一个字符/^[ab]
[^]  匹配不在指定字符组内的任意一个字符
()   子表达式
|    或者
\    转义符
~,!~ 匹配或不匹配的条件语句
x{m} x字符重复m次
x{m,} x字符至少重复m次
X{m,n} x字符至少重复m次但不起过n次(需指定参数-posix或--re-interval)

Linux三剑客Sed命令详解

命令名称

Sed一个强大的流式文本编辑器

详细说明

sed是一种流编辑器,也是文本处理中非常好的工具,配合正则使用更强大处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区的内容,完成后输出到屏幕,接着处理下一行.

命令格式

 sed [options] 'command' file(s)

 sed [options] -f scriptfile file(s)

常用参数

-e #以指定的指令来处理输入的文本文件
-n  #取消默认输出(如果和p命令同时使用只会打印发生改变的行**)
-h #帮助
-V #显示版本信息

常用命令

a #在当前行下面插入文本 

i #在当前行上面插入文本 

c #把选定的行改为新的文本 

d #删除,删除选择的行 

D #删除模板块的第一行 

s #替换指定字符 

h #拷贝模板块的内容到内存中的缓冲区

H #追加模板块的内容到内存中的缓冲区 

g #获得内存缓冲区的内容,并替代当前模板块中的文本 

G #获得内存缓冲区的内容,并追加到当前模板块文本的后面 

l #列表不能打印字符的清单 

n #读取下一个输入行,用下一个命令处理新的行而不是用第一个命令 

N #追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码 

p  #打印匹配的行 

P #(大写)打印模板的第一行

q  #退出Sed 

b  #lable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾 

r #file 从file中读行 

t #label if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾 

T #label 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾 

w #file 写并追加模板块到file末尾

W #file 写并追加模板块的第一行到file末尾

!  #表示后面的命令对所有没有被选定的行发生作用 

=  #打印当前行号码

# #把注释扩展到下一个换行符以前

Sed替换命令

g #表示行内全面替换(全局替换配合s命令使用)

p #表示打印行 

w  #表示把行写入一个文件 

x #表示互换模板块中的文本和缓冲区中的文本 

y #表示把一个字符翻译为另外的字符(但是不用于正则表达式) 

1  #子串匹配标记 

& #已匹配字符串标记

Sed正则

^ #匹配行开始 

$ #匹配行结束

. #匹配一个非换行符的任意字符

 #匹配0个或多个字符

[] #匹配一个指定范围内的字符

[^]  #匹配一个不在指定范围内的字符 

(..) #匹配子串

&  #保存搜索字符用来替换其他字符

< #匹配单词的开始

>  #匹配单词的结束

x{m} #重复字符x,m次

x{m,} #重复字符x,至少m次 

x{m,n} #重复字符x,至少m次,不多于n次

Sed常用实例

1、替换操作

echo "hello world" |sed 's/ /-/1g'
hello-world 
#从第一个空格开始全局替换成-,只不过文本中只有一个空格

2、删除操作

sed '/^$/d' filename #删除空白行

sed '2d' filename #删除第二行

sed '2,$d' filename #删除第二直到未尾所有行

sed '$d' filename #删除最后一行

sed '/^test/'d filename #删除以test开头行

3、匹配替换

echo "hello world" |sed 's/w+/[&]/g'

[hello] [world]

echo "hello world" |sed 's/w+/"&"/g'

"hello" "world"

#w+匹配每一个单词,&表示匹配到的字符串

echo AAA bbb |sed 's/([A-Z]+) ([a-z]+)/[2] [1]/'

[bbb] [AAA]

#子串匹配替换

4、选定范围

sed -n '/= 0/,/max/p' svnserve.conf

#min-encryption = 0

#max-encryption = 256

#所有在=0到max范围内的行都会被打印出来

5、sed多点编辑功能(-e)

[root@centos001 ~]#cat -n test 
1  this is a test file
2  welcome
3  to
4  here
5  hello WORLD
6
7  linux centos6.8
8  redhat

sed -e '2,6d' -e 's/linux centos6.8/Linux Centos6.8/' test
this is a test file
Linux Centos6.8
redhat
#如果两条命令功能一样,那么就需要用到下面的参数

sed --expression='s/linux centos6.8/Linux Centos6.8/' --expression='s/to/TO/' test**
this is a test file
welcome
TO
here
hello WORLD
Linux CenTOs6.8
redhat

6、读入与写入

[root@centos001 ~]#cat test1
welcom 
to 
here

[root@centos001 ~]#sed '/here/r test1' test
this is a test file
welcome
to
here
#welcom
to
here#
hello WORLD
linux centos6.8
redhat

#将test1的文件内容读取显示所有匹配here行的后面
sed -n '/centos6.8/w test2' test

[root@centos001 ~]#cat test2
linux centos6.8

#将test文件匹配到centos6.8的所有行都写入到test2文件中,文件可以不存在.
#如果文件存在,就会被重定向不是追加

7、追加与插入

[root@centos001 ~]#sed '/^l/a2017-08-08' test2
linux centos6.8
2017-08-08
#在匹配以l开头的行的后面追加2017-08-08

[root@centos001 ~]#sed '1a2017-08-08' test2
linux centos6.8
2017-08-08
#在第一行的后面追加2017-08-08

[root@centos001 ~]#sed '/^l/i2017-08-08' test2
2017-08-08
linux centos6.8
#在匹配以l开头的行的前面插入2017-08-08
#######以上操作是不会改变文件内容################

[root@centos001 ~]#sed -i '/^l/i2017-08-08' test2
[root@centos001 ~]#cat test2
2017-08-08
linux centos6.8

8、其它命令实例

[root@centos001 ~]#cat -n test2
 1 2017-08-08
 2 linux centos6.8
 3 08
 4
 5 test

[root@centos001 ~]#**sed '/08/{ n; s/l/L/; }' test2
2017-08-08
Linux centos6.8
08
test
#如果08匹配到就跳到下一行,将小写l替换成大写,注意到第三行也是被匹配到
#但是后面的条件不满足,所有没有被替换

[root@centos001 ~]#sed '1,4y/8/9/' test2
2017-09-09
linux centos6.9
09
test
#将1至4行所有的数字8替换成9

[root@centos001 ~]#**sed '1q' test2**
2017-08-08
#打印第一行内容后退出

9、打印奇数或公偶数行

[root@centos001 ~]#sed -n 'p;n' test2
20170808
08

[root@centos001 ~]#sed -n 'n;p' test2
linux centos6.8
test

[root@centos001 ~]#sed -n '1~2p' test2
20170808
08

[root@centos001 ~]#sed -n '2~2p' test2
linux centos6.8
test

10、打印匹配字符串行的下一行

[root@centos001 ~]#sed -n '/linux/{n;p}' test2
08

[root@centos001 ~]#awk '/linux/{getline; print}' test2
08

Linux三剑客Grep 命令详解

命令名称:
grep

命令作用:

文本查找或搜索工具

详细说明:

同样可以配合正则表达式来搜索文本,并将匹配的行打印输出,也可用于过滤与搜索特定字符串,使用十分灵活

常用参数

-a  #不要忽略二进制数据

-A  #除了显示符合范本样式的那一行之外,并显示该行之后的内容

-b  #在显示符合范本样式的那一行之外,并显示该行之前的内容

-B  #除了显示符合样式的那一行之外,并显示该行之前的内容

-c  #计算符合范本样式的列数

-C  #除了显示符合范本样式的那一列之外,并显示该列之前后的内容

-d  #当指定要查找的是目录而非文件时,必须使用这项参数,否则grep命令将回报信息并停止动作

-e  #指定字符串作为查找文件内容的范本样式

-E  #将范本样式为延伸的普通表示法来使用,意味着使用能使用扩展正则表达式

-f  #指定范本文件,其内容有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每一列的范本样式

-F  #将范本样式视为固定字符串的列表

-G  #将范本样式视为普通的表示法来使用

-h  #在显示符合范本样式的那一列之前,不标示该列所属的文件名称

-H  #在显示符合范本样式的那一列之前,标示该列的文件名称

-i  #忽略字符大小写的差别

-l  #列出文件内容符合指定的范本样式的文件名称

-L  #列出文件内容不符合指定的范本样式的文件名称

-n  #在显示符合范本样式的那一列之前,标示出该列的编号

-q  #不显示任何信息

-R/-r #此参数的效果和指定“-d recurse”参数相同

-s  #不显示错误信息

-v  #反转查找

-V  #显示版本信息 

-w  #只显示全字符合的列

-x  #只显示全列符合的列

-y  #此参数效果跟“-i”相同

-o  #只输出文件中匹配到的部分

正则表达式

^  #匹配以XX开头的行

$  #匹配以XX结尾的行

常用实例

1、在多个文件中查找:

grep "file" file_1 file_2 file_3 

2、输出除之外的所有行 -v 选项:

grep -v "file" file_name

3、标记匹配颜色 --color=auto 选项:

grep "file" file_name --color=auto

4、使用正则表达式 -E 选项:

grep -E "[1-9]+"

egrep "[1-9]+"

5、只输出文件中匹配到的部分 -o 选项:

echo this is a test line. | grep -o -E "[a-z]+."

line.

echo this is a test line. | egrep -o "[a-z]+."

line.

6、统计文件或者文本中包含匹配字符串的行数-c 选项:

grep -c "text" file_name

2

7、输出包含匹配字符串的行数 -n 选项:

grep "text" -n file_name

或

cat file_name | grep "text" -n

8、多个文件

grep "text" -n file_1 file_2

9、搜索多个文件并查找匹配文本在哪些文件中:

grep -l "text" file1 file2 file3...

10、grep递归搜索文件

在多级目录中对文本进行递归搜索:

grep "text" . -r -n

11、忽略匹配样式中的字符大小写:

echo "hello world" | grep -i "HELLO"

hello

12、选项 -e 指定多个匹配样式:

echo this is a text line | grep -e "is" -e "line" -o

is

line

13、也可以使用 -f 选项来匹配多个样式,在样式文件中逐行写出需要匹配的字符。

cat patfile

aaa

bbb

echo aaa bbb ccc ddd eee | grep -f patfile -o

14、在grep搜索结果中包括或者排除指定文件:

只在目录中所有的.php和.html文件中递归搜索字符"main()"

grep "main()" . -r --include *.{php,html}

15、在搜索结果中排除所有README文件

grep "main()" . -r --exclude "README"

16、在搜索结果中排除filelist文件列表里的文件

grep "main()" . -r --exclude-from filelist

Linux三剑客Awk、Sed、Grep 命令详解,到这里就介绍完了。欢迎评论、点赞、转发分享支持。

注:未经授权,禁止任何方式的转载。
image

查看原文

guoshaomin 关注了标签 · 2020-09-30

关注 511

guoshaomin 关注了标签 · 2020-09-30

c++

C++是一种静态数据类型检查的,支持多范型的通用程序设计语言。C++支持过程化程序设计、数据抽象化、面向对象程序设计、泛型程序设计、基于原则设计等多种程序设计风格。

关注 14754

guoshaomin 关注了标签 · 2020-09-30

golang

Go语言是谷歌2009发布的第二款开源编程语言。Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。
Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发Go,是因为过去10多年间软件开发的难度令人沮丧。Go是谷歌2009发布的第二款编程语言。

七牛云存储CEO许式伟出版《Go语言编程
go语言翻译项目 http://code.google.com/p/gola...
《go编程导读》 http://code.google.com/p/ac-m...
golang的官方文档 http://golang.org/doc/docs.html
golang windows上安装 http://code.google.com/p/gomi...

关注 26194

guoshaomin 关注了用户 · 2019-12-03

梦想家 @xhy_ss

关注 70

guoshaomin 收藏了文章 · 2019-12-02

阿里云开源 image-syncer 工具,容器镜像迁移同步的终极利器

为什么要做这个工具?

由于阿里云上的容器服务 ACK 在使用成本、运维成本、方便性、长期稳定性上大大超过公司自建自维护 Kubernets 集群,有不少公司纷纷想把之前自己维护 Kubernetes 负载迁移到阿里云 ACK 服务上。在迁移过程中,往往会碰到一个不大不小的坑:那就是怎么把已有的容器镜像平滑的迁移到阿里云镜像服务 ACR 上。这个问题看起来非常简单,如果只有三五个镜像,只要做一次 docker pull/docker push 就能完成,但实际生产中涉及到成千上百个镜像,几 T 的镜像仓库数据时,迁移过程就变的耗时非常漫长,甚至丢失数据。

阿里云云原生应用平台的工程师——也就是我们,发现这是一个通用的需求,用户会在各种容器镜像仓库之间做迁移,或者进一步,期望有同步复制的能力,所以我们研发了 image-syncer 这个项目来支持迁云,并同时开源给业界大众,用来解决通用的容器镜像批量迁移/同步的问题。

这个工具在实际生产中,已经帮助了多家客户进行镜像迁移,其中最大镜像仓库的总量达到 3T 以上,同步时能跑满机器带宽,进行同步任务的机器磁盘容量没有要求。

image-syncer 简介

如上所述,在 k8s 集群迁移场景中,镜像仓库之间进行镜像迁移/同步是基本需求,而使用 docker pull/push 结合脚本的传统方式进行镜像同步,有如下几个局限性:

  1. 依赖磁盘存储,需要及时进行本地镜像的清理,并且落盘造成多余的时间开销,难以胜任生产场景中大量镜像的迁移
  2. 依赖 docker 程序,docker daemon 对 pull/push 的并发数进行了严格的限制,无法进行高并发同步
  3. 一些功能只能通过 HTTP api 进行操作,单纯使用 docker cli 无法做到,使脚本变得复杂

image-syncer 的定位是一个简单、易用的批量镜像迁移/同步工具,支持几乎所有目前主流的基于 docker registry V2 搭建的镜像存储服务,比如 ACR、Docker 
Hub、Quay、自建 Harbor 等,目前已经初步经过了 TB 级别的生产环境镜像迁移验证,并开源于 https://github.com/AliyunContainerService/image-syncer ,欢迎大家下载使用以及提供宝贵的建议~

工具特性

image-syncer 的特性如下:

1.支持多对多镜像仓库同步
2.支持基于 Docker Registry V2 搭建的 docker 镜像仓库服务 (如 Docker Hub、 Quay、 阿里云镜像服务 ACR、 Harbor等)
3.同步只经过内存和网络,不依赖磁盘存储,同步速度快
4.增量同步, 通过对同步过的镜像 blob 信息落盘,不重复同步已同步的镜像
5.并发同步,可以通过配置文件调整并发数
6.自动重试失败的同步任务,可以解决大部分镜像同步中的网络抖动问题
7.不依赖 docker 以及其他程序

借助 image-syncer,只需要保证 image-syncer 的运行环境与需要同步的 registry 网络连通,你可以快速地完成从镜像仓库的迁移、拷贝以及增量同步,并且对硬件资源几乎没有要求(因为 image-syncer 严格控制网络连接数目=并发数,所以只有在当单个镜像层过大的情况下,并发数目过大可能会打满内存,内存占用 <= 并发数 x 最大镜像层大小);除了使用重传机制规避同步过程中可能出现的偶发问题之外, image-syncer 会在运行结束时统计最后同步失败的镜像个数,并且打印出详细的日志,帮助使用者定位同步过程中出现的问题。

使用指南

image-syncer 运行,只需要用户提供一个配置文件,内容如下:

{
    "auth": {                   // 认证字段,其中每个对象为一个registry的一个账号和
                                // 密码;通常,同步源需要具有pull以及访问tags权限,
                                // 同步目标需要拥有push以及创建仓库权限,如果没有提供,则默认匿名访问

        "quay.io": {            // registry的url,需要和下面images中对应registry的url相同
            "username": "xxx",               // 用户名,可选
            "password": "xxxxxxxxx",         // 密码,可选
            "insecure": true                 // registry是否是http服务,如果是,insecure 字段需要为true,默认是false,可选,支持这个选项需要image-syncer版本 > v1.0.1
        },
        "registry.cn-beijing.aliyuncs.com": {
            "username": "xxx",
            "password": "xxxxxxxxx"
        },
        "registry.hub.docker.com": {
            "username": "xxx",
            "password": "xxxxxxxxxx"
        }
    },
    "images": {
        // 同步镜像规则字段,其中条规则包括一个源仓库(键)和一个目标仓库(值)

        // 同步的最大单位是仓库(repo),不支持通过一条规则同步整个namespace以及registry

        // 源仓库和目标仓库的格式与docker pull/push命令使用的镜像url类似(registry/namespace/repository:tag)
        // 源仓库和目标仓库(如果目标仓库不为空字符串)都至少包含registry/namespace/repository
        // 源仓库字段不能为空,如果需要将一个源仓库同步到多个目标仓库需要配置多条规则
        // 目标仓库名可以和源仓库名不同(tag也可以不同),此时同步功能类似于:docker pull + docker tag + docker push
        "quay.io/coreos/kube-rbac-proxy": "quay.io/ruohe/kube-rbac-proxy",
        "xxxx":"xxxxx",
        "xxx/xxx/xx:tag1,tag2,tag3":"xxx/xxx/xx"
        // 当源仓库字段中不包含tag时,表示将该仓库所有tag同步到目标仓库,此时目标仓库不能包含tag
        // 当源仓库字段中包含tag时,表示只同步源仓库中的一个tag到目标仓库,如果目标仓库中不包含tag,则默认使用源tag
        // 源仓库字段中的tag可以同时包含多个(比如"a/b/c:1,2,3"),tag之间通过","隔开,此时目标仓库不能包含tag,并且默认使用原来的tag

        // 当目标仓库为空字符串时,会将源镜像同步到默认registry的默认namespace下,并且repo以及tag与源仓库相同,默认registry和默认namespace可以通过命令行参数以及环境变量配置,参考下面的描述
    }     
}

用户可以根据配置不同的镜像同步规则组合,以匹配不同的迁移/同步需求,如将单个镜像 repo 同步到多个不同的镜像 repo、将多个源镜像同步到单个镜像 repo 中(以 tag 区分)、在同一个 registry 中以不同的名字拷贝一个镜像 repo 等等。
使用时需要注意,如果匿名访问作为同步源的 registry 地址,可能存在权限问题无法 pull 镜像以及无法获取 tags,这种情况下需要在" auth "中加入有对应权限的账号密码;而如果匿名访问作为同步目标的 registry 地址,可能存在权限问题无法 push 镜像,同样也可能需要用户提供有对应权限的账号密码。
image-syncer 同时支持 insecure 的 registry(类比 docker 的-- insecure - registry 参数,在" auth "的相应条目中添加 " insecure ": true ),可以同时在 http 和 https 两种类型的镜像服务之间迁移。
image-syncer 还提供了一些简单的参数来控制程序的运行,包括并发数目控制、重传次数设置等等:

-h  --help       使用说明,会打印出一些启动参数的当前默认值
    --config     设置用户提供的配置文件所在路径,使用之前需要创建配置文件,默认为当前工作目录下的image-syncer.json文件
    --log        打印出来的log文件路径,默认打印到标准错误输出,如果将日志打印到文件将不会有命令行输出,此时需要通过cat对应的日志文件查看
    --namespace  设置默认的目标namespace,当配置文件内一条images规则的目标仓库为空,并且默认registry也不为空时有效,可以通过环境变量DEFAULT_NAMESPACE设置,同时传入命令行参数会优先使用命令行参数值
    --registry   设置默认的目标registry,当配置文件内一条images规则的目标仓库为空,并且默认namespace也不为空时有效,可以通过环境变量DEFAULT_REGISTRY设置,同时传入命令行参数会优先使用命令行参数值
    --proc       并发数,进行镜像同步的并发goroutine数量,默认为5
    --records    指定传输过程中保存已传输完成镜像信息(blob)的文件输出/读取路径,默认输出到当前工作目录,一个records记录了对应目标仓库的已迁移信息,可以用来进行连续的多次迁移(会节约大量时间,但不要把之前自己没执行过的records文件拿来用),如果有unknown blob之类的错误,可以删除该文件重新尝试
    --retries    失败同步任务的重试次数,默认为2,重试会在所有任务都被执行一遍之后开始,并且也会重新尝试对应次数生成失败任务的生成。一些偶尔出现的网络错误比如io timeout、TLS handshake timeout,都可以通过设置重试次数来减少失败的任务数量

在同步结束之后,image-syncer
会统计成功和失败的同步任务数目(每个同步任务代表一个镜像),并在标准输出和日志中打印 "Finished, FAILED TASKS> sync tasks failed, TASKS> tasks generate failed" 的字样,从而可以获得同步的结果。更多FAQ参见 FAQs.md

使用示例

ACR(Alibaba Cloud Container Registry)是阿里云提供的容器镜像托管服务,支持全球20个地域的镜像全生命周期管理,联合容器服务等云产品,打造云原生应用的一站式体验。这里通过将自建 harbor 上的镜像同步到 ACR,提供 image-syncer 的基本使用示例

从自建 harbor 同步镜像到 ACR

1.在阿里云控制台上开通容器镜像服务,并进入 ACR 控制台

2.创建命名空间,默认仓库类型决定了当仓库不存在时,docker push 自动创建的仓库类型是公有的还是私有的;如果部分需要同步的目标仓库不存在,需要打开自动创建仓库按钮,让类似" docker push "的操作能自动创建仓库

3.创建访问凭证,对应的账号即为 docker login 的账号,如下图:

4.上面的操作使用的是主账号,默认拥有全部权限;为了进行权限管理,我们也可以通过创建 RAM 子账号,并配置对应权限,这里的场景中我们只使用到了创建、更新镜像仓库相关权限,最小权限设置如下,访问控制的资源粒度为 image-syncer 命名空间:

{
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cr:CreateRepository",
                "cr:UpdateRepository",
                "cr:PushRepository",
                "cr:PullRepository"
            ],
            "Resource": [
                "acs:cr:*:*:repository/image-syncer/*"
            ]
        }
    ],
    "Version": "1"
}

5.同样,RAM 账号需要通过 RAM 用户登陆入口登陆阿里云控制台,并进入 ACR 控制台创建访问凭证(同3.)

6.然后我们可以通过访问凭证中创建的密码,完成如下 image-syncer 的同步配置(配置中使用 RAM 子账号的访问凭证);这里我们将本地搭建的 harbor( http 服务,要设置 insecure,通过 harbor.myk8s.paas.com:32080 访问)中的 library/nginx 仓库同步到华北2(通过为 registry.cn-beijing.aliyuncs.com 访问)中的 image-syncer 命名空间下,并且保持仓库名称为 nginx,config.json 如下:

{
    "auth": {
        "harbor.myk8s.paas.com:32080": {
            "username": "admin",
            "password": "xxxxxxxxx",
            "insecure": true
        },
        "registry.cn-beijing.aliyuncs.com": {
            "username": "acr_pusher@1938562138124787",
            "password": "xxxxxxxx"
        }
    },
    "images": {
        "harbor.myk8s.paas.com:32080/library/nginx": ""
    }
}

7.下载最新的 image-syncer 可执行文件(目前只支持 linux amd64 版本,可以自行编译),解压,并运行工具

执行命令:

# 设置默认目标registry为registry.cn-beijing.aliyuncs.com,默认目标namespace为image-syncer
# 并发数为10,重试次数为10
# 日志输出到./log文件下,不存在会自动创建,不指定的话默认会将日志打印到Stderr
# 指定配置文件为harbor-to-acr.json,内容如上所述
./image-syncer --proc=10 --config=./harbor-to-acr.json --registry=registry.cn-beijing.aliyuncs.com --namespace=image-syncer --retries=10 --log=./log

一次同步会经历三个阶段:生成同步任务、执行同步任务以及重试失败任务;其中,每个同步任务都代表了一个需要同步的 tag (镜像),如果配置文件中某条规则没有指定 tag,在“生成同步任务”阶段会自动 list 源仓库所有 tag,并生成对应的同步任务,如果生成同步任务失败,也会在重试阶段进行重试,(故意配错账号密码时)执行输出如下:

正常运行的输出:

在运行时,image-syncer 会打印出如下的日志信息:

从自建 harbor 同步镜像到 ACR 企业版

ACR 企业版提供企业级容器镜像、Helm Chart 安全托管能力,拥有企业级安全独享特性,具备千节点镜像分发、全球多地域同步能力。提供云原生应用交付链,实现一次应用变更,全球化多场景自动交付。强烈推荐安全需求高、业务多地域部署、拥有大规模集群节点的企业级客户使用。

同步到 ACR 企业版和 ACR 普通版所需的操作基本相同:

1.创建 ACR 企业版实例

2.创建命名空间,并对默认仓库类型进行设置,并打开自动创建仓库的功能

3.配置公网的访问控制,需要打开 ACR 企业版的访问入口,并添加公网白名单,使外部能访问镜像服务

4.配置访问凭证,这部分和 ACR 普通版相同

5.使用访问凭证中创建的密码,完成如下 image-syncer 的同步配置;与之前同步到ACR共享版不同的是,每个ACR企业版实例有自己单独的域名(一个公网可见,一个仅专有网络可见,如果镜像同步工具运行在个人环境上需要使用公网域名;如果要使用仅专有网络可见的域名,则将镜像同步工具运行在阿里云ECS实例上,并且通过配置使域名对该ECS所在的专有网络可见;这里使用的是公网域名
ruohe-test-registry.cn-shanghai.cr.aliyuncs.com),并且namespace对于每个不同企业版实例之间来说都是隔离的。我们同样将本地搭建的 harbor(http 服务,要设置i nsecure,通过 harbor.myk8s.paas.com:32080 访问)中的 library/nginx 仓库同步到 ACR 企业版实例中 image-syncer 命名空间下,并且保持仓库名称为 nginx,config.json 如下:

{
    "auth": {
        "harbor.myk8s.paas.com:32080": {
            "username": "admin",
            "password": "xxxxxxxxx",
            "insecure": true
        },
        "ruohe-test-registry.cn-shanghai.cr.aliyuncs.com": {
            "username": "ruohehhy",
            "password": "xxxxxxxx"
        }
    },
    "images": {
        "harbor.myk8s.paas.com:32080/library/nginx": ""
    }
}

6.运行工具
执行命令

# 设置默认目标registry为ruohe-test-registry.cn-shanghai.cr.aliyuncs.com,默认目标namespace为image-syncer
# 并发数为10,重试次数为10
# 日志输出到./log文件下,不存在会自动创建,不指定的话默认会将日志打印到Stderr
# 指定配置文件为harbor-to-acr.json,内容如上所述
./image-syncer --proc=10 --config=./harbor-to-acr.json --registry=ruohe-test-registry.cn-shanghai.cr.aliyuncs.com --namespace=image-syncer --retries=10

输出与前述相同

更多能力

以上的 image-syncer 满足了你的容器镜像迁移同步的所有诉求吗?如果有更多的需求、甚至想共建更多的能力,欢迎访问 https://github.com/AliyunContainerService/image-syncer 留下 issue。

开源不易,长期的维护项目更不容易,大家觉得好就请给这个项目点个 star,公司内的老板会看这个项目的 star 数量来决定后续能不能投更多的研发资源来维护这个项目,万分感谢:)

One More Thing

那么,镜像仓库能顺利迁移,是否迁云就能顺利进行呢?答案是——并没有那么简单,仓库只是迁云过程中碰到的问题之一,还需要解决其他痛点。

对于已经在私有云/公有云上已经把业务应用跑在 k8s 上的用户来说,如何让业务在迁云过程中不受影响是头等大事。阿里云云原生应用平台的解决方案架构师对此已经有了完善的考虑,力助用户应用高效稳定的迁移到 ACK 服务上。在帮助这些用户落实迁云方案的同时,我们也在不断思考如何把这些案例中共性的东西做一些沉淀,总结出一些优秀的解决方案、最佳实践以及开发一些工具来帮助用户快速完成迁云的这件事情,这是我们迁移过程中为用户考虑到的点

如果你有迁移上阿里云 ACK 的需求,请点击我!期待你的留言~


本文作者:阿里巴巴云原生小助手

阅读原文

本文为云栖社区原创内容,未经允许不得转载。

查看原文

guoshaomin 收藏了文章 · 2019-11-23

宇宙最强vscode教程(基础篇)

本文主要介绍vscode在工作中常用的快捷键及插件,目标在于提高工作效率

本文的快捷键是基于mac的,windows下的快捷键放在括号里 Cmd+Shift+P(win Ctrl+Shift+P)

[TOC]

零、快速入门

有经验的可以跳过快速入门或者大致浏览一遍

1. 命令面板

命令面板是vscode快捷键的主要交互界面,可以使用f1或者Cmd+Shift+P(win Ctrl+Shift+P)打开。

在命令面板中你可以输入命令进行搜索(中英文都可以),然后执行。

命名面板中可以执行各种命令,包括编辑器自带的功能和插件提供的功能。

所以一定要记住它的快捷键Cmd+Shift+P

image-20190120143658078

2. 界面介绍

刚上手使用vscode时,建议要先把它当做一个文件编辑器(可以打字然后保存),等到有了一定经验再去熟悉那些快捷键

先来熟悉一下界面及快捷命令(不用记)

3. 在命令行中使用vscode

如果你是 Windows用户,安装并重启系统后,你就可以在命令行中使用 code 或者 code-insiders了,如果你希望立刻而不是等待重启后使用,可以将 VS Code 的安装目录添加到系统环境变量 PATH

如果你是mac用户,安装后打开命名面板Cmd+Shift+P,搜索shell命令,点击在PAth中安装code命令,然后重启终端就ok了

image-20190120144757840

最基础的使用就是使用code命令打开文件或文件夹

code 文件夹地址,vscode 就会在新窗口中打开该文件夹

如果你希望在已经打开的窗口打开文件,可以使用-r参数

vscode命令还有其他功能,比如文件比较,打开文件跳转到指定的行和列,如有需要自行百度:bowing_woman:

注意:

在继续看文章之前记住记住打开命令面板的快捷键Cmd+shift+P(win下是Ctrl+shift+p)

一、代码编辑

windows下的快捷键放在括号里

光标的移动

基础

  1. 移动到行首 Cmd+左方向键 (win Home)
  2. 移动到行尾 Cmd+右方向键 (win End)
  3. 移动到文档的开头和末尾 Cmd+上下方向键 (win Ctrl+Home/End)
  4. 在花括号{}左边右边之间跳转 Cmd+Shift+ (win Ctrl+Shift+)

进阶

  1. 回到上一个光标的位置,Cmd+U(win Ctrl+U) 非常有用,有时候vue文件,你改了html,需要去下面改js,改完js又需要回去,这时候Cmd+U直接回
  2. 在不同的文件之间回到上一个光标的位置 Control+- (win 没测试,不知道),你改了a文件,改了b文件之后想回到a文件继续编辑,mac使用controls+-

文本选择

  1. 你只需要多按一个shift键就可以在光标移动的时候选中文本
  2. 选中单词 Cmd+D 下面要讲的多光标也会讲到Cmd+D
  3. 对于代码块的选择没有快捷键,可以使用cmd+shift+p打开命令面板,输入选择括号所有内容,待会说下如何添加快捷键

1

删除

  1. 你可以选中了代码之后再删除,再按Backpack(是backpack吗)或者delete删除,但是那样做太low了
  2. 所以,最Geek的删除方式是Cmd+Shift+K (win Ctrl+Shift+K),想删多少删多少,当前你可以使用ctrl+x剪切,效果一样的

2

代码移动

  • Option+上下方向键(win Alt+上下)

3

  • 代码移动的同时按住shift就可以实现代码复制 Option+Shift+上下3

添加注释

注释有两种形式,单行注释和块注释(在js中,单行注释//,块注释/**/)

  • 单行注释 Cmd+/ (win Ctrl +/)
  • 块注释 Option+Shift+A

注意:不同语言使用的注释不同

二、代码格式

代码格式化

  • 对整个文档进行格式化:Option+Shift+F (win Alt+Shift+F),vscode会根据你使用的语言,使用不同的插件进行格式化,记得要下载相应格式化的插件
  • 对选中代码进行格式化: Cmd+K Cmk+F win(Ctrl+K Ctrl+F)

代码缩进

  • 真个文档进行缩进调节,使用Cmd+Shift+P打开命令面板,输入缩进,然后选择相应的命令
  • 选中代码缩进调节:Cmd+] Cmd+[ 分别是减小和增加缩进(win 下不知道,自行百度)

三、一些小技巧

  • 调整字符的大小写,选中,然后在命令面板输入转化为大写或者转化为小写

  • 合并代码行,多行代码合并为一行,Cmd+J(win下未绑定)

  • 行排序,将代码行按照字母顺序进行排序,无快捷键,调出命令面板,输入按升序排序或者按降序排序

四、多光标特性

使用鼠标:

按住Option(win Alt),然后用鼠标点,鼠标点在哪里哪里就会出现一个光标

注意:有的mac电脑上是按住Cmd,然后用鼠标点才可以

快捷命令

  1. Cmd+D (win Ctrl+D) 第一次按下时,它会选中光标附近的单词;第二次按下时,它会找到这个单词第二次出现的位置,创建一个新的光标,并且选中它。(注:cmd-k cmd-d 跳过当前的选择)

  2. Option+Shift+i (win Alt+Shift+i) 首先你要选中多行代码,然后按Option+Shift+i,这样做的结果是:每一行后面都会多出来一个光标

撤销多光标

  • 使用Esc 撤销多光标
  • 鼠标点一下撤销

五、快速跳转(文件、行、符号)

快速打开文件

Cmd+P (win Ctrl+P)输入你要打开的文件名,回车打开

这里有个小技巧,选中你要打开的文件后,按Cmd+Enter,就会在一个新的编辑器窗口打开(窗口管理,见下文)

在tab不同的文件间切换,cmd+shift+[]

行跳转

加入浏览器报了个错,错误在53行,如何快速跳转到53行

Ctrl+g 输入行号

如果你想跳转到某个文件的某一行,你只需要先按下 “Cmd + P”,输入文件名,然后在这之后加上 “:”和指定行号即可。

符号跳转

符号可以是文件名、函数名,可以是css的类名

Cmd+Shift+O(win Ctrl+Shift+o) 输入你要跳转的符号,回车进行跳转

win下输入Ctrl+T,可以在不同文件的符号间进行搜索跳转

定义(definition)和实现(implementation)处

f12跳到函数的定义处

Cmd+f12(win Ctrl+f12)跳转到函数的实现处

引用跳转

很多时候,除了要知道一个函数或者类的定义和实现以外,你可能还希望知道它们被谁引用了,以及在哪里被引用了。这时你只需要将光标移动到函数或者类上面,然后按下 Shift + F12,VS Code 就会打开一个引用列表和一个内嵌的编辑器。在这个引用列表里,你选中某个引用,VS Code 就会把这个引用附近的代码展示在这个内嵌的编辑器里。

六、代码重构

当我们想修改一个函数或者变量的名字时候,我们只需把光标放到函数或者变量名上,然后按下 F2,这样这个函数或者变量出现的地方就都会被修改。

查看原文

guoshaomin 赞了文章 · 2019-11-23

宇宙最强vscode教程(基础篇)

本文主要介绍vscode在工作中常用的快捷键及插件,目标在于提高工作效率

本文的快捷键是基于mac的,windows下的快捷键放在括号里 Cmd+Shift+P(win Ctrl+Shift+P)

[TOC]

零、快速入门

有经验的可以跳过快速入门或者大致浏览一遍

1. 命令面板

命令面板是vscode快捷键的主要交互界面,可以使用f1或者Cmd+Shift+P(win Ctrl+Shift+P)打开。

在命令面板中你可以输入命令进行搜索(中英文都可以),然后执行。

命名面板中可以执行各种命令,包括编辑器自带的功能和插件提供的功能。

所以一定要记住它的快捷键Cmd+Shift+P

image-20190120143658078

2. 界面介绍

刚上手使用vscode时,建议要先把它当做一个文件编辑器(可以打字然后保存),等到有了一定经验再去熟悉那些快捷键

先来熟悉一下界面及快捷命令(不用记)

3. 在命令行中使用vscode

如果你是 Windows用户,安装并重启系统后,你就可以在命令行中使用 code 或者 code-insiders了,如果你希望立刻而不是等待重启后使用,可以将 VS Code 的安装目录添加到系统环境变量 PATH

如果你是mac用户,安装后打开命名面板Cmd+Shift+P,搜索shell命令,点击在PAth中安装code命令,然后重启终端就ok了

image-20190120144757840

最基础的使用就是使用code命令打开文件或文件夹

code 文件夹地址,vscode 就会在新窗口中打开该文件夹

如果你希望在已经打开的窗口打开文件,可以使用-r参数

vscode命令还有其他功能,比如文件比较,打开文件跳转到指定的行和列,如有需要自行百度:bowing_woman:

注意:

在继续看文章之前记住记住打开命令面板的快捷键Cmd+shift+P(win下是Ctrl+shift+p)

一、代码编辑

windows下的快捷键放在括号里

光标的移动

基础

  1. 移动到行首 Cmd+左方向键 (win Home)
  2. 移动到行尾 Cmd+右方向键 (win End)
  3. 移动到文档的开头和末尾 Cmd+上下方向键 (win Ctrl+Home/End)
  4. 在花括号{}左边右边之间跳转 Cmd+Shift+ (win Ctrl+Shift+)

进阶

  1. 回到上一个光标的位置,Cmd+U(win Ctrl+U) 非常有用,有时候vue文件,你改了html,需要去下面改js,改完js又需要回去,这时候Cmd+U直接回
  2. 在不同的文件之间回到上一个光标的位置 Control+- (win 没测试,不知道),你改了a文件,改了b文件之后想回到a文件继续编辑,mac使用controls+-

文本选择

  1. 你只需要多按一个shift键就可以在光标移动的时候选中文本
  2. 选中单词 Cmd+D 下面要讲的多光标也会讲到Cmd+D
  3. 对于代码块的选择没有快捷键,可以使用cmd+shift+p打开命令面板,输入选择括号所有内容,待会说下如何添加快捷键

1

删除

  1. 你可以选中了代码之后再删除,再按Backpack(是backpack吗)或者delete删除,但是那样做太low了
  2. 所以,最Geek的删除方式是Cmd+Shift+K (win Ctrl+Shift+K),想删多少删多少,当前你可以使用ctrl+x剪切,效果一样的

2

代码移动

  • Option+上下方向键(win Alt+上下)

3

  • 代码移动的同时按住shift就可以实现代码复制 Option+Shift+上下3

添加注释

注释有两种形式,单行注释和块注释(在js中,单行注释//,块注释/**/)

  • 单行注释 Cmd+/ (win Ctrl +/)
  • 块注释 Option+Shift+A

注意:不同语言使用的注释不同

二、代码格式

代码格式化

  • 对整个文档进行格式化:Option+Shift+F (win Alt+Shift+F),vscode会根据你使用的语言,使用不同的插件进行格式化,记得要下载相应格式化的插件
  • 对选中代码进行格式化: Cmd+K Cmk+F win(Ctrl+K Ctrl+F)

代码缩进

  • 真个文档进行缩进调节,使用Cmd+Shift+P打开命令面板,输入缩进,然后选择相应的命令
  • 选中代码缩进调节:Cmd+] Cmd+[ 分别是减小和增加缩进(win 下不知道,自行百度)

三、一些小技巧

  • 调整字符的大小写,选中,然后在命令面板输入转化为大写或者转化为小写

  • 合并代码行,多行代码合并为一行,Cmd+J(win下未绑定)

  • 行排序,将代码行按照字母顺序进行排序,无快捷键,调出命令面板,输入按升序排序或者按降序排序

四、多光标特性

使用鼠标:

按住Option(win Alt),然后用鼠标点,鼠标点在哪里哪里就会出现一个光标

注意:有的mac电脑上是按住Cmd,然后用鼠标点才可以

快捷命令

  1. Cmd+D (win Ctrl+D) 第一次按下时,它会选中光标附近的单词;第二次按下时,它会找到这个单词第二次出现的位置,创建一个新的光标,并且选中它。(注:cmd-k cmd-d 跳过当前的选择)

  2. Option+Shift+i (win Alt+Shift+i) 首先你要选中多行代码,然后按Option+Shift+i,这样做的结果是:每一行后面都会多出来一个光标

撤销多光标

  • 使用Esc 撤销多光标
  • 鼠标点一下撤销

五、快速跳转(文件、行、符号)

快速打开文件

Cmd+P (win Ctrl+P)输入你要打开的文件名,回车打开

这里有个小技巧,选中你要打开的文件后,按Cmd+Enter,就会在一个新的编辑器窗口打开(窗口管理,见下文)

在tab不同的文件间切换,cmd+shift+[]

行跳转

加入浏览器报了个错,错误在53行,如何快速跳转到53行

Ctrl+g 输入行号

如果你想跳转到某个文件的某一行,你只需要先按下 “Cmd + P”,输入文件名,然后在这之后加上 “:”和指定行号即可。

符号跳转

符号可以是文件名、函数名,可以是css的类名

Cmd+Shift+O(win Ctrl+Shift+o) 输入你要跳转的符号,回车进行跳转

win下输入Ctrl+T,可以在不同文件的符号间进行搜索跳转

定义(definition)和实现(implementation)处

f12跳到函数的定义处

Cmd+f12(win Ctrl+f12)跳转到函数的实现处

引用跳转

很多时候,除了要知道一个函数或者类的定义和实现以外,你可能还希望知道它们被谁引用了,以及在哪里被引用了。这时你只需要将光标移动到函数或者类上面,然后按下 Shift + F12,VS Code 就会打开一个引用列表和一个内嵌的编辑器。在这个引用列表里,你选中某个引用,VS Code 就会把这个引用附近的代码展示在这个内嵌的编辑器里。

六、代码重构

当我们想修改一个函数或者变量的名字时候,我们只需把光标放到函数或者变量名上,然后按下 F2,这样这个函数或者变量出现的地方就都会被修改。

查看原文

赞 456 收藏 339 评论 19

认证与成就

  • 获得 1 次点赞
  • 获得 12 枚徽章 获得 0 枚金徽章, 获得 1 枚银徽章, 获得 11 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2016-07-26
个人主页被 647 人浏览