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

来源:互联网 发布:中国gdp 知乎 编辑:程序博客网 时间:2024/05/29 15:16

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  >> realOutputStreamnew Thread(new Runnable() {@Overridepublic 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 >> clientOutputStreamnew Thread(new Runnable() {@Overridepublic 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);}}





0 0