Haproxy反向代理MySQL底层原理分析

Haproxy反向代理MySQL底层原理分析

最近研究了一下Haproxy反向代理的机制,它支持俩中模式的反向代理,有4层模式与7层模式。

@:使用7层模式作为Web代理,下面是官方的解释,按照http模式工作,客户端的请求在被转发到真实服务器之前会被代理服务器深度分析,任何请求如果不满足(RFC-compliant)Web标准将被拒绝,会对请求进行过滤 处理 和 路由。也就是与目前比较流行的Nginx原理都差不多,这里不做过多的解释。
http      The instance will work in HTTP mode. The client request will be
          analyzed in depth before connecting to any server. Any request
          which is not RFC-compliant will be rejected. Layer 7 filtering,
          processing and switching will be possible. This is the mode which
          brings HAProxy most of its value.



@:使用4层模式作为TCP/IP协议的代理,下面是官方的解释,按照tcp的模式工作,全双工的tcp连接建立在客户端与服务器之间,没有7层模式的检查,默认模式。可以支持
SSL SSH SMTP等等..
tcp       The instance will work in pure TCP mode. A full-duplex connection
          will be established between clients and servers, and no layer 7
          examination will be performed. This is the default mode. It
          should be used for SSL, SSH, SMTP, ...

@:看了文档之后发现haproxy所谓的4层代理,我个人认为它并不是真正意义上的4层代理,:haproxy的4层tcp模式的工作原理如下图。


@:haproxy的4层tcp模式的工作原理是这样的。
1:客户端与haproxy服务器建立TCP连接,Haproxy在收到客户端的TCP连接后,会与真实服务器建立一个TCP连接,并与之对应起来。
2:客户端发送数据到Haproxy服务器,系统内核会把数据包交给应用层(Haproxy)。备注:这里数据已经到应用层了,所以我说它是伪4层。
3:Haproxy软件会把数据流原封不动的发送之前与真实服务器建立的TCP连接。这样就发成了对TCP数据流的转发。
4:真实服务器返回数据的过程与上面一个道理。


@:根据上面的理论,我用Java简单写个程序还验证一下。
其中:192.168.80.111", 3306 是数据库的IP与端口,本机192.168.1.125充当代理服务器监听3306端口,在用一台机器充当客户端。

package com.framework.code.demo;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class MySqlReplicationDriverDemo {

	public static void main(String[] args) throws Exception {
		//监听本机3306端口,本机作为代理服务器
		ServerSocket serverSocket = new ServerSocket(3306);
		//这里为了测试只能与一个客户端进行连接
		final Socket socket = serverSocket.accept();
		//对应客户端的输出流
		final InputStream clientInputStream = socket.getInputStream();
		//对应客户端的输入流
		final OutputStream clientOutputStream = socket.getOutputStream();
		
		
		//与真实后端服务器进行tcp连接
		Socket mysqlSocker = new Socket("192.168.80.111", 3306);
		//对应后端输入流
		final InputStream realInputStream = mysqlSocker.getInputStream();
		//对应后端输出流
		final OutputStream realOutputStream = mysqlSocker.getOutputStream();
		
		//启动一个线程,负责读取客户端的输入数据,从客户端读取的所有数据全部转发给后端真实服务器
		//clientInputStream  >> realOutputStream
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					byte[] cache = new byte[2048];
					while(true) {
						//读取客户端的二进制数据
						int index = clientInputStream.read(cache);
						if(index == -1) {
							return;
						}
						//全部发送给真实服务器
						realOutputStream.write(cache, 0, index);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		//启动一个线程,负责读取真实服务器的输入数据,全部发送给客户端
		//realInputStream >> clientOutputStream
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					byte[] cache = new byte[2048];
					while(true) {
						//读取真实服务器的二进制数据
						int index = realInputStream.read(cache);
						if(index == -1) {
							return;
						}
						//全部发送给客户端
						clientOutputStream.write(cache, 0, index);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		Thread.sleep(300000);
	}

}





猜你喜欢

转载自blog.csdn.net/nimasike/article/details/62883365