# 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();
```