当前位置: 首页 > news >正文

怎么做的英文网站什么是虚拟网站

怎么做的英文网站,什么是虚拟网站,青海省住房和城乡建设厅门户网站,企业网站建设实训指导书文章目录 Pre1. 引言2. 缓冲概念与类比3. Java I/O 中的缓冲实现3.1 FileReader vs BufferedReader#xff1a;装饰者模式设计3.2 BufferedInputStream 源码剖析3.2.1 缓冲区大小的权衡与默认值 4. 异步日志中的缓冲#xff1a;Logback 异步日志原理与配置要点4.1 Logback 异… 文章目录 Pre1. 引言2. 缓冲概念与类比3. Java I/O 中的缓冲实现3.1 FileReader vs BufferedReader装饰者模式设计3.2 BufferedInputStream 源码剖析3.2.1 缓冲区大小的权衡与默认值 4. 异步日志中的缓冲Logback 异步日志原理与配置要点4.1 Logback 异步日志原理4.2 核心配置示例4.2.1 三个关键参数 5. 缓冲区设计思路—同步 vs 异步5.1 同步缓冲5.2 异步缓冲 6. Kafka 生产者缓冲示例6.1 Kafka 生产者缓冲原理6.2 缓冲区丢数据风险6.3 缓冲区过载与业务可用性 7. 其他缓冲场景与示例8. 注意事项与异常场景9. 小结 Pre 性能优化 - 理论篇常见指标及切入点 性能优化 - 理论篇性能优化的七类技术手段 性能优化 - 理论篇CPU、内存、I/O诊断手段 性能优化 - 工具篇常用的性能测试工具 性能优化 - 工具篇基准测试 JMH 引言重温缓冲本质与设计动机缓冲概念与类比蓄水池与生产线示例Java I/O 中的缓冲实现 3.1 FileReader vs BufferedReader装饰者模式设计 3.2 BufferedInputStream 源码剖析fill() 逻辑与缓冲区扩容 3.3 缓冲区大小的权衡与默认值8KB异步日志中的缓冲Logback 异步日志原理与配置要点queueSize、maxFlushTime、discardingThreshold缓冲区设计思路—同步 vs 异步 5.1 同步缓冲单线程或方法内批量触发策略 5.2 异步缓冲生产者策略抛弃/阻塞/异常与多线程消费者的同步问题Kafka 生产者缓冲示例batch.size、linger.ms 如何影响消息丢失与可用性其他缓冲场景与示例StringBuilder/StringBuffer、操作系统网络缓冲、数据库 Buffer Pool、ID 生成器缓存注意事项与异常场景缓冲区数据丢失风险、预写日志与 WAL 简述小结缓冲区优化的收益与权衡 1. 引言 在 性能优化 - 理论篇性能优化的七类技术手段 中,已经初步了解“复用优化”领域下的两大子方向缓存Cache 与 缓冲Buffer。 接下来我们聚焦于“缓冲”这一个技术手段深入理解它在 Java 语言与中间件中的各类应用场景以及在设计时需要注意的权衡与异常处理。 为什么要用缓冲 设备之间速度差异CPU/内存读写速度≪磁盘或网络 I/O频繁、小量的随机 I/O 会导致寻道或上下文切换开销巨大缓冲通过在内存中聚合数据批量顺序写/读显著提高吞吐。 接下来将从概念、源码、配置与设计思路几个维度展开对“缓冲”有一个系统化的认识。 2. 缓冲概念与类比 缓冲Buffer最本质的作用是将“生产方”与“消费方”之间的不一致速度化解为一个容量有限的“中间池”。 蓄水池比喻 放水端消费方以恒定速率流出就如程序中读取缓冲区后进行处理进水端生产方速率不确定可能快也可能慢就如磁盘或网络向缓冲写数据缓冲区蓄水池大小当进水过快或消费端处理慢时水就会在池中积累当池满时生产方必须等待或做其他处理。 包饺子流水线 擀皮工序 vs 包馅工序如果一擀一交彼此就停止效率低加入一个盆子作为中间缓冲擀皮不断往盆里扔包馅者随时取用两者最大限度保持各自节奏。 从宏观而言Java 的堆本身也可视作一个“对象缓冲区”——应用线程在其中不断分配对象而垃圾回收线程GC则以另一种节奏“消费”这些对象。 对比于“缓存Cache”缓冲侧重于写或读过程中的批量与顺序让慢速设备前端获得“可持续的小幅流量”。 3. Java I/O 中的缓冲实现 在 Java 中缓冲最常见的应用场景就是文件与网络 I/O。底层设备如磁盘、Socket本身速度较慢而 Java I/O 通过装饰者模式将原始流包装为“带缓冲的流”让单次 read()/write() 调用变为“先读/写到内存缓冲区再批量交给底层设备”。 3.1 FileReader vs BufferedReader装饰者模式设计 FileReader直接从磁盘逐个字符读取一次 read() 需要 操作系统触发文件系统寻道读取一个字节到内核缓冲再从内核缓冲拷贝到用户空间返回给应用。 由于每调用一次 read() 都要重复上述步骤效率极低。 BufferedReader以 Reader reader new BufferedReader(new FileReader(path)) 方式包装后 在首次 read() 时会一次性将后续 buffer.length 个字节默认 8KB读入 Java 堆内存中的 byte[] buffer之后的多次调用 read()只需从内存 buffer 中读取字符直到 pos count才触发下次 fill()大多数情况下减少了对磁盘和内核空间的多次交互。 这种添加功能而不修改原类代码的模式就是装饰者Decorator模式。 public class Demo {public int readWithoutBuffer(String path) throws IOException {int result 0;try (Reader reader new FileReader(path)) {int value;while ((value reader.read()) ! -1) {result value;}}return result;}public int readWithBuffer(String path) throws IOException {int result 0;try (Reader reader new BufferedReader(new FileReader(path))) {int value;while ((value reader.read()) ! -1) {result value;}}return result;} }如果将两段代码用 JMH 对比测试后者在绝大多数文件大小与硬件环境下都能以数倍乃至十数倍的速度胜出未考虑 OS page cache。 3.2 BufferedInputStream 源码剖析 以 BufferedInputStream 为例下面我们重点关注它的 read() 与 fill() 实现理解缓冲区如何管理数据。 public synchronized int read() throws IOException {if (pos count) {fill();if (pos count)return -1;}return getBufIfOpen()[pos] 0xff; }private void fill() throws IOException {byte[] buffer getBufIfOpen();if (markpos 0)pos 0; /* no mark: throw away the buffer */else if (pos buffer.length) /* no room left in buffer */if (markpos 0) { /* can throw away early part of buffer */int sz pos - markpos;System.arraycopy(buffer, markpos, buffer, 0, sz);pos sz;markpos 0;} else if (buffer.length marklimit) {markpos -1; /* buffer got too big, invalidate mark */pos 0; /* drop buffer contents */} else if (buffer.length MAX_BUFFER_SIZE) {throw new OutOfMemoryError(Required array size too large);} else { /* grow buffer */int nsz (pos MAX_BUFFER_SIZE - pos)? pos * 2 : MAX_BUFFER_SIZE;if (nsz marklimit)nsz marklimit;byte nbuf[] new byte[nsz];System.arraycopy(buffer, 0, nbuf, 0, pos);buf nbuf;buffer nbuf;}count pos;int n getInIfOpen().read(buffer, pos, buffer.length - pos);if (n 0)count n pos; }pos 与 count pos当前缓冲区已经消费到的位置索引count缓冲区中实际可用字节数读取自底层 InputStream。 当 pos count 时调用 fill() 无 mark 逻辑如果未在流上调用过 mark()则直接 pos 0丢弃旧缓冲区内容有 mark 逻辑如果调用过 mark() 并且 buffer 尚未超过 marklimit会先将 buffer[markpos, pos) 部分拷贝到 buffer[0, sz)保留标记区域否则当 buffer 大小接近 marklimit会放弃缓存并重置 markpos -1。缓冲区扩容若 buffer.length marklimit 且 pos buffer.length则按 pos*2 或 marklimit 的大小扩容以承载更多数据最大不超过 MAX_BUFFER_SIZE。 从底层流读取数据 调用 getInIfOpen().read(buffer, pos, buffer.length - pos)一次性将尽量多的数据填入 buffer[pos, buffer.length)读取后把 count pos n表示新的缓冲区可读取字节数。随后 read() 方法从内存 buffer 中依次提供单字节给调用者。 这样绝大多数 reader.read() 调用都不会触发一次真正的磁盘或网络 I/O而是走内存读取直到缓冲耗尽才会调用一次底层的 read(...)。 3.2.1 缓冲区大小的权衡与默认值 为什么不一次性把整个文件都读到缓冲 缓冲区太小时需要频繁地调用 fill()失去缓冲效果缓冲区太大单次 fill() 就涉及大量内存分配并可能导致垃圾回收压力默认缓冲区大小一般为 8192 字节8KB是工业界常见的折中值既能减少单次 fill() 带来的系统调用开销又不会占用过多堆内存。 调整缓冲区大小的思路 对于小文件或小 HTTP 响应可将缓冲区设置为 4KB 或更小减少内存消耗对于大文件复制、视频流处理等场景可适当增大为 32KB 或 64KB以减少 I/O 调用频率但文件过大时缓存整个文件到内存会导致 OOM因此需结合实际业务与可用堆内存大小谨慎配置。 4. 异步日志中的缓冲Logback 异步日志原理与配置要点 在高并发服务中同步日志会成为性能瓶颈 每次调用 logger.info(...) 都要先拼接日志消息再调用底层 I/O 将文本写入磁盘如果并发量大业务线程在等待磁盘 I/O 完成时被阻塞整体延迟显著增加即便日志输出到控制台也会占用 CPU 时间来格式化。这时可以引入“异步日志”来解耦业务线程与磁盘写入。 4.1 Logback 异步日志原理 Logback 的异步日志基于 AsyncAppender其核心思路 业务线程生产者调用 logger 时只需将待写入的日志事件先放入内存中的阻塞队列ArrayBlockingQueue异步 Worker 线程消费者在后台单线程循环不断地从队列 poll() 日志事件然后批量地将它们写入磁盘。 这样业务线程仅关心向缓冲队列“放入”日志I/O 写入由独立线程异步完成。 4.2 核心配置示例 在 logback.xml 中添加如下内容 !-- 定义一个 FileAppender负责将日志写入磁盘 -- appender nameFILE classch.qos.logback.core.FileAppenderfileapp.log/fileencoderpattern%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/pattern/encoder /appender!-- 定义一个 AsyncAppender将日志事件缓冲到队列 -- appender nameASYNC classch.qos.logback.classic.AsyncAppender!-- 当队列中的事件数量达到 discardingThreshold 时可以丢弃低级别日志 --discardingThreshold0/discardingThreshold!-- 队列大小最多容纳 512 条事件 --queueSize512/queueSize!-- 指定要异步包装的目标 appender --appender-ref refFILE/ /appenderroot levelINFO!-- 使用异步日志器 --appender-ref refASYNC/ /root4.2.1 三个关键参数 queueSize队列容量 默认值为 256当待写入事件数量超过 queueSize 时生产者线程会根据 discardingThreshold 策略进行处理如果设置过大进程突然断电队列内未落盘的日志全部丢失风险增大 discardingThreshold丢弃阈值 取值范围 0 discardingThreshold queueSize当队列长度 ≥ discardingThreshold 时低于或等于设定级别的日志事件可被丢弃以保护高优先级日志默认值为 queueSize × 0.8即队列达到 80% 时开始丢弃低级别日志若设置为 0则不丢弃任何事件但可能导致生产者阻塞或抛出异常 maxFlushTime关闭时最长等待时间 当应用优雅关闭时AsyncAppender 会调用 worker.join(maxFlushTime)等待后台线程将剩余日志写完如果等待超时应用仍会强制退出此时缓冲区中未落盘的日志将丢失合理设置该值如 5 秒或 10 秒在性能与丢失风险之间权衡。 5. 缓冲区设计思路—同步 vs 异步 缓冲区优化常见于需要对“生产端”和“消费端”解耦的场景。但在设计时需要考虑“同步缓冲”与“异步缓冲”两种模式取舍点在于编程模型复杂度与性能收益。 5.1 同步缓冲 模型示意 生产者 →→ [缓冲区] →→ 消费者整个过程在同一个线程或调用链中执行。常见策略 阈值触发写入当缓冲区积累元素数量 ≥ flushThreshold或累积字节数 ≥ byteThreshold 时一次性批量写入底层资源定时触发写入如果缓冲区在 maxIdleTime 内未达到 flushThreshold则定时将已有数据写出保证高延迟数据得以及时消费 优缺点 优点编程模型直观、逻辑简单无额外线程缺点当底层写入耗时出现波动如突发磁盘抖动会阻塞生产者线程导致整体响应能力下降。 示例 字符串拼接时使用 StringBuilder一次性将多次 append() 的结果通过 toString() 写入磁盘JDBC 批量插入在内存中将多条 SQL 语句缓存在 PreparedStatement 中达到 batchSize 时通过 executeBatch() 一次性写入数据库。 5.2 异步缓冲 模型示意 生产者线程 A →→ [缓冲区队列] →→ 消费者后台线程 B生产者仅负责往缓冲区写入消费者由独立线程不断从缓冲区读取并写出。 生产者策略 阻塞当队列已满生产者调用 put() 时会阻塞直到有空位非阻塞失败调用 offer()若缓冲区已满则返回 false让上层逻辑根据返回值做重试或丢弃异常抛出直接在 put() 或自定义方法中抛出 RejectedExecutionException 等通知调用方“缓冲已满”回调机制在生产者线程注册回调当数据真正被消费后才触发也可以用于跟踪已消费数据。 消费者设计 启动单线程或线程池不断从队列 poll() 数据处理逻辑应考虑批量拉取以减少 I/O 写入次数例如 drainTo()若消费者处理速度不足队列会持续积压生产者需根据业务侧容忍值判断是否阻塞或快速失败。 多消费者与同步问题 当缓冲区被多个消费者并发读写时需要保证数据顺序或一致性可使用有序队列如基于 BlockingQueue或根据分区Partition分流同时考虑多个消费者线程各自的吞吐能力与负载均衡。 6. Kafka 生产者缓冲示例 Kafka 生产者客户端的“批量发送”与“缓冲区”设计。下面以常见参数 batch.size 与 linger.ms 为例说明缓冲区对性能与可靠性的影响。 6.1 Kafka 生产者缓冲原理 batch.size字节指定针对每个 partition 为单个批次消息设置的最大字节容量默认为 16KB。当该容量被填满后生产者立即将该 batch 发送给对应的 broker。linger.ms毫秒指定“批次最大等待时间”即在 batch.size 未被填满的情况下生产者也会等待 linger.ms 后把已积累的消息强制发送以减少每条消息都立刻网络发送带来的开销。 具体流程 当调用 producer.send(record) 时Kafka 生产者客户端先把 record 序列化后放入对应 partition 的缓冲队列内存如果当前 batch 的累积字节数 ≥ batch.size则立即触发发送若 batch.size 未满且当前时间超过 linger.ms也会把已累积消息发送发送出发后会异步等待 broker ACK 确认或重试。 6.2 缓冲区丢数据风险 假设生产者程序发生以下情况 机器突然断电JVM 进程被 kill -9 杀死 此时如果缓冲队列中仍有尚未被 send() 到 Broker 或未获 ACK 的消息全部会丢失。默认情况下缓冲区大小为 16KB如果生产方业务持续产生大量消息且 broker 短暂不可用就会导致缓冲区快速填满。 解决方案 缩小 batch.size使得缓冲队列更频繁地发送虽然牺牲吞吐量但可减少丢失概率降低 linger.ms即使在低流量情况下也会在较短等待后发送保证消息尽快到达 broker开启幂等性与 ACK 配置设置 enable.idempotencetrue 并且 acksall让 broker 等待所有 ISRin-sync replicas确认后再 ACK确保至少写入一个副本或多副本生产者写入前落盘预写日志在生产者本地先记录“即将发送的消息”待发送成功后再删除重启后可根据预写日志补发使用电池或 UPS在极端断电场景下保证机器有足够时间将缓冲持久化到磁盘。 6.3 缓冲区过载与业务可用性 当 broker 暂时不可用或网络抖动时生产者缓冲区会不断积累消息直至达到 buffer.memory内存缓冲池或达成 max.block.ms此时默认行为是阻塞调用线程。若业务对等待较敏感可能导致线程被长时间阻塞最终耗尽线程池资源从而引起整个服务不可用。 可选对策 调整 max.block.ms一旦超时则抛出 TimeoutException 告知调用方“消息积压发送超时”限流策略在业务层做流控如令牌桶防止短时间内压入大量消息异步重试将消息暂存在本地队列或数据库后台线程定时重试投递 7. 其他缓冲场景与示例 除了文件 I/O 与消息中间件缓冲思想在常见的 Java 开发中无处不在 StringBuilder / StringBuffer 在 Java 中频繁使用 String 做拼接会产生大量临时对象StringBuilder 通过在内存中维护一个 char[] 缓冲每次 append() 写入缓冲中最后一次性 toString() 时整体创建一个 String显著提高拼接性能。 操作系统网络缓冲SO_SNDBUF / SO_RCVBUF TCP Socket 在内核中会分配发送与接收缓冲区大小可通过 socket.setSendBufferSize(...) / socket.setReceiveBufferSize(...) 进行调优适当增大操作系统缓冲区可应对应用端瞬时突发流量减少 packet drop但过大会占用更多内核内存。 数据库 InnoDB Buffer Pool MySQL InnoDB 存储引擎通过 innodb_buffer_pool_size 配置将数据页和索引页缓存在内存中减少磁盘读取合理将 buffer_pool_size 设置为物理内存的 60%~80%能显著提升查询和写入性能。 ID 生成器缓存 常见的全局递增 ID 生成如 Twitter Snowflake 或数据库自增 ID为了减少每次网络交互往往将一段 ID如 1000 个一次性从数据库或中央服务拉取到本地缓冲应用只需从本地缓冲取得下一个 ID当耗尽后再异步从中央服务拉取下一段减少延迟。 8. 注意事项与异常场景 虽然缓冲区能带来明显性能提升但在设计时还要考虑以下几方面的风险与权衡 缓冲区数据丢失 突发断电、kill -9 等强制销毁进程时缓冲区中的数据尚未落盘或未发送全部丢失对金融、订单类等对数据可靠性要求极高的系统可通过“先写 WAL 日志再入缓冲”来保证数据不丢 缓冲区内存占用与 OOM 大容量缓冲区占用堆内存较大可能导致垃圾回收压力增大或堆内存不足需根据可用物理内存与业务吞吐量合理设置如 8KB64KB、512MB2GB 等 顺序与一致性问题 在多线程/多消费者场景下若需要保证“消息顺序”必须使用单队列或分区队列对于都依赖同一缓存状态的读写需要在并发消费者之间做好状态一致性或加锁、防重入等处理 性能收益递减 缓冲区过小则频繁交互过大则内存占用过高需要在吞吐与延迟之间做折中在高并发网络场景Socket / OS 层面也会加入多级缓冲需要一体化考虑。 预写日志与数据恢复 常见做法是在写入缓冲前先将关键元数据例如 Kafka 消息 key写到本地磁盘日志待缓冲数据真正被提交到 broker 后再标记该日志为成功。重启后扫描日志补发未成功消息。这种“先 WAL 后缓存”的策略会带来额外写盘开销需要衡量业务对丢失率的容忍度。 9. 小结 系统地探讨了**缓冲Buffer**在 Java 语言与中间件中的典型应用 缓冲本质与类比 缓冲区是解耦生产者与消费者速度差异的内存“蓄水池”让慢速设备接收“小而频繁” → “大而顺序” 的 I/O 请求大幅提高吞吐。 Java I/O 缓冲实现 BufferedReader / BufferedInputStream 通过 fill() 方法一次性从底层流读入 8KB默认数据到内存通过 pos、count 指针管理缓冲区消费位置自动扩容至 marklimit在保证性能的同时兼容 mark()/reset()。 异步日志缓冲 Logback AsyncAppender 将日志事件先缓存在 ArrayBlockingQueue 中后台线程异步写入磁盘重要参数queueSize队列容量、discardingThreshold丢弃阈值、maxFlushTime关闭时等待时间。 缓冲设计思路—同步 vs 异步 同步缓冲批量触发策略简单但会阻塞生产者异步缓冲解耦写入与消费需设计生产者满载后的处理策略与多消费者同步。 Kafka 生产者缓冲示例 通过 batch.size linger.ms 实现消息批量发送缓冲区满或超时触发网络发送带来吞吐与延迟权衡在断电或 kill -9 场景下缓冲中消息或未获 ACK 消息会丢失可结合写盘预写日志或副本策略降低风险。 其他缓冲场景 StringBuilderStringBuffer 字符串拼接操作系统 Socket 缓冲SO_SNDBUFSO_RCVBUF数据库 InnoDB Buffer PoolID 生成器段缓存等。 注意事项与异常场景 缓冲区丢失风险、内存占用风险顺序一致性与并发读写冲突性能收益递减点WAL预写日志策略平衡可靠性与性能。 总之缓冲区优化是 Java 性能优化中一项非常重要的技术手段它既能显著提高磁盘与网络 I/O 吞吐也带来了异步设计下的编程复杂度与故障恢复挑战。 在实际项目中应结合业务对“数据丢失概率”与“延迟/吞吐”之间的容忍度合理设置缓冲大小与处理策略。
http://www.pierceye.com/news/49924/

相关文章:

  • 公司网站建设费属于宣传费吗建设网站 请示 报告
  • 企业网站公告怎么做天商阳光网站邮箱
  • 石家庄外贸做网站手机怎么安装网站程序
  • 东莞最近三天的新闻大事搜索引擎优化方案模板
  • 做网站asp用什么软件重庆制作网站模板建站公司
  • 网站群建设原则洛阳哪家网站做的好
  • 哪个小说网站版权做的好处做网站应该用什么配置的手提电脑
  • 织梦网站做站群长春网站设计网站建设网站制作880元
  • 做网站建设需要做哪些工作济南做网站互联网公司有哪些
  • 宁夏住房城乡建设厅网站怎样成立网站
  • 网站策划方案自建网站系统
  • 做网站电脑和手机都是一样可以看吗wordpress 自定义搜索
  • 网站建设简介淄博php 建设网站制作
  • 常州网站建设公司信息精品ppt模板免费下载
  • 美食网站设计目的个人网站代码编写
  • 提供零基础网站建设教学培训wordpress 群晖 局域网
  • dw网站建设怎么放在网上wordpress英文导航模板
  • wordpress网站模版永登网站设计与建设
  • 网站中木马怎么办推广软文范例大全500
  • 手机端网站开发价格朝阳网络推广公司
  • 网站建设优化过程中的优化策略网站建设招标评分标准
  • 网站建设云服务做番号网站的 违法
  • 网站 文章排版健康陕西app管理端最新版
  • 浏览器网站建设的步骤过程oppo商城
  • 网站平台建设方案wordpress 七牛
  • 山东新华电脑学院学网站开发wordpress词汇插件
  • 建设工程安全管理网站郴州人为什么不像湖南人
  • seo站长工具推广平台行业门户网站大全
  • 给网站做seo诊断山东城市建设职业学院图书馆网站
  • 四川泰龙建设集团公司官方网站帮网站做关键词排名优化