当前位置: 首页 > 编程日记 > 正文

[Big Data - Kafka] kafka学习笔记:知识点整理

一、为什么需要消息系统

复制代码
1.解耦:
  允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。 2.冗余:消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。 3.扩展性:因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。 4.灵活性 & 峰值处理能力:在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。 5.可恢复性:系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。 6.顺序保证:在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。(Kafka 保证一个 Partition 内的消息的有序性) 7.缓冲:有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。 8.异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
复制代码

二、kafka 架构

2.1 拓扑结构

如下图:

图.1

2.2 相关概念

如图.1中,kafka 相关名词解释如下:

复制代码
1.producer:消息生产者,发布消息到 kafka 集群的终端或服务。
2.broker:kafka 集群中包含的服务器。
3.topic:每条发布到 kafka 集群的消息属于的类别,即 kafka 是面向 topic 的。
4.partition:partition 是物理上的概念,每个 topic 包含一个或多个 partition。kafka 分配的单位是 partition。
5.consumer:从 kafka 集群中消费消息的终端或服务。
6.Consumer group:high-level consumer API 中,每个 consumer 都属于一个 consumer group,每条消息只能被 consumer group 中的一个 Consumer 消费,但可以被多个 consumer group 消费。
7.replica:partition 的副本,保障 partition 的高可用。
8.leader:replica 中的一个角色, producer 和 consumer 只跟 leader 交互。
9.follower:replica 中的一个角色,从 leader 中复制数据。
10.controller:kafka 集群中的其中一个服务器,用来进行 leader election 以及 各种 failover。
12.zookeeper:kafka 通过 zookeeper 来存储集群的 meta 信息。
复制代码

2.3 zookeeper 节点

kafka 在 zookeeper 中的存储结构如下图所示:

图.2

三、producer 发布消息

3.1 写入方式

producer 采用 push 模式将消息发布到 broker,每条消息都被 append 到 patition 中,属于顺序写磁盘(顺序写磁盘效率比随机写内存要高,保障 kafka 吞吐率)。

3.2 消息路由

producer 发送消息到 broker 时,会根据分区算法选择将其存储到哪一个 partition。其路由机制为:

1. 指定了 patition,则直接使用;
2. 未指定 patition 但指定 key,通过对 key 的 value 进行hash 选出一个 patition
3. patition 和 key 都未指定,使用轮询选出一个 patition。

附上 java 客户端分区源码,一目了然:

复制代码
//创建消息实例
public ProducerRecord(String topic, Integer partition, Long timestamp, K key, V value) {if (topic == null)throw new IllegalArgumentException("Topic cannot be null");if (timestamp != null && timestamp < 0)throw new IllegalArgumentException("Invalid timestamp " + timestamp);this.topic = topic;this.partition = partition;this.key = key;this.value = value;this.timestamp = timestamp;
}//计算 patition,如果指定了 patition 则直接使用,否则使用 key 计算
private int partition(ProducerRecord<K, V> record, byte[] serializedKey , byte[] serializedValue, Cluster cluster) {Integer partition = record.partition();if (partition != null) {List<PartitionInfo> partitions = cluster.partitionsForTopic(record.topic());int lastPartition = partitions.size() - 1;if (partition < 0 || partition > lastPartition) {throw new IllegalArgumentException(String.format("Invalid partition given with record: %d is not in the range [0...%d].", partition, lastPartition));}return partition;}return this.partitioner.partition(record.topic(), record.key(), serializedKey, record.value(), serializedValue, cluster);
}// 使用 key 选取 patition
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);int numPartitions = partitions.size();if (keyBytes == null) {int nextValue = counter.getAndIncrement();List<PartitionInfo> availablePartitions = cluster.availablePartitionsForTopic(topic);if (availablePartitions.size() > 0) {int part = DefaultPartitioner.toPositive(nextValue) % availablePartitions.size();return availablePartitions.get(part).partition();} else {return DefaultPartitioner.toPositive(nextValue) % numPartitions;}} else {//对 keyBytes 进行 hash 选出一个 patitionreturn DefaultPartitioner.toPositive(Utils.murmur2(keyBytes)) % numPartitions;}
}
复制代码

3.3 写入流程

producer 写入消息序列图如下所示:

图.3

流程说明:

复制代码
1. producer 先从 zookeeper 的 "/brokers/.../state" 节点找到该 partition 的 leader
2. producer 将消息发送给该 leader
3. leader 将消息写入本地 log
4. followers 从 leader pull 消息,写入本地 log 后 leader 发送 ACK
5. leader 收到所有 ISR 中的 replica 的 ACK 后,增加 HW(high watermark,最后 commit 的 offset) 并向 producer 发送 ACK
复制代码

3.4 producer delivery guarantee

一般情况下存在三种情况:

1. At most once 消息可能会丢,但绝不会重复传输
2. At least one 消息绝不会丢,但可能会重复传输
3. Exactly once 每条消息肯定会被传输一次且仅传输一次

当 producer 向 broker 发送消息时,一旦这条消息被 commit,由于 replication 的存在,它就不会丢。但是如果 producer 发送数据给 broker 后,遇到网络问题而造成通信中断,那 Producer 就无法判断该条消息是否已经 commit。虽然 Kafka 无法确定网络故障期间发生了什么,但是 producer 可以生成一种类似于主键的东西,发生故障时幂等性的重试多次,这样就做到了 Exactly once,但目前还并未实现。所以目前默认情况下一条消息从 producer 到 broker 是确保了 At least once,可通过设置 producer 异步发送实现At most once。

四、broker 保存消息

4.1 存储方式

物理上把 topic 分成一个或多个 patition(对应 server.properties 中的 num.partitions=3 配置),每个 patition 物理上对应一个文件夹(该文件夹存储该 patition 的所有消息和索引文件),如下:

图.4

4.2 存储策略

无论消息是否被消费,kafka 都会保留所有消息。有两种策略可以删除旧数据:

1. 基于时间:log.retention.hours=168
2. 基于大小:log.retention.bytes=1073741824

需要注意的是,因为Kafka读取特定消息的时间复杂度为O(1),即与文件大小无关,所以这里删除过期文件与提高 Kafka 性能无关。

4.3 topic 创建与删除

4.3.1 创建 topic

创建 topic 的序列图如下所示:

图.5

流程说明:

复制代码
1. controller 在 ZooKeeper 的 /brokers/topics 节点上注册 watcher,当 topic 被创建,则 controller 会通过 watch 得到该 topic 的 partition/replica 分配。
2. controller从 /brokers/ids 读取当前所有可用的 broker 列表,对于 set_p 中的每一个 partition:2.1 从分配给该 partition 的所有 replica(称为AR)中任选一个可用的 broker 作为新的 leader,并将AR设置为新的 ISR2.2 将新的 leader 和 ISR 写入 /brokers/topics/[topic]/partitions/[partition]/state
3. controller 通过 RPC 向相关的 broker 发送 LeaderAndISRRequest。
复制代码

4.3.2 删除 topic

删除 topic 的序列图如下所示:

图.6

流程说明:

1. controller 在 zooKeeper 的 /brokers/topics 节点上注册 watcher,当 topic 被删除,则 controller 会通过 watch 得到该 topic 的 partition/replica 分配。
2. 若 delete.topic.enable=false,结束;否则 controller 注册在 /admin/delete_topics 上的 watch 被 fire,controller 通过回调向对应的 broker 发送 StopReplicaRequest。

五、kafka HA

5.1 replication

如图.1所示,同一个 partition 可能会有多个 replica(对应 server.properties 配置中的 default.replication.factor=N)。没有 replica 的情况下,一旦 broker 宕机,其上所有 patition 的数据都不可被消费,同时 producer 也不能再将数据存于其上的 patition。引入replication 之后,同一个 partition 可能会有多个 replica,而这时需要在这些 replica 之间选出一个 leader,producer 和 consumer 只与这个 leader 交互,其它 replica 作为 follower 从 leader 中复制数据。

Kafka 分配 Replica 的算法如下:

1. 将所有 broker(假设共 n 个 broker)和待分配的 partition 排序
2. 将第 i 个 partition 分配到第(i mod n)个 broker 上
3. 将第 i 个 partition 的第 j 个 replica 分配到第((i + j) mode n)个 broker上

5.2 leader failover

当 partition 对应的 leader 宕机时,需要从 follower 中选举出新 leader。在选举新leader时,一个基本的原则是,新的 leader 必须拥有旧 leader commit 过的所有消息。

kafka 在 zookeeper 中(/brokers/.../state)动态维护了一个 ISR(in-sync replicas),由3.3节的写入流程可知 ISR 里面的所有 replica 都跟上了 leader,只有 ISR 里面的成员才能选为 leader。对于 f+1 个 replica,一个 partition 可以在容忍 f 个 replica 失效的情况下保证消息不丢失。

当所有 replica 都不工作时,有两种可行的方案:

1. 等待 ISR 中的任一个 replica 活过来,并选它作为 leader。可保障数据不丢失,但时间可能相对较长。
2. 选择第一个活过来的 replica(不一定是 ISR 成员)作为 leader。无法保障数据不丢失,但相对不可用时间较短。

kafka 0.8.* 使用第二种方式。

kafka 通过 Controller 来选举 leader,流程请参考5.3节。

5.3 broker failover

kafka broker failover 序列图如下所示:

图.7

流程说明:

复制代码
1. controller 在 zookeeper 的 /brokers/ids/[brokerId] 节点注册 Watcher,当 broker 宕机时 zookeeper 会 fire watch
2. controller 从 /brokers/ids 节点读取可用broker
3. controller决定set_p,该集合包含宕机 broker 上的所有 partition
4. 对 set_p 中的每一个 partition4.1 从/brokers/topics/[topic]/partitions/[partition]/state 节点读取 ISR4.2 决定新 leader(如4.3节所描述)4.3 将新 leader、ISR、controller_epoch 和 leader_epoch 等信息写入 state 节点
5. 通过 RPC 向相关 broker 发送 leaderAndISRRequest 命令
复制代码

5.4 controller failover

当 controller 宕机时会触发 controller failover。每个 broker 都会在 zookeeper 的 "/controller" 节点注册 watcher,当 controller 宕机时 zookeeper 中的临时节点消失,所有存活的 broker 收到 fire 的通知,每个 broker 都尝试创建新的 controller path,只有一个竞选成功并当选为 controller。

当新的 controller 当选时,会触发 KafkaController.onControllerFailover 方法,在该方法中完成如下操作:

复制代码
1. 读取并增加 Controller Epoch。
2. 在 reassignedPartitions Patch(/admin/reassign_partitions) 上注册 watcher。
3. 在 preferredReplicaElection Path(/admin/preferred_replica_election) 上注册 watcher。
4. 通过 partitionStateMachine 在 broker Topics Patch(/brokers/topics) 上注册 watcher。
5. 若 delete.topic.enable=true(默认值是 false),则 partitionStateMachine 在 Delete Topic Patch(/admin/delete_topics) 上注册 watcher。
6. 通过 replicaStateMachine在 Broker Ids Patch(/brokers/ids)上注册Watch。
7. 初始化 ControllerContext 对象,设置当前所有 topic,“活”着的 broker 列表,所有 partition 的 leader 及 ISR等。
8. 启动 replicaStateMachine 和 partitionStateMachine。
9. 将 brokerState 状态设置为 RunningAsController。
10. 将每个 partition 的 Leadership 信息发送给所有“活”着的 broker。
11. 若 auto.leader.rebalance.enable=true(默认值是true),则启动 partition-rebalance 线程。
12. 若 delete.topic.enable=true 且Delete Topic Patch(/admin/delete_topics)中有值,则删除相应的Topic。
复制代码

6. consumer 消费消息

6.1 consumer API

kafka 提供了两套 consumer API:

1. The high-level Consumer API
2. The SimpleConsumer API

其中 high-level consumer API 提供了一个从 kafka 消费数据的高层抽象,而 SimpleConsumer API 则需要开发人员更多地关注细节。

6.1.1 The high-level consumer API

high-level consumer API 提供了 consumer group 的语义,一个消息只能被 group 内的一个 consumer 所消费,且 consumer 消费消息时不关注 offset,最后一个 offset 由 zookeeper 保存。

使用 high-level consumer API 可以是多线程的应用,应当注意:

1. 如果消费线程大于 patition 数量,则有些线程将收不到消息
2. 如果 patition 数量大于线程数,则有些线程多收到多个 patition 的消息
3. 如果一个线程消费多个 patition,则无法保证你收到的消息的顺序,而一个 patition 内的消息是有序的

6.1.2 The SimpleConsumer API

如果你想要对 patition 有更多的控制权,那就应该使用 SimpleConsumer API,比如:

1. 多次读取一个消息
2. 只消费一个 patition 中的部分消息
3. 使用事务来保证一个消息仅被消费一次

但是使用此 API 时,partition、offset、broker、leader 等对你不再透明,需要自己去管理。你需要做大量的额外工作:

1. 必须在应用程序中跟踪 offset,从而确定下一条应该消费哪条消息
2. 应用程序需要通过程序获知每个 Partition 的 leader 是谁
3. 需要处理 leader 的变更

使用 SimpleConsumer API 的一般流程如下:

复制代码
1. 查找到一个“活着”的 broker,并且找出每个 partition 的 leader
2. 找出每个 partition 的 follower
3. 定义好请求,该请求应该能描述应用程序需要哪些数据
4. fetch 数据
5. 识别 leader 的变化,并对之作出必要的响应
复制代码

以下针对 high-level Consumer API 进行说明。

6.2 consumer group

如 2.2 节所说, kafka 的分配单位是 patition。每个 consumer 都属于一个 group,一个 partition 只能被同一个 group 内的一个 consumer 所消费(也就保障了一个消息只能被 group 内的一个 consuemr 所消费),但是多个 group 可以同时消费这个 partition。

kafka 的设计目标之一就是同时实现离线处理和实时处理,根据这一特性,可以使用 spark/Storm 这些实时处理系统对消息在线处理,同时使用 Hadoop 批处理系统进行离线处理,还可以将数据备份到另一个数据中心,只需要保证这三者属于不同的 consumer group。如下图所示:

图.8

6.3 消费方式

consumer 采用 pull 模式从 broker 中读取数据。

push 模式很难适应消费速率不同的消费者,因为消息发送速率是由 broker 决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成 consumer 来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而 pull 模式则可以根据 consumer 的消费能力以适当的速率消费消息。

对于 Kafka 而言,pull 模式更合适,它可简化 broker 的设计,consumer 可自主控制消费消息的速率,同时 consumer 可以自己控制消费方式——即可批量消费也可逐条消费,同时还能选择不同的提交方式从而实现不同的传输语义。

6.4 consumer delivery guarantee

如果将 consumer 设置为 autocommit,consumer 一旦读到数据立即自动 commit。如果只讨论这一读取消息的过程,那 Kafka 确保了 Exactly once。

但实际使用中应用程序并非在 consumer 读取完数据就结束了,而是要进行进一步处理,而数据处理与 commit 的顺序在很大程度上决定了consumer delivery guarantee:

复制代码
1.读完消息先 commit 再处理消息。这种模式下,如果 consumer 在 commit 后还没来得及处理消息就 crash 了,下次重新开始工作后就无法读到刚刚已提交而未处理的消息,这就对应于 At most once
2.读完消息先处理再 commit。这种模式下,如果在处理完消息之后 commit 之前 consumer crash 了,下次重新开始工作时还会处理刚刚未 commit 的消息,实际上该消息已经被处理过了。这就对应于 At least once。
3.如果一定要做到 Exactly once,就需要协调 offset 和实际操作的输出。精典的做法是引入两阶段提交。如果能让 offset 和操作输入存在同一个地方,会更简洁和通用。这种方式可能更好,因为许多输出系统可能不支持两阶段提交。比如,consumer 拿到数据后可能把数据放到 HDFS,如果把最新的 offset 和数据本身一起写到 HDFS,那就可以保证数据的输出和 offset 的更新要么都完成,要么都不完成,间接实现 Exactly once。(目前就 high-level API而言,offset 是存于Zookeeper 中的,无法存于HDFS,而SimpleConsuemr API的 offset 是由自己去维护的,可以将之存于 HDFS 中)
复制代码

总之,Kafka 默认保证 At least once,并且允许通过设置 producer 异步提交来实现 At most once(见文章《kafka consumer防止数据丢失》)。而 Exactly once 要求与外部存储系统协作,幸运的是 kafka 提供的 offset 可以非常直接非常容易得使用这种方式。

更多关于 kafka 传输语义的信息请参考《Message Delivery Semantics》。

6.5 consumer rebalance

当有 consumer 加入或退出、以及 partition 的改变(如 broker 加入或退出)时会触发 rebalance。consumer rebalance算法如下:

复制代码
1. 将目标 topic 下的所有 partirtion 排序,存于PT
2. 对某 consumer group 下所有 consumer 排序,存于 CG,第 i 个consumer 记为 Ci
3. N=size(PT)/size(CG),向上取整
4. 解除 Ci 对原来分配的 partition 的消费权(i从0开始)
5. 将第i*N到(i+1)*N-1个 partition 分配给 Ci
复制代码

在 0.8.*版本,每个 consumer 都只负责调整自己所消费的 partition,为了保证整个consumer group 的一致性,当一个 consumer 触发了 rebalance 时,该 consumer group 内的其它所有其它 consumer 也应该同时触发 rebalance。这会导致以下几个问题:

复制代码
1.Herd effect任何 broker 或者 consumer 的增减都会触发所有的 consumer 的 rebalance
2.Split Brain每个 consumer 分别单独通过 zookeeper 判断哪些 broker 和 consumer 宕机了,那么不同 consumer 在同一时刻从 zookeeper 看到的 view 就可能不一样,这是由 zookeeper 的特性决定的,这就会造成不正确的 reblance 尝试。
3. 调整结果不可控所有的 consumer 都并不知道其它 consumer 的 rebalance 是否成功,这可能会导致 kafka 工作在一个不正确的状态。
复制代码

基于以上问题,kafka 设计者考虑在0.9.*版本开始使用中心 coordinator 来控制 consumer rebalance,然后又从简便性和验证要求两方面考虑,计划在 consumer 客户端实现分配方案。(见文章《Kafka Detailed Consumer Coordinator Design》和《Kafka Client-side Assignment Proposal》),此处不再赘述。

七、注意事项

7.1 producer 无法发送消息的问题

最开始在本机搭建了kafka伪集群,本地 producer 客户端成功发布消息至 broker。随后在服务器上搭建了 kafka 集群,在本机连接该集群,producer 却无法发布消息到 broker(奇怪也没有抛错)。最开始怀疑是 iptables 没开放,于是开放端口,结果还不行(又开始是代码问题、版本问题等等,倒腾了很久)。最后没办法,一项一项查看 server.properties 配置,发现以下两个配置:

复制代码
# The address the socket server listens on. It will get the value returned from 
# java.net.InetAddress.getCanonicalHostName() if not configured.
#   FORMAT:
#     listeners = security_protocol://host_name:port
#   EXAMPLE:
#     listeners = PLAINTEXT://your.host.name:9092
listeners=PLAINTEXT://:9092

# Hostname and port the broker will advertise to producers and consumers. If not set, 
 # it uses the value for "listeners" if configured. Otherwise, it will use the value
 # returned from java.net.InetAddress.getCanonicalHostName().
 #advertised.listeners=PLAINTEXT://your.host.name:9092

复制代码

以上说的就是 advertised.listeners 是 broker 给 producer 和 consumer 连接使用的,如果没有设置,就使用 listeners,而如果 host_name 没有设置的话,就使用 java.net.InetAddress.getCanonicalHostName() 方法返回的主机名。

修改方法:

1. listeners=PLAINTEXT://121.10.26.XXX:9092
2. advertised.listeners=PLAINTEXT://121.10.26.XXX:9092

修改后重启服务,正常工作。关于更多 kafka 配置说明,见文章《Kafka学习整理三(borker(0.9.0及0.10.0)配置)》。

八、参考文章

1. 《Kafka剖析(一):Kafka背景及架构介绍》

2. 《Kafka设计解析(二):Kafka High Availability (上)》

3. 《Kafka设计解析(二):Kafka High Availability (下)》

4. 《Kafka设计解析(四):Kafka Consumer解析》

5. 《Kafka设计解析(五):Kafka Benchmark》

6. 《Kafka学习整理三(borker(0.9.0及0.10.0)配置)》

7. 《Using the High Level Consumer》

8. 《Using SimpleConsumer》

9. 《Consumer Client Re-Design》

10. 《Message Delivery Semantics》

11. 《Kafka Detailed Consumer Coordinator Design》

12. 《Kafka Client-side Assignment Proposal》

13. 《Kafka和DistributedLog技术对比》

14. 《kafka安装和启动》

15. 《kafka consumer防止数据丢失》

作者:cyfonly
出处:http://www.cnblogs.com/cyfonly/
本文版权归作者和博客园共有,欢迎转载,未经同意须保留此段声明,且在文章页面明显位置给出原文连接。欢迎指正与交流。

相关文章:

自然语言处理十问!独家福利

最近&#xff0c;NLP 圈简直不要太热闹&#xff01;预训练模型频频刷新榜单&#xff0c;让一众研究者、开发者“痛并快乐着”。自 2018 年 10 月&#xff0c;Google 提出 BERT 以来&#xff0c;NLP 领域预训练模型的发展仿佛坐上了火箭&#xff0c;完全控制不住。BERT 出世前&a…

BERT的成功是否依赖于虚假相关的统计线索?

作者 | 李理来源 | 个人博客导读&#xff1a;本文介绍论文Probing Neural Network Comprehension of Natural Language Arguments&#xff0c;讨论BERT在ACRT任务下的成绩是否依赖虚假的统计线索&#xff0c;同时分享一些个人对目前机器学习尤其是自然语言理解的看法。目录论文…

【电子基础】模拟电路问答

模拟电路基础知识问答整理 mystery 1、温度对半导体材料的导电性能有什么影响? 答&#xff1a;温度对半导体的导电性能有很大影响。当温度升高时&#xff0c;半导体材料内的自由电子和空穴数量迅速增加&#xff0c;半导体的导电性能将迅速提高。 2、什么是本征半导体和杂质半导…

XML解析简介及Xerces-C++简单使用举例

XML是由World WideWeb联盟(W3C)定义的元语言。它已经成为一种通用的数据交换格式&#xff0c;它的平台无关性&#xff0c;语言无关性&#xff0c;系统无关性&#xff0c;给数据集成与交互带来了极大的方便。XML在不同的语言里解析方式都是一样的&#xff0c;只不过实现的语法不…

[干货]Kaggle热门 | 用一个框架解决所有机器学习难题

新智元推荐 来源&#xff1a;LinkedIn 作者&#xff1a;Abhishek Thakur 译者&#xff1a;弗格森 【新智元导读】本文是数据科学家Abhishek Thakur发表的Kaggle热门文章。作者总结了自己参加100多场机器学习竞赛的经验&#xff0c;主要从模型框架方面阐述了机器学习过程中可能会…

gtest简介及简单使用

gtest是一个跨平台(Liunx、Mac OS X、Windows、Cygwin、Windows CE and Symbian)的C测试框架&#xff0c;有google公司发布。gtest测试框架是在不同平台上为编写C测试而生成的。从http://code.google.com/p/googletest/downloads/detail?namegtest-1.7.0.zip&can2&q下…

新浪微博推广网站的一些实践体会

本以为微博推广很难&#xff0c;每天都要刷粉刷内容的&#xff0c;也本以为做微博推广也很简单&#xff0c;一不卖产品、二不卖服务的&#xff0c;目的单纯灵活性强些&#xff0c;做了之后才发现都不是那么回事&#xff0c;微博虽然也过了“火了”&#xff0c;但新媒体还真是不…

AI和大数据如何落地智能城市?京东城市这6篇论文必读 | KDD 2019

来源 | 京东城市&#xff08;ID: icity-jd&#xff09;作为世界数据挖掘领域的最高级别的学术会议&#xff0c;ACM SIGKDD&#xff08;国际数据挖掘与知识发现大会&#xff0c;简称 KDD&#xff09;将于 2019 年 8 月 4 日—8 日在美国阿拉斯加州安克雷奇市举行。自 1995 年以来…

OSError: Could not find library geos_c or load any of its variants ['libgeos_c.so.1', 'libgeos_c.so

OSError: Could not find library geos_c or load any of its variants [libgeos_c.so.1, libgeos_c.so 解决&#xff1a; sudo vim /etc/ld.so.conf 添加&#xff1a;/opt/source/geos-3.5.0/build/lib sudo ldconfig

五分钟搭建BERT服务,实现1000+QPS​,这个Service-Streamer做到了

作者 | 刘欣简介&#xff1a;刘欣&#xff0c;Meteorix&#xff0c;毕业于华中科技大学&#xff0c;前网易游戏技术总监&#xff0c;现任香侬科技算法架构负责人。之前专注游戏引擎工具架构和自动化领域&#xff0c;2018年在GDC和GoogleIO开源Airtest自动化框架&#xff0c;广泛…

Nagios+pnp4nagios+rrdtool 安装配置为nagios添加自定义插件(三)

nagios博大精深&#xff0c;可以以shell、perl等语句为nagios写插件&#xff0c;来满足自己监控的需要。本文写mysql中tps、qps的插件&#xff0c;并把收集到的结果以图形形式展现出来&#xff0c;这样输出的结果就有一定的要求了。 编写插件tps qps check_qps 插件如下内容 #…

OpenSSL简介及在Windows、Linux、Mac系统上的编译步骤

OpenSSL介绍&#xff1a;OpenSSL是一个强大的安全套接字层密码库&#xff0c;囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议&#xff0c;并提供丰富的应用程序供测试或其它目的使用。 SSL是SecureSockets Layer(安全套接层协议)的缩写&#xff0c;可以在Interne…

Guava Cache本地缓存在 Spring Boot应用中的实践

概述 在如今高并发的互联网应用中&#xff0c;缓存的地位举足轻重&#xff0c;对提升程序性能帮助不小。而 3.x开始的 Spring也引入了对 Cache的支持&#xff0c;那对于如今发展得如火如荼的 Spring Boot来说自然也是支持缓存特性的。当然 Spring Boot默认使用的是 SimpleCache…

Windows 8.1 Preview(Windows Blue)预览版简体中文官方下载(ISO完整版镜像)

Windows 8.1是微软继Windows 8以来的又一全新力作&#xff0c;又名Windows Blue&#xff08;视窗蓝&#xff0c;专注蓝屏30年&#xff09;&#xff0c;个人觉得Win8还是比较流畅的但大众始终觉得还是有很多需要改进或者改善的&#xff0c;如今微软为了迎合大众需求对Win8进行升…

Linux下编辑器vi/vim的使用介绍

vi编辑器是所有Unix及Linux系统下标准的编辑器。对Unix及Linux系统的任何版本&#xff0c;vi编辑器是完全相同的。 基本上vi可以分为三种状态&#xff0c;分别是命令模式(commandmode)、插入模式(insert mode)和底行模式(last line mode)&#xff0c;各模式的功能为&#xff1…

Clojure程序设计

《Clojure程序设计》基本信息作者&#xff1a; (美)Stuart Halloway Aaron Bedra [作译者介绍]出版社&#xff1a;人民邮电出版社ISBN&#xff1a;9787115308474上架时间&#xff1a;2013-3-1出版日期&#xff1a;2013 年3月开本&#xff1a;16开页码&#xff1a;230版次&#…

重磅!AI Top 30+案例评选正式启动

2019 年&#xff0c;人工智能应用落地的重要性正在逐步得到验证&#xff0c;这是关乎企业生死攸关的一环。科技巨头、AI 独角兽还有起于草莽的创业公司在各领域进行着一场多方角斗。进行平台布局的科技巨头们&#xff0c;正在加快承载企业部署 AI 应用的步伐&#xff0c;曾经无…

直播回顾 | 关于Apollo 5.0控制在环仿真技术的分享

Apollo 用于模型验证和测试的基于 Web 的仿真平台 Dreamland 已经更新到能使用更强大的场景编辑器和环控制模拟。基于 Apollo 流水线和机器学习的动力学模型&#xff0c;复杂度较高&#xff0c;同时基于 AI 的全景数据建模&#xff0c;模型精细度高&#xff0c;误差比传统方式可…

eclipes 安装 pytdev,svn,插件

1&#xff0c; python pydevhttp://pydev.org/updates2, svnhttp://subclipse.tigris.org/update3, 推荐http://subclipse.tigris.org/update_1.10.x 转载于:https://blog.51cto.com/swq499809608/1240873

FFmpeg简介及在vc2010下编译步骤

FFmpeg是一个开源的多媒体库&#xff0c;最新版本是2.4.3&#xff0c;它的License是LGPL或GPL。FFmpeg可以用来记录、转换数字音频、视频&#xff0c;并能将其转换为流的开源计算机程序。它包括了音/视频编码库libavcodec。FFmpeg是在Linux下开发出来的&#xff0c;但它可以在包…

医院六级电子病历建设思路及要点

产生背景 在医院电子病历信息化发展的过程中&#xff0c;先后经历了纸质病历、电子病历、结构化电子病历以及具有全医疗过程管理能力的电子病历四个阶段。临床业务需求质量的逐步提升&#xff0c;标准规范的逐步细化&#xff0c;互联网战略的落地实施&#xff0c;无疑对目前电子…

上手必备!不可错过的TensorFlow、PyTorch和Keras样例资源

作者 | 黄海广来源 | 机器学习初学者&#xff08;ID: ai-start-com&#xff09;TensorFlow、Keras和PyTorch是目前深度学习的主要框架&#xff0c;也是入门深度学习必须掌握的三大框架&#xff0c;但是官方文档相对内容较多&#xff0c;初学者往往无从下手。本人从github里搜到…

Linux下gdb调试工具的使用

gdb是GNU开源组织发布的一个强大的Linux下的程序调试工具。 gdb主要完成四个方面的功能&#xff1a;(1)、启动你的程序&#xff0c;可以按照你的自定义的要求随心所欲的运行程序&#xff1b;(2)、可让被调试的程序在你所指定的调试的断点处停住(断点可以是条件表达式)&#xf…

UESTC 1726 整数划分(母函数)

题目链接&#xff1a;http://222.197.181.5/problem.php?pid1726 题意&#xff1a;求n的划分数。一种划分方案中不能有相同的数字。 思路&#xff1a;(1x)(1x^2)(1x^3)……(1x^1000). int f[N];void init() {f[1]1;int a[N]{0};a[0]1; a[1]1;int i,j;for(i2;i<1000;i){for(…

JS nodeType返回类型

JS nodeType返回类型 前几天朋友正好问道 这个 js的nodeType是个什么概念&#xff08;做浏览器底层的&#xff09;正好遇到这篇文章可以向大家解释下 将HTML DOM中几个容易常用的属性做下记录&#xff1a; nodeName、nodeValue 以及 nodeType 包含有关于节点的信息。 nodeName …

C# 获取指定目录下所有文件信息、移动目录、拷贝目录

/// <summary>/// 返回指定目录下的所有文件信息/// </summary>/// <param name"strDirectory"></param>/// <returns></returns>public List<FileInfo> GetAllFilesInDirectory(string strDirectory){List<FileInfo&g…

文件夹浏览(SHBrowseForFolder)

from http://www.cnblogs.com/Clingingboy/archive/2011/04/16/2018284.html 一.首先要为SHBrowseForFolder准备一个结构体BROWSEINFO typedef struct _browseinfoW {HWND hwndOwner;PCIDLIST_ABSOLUTE pidlRoot;LPWSTR pszDisplayName; // Return display…

技术新贵:RPA与NLP技术的结合与应用

什么是 RPA&#xff08;Robotic Process Automation&#xff09;&#xff1f;机器人流程自动化&#xff08;RPA&#xff09;是一种自动化工具&#xff0c;用于创建软件机器人的虚拟劳动力&#xff0c;从而优化和降低企业中端到端业务流程的成本。RPA 可以翻译成机器人流程自动化…

API Sanity Checker在Ubuntu中的使用

API Sanity Checker是一个自动生成单元测试用例的工具&#xff0c;可用于链接测试。它可用于三大桌面平台&#xff0c;下面简单介绍它在Linux下的使用步骤&#xff1a;1. 从http://ispras.linuxbase.org/index.php/API_Sanity_Autotest 下载最新的api-sanity-checker-1.98…

手动脱壳—dump与重建输入表(转)

文章中用到的demo下载地址&#xff1a; http://download.csdn.net/detail/ccnyou/4540254 附件中包含demo以及文章word原稿 用到工具: Ollydbg LordPE ImportREC 这些工具请自行下载准备 Dump原理这里也不多做描述&#xff0c;想要了解google it&#xff01;常见的dump软件有Lo…