问题描述:
两个腾讯云服务器,在B服务器的服务向A服务器的nacos注册时,用的内网ip,因为俩服务器不在同一个网段,造成B服务器注册上nacos后无法访问服务的情况。又不想每次运行输入ip端口,也不想在每个服务器都放sh脚本,所以有了这个方案
百度一大通后,发现其他博主这个方案很野,我很喜欢!又稍微改良了一下。可以区分本地和服务器,本地运行注册还是要用内网ip的嘛
关于将服务注册上nacos的过程(这里是原理可以跳过)
如果没有配置ip配置选项 走的是这些配置
@Bean
@ConditionalOnMissingBean
public SimpleDiscoveryProperties simpleDiscoveryProperties(@Value("${spring.application.name:application}") String serviceId) {
this.simple.getLocal().setServiceId(serviceId);
this.simple.getLocal().setUri(URI.create("http://" + this.inet.findFirstNonLoopbackHostInfo().getHostname() + ":" + this.findPort()));
return this.simple;
}
其中 findFirstNonLoopbackHostInfo()
public HostInfo findFirstNonLoopbackHostInfo() {
InetAddress address = this.findFirstNonLoopbackAddress();
if (address != null) {
return this.convertAddress(address);
} else {
HostInfo hostInfo = new HostInfo();
hostInfo.setHostname(this.properties.getDefaultHostname());
hostInfo.setIpAddress(this.properties.getDefaultIpAddress());
return hostInfo;
}
}
所以,想要注册公网ip,只能配置网卡或者spring.cloud.nacos.discovery.ip=xxx.xxx.xxx.xxx
野路子,无需配置公网ip或者适配网卡
配置nginx,获取部署服务的服务器的公网ip。
在主服务器的nginx上配置
location = /getIp{
return 200 “$remote_addr”;
}
这里有个坑,如果你挂了cdn,请不要用域名去请求,用ip,不然你会获取到cdn的ip。或者你改成取cdn转发的真实ip判断这个公网地址是本地开发环境or线上运行环境,并且如果是线上环境把公网ip更新到配置中去
public class AfterConfigListener implements SmartApplicationListener, Ordered { @Override public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) { return (ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(aClass) || ApplicationPreparedEvent.class.isAssignableFrom(aClass)); } @Override public int getOrder() { return (ConfigFileApplicationListener.DEFAULT_ORDER + 1); } @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { // 判断服务ip+端口是否通,不通则大概率是本地,不设置公网ip String ip = null; try { ip = InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { throw new RuntimeException(e); } // 设置端口,服务器linux设置22,windows设置3389 int port = 22; int timeOut = 3000; if (testIpAndPort(ip, port, timeOut)) { // 可以访问通,证明是公网ip,设置注册nacos为公网获取到的ip RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response = restTemplate.getForEntity("http://域名 或者 服务器ip/getIp", String.class); String currenIp = response.getBody(); if (applicationEvent instanceof ApplicationEnvironmentPreparedEvent) { System.setProperty("spring.cloud.nacos.discovery.ip", currenIp); } } } /** * 测试ip及端口连通性 * @param host * @param port * @param timeout * @return boolean */ public static boolean testIpAndPort(String host, int port, int timeout) { Socket s = new Socket(); boolean status = false; try { s.connect(new InetSocketAddress(host, port), timeout); System.out.println("ip及端口访问正常"); status = true; } catch (IOException e) { System.out.println(host + ":" + port + "无法访问!"); } finally { try { s.close(); } catch (IOException ex) { System.out.println("关闭socket异常" + ex); } } return status; } }
因为本地大概率你的3389和22端口是不开放的。所以这里如果你的开发环境很特殊请使用其他方案:比如在服务器运行一个nginx什么的都放,打开80端口。访问的时候访问80端口
在启动类的main方法中注册这个listener
SpringApplication springApplication = new SpringApplication(xxxxApplication.class); springApplication.addListeners(new AfterConfigListener()); springApplication.run(args);
这时候你到nacos控制台上就能发现,ip已经是公网ip了
两个服务之间就不用在同个局域网内了
评论区