# mini-nginx **Repository Path**: carlval/mini-nginx ## Basic Information - **Project Name**: mini-nginx - **Description**: No description available - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2020-11-04 - **Last Updated**: 2021-07-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## - 自定义实现简单Nginx 的反向代理和负载均衡技术 ### 1.Mini-Niginx 使用非阻塞NIO模型 ​ ```java private void init() throws Exception { //创建一个选择器 selector = Selector.open(); //创建一个ServerSocketChanel ServerSocketChannel channel = ServerSocketChannel.open(); //设置非阻塞 channel.configureBlocking(false); //打开一个ServerSocket ServerSocket serverSocket = channel.socket(); //地址 InetSocketAddress address = new InetSocketAddress(port); //绑定 serverSocket.bind(address); //注册事件 channel.register(this.selector, SelectionKey.OP_ACCEPT); } public void start() throws Exception { init(); System.out.println("Mini Nginx is running in port : " + port); while (true) { this.selector.select(); Iterator iterator = this.selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); if (key.isAcceptable()) { accept(key); } else if (key.isReadable()) { read(key); } } } } private void accept(SelectionKey key) { ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); SocketChannel channel = null; try { channel = serverSocketChannel.accept(); //把这个设置为非阻塞 channel.configureBlocking(false); //注册读事件 channel.register(selector, SelectionKey.OP_READ); } catch (IOException e) { e.printStackTrace(); } } private void read(SelectionKey key) throws IOException { ByteBuffer buffer = ByteBuffer.allocate(1024); SocketChannel channel = (SocketChannel) key.channel(); channel.read(buffer); String requestBuffer = new String(buffer.array()).trim(); if(requestBuffer.equals("")){ channel.close(); return; } System.out.println("获取请求"+requestBuffer); Request request = new Request(requestBuffer); ByteBuffer outbuffer = ByteBuffer.wrap(HttpResponseUtils.getRootResponse().getBytes()); outbuffer = handleRequest(request); channel.write(outbuffer); channel.close(); } ``` ### 2. 负载均衡算法 ```java /** * 轮询策略. * * @param processor * @return */ private Tomcat doCheckPoll(NginxProcessor processor) { Tomcat tomcat = processor.getInstance(this.point - 1); if (this.point == processor.getServerCount()) { this.point = 1; } else { this.point++; } return tomcat; } /** * IP_HASH策略. * * @param remoteIp * @param processor * @return */ private Tomcat doCheckIpHash(String remoteIp, NginxProcessor processor) { int serverIndex = Math.abs(remoteIp.hashCode()) % processor.getServerCount(); Tomcat tomcat = processor.getInstance(serverIndex); if (tomcat != null) { System.out.println("ip: [" + remoteIp + "] 被路由到服务器" + tomcat.getHost() + ":" + tomcat.getPort()); return tomcat; } return null; } ``` ### 3.使用方法 1. 定义NginxConfig 配置nginx 端口,以及负载均衡使用的策略 ```java NginxConfig config = new NginxConfig("127.0.0.1", 8080, NginxConfig.LoadBalance.POLL); ``` 2. 注册Tomcat服务器 ```java Tomcat tomcat_81 = new Tomcat("127.0.0.1", 8081); Tomcat tomcat_82 = new Tomcat("127.0.0.1", 8082); Tomcat tomcat_83 = new Tomcat("127.0.0.1", 8083); TomcatUpStream tomcatUpStream = new TomcatUpStream(); tomcatUpStream.setUrlPatteen(Pattern.compile("^/tomcat")); tomcatUpStream.setTomcatServers(Arrays.asList(tomcat_81, tomcat_82, tomcat_83)); config.register(tomcatUpStream); ``` 3. 将NginxConfig 注入 MiniNginx并开启服务 ```java MiniNginx nginx = new MiniNginx(config); nginx.start(); ```