高并发之步步为营推理串联

1.什么是高并发

 1. 通过英文意思上去脑补
英文为High Concurrency,词义上分析,currency是流通货币的意思,con有一起的意思,
合在一起就是一起抢钱,加上high就是疯狂一起抢钱了。
 2. 就如下图那样就是高并发了。
 3. 那么我们希望这种事情的发生么?
 4. 答案是:我们希望,我们也不希望
 5. 我们希望的是我们的网站或者我们的商店能够有这么大的热度达到被抢购的状态。
 6. 我们不希望的是如此高并发而导致如下图那样的拥堵,从而导致客户体验度差。
 7. 所以高并发是互联网分布式系统架构设计中必须考虑的因素之一。
 8. 它指的是通过一定的系统设计保证系统能够同时并行处理很多请求
 9. 从而使得减少如下图的那种状况的发生。

这里写图片描述

2.1. 为什么只谈并发编程而不怎么谈并行编程呢?

 1. 通过2.2.的区别分析可以看出,在理想环境下,大家都是王思聪,不考虑成本问题的情况下
 2. 明显并行得优于并发的,不管来多少人访问我的网站,我都给你vip待遇,就不会造成拥堵了。
 3. 然,现实总归是现实。即然一个人可以多件事情,why not,尽可能的加以利用咯。
 4. 所以并发编程就在web编程中变得尤为重要了,但也同时带来了诸多需要考虑的问题。
 5. 但也不是说不谈并行编程,并行计算是大数据平台的主角,是分而治之思想的一个主要思想
 6. 实际上,我们架构也是 并行+并发 的模式,以达到最高效的解决“拥堵”的问题。

2.2. 并发与并行是什么区别呢?

并发(Concurrency):一个实体在一定时间间隔内干多件事情-->逻辑上的同时执行任务-->单核多线程
并行(parallelism):多个实体在同一时间干多件事情-->物理上的同时执行任务-->多核执行

那么如何提高系统的并发能力

scale up:垂直扩展-->提升单机处理能力(cpu的核数,内存的容量,硬盘的存储容量和访问速度,网络带宽的速度)-->简单暴力也最有效
sacle out:水平扩展-->增加服务器,线性扩充系统系能-->复杂但长远来说更有效

水平扩展的方式

 1. 反向代理层的水平扩展:dns轮询
 2. 应用服务器层的水平扩展:nginx反向代理
 3. 服务层的水平扩展:服务连接池
 4. 数据层的水平扩展:缓存数据库,master-slave数据库,范围拆分,hash拆分
 5. 线程的水平扩展:多线程--->垂直扩展当然也得用多线程,是一个基本的提升性能的操作

高并发-多线程-传统IO

阻塞:在server.accept(),inputStream.read(bytes)阻塞
所以,得使用线程池来保证多线程的使用

线程池使用案例

#服务端代码
public class OioServer {

    public static void main(String[] args) throws Exception {

        ExecutorService pool= Executors.newCachedThreadPool();

        ServerSocket server=new ServerSocket(6666);
        System.out.println("server start");
        while (true){
            final Socket socket=server.accept();
            System.out.println("client in");
            pool.execute(new Runnable() {
                @Override
                public void run(){
                    handler(socket);
                }
            });


        }
    }

    public static void handler(Socket socket){
        try{
            byte[] bytes=new byte[1024];
            InputStream inputStream=socket.getInputStream();
            while (true){
                int read=inputStream.read(bytes);
                if(read != -1){
                    System.out.println(new String(bytes,0,read));

                }else{
                    break;
                }
            }
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                System.out.println("socket close");
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }

}
#客户端使用telnet去访问服务端
telnet localhost 6666

高并发-多线程-NIO

#服务端代码
public class NioServer {

    private Selector selector;
    public  void initServer(int port) throws Exception{
        ServerSocketChannel serverSocketChannel =ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.socket().bind(new InetSocketAddress(port));
        this.selector=Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    }

    public  void listen() throws  Exception{
        System.out.println("server start");
        while (true){
            selector.select();
            Iterator<?> ite=this.selector.selectedKeys().iterator();
            while (ite.hasNext()){
                SelectionKey key=  (SelectionKey) ite.next();
                ite.remove();
                handler(key);
            }
        }
    }
    public  void handler(SelectionKey key) throws Exception{
        if(key.isAcceptable()){
            handlerAccept(key);
        }else if(key.isReadable()){
            handleRead(key);
        }
    }
    public  void handlerAccept(SelectionKey key) throws  Exception{
        ServerSocketChannel server=(ServerSocketChannel)key.channel();
        SocketChannel channel=server.accept();
        channel.configureBlocking(false);
        System.out.println("client in");
        channel.register(this.selector,SelectionKey.OP_READ);
    }

    public  void handleRead(SelectionKey key) throws Exception{
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer buffer=ByteBuffer.allocate(20);
        channel.read(buffer);
        byte[] data=buffer.array();
        String msg=new String(data).trim();
        System.out.println("server msg:" + msg);
        ByteBuffer outbuffer=ByteBuffer.wrap(msg.getBytes());
        channel.write(outbuffer);

    }


    public static void main(String[] args) throws  Exception{
            NioServer nioServer=new NioServer();
            nioServer.initServer(7777);
            nioServer.listen();
    }
}
#客户端使用telnet去访问服务端
telnet localhost 7777

高并发-多线程-IOvsNIO

NIO                     IO
ServerSocketChannel ServerSocket   #带频道的监听端口 vs 监听端口
SocketChannel       Socket         #带频道的Socket服务 vs Socket服务 
ByteBuffer      Stream         #缓冲区 vs 数据流  
Selector,SelectionKey                 #选择器 vs 空空如也

未完待续。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值