简体   繁体   English

DefaultHttpClient 调用在具有公共 ip 的同一个 tomcat 中抛出连接被拒绝

[英]DefaultHttpClient call throws connection refused in the same tomcat with public ip

centos 7, tomcat 8.5. centos 7,tomcat 8.5。

a.war and rest.war are in the same tomcat . a.warrest.war在同一个 tomcat 中

a.war use following code to call rest.war : a.war使用以下代码调用rest.war

import org.apache.http.impl.client.DefaultHttpClient;

DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);

httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");  

StringEntity se = new StringEntity(json.toString());

se.setContentType("text/json");
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));

httpPost.setEntity(se);

HttpResponse response = httpClient.execute(httpPost);

however, if url of HttpPost(url) is <public ip>:80 , then httpClient.execute(httpPost) will throw connection refused .但是,如果urlHttpPost(url)<public ip>:80 ,然后httpClient.execute(httpPost)将抛出connection refused

while if url of HttpPost(url) is localhost:80 or 127.0.0.1:80 , then httpClient.execute(httpPost) is success.而如果urlHttpPost(url)localhost:80127.0.0.1:80 ,然后httpClient.execute(httpPost)是成功。

why?为什么? and how can solve this problem?以及如何解决这个问题?

Note: if I access a.war from browser with public ip like http://<public ip>/a in my computer, all operations are success.注意:如果我从浏览器访问a.war ,公网ip如http://<public ip>/a在我的电脑上,所有操作都是成功的。

my tomcat connector is:我的 tomcat 连接器是:

<Connector  
            port="80"
                protocol="HTTP/1.1"  
                connectionTimeout="60000" 
                keepAliveTimeout="15000"
                maxKeepAliveRequests="-1"
                maxThreads="1000"  
                minSpareThreads="200"  
                maxSpareThreads="300"
                minProcessors="100" 
                maxProcessors="900" 
                acceptCount="1000" 
                enableLookups="false"
                executor="tomcatThreadPool"
                maxPostSize="-1"
                compression="on"
                compressionMinSize="1024"               
                redirectPort="8443" />

my server has no domain, only has a public ip, its /etc/hosts is:我的服务器没有域,只有一个公共 IP,它的/etc/hosts是:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

updated with some commands run in server:更新了一些在服务器中运行的命令:

ss -nltp

State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:111                      *:*                   users:(("rpcbind",pid=643,fd=8))
LISTEN     0      128          *:80                       *:*                   users:(("java",pid=31986,fd=53))
LISTEN     0      128          *:22                       *:*                   users:(("sshd",pid=961,fd=3))
LISTEN     0      1      127.0.0.1:8005                     *:*                   users:(("java",pid=31986,fd=68))
LISTEN     0      128         :::111                     :::*                   users:(("rpcbind",pid=643,fd=11))
LISTEN     0      128         :::22                      :::*                   users:(("sshd",pid=961,fd=4))
LISTEN     0      80          :::3306                    :::*                   users:(("mysqld",pid=1160,fd=19))
netstat -nltp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      643/rpcbind         
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      31986/java          
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      961/sshd            
tcp        0      0 127.0.0.1:8005          0.0.0.0:*               LISTEN      31986/java          
tcp6       0      0 :::111                  :::*                    LISTEN      643/rpcbind         
tcp6       0      0 :::22                   :::*                    LISTEN      961/sshd            
tcp6       0      0 :::3306                 :::*                    LISTEN      1160/mysqld 
ifconfig

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 1396428  bytes 179342662 (171.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1396428  bytes 179342662 (171.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

p2p1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.25  netmask 255.255.255.0  broadcast 192.168.1.255
        ether f8:bc:12:a3:4f:b7  txqueuelen 1000  (Ethernet)
        RX packets 5352432  bytes 3009606926 (2.8 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2839034  bytes 559838396 (533.9 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
ip addr show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: p2p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether f8:bc:12:a3:4f:b7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.25/24 brd 192.168.1.255 scope global noprefixroute dynamic p2p1
       valid_lft 54621sec preferred_lft 54621sec
route

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    100    0        0 p2p1
192.168.1.0     0.0.0.0         255.255.255.0   U     100    0        0 p2p1
ip route

default via 192.168.1.1 dev p2p1 proto dhcp metric 100 
192.168.1.0/24 dev p2p1 proto kernel scope link src 192.168.1.25 metric 100
iptables -L -n -v --line-numbers

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

You probably have configured one of these:您可能已经配置了以下其中一项:

  1. Firewall public IP's ports, so that nothing goes through.防火墙公共 IP 的端口,所以没有任何东西通过。
  2. Tomcat may bind a specific IP, eg localhost (see Connector elements in tomcat's server.xml) Tomcat 可能会绑定一个特定的 IP,例如 localhost(请参阅 tomcat 的 server.xml 中的连接器元素)
  3. Apache httpd, nginx or another reverse proxy might handle various virtual host names, and also they might handle localhost different than the public IP Apache httpd、nginx 或其他反向代理可能会处理各种虚拟主机名,而且它们可能会处理与公共 IP 不同的 localhost
  4. Port Forwarding - if you only forward localhost:80 to localhost:8080 (tomcat's default port), you might not have anything on publicip:80 that forwards that traffic as well.端口转发 - 如果您只将 localhost:80 转发到 localhost:8080(tomcat 的默认端口),则在 publicip:80 上可能没有任何转发该流量的内容。

Edit after your comment:在您的评论后编辑:

  1. incoming traffic seems to be fine, but outgoing you do have those problems.传入流量似乎没问题,但传出流量确实存在这些问题。 Adding from @stringy05's comment: Check if the IP in question is routable from your server: You're connecting to whatever IP from that server , so use another means to create an outgoing connection, eg curl .从@stringy05 的评论中添加:检查有问题的 IP 是否可以从您的服务器路由:您正在连接到来自该服务器的任何 IP,因此请使用另一种方式创建传出连接,例如curl

Explanation for #1 & #3: If you connect to an external http server, it will handle the request differently based on the hostname used. #1 & #3 的解释:如果您连接到外部 http 服务器,它将根据使用的主机名以不同方式处理请求。 It might well be that the IP "hostname" is blocked, either by a high level firewall, or just handled differently than the URL by the webserver itself.很可能是 IP“主机名”被高级防火墙阻止,或者只是网络服务器本身对 URL 的处理方式不同。 In most cases you can check this by connecting to the webserver in question from any other system, eg your own browser.在大多数情况下,您可以通过从任何其他系统(例如您自己的浏览器)连接到相关网络服务器来检查这一点。

Try putting your public domain names into the local /etc/hosts file of your server like this: 127.0.0.1 localhost YOURPUBLIC.DOMAIN.NAME尝试将您的公共域名放入服务器的本地 /etc/hosts 文件中,如下所示: 127.0.0.1 localhost YOURPUBLIC.DOMAIN.NAME

This way your Java code does not need to try to use the external IP-adres but instead connects directly to Tomcat.这样您的 Java 代码就不需要尝试使用外部 IP 地址,而是直接连接到 Tomcat。

Good luck!祝你好运!

If Tomcat is listening (bound) to your public IP-adres it should work, but maybe your public IP-adres belongs to some other device, like a SOHO router, than your problem is similar to this:如果 Tomcat 正在侦听(绑定)到您的公共 IP 地址,它应该可以工作,但是您的公共 IP 地址可能属于某个其他设备,例如 SOHO 路由器,那么您的问题与此类似:

https://superuser.com/questions/208710/public-ip-address-answered-by-router-not-internal-web-server-with-port-forwardi https://superuser.com/questions/208710/public-ip-address-answered-by-router-not-internal-web-server-with-port-forwardi

But without an DNS name you cannot simply add a line to /etc/hosts but you can add the public IP-adres to one of your Network Interfaces Cards (NIC) like lo (loopback), eth0, etc. as described in one of these articles:但是如果没有 DNS 名称,您不能简单地向 /etc/hosts 添加一行,但您可以将公共 IP 地址添加到您的网络接口卡 (NIC) 之一,如 lo(环回)、eth0 等,如以下之一所述这些文章:

Eg with public IP-address 1.2.3.4 you would need (which will only be effective until next reboot and worst case might interfere with your ability to connect to the server with eg SSH!):例如,您需要使用公共 IP 地址 1.2.3.4(这只会在下次重新启动之前有效,最坏的情况可能会干扰您使用例如 SSH 连接到服务器的能力!):

sudo ip addr add 1.2.3.4/32 dev lo

It may be useful to have the output of these commands to better understand your setup, feel free to share it in your question, with consistently anonymized public IP-adres):让这些命令的输出更好地理解您的设置可能很有用,请随时在您的问题中分享它,并使用始终匿名的公共 IP 地址):

Either one of these (ss = socket stat, newer replacement for good old netstat):其中之一(ss = socket stat,旧的netstat的新替代品):

  1. ss -nltp ss -nltp
  2. netstat -nltp netstat -nltp

And one of these:其中之一:

  1. ifconfig如果配置
  2. ip addr show ip地址显示

And last but not least either one of these:最后但并非最不重要的其中一项:

  1. route路线
  2. ip route路由

I don't expect that we need to know your firewall config, but if you use it, it may be interesting to keep an eye on it while you are at it:我不希望我们需要知道您的防火墙配置,但是如果您使用它,那么在您使用它时留意它可能会很有趣:

iptables -L -n -v --line-numbers iptables -L -n -v --line-numbers

I think the curl timeout explains it - you have a firewall rule somewhere that is stopping the server accessing the public IP address.我认为 curl 超时解释了它 - 您在某处有一个防火墙规则阻止服务器访问公共 IP 地址。

If there's no reason the service can't be accessed using localhost or the local hostname then do that but if you need to call the service via a public IP then it's a matter of working out why the request gets a timeout from the server.如果没有理由无法使用 localhost 或本地主机名访问该服务,那么请执行此操作,但如果您需要通过公共 IP 调用该服务,则需要弄清楚请求从服务器超时的原因。

Some usual suspects:一些常见的嫌疑人:

  • The server might not actually have internet access - can you curl https://www.google.com ?服务器实际上可能无法访问互联网 - 您可以curl https://www.google.com吗?
  • There might be a forward proxy required - a sys admin will know this sort of thing可能需要转发代理 - 系统管理员会知道这种事情
  • There might be IP whitelisting on some infra around your server - think AWS security groups, load balancer IP whitelists that sort of thing.您的服务器周围的某些基础设施上可能存在 IP 白名单 - 想想 AWS 安全组、负载均衡器 IP 白名单之类的事情。 To fix that you need to know the public IP of your server curl https://canihazip.com/s and get that added to the whitelist要解决此问题,您需要知道服务器curl https://canihazip.com/s的公共 IP 并将其添加到白名单

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM