最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

利用Java獲取被nginx代理的emqx客戶端真實ip

 更新時間:2025年08月22日 08:30:48   作者:BothSavage  
使用nginx作為負(fù)載均衡(Load Balancing)的時候,發(fā)現(xiàn)真實ip無法獲取,所以本文小編就來和大家介紹一下如何使用Java獲取被nginx代理的emqx客戶端真實ip地址吧

契機(jī)

使用nginx作為負(fù)載均衡(Load Balancing)的時候,發(fā)現(xiàn)真實ip無法獲取。幾經(jīng)折騰終于拿到真實ip,又發(fā)現(xiàn)被代理的端口又無法使用非代理模式連接,由于之前暴露的docker端口有限,從中部分取巧終于撥開云霧見光明,再結(jié)合Java客戶端獲取真實ip一氣呵成。

EMQX配置

#docker部署
#18083為管理頁面端口,1883為默認(rèn)mqtt端口,8883為默認(rèn)mqtts端口
#如果還沒有新建emqx容器,建議多暴露端口,具體原因見下文
docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx:5.7.2
  • 進(jìn)入emqx管理頁面,新建proxy_tcp監(jiān)聽器,類型為tcp,端口為8883
  • 然后關(guān)閉之前ssl-8883監(jiān)聽
  • 借用端口是因為docker暴露到宿主機(jī)的端口不夠了,一旦設(shè)置比如proxy_tcp監(jiān)聽器的8883代理監(jiān)聽后,客戶端就只能通過nginx代理連接這個8883端口了,直接連接8883就不行了

#獲取emqx的容器id,假如為1111
docker ps | grep emqx 

#將配置文件拷貝出來
docker cp 1111:/opt/emqx/etc/emqx.conf .

#修改,添加下面項目
vim emqx.conf 

#打開proxy_tcp的代理監(jiān)聽
listeners.tcp.proxy_tcp {
  proxy_protocol = true
}

#關(guān)閉default的代理,默認(rèn)是關(guān)閉的
#但是一旦打開過,就要手動設(shè)置為false
listeners.tcp.default {
  proxy_protocol = false
}

#放置回去
docker cp ./emqx.conf 1111:/opt/emqx/etc/

#重啟容器
docker restart 1111

此時

  • 直接使用客戶端設(shè)備連接8883端口失敗,無論mqtt/mqtts協(xié)議
  • 1883端口可以使用mqtt協(xié)議可以正常連接
  • emqx不存放證書,ssl認(rèn)證是一個耗時的操作,丟到nginx去搞

nginx配置

#nginx安裝 - 略

#nginx安裝模塊
sudo yum install nginx-mod-stream

#修改nginx配置文件
vim /etc/nginx/nginx.conf

#配置文件如下
#192.168.0.1為emqx所在服務(wù)器,與nginx不在一個服務(wù)器
#監(jiān)聽1883為mqtt
#監(jiān)聽8883為mqtts
stream {
    upstream stream_backend {
      zone tcp_servers 64k;
      hash $remote_addr;
      server 192.168.0.1:1883 max_fails=2 fail_timeout=30s;
    }

    server {
        listen 1883;
        proxy_pass stream_backend;
        proxy_buffer_size 4k;
    }

    upstream stream_backend_ssl {
      zone tcp_servers 64k;
      hash $remote_addr;
      server 192.168.0.1:8883 max_fails=2 fail_timeout=30s;
    }

    server {
        listen 8883 ssl;
        proxy_protocol on;        
        proxy_pass stream_backend_ssl;
        proxy_buffer_size 4k;
        ssl_handshake_timeout 15s;
        ssl_certificate     /etc/nginx/cert/_.xx.pem;
        ssl_certificate_key /etc/nginx/cert/_.xx.key;
    }

}

#重啟nginx
sudo systemctl restart nginx

此時

  • 8883為mqtts端口,鏈接mqtts,emqx控制臺可以看到真實ip
  • 1883為mqtt端口,鏈接mqtt,emqx控制臺看不到真實ip
  • 理論上業(yè)務(wù)只暴露mqtts端口到外網(wǎng),mqtt為內(nèi)部調(diào)試方便抓包用的

腳本獲取

設(shè)置api密鑰,保存下username和pasword

#!/bin/bash

# Check if both host and password arguments are provided
if [ $# -lt 2 ]; then
  echo "Usage: $0 <host> <password>"
  exit 1
fi

# Define host, username, and password
HOST="$1"
USERNAME="username"
PASSWORD="$2"

# Encode username and password in Base64
AUTH=$(echo -n "$USERNAME:$PASSWORD" | base64)

# Create the curl command
curl -H "Authorization: Basic $AUTH" "http://$HOST:18083/api/v5/clients?like_username=server"

#運(yùn)行
chmod +x ./emqx_curl.sh
./emqx_curl.sh localhost your_password_here

Java獲取

service

package com.bothsavage.common.mqtt.service;

import com.alibaba.fastjson.JSONObject;
import com.bothsavage.common.mqtt.config.interceptor.EmqxAuthInterceptor;
import com.bothsavage.common.mqtt.entity.dto.ClientInfoDTO;
import com.bothsavage.common.mqtt.entity.dto.EmqxRespDTO;

import feign.Headers;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * Emqx請求
 *
 * @author bothSavage
 */
@FeignClient(name = "emqxRmiService", url = "${emqx.rmi.url:http://127.0.0.1:18083/}",configuration = EmqxAuthInterceptor.class)
public interface EmqxRmiService {

    /**
     * 獲取客戶端信息
     *
     * @param clientId 客戶端id
     * @return -
     */
    @GetMapping(value = "/api/v5/clients/{id}")
    @Headers(value = {"Content-Type=application/json;charset=UTF-8", "Accept=application/json"})
    ClientInfoDTO getClientById(@PathVariable("id") String clientId);

    /**
     * 查詢客戶端信息
     *
     * @param likeUserName 客戶端名稱
     * @return -
     */
    @GetMapping(value = "/api/v5/clients")
    @Headers(value = {"Content-Type=application/json;charset=UTF-8", "Accept=application/json"})
    EmqxRespDTO<ClientInfoDTO> getClientsByUserName(@RequestParam("like_username") String likeUserName);

}

auth

package com.bothsavage.common.mqtt.config.interceptor;

import feign.RequestInterceptor;
import feign.RequestTemplate;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import java.util.Base64;

/**
 * Emqx請求權(quán)限攔截
 *
 * @author bothSavage
 */
@Configuration
public class EmqxAuthInterceptor implements RequestInterceptor {

    @Value("${emqx.rmi.username:x}")
    private String username;

    @Value("${emqx.rmi.password:x}")
    private String password;

    @Override
    public void apply(RequestTemplate template) {
        String auth = username + ":" + password;
        String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
        template.header("Authorization", "Basic " + encodedAuth);
    }

}

dto

package com.bothsavage.common.mqtt.entity.dto;

import com.alibaba.fastjson.annotation.JSONField;

import lombok.Data;

/**
 * dto
 *
 * @author bothSavage
 */
@Data
public class ClientInfoDTO {

    @JSONField(name = "clientid")
    private String clientid;

    @JSONField(name = "mqueue_len")
    private Integer mqueueLen;

    @JSONField(name = "reductions")
    private Integer reductions;

    @JSONField(name = "keepalive")
    private Integer keepalive;

    @JSONField(name = "listener")
    private String listener;

    @JSONField(name = "proto_ver")
    private Integer protoVer;

    @JSONField(name = "recv_msg.dropped.await_pubrel_timeout")
    private Integer recvMsgDroppedAwaitPubrelTimeout;

    @JSONField(name = "send_msg.dropped.expired")
    private Integer sendMsgDroppedExpired;

    @JSONField(name = "mountpoint")
    private Object mountpoint;

    @JSONField(name = "mailbox_len")
    private Integer mailboxLen;

    @JSONField(name = "send_msg")
    private Integer sendMsg;

    @JSONField(name = "zone")
    private String zone;

    @JSONField(name = "subscriptions_cnt")
    private Integer subscriptionsCnt;

    @JSONField(name = "heap_size")
    private Integer heapSize;

    @JSONField(name = "recv_msg")
    private Integer recvMsg;

    @JSONField(name = "recv_cnt")
    private Integer recvCnt;

    @JSONField(name = "send_msg.dropped.too_large")
    private Integer sendMsgDroppedTooLarge;

    @JSONField(name = "awaiting_rel_cnt")
    private Integer awaitingRelCnt;

    @JSONField(name = "subscriptions_max")
    private String subscriptionsMax;

    @JSONField(name = "recv_msg.qos0")
    private Integer recvMsgQos0;

    @JSONField(name = "recv_msg.qos1")
    private Integer recvMsgQos1;

    @JSONField(name = "recv_msg.qos2")
    private Integer recvMsgQos2;

    @JSONField(name = "node")
    private String node;

    @JSONField(name = "inflight_max")
    private Integer inflightMax;

    @JSONField(name = "port")
    private Integer port;

    @JSONField(name = "recv_pkt")
    private Integer recvPkt;

    @JSONField(name = "send_oct")
    private Integer sendOct;

    @JSONField(name = "inflight_cnt")
    private Integer inflightCnt;

    @JSONField(name = "awaiting_rel_max")
    private String awaitingRelMax;

    @JSONField(name = "is_persistent")
    private Boolean isPersistent;

    @JSONField(name = "send_msg.dropped")
    private Integer sendMsgDropped;

    @JSONField(name = "recv_msg.dropped")
    private Integer recvMsgDropped;

    @JSONField(name = "clean_start")
    private Boolean cleanStart;

    @JSONField(name = "send_msg.qos0")
    private Integer sendMsgQos0;

    @JSONField(name = "created_at")
    private String createdAt;

    @JSONField(name = "connected_at")
    private String connectedAt;

    @JSONField(name = "enable_authn")
    private Boolean enableAuthn;

    @JSONField(name = "mqueue_dropped")
    private Integer mqueueDropped;

    @JSONField(name = "is_bridge")
    private Boolean isBridge;

    @JSONField(name = "send_msg.dropped.queue_full")
    private Integer sendMsgDroppedQueueFull;

    @JSONField(name = "proto_name")
    private String protoName;

    @JSONField(name = "ip_address")
    private String ipAddress;

    @JSONField(name = "send_cnt")
    private Integer sendCnt;

    @JSONField(name = "connected")
    private Boolean connected;

    @JSONField(name = "recv_oct")
    private Integer recvOct;

    @JSONField(name = "mqueue_max")
    private Integer mqueueMax;

    @JSONField(name = "send_msg.qos2")
    private Integer sendMsgQos2;

    @JSONField(name = "send_msg.qos1")
    private Integer sendMsgQos1;

    @JSONField(name = "expiry_interval")
    private Integer expiryInterval;

    @JSONField(name = "send_pkt")
    private Integer sendPkt;

    @JSONField(name = "username")
    private String username;

}

test

clientIp = emqxRmiService.getClientById("clientId").getIpAddress();

總結(jié)

  • 路線清晰,只是操作起來稍微麻煩點
  • 注意:emqx打開了代理的訪問的監(jiān)聽器,只能通過nginx來中轉(zhuǎn),無法直接鏈接了
  • 當(dāng)前只用了一個emqx,沒有做集群
  • docker端口 暴露需要前期規(guī)劃好,要不然特別麻煩

到此這篇關(guān)于利用Java獲取被nginx代理的emqx客戶端真實ip的文章就介紹到這了,更多相關(guān)Java獲取客戶端ip內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 阿里云發(fā)布 Spring Boot 新腳手架工程

    阿里云發(fā)布 Spring Boot 新腳手架工程

    這篇文章主要介紹了阿里云發(fā)布 Spring Boot 新腳手架的相關(guān)資料,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,可以參考下
    2020-04-04
  • Java設(shè)計模式之策略模式詳細(xì)解析

    Java設(shè)計模式之策略模式詳細(xì)解析

    這篇文章主要介紹了Java設(shè)計模式之策略模式詳細(xì)解析,策略模式中,定義算法族,分別封裝起來,讓他們之間可以相互轉(zhuǎn)化,此模式讓算法的變化獨(dú)立于使用算法的客戶,需要的朋友可以參考下
    2023-11-11
  • SpringBoot項目docker分層鏡像構(gòu)建案例

    SpringBoot項目docker分層鏡像構(gòu)建案例

    本文主要介紹Spring Boot項目的docker鏡像分層構(gòu)建,通過將外部依賴、內(nèi)部依賴和應(yīng)用程序代碼分離,可以利用Docker的緩存機(jī)制,加快構(gòu)建速度和測試環(huán)境鏡像拉取速度,感興趣的可以了解一下
    2026-02-02
  • SpringBoot 如何從配置文件讀取值到對象中

    SpringBoot 如何從配置文件讀取值到對象中

    這篇文章主要介紹了SpringBoot 如何從配置文件讀取值到對象中,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java實現(xiàn)Redisson看門狗機(jī)制

    java實現(xiàn)Redisson看門狗機(jī)制

    redission看門狗機(jī)制是解決分布式鎖的續(xù)約問題,本文就來詳細(xì)的介紹一下java實現(xiàn)Redisson看門狗機(jī)制,具有一定的參考價值,感興趣的可以了解一下
    2024-09-09
  • 詳解Spring注解--@Autowired、@Resource和@Service

    詳解Spring注解--@Autowired、@Resource和@Service

    本篇文章主要介紹最重要的三個Spring注解,也就是@Autowired、@Resource和@Service,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-05-05
  • MybatisPlus如何自動生成映射文件

    MybatisPlus如何自動生成映射文件

    這篇文章主要介紹了MybatisPlus如何自動生成映射文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Mybatis延遲加載原理和延遲加載配置詳解

    Mybatis延遲加載原理和延遲加載配置詳解

    這篇文章主要介紹了Mybatis延遲加載原理和延遲加載配置詳解,MyBatis中的延遲加載,也稱為懶加載,是指在進(jìn)行表的關(guān)聯(lián)查詢時,按照設(shè)置延遲規(guī)則推遲對關(guān)聯(lián)對象的select查詢,需要的朋友可以參考下
    2023-10-10
  • Java設(shè)計模式之代理模式詳細(xì)解讀

    Java設(shè)計模式之代理模式詳細(xì)解讀

    這篇文章主要介紹了Java設(shè)計模式的代理模式,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)Java設(shè)計模式的小伙伴有很大的幫助,感興趣的小伙伴可以參考一下
    2021-08-08
  • 手把手教你搭建SpringMVC框架——最小化配置

    手把手教你搭建SpringMVC框架——最小化配置

    這篇文章主要介紹了手把手教你搭建SpringMVC框架——最小化配置,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-02-02

最新評論

连州市| 大城县| 德格县| 石泉县| 伊吾县| 中江县| 什邡市| 乌鲁木齐县| 独山县| 广安市| 杭锦后旗| 合作市| 独山县| 关岭| 定远县| 类乌齐县| 吴旗县| 阿鲁科尔沁旗| 兴宁市| 开平市| 彭州市| 天峻县| 山东省| 天镇县| 惠安县| 自贡市| 洛扎县| 西吉县| 太仆寺旗| 菏泽市| 太湖县| 孝感市| 高平市| 大埔区| 钦州市| 孝感市| 新绛县| 洪洞县| 来安县| 永川市| 石林|