<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                * 非阻塞 IO * 其實無論是用 Java NIO 還是用 Netty,達到百萬連接都沒有任何難度。因為它們都是非阻塞的 IO,不需要為每個連接創建一個線程了。 * nio 和 io的區別 * nio的核心:Channel 通道,Buffer 緩沖區,Selector 選擇器如果是百萬級測試,怎么去找那么多機器?單機最多可以有 6W 的連接,百萬連接起碼需要17臺機器! ### 如何才能突破這個限制呢? * 其實這個限制來自于網卡。 可以通過使用虛擬機,并且把虛擬機的虛擬網卡配置成了橋接模式解決了問題。 根據物理機內存大小,單個物理機起碼可以跑4-5個虛擬機,所以最終百萬連接只要4臺物理機就夠了。 ### 端口受限設置 #### windows客戶端 * 打開注冊表:regedit HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\TCPIP\Parameters 新建 DWORD值,name:TcpTimedWaitDelay,value:0(十進制) –> 設置為0 新建 DWORD值,name:MaxUserPort,value:65534(十進制) –> 設置最大連接數65534 重啟系統 #### liunx客戶端 ``` shell cat /proc/sys/net/ipv4/ip_local_port_range 值為32768 610 ``` * 大概也就是共61000-32768=28232個端口可以使用,單個IP對外只能發送28232個TCP請求。 * 以管理員身份,把端口的范圍區間增到最大: ``` shell echo "1024 65535"> /proc/sys/net/ipv4/ip_local_port_range ``` 現在有64511個端口可用. * 以上做法只是臨時,系統下次重啟,會還原。 更為穩妥的做法是修改/etc/sysctl.conf文件,增加一行內容 ``` net.ipv4.ip_local_port_range= 1024 65535 sysctl -p ``` * 現在可以使用的端口達到64510個(假設系統所有運行的服務器是沒有占用大于1024的端口的,較為純凈的centos系統可以做到),要想達到50萬請求,還得再想辦法。 增加IP地址 * 一般假設本機網卡名稱為 eth0,那么手動再添加幾個虛擬的IP: ifconfig eth0:1 192.168.190.151 ifconfig eth0:2 192.168.190.152 ...... 或者偷懶一些: for i in seq 1 9; do ifconfig eth0:$i 192.168.190.15$i up ; done 這些虛擬的IP地址,一旦重啟,或者 service network restart 就會丟失。 為了模擬較為真實環境,在測試端,手動再次添加9個vmware虛擬機網卡 ### 代碼 #### 入口 ``` package com.nio.test; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpRequestEncoder; import io.netty.handler.codec.http.HttpResponseDecoder; import io.netty.handler.codec.http.HttpVersion; import java.net.URI; import java.nio.charset.StandardCharsets; public class HttpClient { public void connect(String host, int port) throws Exception { EventLoopGroup workerGroup = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); b.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // 客戶端接收到的是httpResponse響應,所以要使用HttpResponseDecoder進行解碼 ch.pipeline().addLast(new HttpResponseDecoder()); // 客戶端發送的是httprequest,所以要使用HttpRequestEncoder進行編碼 ch.pipeline().addLast(new HttpRequestEncoder()); ch.pipeline().addLast(new HttpClientInboundHandler()); } }); ChannelFuture f = b.connect(host, port).sync(); URI uri = new URI("http://gc.ditu.aliyun.com:80/geocoding?a=深圳市"); String msg = "Are you ok?"; DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toASCIIString(), Unpooled.wrappedBuffer(msg.getBytes("UTF-8"))); // 構建http請求 request.headers().set(HttpHeaders.Names.HOST, host); request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); request.headers().set(HttpHeaders.Names.CONTENT_LENGTH, request.content().readableBytes()); // 發送http請求 f.channel().write(request); f.channel().flush(); f.channel().closeFuture().sync(); // } } finally { workerGroup.shutdownGracefully(); } } public void connect_post(String host, int port) throws Exception { EventLoopGroup workerGroup = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); b.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // 客戶端接收到的是httpResponse響應,所以要使用HttpResponseDecoder進行解碼 ch.pipeline().addLast(new HttpResponseDecoder()); // 客戶端發送的是httprequest,所以要使用HttpRequestEncoder進行編碼 ch.pipeline().addLast(new HttpRequestEncoder()); ch.pipeline().addLast(new HttpClientInboundHandler()); } }); ChannelFuture f = b.connect(host, port).sync(); URI uri = new URI("http://gc.ditu.aliyun.com:80/geocoding?a=深圳市"); FullHttpRequest request = new DefaultFullHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.POST, uri.getRawPath()); // 構建http請求 request.headers().set(HttpHeaders.Names.HOST, host); request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); // or HttpHeaders.Values.CLOSE request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP); request.headers().add(HttpHeaders.Names.CONTENT_TYPE, "application/json"); ByteBuf bbuf = Unpooled.copiedBuffer("{\"jsonrpc\":\"2.0\",\"method\":\"calc.add\",\"params\":[1,2],\"id\":1}", StandardCharsets.UTF_8); request.headers().set(HttpHeaders.Names.CONTENT_LENGTH, bbuf.readableBytes()); // 發送http請求 f.channel().write(request); f.channel().flush(); f.channel().closeFuture().sync(); // } } finally { workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { HttpClient client = new HttpClient(); //請自行修改成服務端的IP for(int k=0; k<1;k++){ client.connect("http://gc.ditu.aliyun.com/", 80); System.out.println(k); } } } ``` #### 監聽代碼 ``` package com.nio.test; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.http.HttpContent; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpResponse; public class HttpClientInboundHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.print("success!~!~"); if (msg instanceof HttpResponse) { HttpResponse response = (HttpResponse) msg; // System.out.println("CONTENT_TYPE:" + response.headers().get(HttpHeaders.Names.CONTENT_TYPE)); System.out.println("HTTP_CODE:" + response.getStatus()); } if(msg instanceof HttpContent) { HttpContent content = (HttpContent)msg; ByteBuf buf = content.content(); System.out.println(buf.toString(io.netty.util.CharsetUtil.UTF_8)); buf.release(); } ctx.close(); } } ``` ### 更多參考 * [netty官網](http://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-10) * [端口受限](http://blog.csdn.net/educast/article/details/23053671) * [Netty 長連接服務測試](http://www.dozer.cc/2014/12/netty-long-connection.html1)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看