Dubbo服务暴露之注册地址和端口

简介: 今天在SIT环境部署dubbo容器的时候遇到一个问题, 明明我的dubbo容器已经注册到zk了, 而且在dubbo控制台也能看到提供者和消费者的信息, 可就是死活调用不了, 仔细一看, 发现提供者的地址不对啊, 这明明不是我的dubbo容器对应的那天服务器地址.这是为什么呢?

今天在SIT环境部署dubbo容器的时候遇到一个问题, 明明我的dubbo容器已经注册到zk了, 而且在dubbo控制台也能看到提供者和消费者的信息, 可就是死活调用不了, 仔细一看, 发现提供者的地址不对啊, 这明明不是我的dubbo容器对应的那天服务器地址.这是为什么呢?下面我们来分析一波dubbo服务暴露注册地址和端口那一段代码.


由于我公司是做海外业务, 服务器的部署都在国外, 由于一些政策原因, 我们是访问不了的, 这时候就需要服务器端口地址进行转发, 我们的做法是在一台国内机器上面再用一层nginx做中间转发, 那么这时候问题就来了, 如果我们部署的项目地址是本机的话, 服务之间是调用不通的, 首先说明项目的服务器也是通过跳板机的形式登陆的. 我们回到文章刚开始那个问题, 其实是没错的, 确实得注册到国内作跳板机服务器的地址上, 原因是因为提供转发的那台机器没有做对我的项目地址进行nginx映射.


我们直接就定位到dubbo服务暴露url组装的方法com.alibaba.dubbo.config.ServiceConfig#doExportUrlsFor1Protocol这个方法源码太多了, 其实查找Host和Port就两行调用代码:


 private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
     // ...
     // 查找host
     String host = this.findConfigedHosts(protocolConfig, registryURLs, map);
     // 查找port
     Integer port = this.findConfigedPorts(protocolConfig, name, map);
     // ...
 }

继续往下撸:

private String findConfigedHosts(ProtocolConfig protocolConfig, List<URL> registryURLs, Map<String, String> map) {
    boolean anyhost = false;
    String hostToBind = getValueFromConfig(protocolConfig, Constants.DUBBO_IP_TO_BIND);
    if (hostToBind != null && hostToBind.length() > 0 && isInvalidLocalHost(hostToBind)) {
        throw new IllegalArgumentException("Specified invalid bind ip from property:" + Constants.DUBBO_IP_TO_BIND + ", value:" + hostToBind);
    }
    // if bind ip is not found in environment, keep looking up
    if (hostToBind == null || hostToBind.length() == 0) {
        hostToBind = protocolConfig.getHost();
        if (provider != null && (hostToBind == null || hostToBind.length() == 0)) {
            hostToBind = provider.getHost();
        }
        if (isInvalidLocalHost(hostToBind)) {
            anyhost = true;
            try {
                hostToBind = InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                logger.warn(e.getMessage(), e);
            }
            if (isInvalidLocalHost(hostToBind)) {
                if (registryURLs != null && !registryURLs.isEmpty()) {
                    for (URL registryURL : registryURLs) {
                        if (Constants.MULTICAST.equalsIgnoreCase(registryURL.getParameter("registry"))) {
                            // skip multicast registry since we cannot connect to it via Socket
                            continue;
                        }
                        try {
                            Socket socket = new Socket();
                            try {
                                SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());
                                socket.connect(addr, 1000);
                                hostToBind = socket.getLocalAddress().getHostAddress();
                                break;
                            } finally {
                                try {
                                    socket.close();
                                } catch (Throwable e) {
                                }
                            }
                        } catch (Exception e) {
                            logger.warn(e.getMessage(), e);
                        }
                    }
                }
                if (isInvalidLocalHost(hostToBind)) {
                    hostToBind = getLocalHost();
                }
            }
        }
    }
    map.put(Constants.BIND_IP_KEY, hostToBind);
    // registry ip is not used for bind ip by default
    String hostToRegistry = getValueFromConfig(protocolConfig, Constants.DUBBO_IP_TO_REGISTRY);
    if (hostToRegistry != null && hostToRegistry.length() > 0 && isInvalidLocalHost(hostToRegistry)) {
        throw new IllegalArgumentException("Specified invalid registry ip from property:" + Constants.DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
    } else if (hostToRegistry == null || hostToRegistry.length() == 0) {
        // bind ip is used as registry ip by default
        hostToRegistry = hostToBind;
    }
    map.put(Constants.ANYHOST_KEY, String.valueOf(anyhost));
    return hostToRegistry;
}


这个方法是获取地址的方法, 从源码我们也看到了这个地址分为两个, 分别是hostToBind和hostToRegistry, 这里很巧妙, 从名称看这是绑定地址和注册地址, 也就是绑定地址用于本地netty监听, 而注册地址是注册到zk上面提供给消费者调用的, 一般来说, 如果没有特殊要求, dubbo是拿本地服务器网卡0的内网ip作为地址, 绑定地址和注册地址都一样, 到是我们公司就遇到了这么个坑爹问题, 服务器在国外,如果绑定地址和监听地址都一样, 那么服务之间就无法通讯了,我们必须在注册地址上面做点手脚才行, 因此我继续往下看.


private String getValueFromConfig(ProtocolConfig protocolConfig, String key) {
    String protocolPrefix = protocolConfig.getName().toUpperCase() + "_";
    String port = ConfigUtils.getSystemProperty(protocolPrefix + key);
    if (port == null || port.length() == 0) {
        port = ConfigUtils.getSystemProperty(key);
    }
    return port;
}


该方法的作用是从系统环境变量里面获取地址信息:

/**
 * System environment -> System properties
 *
 * @param key key
 * @return value
 */
public static String getSystemProperty(String key) {
  String value = System.getenv(key);
  if (value == null || value.length() == 0) {
    value = System.getProperty(key);
  }
  return value;
}


这里System.getenv(key);方法作用是获取环境变量key中的地址值,如果环境变量没有配置对应key的值,那么就会调用System.getProperty(key);方法自动获取本地网卡的内网地址。


public class Constants {
  public static final String DUBBO_IP_TO_REGISTRY = "DUBBO_IP_TO_REGISTRY";
  public static final String DUBBO_PORT_TO_REGISTRY = "DUBBO_PORT_TO_REGISTRY";
  public static final String DUBBO_IP_TO_BIND = "DUBBO_IP_TO_BIND";
  public static final String DUBBO_PORT_TO_BIND = "DUBBO_PORT_TO_BIND";
}


以上就是我们地址和端口的绑定与注册的key值,如果我们想要将指定的地址和端口注册到zk,我们可以在本地配置环境变量:


export DUBBO_DUBBO_IP_TO_REGISTRY=指定ip
export DUBBO_PORT_TO_REGISTRY=指定端口


我将本地服务器这两个环境变量配置成跳板机的ip和端口,下面我还要将跳板机配置nginx映射。


upstream service-172.17.10.121-20040 {
    server 172.17.10.121:20040 weight=1 max_fails=2 fail_timeout=30s;
}
server {
    listen 20040;
    access_log /log/nginx/access_service-172.17.10.121-20040.log str_basic;
    error_log /log/nginx/error_service-172.17.10.121-20040.log;
    proxy_connect_timeout 2s;
    proxy_pass service-172.17.10.121-20040;
}


由于我的服务注册到zk的地址是跳板机的地址,那么其他消费者调用我提供的服务,就会访问跳板机,然后跳板机再做一层转发,就完美解决了这个问题.

相关文章
|
缓存 NoSQL 网络安全
【Azure Redis 缓存】Azure Redis服务开启了SSL(6380端口), PHP如何访问缓存呢?
【Azure Redis 缓存】Azure Redis服务开启了SSL(6380端口), PHP如何访问缓存呢?
395 0
|
缓存 负载均衡 应用服务中间件
Nginx 实现一个端口代理多个前后端服务
【10月更文挑战第19天】Nginx 的强大功能不仅限于此,它还可以与其他技术和工具相结合,为我们的应用提供更强大的支持和保障。在不断发展的互联网时代,掌握 Nginx 的使用技巧将为我们的工作和生活带来更多的便利和效益。
|
安全 网络协议 网络安全
【Azure APIM】APIM服务配置网络之后出现3443端口不通,Management Endpoint不健康状态
如果没有关联的网络安全组,则阻止所有网络流量通过子网和网络接口。
567 30
|
网络协议 Java Shell
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
1293 7
|
安全 Linux 网络安全
nmap 是一款强大的开源网络扫描工具,能检测目标的开放端口、服务类型和操作系统等信息
nmap 是一款强大的开源网络扫描工具,能检测目标的开放端口、服务类型和操作系统等信息。本文分三部分介绍 nmap:基本原理、使用方法及技巧、实际应用及案例分析。通过学习 nmap,您可以更好地了解网络拓扑和安全状况,提升网络安全管理和渗透测试能力。
1168 5
|
监控 Dubbo Java
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
这篇文章详细介绍了如何将Spring Boot与Dubbo和Zookeeper整合,并通过Dubbo管理界面监控服务注册情况。
1476 0
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
|
开发框架 .NET Linux
【Azure 应用服务】 部署到App Service for Linux 服务的Docker 镜像,如何配置监听端口呢?
【Azure 应用服务】 部署到App Service for Linux 服务的Docker 镜像,如何配置监听端口呢?
372 0
|
SQL Apache Windows
Windows服务器80端口被占用的全面解决方案
在服务管理器中启动apache2服务,即可正常使用80端口。若系统中还安装了其他微软产品如sql等,也可尝试停止其服务进行测试,但请注意,SQL通常不会使用80端口,因此一般不会受到影响。以上就是关于80端口被system占用的详细解决方法,希望对你有所帮助。
|
网络协议 安全 应用服务中间件
云服务器怎么开启被关闭的端口?手把手教你开启端口
在使用云服务器时,若发现某些服务无法访问,可能是端口被关闭。本文介绍了端口关闭的原因、检查方法及开启步骤。原因包括初始设置限制、防火墙规则和外部网络策略;可通过netstat或ss命令检查端口状态,用ufw、iptables或firewalld调整防火墙规则。最后提供了解决常见问题的建议,确保端口正常开放并可供外网访问。
2781 9
|
网络协议
端口最多只有65535个,为什么服务器能承受百万并发
服务器通过四元组(源IP、源端口、目标IP、目标端口)识别不同TCP连接,每条连接对应独立socket。数据包携带四元组信息,服务端据此查找对应socket进行通信。只要四元组任一元素不同,即视为新连接,可创建独立socket。资源充足时,单进程可支持百万级并发连接,socket与端口非一一对应。
751 10
端口最多只有65535个,为什么服务器能承受百万并发

热门文章

最新文章