Java性能 -- synchronized锁升级优化
synchronized / Lock JDK 1.5之前,Java通过synchronized关键字来实现锁功能 synchronized是JVM实现的内置锁,锁的获取和释放都是由JVM隐式实现的 JDK 1.5,并发包中新增了Lock接口来实现锁功能 提供了与synchronized类似的同步功能,但需要显式获取和释放锁 Lock同步锁是基于Java实现的,而synchronized是基于底层操作系统的Mutex Lock实现的 每次获取和释放锁都会带来用户态和内核态的切换,从而增加系统的性能开销 在锁竞争激烈的情况下,synchronized同步锁的性能很糟糕 在JDK 1.5,在单线程重复申请锁的情况下,synchronized锁性能要比Lock的性能差很多 JDK 1.6,Java对synchronized同步锁做了充分的优化,甚至在某些场景下,它的性能已经超越了Lock同步锁 实现原理12345678910public class SyncTest { public synchronized void method1() { ...
Kafka -- 拦截器
设计思路 基本思想:允许应用程序在不修改逻辑的情况下,动态地实现一组可插拔的事件处理逻辑链 拦截器能够在主业务操作的前后多个时间点上插入对应的拦截逻辑 以配置拦截器类的方式动态插入到应用程序中,可以快速地切换不同的拦截器,而不影响主程序逻辑 Kafka拦截器 Kafka拦截器自0.10.0.0版本被引入后并未得到太多的实际应用 Kafka拦截器分为生产者拦截器和消费者拦截器 生产者拦截器:允许在发送消息前以及消息提交成功后植入拦截逻辑 消费者拦截器:允许在消费消息前以及提交位移后植入拦截逻辑 Kafka拦截器支持链式调用,Kafka会按照添加顺序依次执行拦截器逻辑 Kafka拦截器通过参数interceptor.classes来配置(生产者和消费者一致) 指定拦截器类时需要使用全限定名 123456789Properties props = new Properties();props.put("bootstrap.servers", "localhost:9092");props.put("key.serializer", S...
Java性能 -- NIO
BIO / NIO 在Tomcat 8.5之前,默认使用BIO线程模型,在高并发的场景下,可以设置为NIO线程模型,来提供系统的网络通信性能 页面请求用于模拟多IO读写操作的请求,Tomcat在IO读写请求比较多的情况下,使用NIO线程模型有明显的优势 网络IO模型优化网络通信中,最底层的是操作系统内核中的网络IO模型,分别为阻塞式IO、非阻塞式IO、IO复用、信号驱动式IO、异步IO TCP工作流程 首先,应用程序通过系统调用socket,创建一个套接字,它是系统分配给应用程序的一个文件描述符 其次,应用程序通过系统调用bind,绑定地址和的端口号,给套接字命名一个名称 然后,系统调用listen,创建一个队列用于存放客户端进来的连接 最后,应用程序通过系统调用accept来监听客户端的连接请求 当有一个客户端连接到服务端后,服务端会通过系统调用fork,创建一个子进程 通过系统调用read监听客户端发来的消息,通过系统调用write向客户端返回消息 阻塞式IO每一个连接创建时,都需要一个用户线程来处理,并且在IO操作没有就绪或者结束时,线程会被挂起,进入阻塞等待状态...
Kafka -- 无消息丢失
持久化保证 Kafka只对已提交的消息做有限度的持久化保证 已提交的消息 当Kafka的若干个Broker成功地接收到一条消息并写入到日志文件后,会告诉生产者这条消息已经成功提交 有限度的持久化保证 Kafka不保证在任何情况下都能做到不丢失消息,例如机房着火等极端情况 消息丢失生产者丢失 目前Kafka Producer是异步发送消息的,Producer.send(record)立即返回,但不能认为消息已经发送成功 丢失场景:网络抖动,导致消息没有到达Broker;消息太大,超过Broker的承受能力,Broker拒收 解决方案:Producer永远要使用带有回调通知的发送API,即**Producer.send(record, callback)** callback能够准确地告知Producer消息是不是真的提交成功,一旦出现消息提交失败,可以进行针对性的处理 消费者丢失 Consumer端丢失数据主要体现在Consumer端要消费的消息不见了 Consumer程序有位移的概念,表示该Consumer当前消费到Topic分区的位置 丢失原因:Consumer接收一批消息后,在未...
Java性能 -- 优化RPC网络通信
服务框架的核心 大型服务框架的核心:RPC通信 微服务的核心是远程通信和服务治理 远程通信提供了服务之间通信的桥梁,服务治理提供了服务的后勤保障 服务的拆分增加了通信的成本,因此远程通信很容易成为系统瓶颈 在满足一定的服务治理需求的前提下,对远程通信的性能需求是技术选型的主要影响因素 很多微服务框架中的服务通信是基于RPC通信实现的 在没有进行组件扩展的前提下,Spring Cloud是基于Feign组件实现RPC通信(基于HTTP+JSON序列化) Dubbo是基于SPI扩展了很多RPC通信框架,包括RMI、Dubbo、Hessian等(默认为Dubbo+Hessian序列化) 性能测试基于Dubbo:2.6.4,单一TCP长连接+Protobuf(响应时间和吞吐量更优),短连接的HTTP+JSON序列化 RPC通信架构演化无论是微服务、SOA、还是RPC架构,都是分布式服务架构,都需要实现服务之间的互相通信,通常把这种通信统称为RPC通信 概念 RPC:Remote Process Call,远程服务调用,通过网络请求远程计算机程序服务的通信技术 RPC框架封装了底层网络通信和序列...
Kafka -- 压缩
压缩的目的时间换空间,用CPU时间去换磁盘空间或网络IO传输量 消息层次 消息集合(Message Set)和消息 一个消息集合中包含若干条日志项(Record Item),而日志项用于封装消息 Kafka底层的消息日志由一系列消息集合日志项组成 Kafka不会直接操作具体的消息,而是在消息集合这个层面上进行写入操作 消息格式 目前Kafka共有两大类消息格式,社区分别称之为V1版本和V2版本(在0.11.0.0引入) V2版本主要针对V1版本的一些弊端进行了优化 优化1:把消息的公共部分抽取到外层消息集合里面 在V1版本中,每条消息都需要执行CRC校验,但在某些情况下,消息的CRC值会发生变化 Broker端可能对消息的时间戳字段进行更新,重新计算后的CRC值也会相应更新 Broker端在执行消息格式转换时(兼容老版本客户端),也会带来CRC值的变化 因此没必要对每条消息都执行CRC校验,浪费空间和时间 在V2版本中,消息的CRC校验被移到了消息集合这一层 优化2:对整个消息集合进行压缩 在V1版本中,对多条消息进行压缩,然后保存到外层消息的消息体字段中 压缩的时机在Kafka...
Java性能 -- 序列化
序列化方案 Java RMI采用的是Java序列化 Spring Cloud采用的是_JSON序列化_ Dubbo虽然兼容Java序列化,但默认使用的是_Hessian序列化_ Java序列化原理 Serializable JDK提供了输入流对象ObjectInputStream和输出流对象ObjectOutputStream 它们只能对实现了Serializable接口的类的对象进行序列化和反序列化 12345// 只能对实现了Serializable接口的类的对象进行序列化// java.io.NotSerializableException: java.lang.ObjectObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_PATH));oos.writeObject(new Object());oos.close(); transient ObjectOutputStream的默认序列化方式,仅对对象的非transient的实例变量进行序列化 不会序列化对象的transient的实例变量...
Kafka -- 生产者消息分区机制
分区概念 主题是承载真实数据的逻辑容器,主题之下分为若干个分区,Kafka的消息组织方式为三级结构:主题、分区、消息 主题下的每条消息只会保存在某个分区中,而不会在多个分区中被保存多份 分区的作用是提供负载均衡的能力,实现系统的高伸缩性 不同的分区能够被放置在不同的机器节点上,而数据读写操作的粒度也是分区 每个机器节点都能独立地执行各自分区的读写请求处理,还可以通过添加新的机器节点来增加整体系统的吞吐量 分区在不同的分布式系统有不同的叫法,但分区的思想都是类似的 Kafka – Partition MongoDB、Elasticsearch – Shard HBase – Region 分区策略 分区策略:决定生产者将消息发送到哪个分区的算法,Kafka提供了默认的分区策略,也支持自定义的分区策略 自定义的分区策略,需要显式地配置生产者端的参数partitioner.class 实现接口:org.apache.kafka.clients.producer.Partitioner 消息数据:topic、key、keyBytes、value、valueBytes 集群数据:cluster ...
Java性能 -- IO模型
什么是IO IO是机器获取和交换信息的主要渠道,而流是完成IO操作的主要方式 在计算机中,流是一种信息的转换 流是有序的 把机器或者应用程序接收外界的信息称为输入流(InputStream) 从机器或者应用程序向外输出的信息称为输出流(OutputStream) 流可以被看作一种数据的载体,通过它可以实现数据的交换和传输 Java IO Java IO主要在java.io下,有四个基本类:InputStream、OutputStream、Reader、Writer,分别用于处理字节流和字符流 字符到字节必须经过转码,该过程非常耗时,如果不知道编码类型就很容易出现乱码问题 因此IO流提供了直接操作字符的接口,方便对字符进行流操作 字节流 字节流的抽象类:InputStream/OutputStream 文件的读写操作:FileInputStream/FileOutputStream 数组的读写操作:ByteArrayInputStream/ByteArrayOutputStream 普通字符串的读写操作:BufferedInputStream/B...
Kafka -- 集群参数
Broker参数存储 log.dir:表示单个路径 log.dirs:表示多个路径,推荐使用 /home/kafka1,/home/kafka2,/home/kafka3 线上生产环境中一定要为log.dirs配置多个路径,格式为CSV,逗号分隔 建议把不同的路径挂载到不同的物理磁盘上 提升读写性能,比起单块硬盘,多块物理磁盘同时读写数据有更高的吞吐量 能够实现故障转移(Failover),从Kafka 1.1引入,坏掉的磁盘上的数据会自动地转移到其他正常的磁盘上 Zookeeper Zookeeper是一个分布式协调框架,负责协调管理并保存Kafka集群的所有元数据信息 集群有哪些Broker在运行,创建了哪些Topic,每个Topic有多少分区、分区的Leader副本在哪些机器上 zookeeper.connect,CSV格式,zk1:2181,zk2:2181,zk3:2181 Zookeeper地chroot,只需写一次,zk1:2181,zk2:2181,zk3:2181/kafka1和zk1:2181,zk2:2181,zk3:2181/kafka2 连接 listene...















