您现在的位置是:首页 > 正文

TCP通信转HTTP桥接器(转发zabbix数据为例)

2024-02-01 02:02:55阅读 2

需求场景

由于项目需要我们有大量服务器部署在互联网上,需要zabbix_agent监控服务器数据,但是用于接收监控数据的zabbix_server对访问安全要求较为严格。zabbix_server部署在专网内,仅接收来自CDN的HTTP请求,同时对Host访问地址有大量限制。

zabbix默认的通信协议为基于TCP协议的自定义通信协议详见:zabbix sender协议的研究,因此必然无法通过CDN,防火墙最终到达zabbix_server。因此我们需要将zabbix_agent与server之间的通信通过HTTP桥接起来。

将原TCP通信的C/S结构软件的数据经由HTTP转发。即:

SERVER <-TCP-> CLIENT

转为:

SERVER <-TCP-> BRIDGE <- HTTP -> BRIDGE <- TCP -> CLIENT

由此实现了C/S间穿过CDN,防火墙等复杂网络设备下的通信。

需要注意的是,由于客户端服务器无固定IP,这里的zabbix_agent使用active模式主动往server汇报数据,并接受server的响应。

当然,本文程序由于不涉及处理TCP数据,因此只要是基于TCP的C/S结构软件,均可以使用本文的方法实现HTTP桥接。

流程与程序设计

数据传输流程

分别在客户端与服务端开启桥接器服务,在客户端桥接器启用TCP监听,在服务端桥接器启用HTTP监听。

  • 1、zabbix_agent 启动,通过TCP发起check active查询,被客户端桥接器监听到。
  • 2、客户端桥接器将TCP数据(byte[])经过Base64编码,通过HTTP方式发送到服务端桥接器。(此时TCP与HTTP连接均未断开)
  • 3、服务端桥接器接收到HTTP请求,解析Base64编码的数据后将其恢复成原始byte[],通过TCP方式发送到zabbix_server,并接受响应。将响应数据经过Base64编码后通过HTTP返回给客户端。
  • 4、客户端获得HTTP 200响应后,从中解析响应字符串,通过Base64恢复为原zabbix_server响应的byte[],并通过TCP发送给zabbix_agent,断开socket。(zabbix_agent 规定一次TCP通信只允许发送一条数据,所以此处断开SOCKET是正确的)
  • 一次桥接通信完成。

程序设计

支持两种启动模式

桥接器功能简单,无需分别实现TCP,HTTP两套程序。只要封装在一个程序里,支持两种启动模式即可。

// 启动服务端HTTP服务
java -jar tcp2httpbridge.jar HTTP
// 启动客户端TCP服务
java -jar tcp2httpbridge.jar TCP

主程序入口如下

public static void main(String[] args) {

        if(args.length<1){
            // 没有指定启动方式
            System.out.println("USAGE : java -jar tcp2httpbridge.jar [HTTP/TCP]");
        } else if(args[0].toUpperCase().equals(StaticValue.APPTYPE.HTTP)){
            // 以HTTP方式启动
            HTTPServer.start();
        } else if(args[0].toUpperCase().equals(StaticValue.APPTYPE.TCP)){
            // 以TCP方式启动
            TCPServer.startServer(
                Integer.parseInt(ConfigLoader.getInstance().getValue("local.tcp.port")), 
                TCPServer.class);
        } else {
            //参数不合法
            System.out.println("USAGE : java -jar tcp2httpbridge.jar [HTTP/TCP]");
        }
    }

程序参数支持配置

将程序常用参数写入app.properties文件中,实现程序的灵活配置。
本示例提取的参数有:

网站文章