程序员必备的十大技能(进阶版)之网络与高并发原理(五)

简介: 教程来源 https://tmywi.cn/ 本节系统讲解高并发场景下的操作系统与JVM深度调优:涵盖Linux网络内核参数(BBR拥塞控制、缓冲区、连接队列)、进程资源限制、JVM G1GC优化及性能压测与瓶颈定位方法,并以百万级WebSocket推送系统为实战案例,体现无锁化、异步非阻塞等高性能设计原则。

六、操作系统内核参数调优

6.1 Linux网络参数优化

#!/bin/bash
# /etc/sysctl.conf 高并发服务器配置

# 文件句柄限制
fs.file-max = 1000000
fs.nr_open = 1000000

# 网络核心参数
net.core.somaxconn = 32768              # listen队列最大长度
net.core.netdev_max_backlog = 5000      # 网卡队列长度
net.core.rmem_default = 87380           # 默认接收缓冲区
net.core.wmem_default = 87380           # 默认发送缓冲区
net.core.rmem_max = 134217728           # 最大接收缓冲区(128MB)
net.core.wmem_max = 134217728           # 最大发送缓冲区(128MB)

# TCP参数
net.ipv4.tcp_max_syn_backlog = 8192     # SYN队列长度
net.ipv4.tcp_syncookies = 1             # SYN Flood防护
net.ipv4.tcp_tw_reuse = 1               # TIME_WAIT复用
net.ipv4.tcp_fin_timeout = 30           # FIN_WAIT2超时
net.ipv4.tcp_keepalive_time = 600       # KeepAlive探测间隔
net.ipv4.tcp_keepalive_intvl = 30       # 探测重试间隔
net.ipv4.tcp_keepalive_probes = 3       # 探测次数
net.ipv4.tcp_slow_start_after_idle = 0  # 禁用空闲后慢启动

# 拥塞控制
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

# 端口范围
net.ipv4.ip_local_port_range = 1024 65535

# 内存参数
net.ipv4.tcp_mem = 786432 1048576 1572864    # 4GB内存配置
net.ipv4.tcp_rmem = 4096 87380 134217728     # 读缓冲区
net.ipv4.tcp_wmem = 4096 65536 134217728     # 写缓冲区

6.2 用户进程限制

# /etc/security/limits.conf
* soft nofile 1000000
* hard nofile 1000000
* soft nproc 100000
* hard nproc 100000

# systemd服务限制(如果使用systemd)
[Service]
LimitNOFILE=1000000
LimitNPROC=100000

6.3 JVM参数调优

# 高并发服务JVM参数示例
# -Xms8G -Xmx8G                     # 堆内存8GB
# -Xmn3G                            # 新生代3GB
# -XX:MetaspaceSize=512M            # 元空间初始大小
# -XX:MaxMetaspaceSize=512M
# -XX:+UseG1GC                      # G1垃圾回收器
# -XX:MaxGCPauseMillis=100          # 目标GC暂停时间
# -XX:G1HeapRegionSize=16M          # G1 Region大小
# -XX:ParallelGCThreads=16          # GC并行线程数
# -XX:ConcGCThreads=4               # 并发GC线程数
# -XX:+UseStringDeduplication       # 字符串去重
# -XX:+DisableExplicitGC            # 禁用显式GC
# -XX:+HeapDumpOnOutOfMemoryError   # OOM时dump堆
# -XX:HeapDumpPath=/logs/heap.hprof

# 网络相关
# -Djava.net.preferIPv4Stack=true
# -Djava.net.preferIPv6Addresses=false

# 高性能模式
# -XX:+UseBiasedLocking             # 偏向锁
# -XX:+UseCompressedOops            # 压缩指针
# -XX:+AlwaysPreTouch               # 启动时预分配内存
# -XX:+UseNUMA                      # NUMA感知
# -XX:AutoBoxCacheMax=20000         # 自动装箱缓存

七、高并发性能测试

7.1 压测工具使用

// JMeter脚本生成(或使用wrk、ab、siege)
// wrk -t16 -c2000 -d30s --latency http://localhost:8080/api

// 自定义压测代码
public class LoadTest {

    public static void main(String[] args) throws InterruptedException {
        int threadCount = 100;
        int requestPerThread = 10000;
        CountDownLatch latch = new CountDownLatch(threadCount);
        AtomicLong totalTime = new AtomicLong();
        AtomicLong successCount = new AtomicLong();
        AtomicLong failCount = new AtomicLong();

        // 预热
        for (int i = 0; i < 100; i++) {
            sendRequest();
        }

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                for (int j = 0; j < requestPerThread; j++) {
                    long requestStart = System.nanoTime();
                    boolean success = sendRequest();
                    long requestTime = System.nanoTime() - requestStart;
                    totalTime.addAndGet(requestTime);

                    if (success) {
                        successCount.incrementAndGet();
                    } else {
                        failCount.incrementAndGet();
                    }
                }
                latch.countDown();
            }).start();
        }

        latch.await();
        long totalDuration = System.currentTimeMillis() - startTime;

        // 输出结果
        long totalRequests = successCount.get() + failCount.get();
        double avgLatency = totalTime.get() / 1_000_000.0 / totalRequests;
        double qps = totalRequests * 1000.0 / totalDuration;

        System.out.printf("Total Requests: %d\n", totalRequests);
        System.out.printf("Success: %d, Fail: %d\n", successCount.get(), failCount.get());
        System.out.printf("QPS: %.2f\n", qps);
        System.out.printf("Avg Latency: %.2f ms\n", avgLatency);
        System.out.printf("Total Duration: %d ms\n", totalDuration);
    }
}

7.2 性能瓶颈定位

# 1. CPU分析
top -H -p <pid>                     # 查看线程CPU使用率
perf top -p <pid>                   # 查看热点函数
perf record -g -p <pid> -- sleep 30 # 采样30秒
perf report                         # 生成报告

# 2. 内存分析
jmap -heap <pid>                    # 查看堆内存分布
jmap -histo:live <pid> | head -20   # 查看存活对象
jstat -gcutil <pid> 1000            # GC统计

# 3. 线程分析
jstack <pid> > thread_dump.txt      # 线程dump
# 统计线程状态
cat thread_dump.txt | grep "java.lang.Thread.State" | sort | uniq -c

# 4. 网络分析
netstat -antp | grep <port> | wc -l # 连接数统计
ss -tni | grep -E "rtt|cwnd"        # TCP详细信息

# 5. 火焰图
# 使用async-profiler
./profiler.sh start <pid>
./profiler.sh stop <pid> -o flamegraph > flamegraph.svg

八、实战案例:百万级长连接推送系统

8.1 架构设计

// 基于Netty的WebSocket推送服务
@SpringBootApplication
public class PushServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(PushServerApplication.class, args);
    }

    @Bean
    public NettyWebSocketServer nettyWebSocketServer() {
        return new NettyWebSocketServer(8080);
    }
}

public class NettyWebSocketServer {

    private final int port;
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;

    // 连接管理(本地缓存 + Redis集群)
    private final ConnectionManager connectionManager;

    public NettyWebSocketServer(int port) {
        this.port = port;
        this.connectionManager = new ConnectionManager();
    }

    public void start() {
        bossGroup = new NioEventLoopGroup(1);
        workerGroup = new NioEventLoopGroup(0); // 自动设置(CPU核心数 * 2)

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 32768)
                .option(ChannelOption.SO_REUSEADDR, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.SO_RCVBUF, 65536)
                .childOption(ChannelOption.SO_SNDBUF, 65536)
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ChannelPipeline pipeline = ch.pipeline();
                        // WebSocket编解码器
                        pipeline.addLast(new HttpServerCodec());
                        pipeline.addLast(new HttpObjectAggregator(65536));
                        pipeline.addLast(new WebSocketServerProtocolHandler("/ws", null, true, 65536));
                        pipeline.addLast(new WebSocketFrameHandler(connectionManager));

                        // 心跳检测
                        pipeline.addLast(new IdleStateHandler(60, 0, 0));
                        pipeline.addLast(new HeartbeatHandler());
                    }
                });

            ChannelFuture future = bootstrap.bind(port).sync();
            log.info("Push server started on port {}", port);
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            log.error("Server interrupted", e);
        } finally {
            shutdown();
        }
    }

    public void shutdown() {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }

    // 连接管理器(支持亿级连接,使用分片)
    static class ConnectionManager {
        // 使用ConcurrentHashMap分片减少竞争
        private final ConcurrentHashMap<String, Channel>[] segments;
        private final int segmentCount = 128;

        @SuppressWarnings("unchecked")
        ConnectionManager() {
            segments = new ConcurrentHashMap[segmentCount];
            for (int i = 0; i < segmentCount; i++) {
                segments[i] = new ConcurrentHashMap<>();
            }
        }

        private int getSegmentIndex(String userId) {
            return Math.abs(userId.hashCode() % segmentCount);
        }

        public void add(String userId, Channel channel) {
            segments[getSegmentIndex(userId)].put(userId, channel);
        }

        public Channel get(String userId) {
            return segments[getSegmentIndex(userId)].get(userId);
        }

        public void remove(String userId) {
            segments[getSegmentIndex(userId)].remove(userId);
        }

        // 广播消息(高效遍历)
        public void broadcast(Object message) {
            for (ConcurrentHashMap<String, Channel> segment : segments) {
                for (Channel channel : segment.values()) {
                    if (channel.isActive()) {
                        channel.writeAndFlush(message);
                    }
                }
            }
        }
    }
}

// WebSocket处理器
class WebSocketFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {

    private final ConnectionManager connectionManager;
    private String userId;

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        log.info("New connection: {}", ctx.channel().remoteAddress());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
        if (frame instanceof TextWebSocketFrame) {
            String text = ((TextWebSocketFrame) frame).text();
            handleMessage(ctx, text);
        }
    }

    private void handleMessage(ChannelHandlerContext ctx, String message) {
        // 解析注册消息
        JsonObject json = JsonParser.parseString(message).getAsJsonObject();
        String type = json.get("type").getAsString();

        if ("register".equals(type)) {
            userId = json.get("userId").getAsString();
            connectionManager.add(userId, ctx.channel());
            log.info("User registered: {}", userId);
        } else if ("ping".equals(type)) {
            // 心跳响应
            ctx.writeAndFlush(new TextWebSocketFrame("{\"type\":\"pong\"}"));
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        if (userId != null) {
            connectionManager.remove(userId);
            log.info("User disconnected: {}", userId);
        }
    }
}

// 推送服务
@RestController
public class PushController {

    @Autowired
    private ConnectionManager connectionManager;

    @PostMapping("/push/{userId}")
    public ResponseEntity<String> pushToUser(@PathVariable String userId, @RequestBody PushRequest request) {
        Channel channel = connectionManager.get(userId);
        if (channel != null && channel.isActive()) {
            String message = new TextWebSocketFrame(JSON.toJSONString(request)).toString();
            channel.writeAndFlush(message);
            return ResponseEntity.ok("success");
        }
        return ResponseEntity.status(404).body("user offline");
    }

    @PostMapping("/push/batch")
    public ResponseEntity<String> pushBatch(@RequestBody BatchPushRequest request) {
        List<String> userIds = request.getUserIds();
        String message = JSON.toJSONString(request.getMessage());

        // 批量推送(使用CompletableFuture并行)
        List<CompletableFuture<Void>> futures = userIds.stream()
            .map(userId -> CompletableFuture.runAsync(() -> {
                Channel channel = connectionManager.get(userId);
                if (channel != null && channel.isActive()) {
                    channel.writeAndFlush(new TextWebSocketFrame(message));
                }
            }))
            .collect(Collectors.toList());

        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
            .join();

        return ResponseEntity.ok("success");
    }
}

高性能设计原则

/*
 * 1. 无锁化:使用CAS代替锁,减少上下文切换
 * 2. 缓存友好:数据结构对齐,避免伪共享
 * 3. 异步非阻塞:IO密集型任务使用异步
 * 4. 批量处理:合并请求,减少系统调用
 * 5. 内存池:复用对象,减少GC
 * 6. 零拷贝:sendfile、mmap
 * 7. 预先计算:缓存热点数据
 * 8. 懒加载:延迟初始化
 * 9. 短路原则:快速失败
 * 10. 降级熔断:保护核心服务
 */

来源:
https://yyvgt.cn/

相关文章
|
4月前
|
设计模式 安全 Java
程序员必备的十大技能(进阶版)之网络与高并发原理(四)
教程来源 https://bncne.cn/ 本节详解高并发四大核心设计模式:①生产者-消费者(基于BlockingQueue与高性能Disruptor);②请求合并(批量处理降低IO压力);③背压控制(RxJava与信号量/滑动窗口限流);④线程封闭(ThreadLocal安全复用资源)。兼顾性能、可靠性与可维护性。
|
4月前
|
运维 Java 程序员
程序员必备的十大技能(进阶版)之性能调优与故障排查(一)
教程来源 https://qeext.cn/ 本文系统讲解性能调优与故障排查核心技能,涵盖故障方法论、CPU/内存/I/O/网络/数据库问题定位、Java诊断工具(Arthas/JVM)、全链路压测及混沌工程,辅以实战案例与黄金排查原则,助开发者从“重启党”进阶为问题终结者。
|
4月前
|
Arthas 运维 Java
程序员必备的十大技能(进阶版)之性能调优与故障排查(二)
教程来源 qfcrz.cn 本节系统梳理Java内存问题排查全流程:涵盖JVM内存结构(堆、元空间、直接内存等)、四大典型泄漏场景(静态集合、ThreadLocal、监听器、动态代理)、jstat/jmap/jcmd/Arthas等实战工具用法、MAT深度分析技巧(Dominator Tree、OQL查询),以及GC调优策略与I/O问题定位方法。
|
1月前
|
存储 前端开发 Java
阿里云-对象存储OSS-配置和使用(Java)
本项目接入阿里云OSS对象存储,聚焦解决文件上传与访问性能问题。采用杭州地域Bucket(air-test1),标准存储+公共读权限,结合RAM子账号与环境变量安全配置,通过Spring Boot集成SDK实现图片/头像等资源高效上传与直链访问。(239字)
269 0
|
Web App开发 编解码 前端开发
VUE网页实时播放海康、大华摄像头RTSP视频流完全方案,300毫秒延迟,支持H.265、可多路同时播放
在遍地都是摄像头的今天,往往需要在各种信息化、数字化、可视化B/S系统中集成实时视频流播放等功能,海康、大华、华为等厂家摄像头或录像机等设备一般也都遵循监控行业标准,支持国际标准的主流传输协议RTSP输出,而Chrome、Firefox、Edge等新一代浏览器从2015年开始取消了NPAPI插件技术支持导致RTSP流无法直接原生播放了
4615 0
|
4月前
|
Prometheus Cloud Native 程序员
程序员必备的十大技能(进阶版)之云原生与容器化(四)
教程来源 https://xcfsr.cn/ Kubernetes配置与密钥管理核心实践:ConfigMap用于解耦非敏感配置(支持字面值、文件、目录创建及环境变量/卷挂载注入);Secret专存敏感数据(Base64编码,支持Opaque/TLS等类型),保障密码、证书安全。
|
4月前
|
存储 Cloud Native 程序员
程序员必备的十大技能(进阶版)之云原生与容器化(一)
教程来源 https://oplhc.cn/ 云原生已成现代应用架构标准范式,本文系统解析容器原理、Docker实践、Kubernetes编排、服务网格、GitOps等核心技术,覆盖从虚拟化演进到可观测性建设的十大维度,助力开发者全面掌握云原生技术体系。
|
4月前
|
设计模式 程序员
程序员必备的十大技能(进阶版)之设计模式与架构思维(二)
教程来源 https://vrhyh.cn/ 结构型模式关注类与对象的组合组织,提升系统灵活性与可维护性。含适配器(兼容接口)、装饰器(动态增强)、代理(控制访问)、外观(简化子系统)、组合(树形结构)五种核心模式,均通过封装、委托与抽象实现松耦合设计。
|
5月前
|
移动开发 小程序 前端开发
前端uinapp打造陪玩系统/陪玩小程序APP上线保姆级别的教程/多端开发打造
本指南详解陪玩平台从0到1搭建全流程:涵盖服务器/域名准备、微信/APP开发者认证、支付接入;宝塔部署ThinkPHP后端;UniApp多端(小程序/H5/APP)编译;后台配置与分账设置;以及资质合规、未成年人保护、内容风控等关键避坑要点。
450 2
|
4月前
|
人工智能 前端开发 Java
让 AI + Vercel 帮我部署网站,太方便了!
大家好,我是程序员鱼皮,今天分享一个提升 AI 编程效率的神技巧。 以前,我们开发一个网站,从写代码到部署上线,每个环节都得自己动手。 但是现在 AI 写代码已经溜飞边子了,在我心里已经取代了古法编程,谁能想到这是短短 1 年就发生的巨变。 而且 AI 的能力不止于此,利用 Skills 技能或 MCP 扩展,AI 甚至可以直接帮我们把网站部署上线! 好好好,合着我 只要提个一句话需求,写代码和部
469 0