new URI(zk_servers_1) 路徑包含下劃線無法獲取host的問題
spring cloud gateway使用zookeeper作為註冊中心呼叫其它服務的時候報了下面這個錯誤:
ava.lang.NullPointerException: null at io.netty.util.NetUtil.isValidIpV4Address(NetUtil.java:648) ~[netty-common-4.1.29.Final.jar:4.1.29.Final] at io.netty.util.NetUtil.createByteArrayFromIpAddressString(NetUtil.java:368) ~[netty-common-4.1.29.Final.jar:4.1.29.Final] at reactor.ipc.netty.options.InetSocketAddressUtil.attemptParsingIpString(InetSocketAddressUtil.java:132) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE] at reactor.ipc.netty.options.InetSocketAddressUtil.createForIpString(InetSocketAddressUtil.java:80) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE] at reactor.ipc.netty.options.InetSocketAddressUtil.createInetSocketAddress(InetSocketAddressUtil.java:69) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE] at reactor.ipc.netty.options.ClientOptions.createInetSocketAddress(ClientOptions.java:253) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE] at reactor.ipc.netty.http.client.HttpClientOptions.getRemoteAddress(HttpClientOptions.java:87) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE] at reactor.ipc.netty.http.client.MonoHttpClientResponse.lambda$subscribe$0(MonoHttpClientResponse.java:76) ~[reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
呼叫的地址是http://zks_servers_1 :18001,zks_servers_1是服務的hosts配置的名稱,空指標異常跟蹤發現是下面這個問題導致的:
//類HttpClientOptions public final InetSocketAddress getRemoteAddress(URI uri) { Objects.requireNonNull(uri, "uri"); boolean secure = isSecure(uri); int port = uri.getPort() != -1 ? uri.getPort() : (secure ? 443 : 80); boolean shouldResolveAddress = !this.useProxy(uri.getHost()); return this.createInetSocketAddress(uri.getHost(), port, shouldResolveAddress); }
uri.getHost()返回值是null,也就是說根據上面的呼叫地址,沒有獲取到對應的host。
uri的建立方式是:
//類MonoHttpClientResponse MonoHttpClientResponse(HttpClient parent, String url, HttpMethod method, Function<? super HttpClientRequest, ? extends Publisher<Void>> handler) { this.parent = parent; boolean isWs = Objects.equals(method, HttpClient.WS); try { this.startURI = new URI(parent.options.formatSchemeAndHost(url, isWs)); } catch (URISyntaxException var7) { throw Exceptions.bubble(var7); } this.method = isWs ? HttpMethod.GET : method; this.handler = handler; }
建立方式是呼叫URI的new URI(String)方法,知道原因之後在本地測試:
try { URI uri = new URI("http://zks_servers_1:18001/test.html"); String host = uri.getHost(); System.out.println(host); } catch (URISyntaxException e) { e.printStackTrace(); }
確實獲取不到host,檢視原始碼發現:
/** * Returns the host component of this URI. * *<li><p> A domain name consisting of one or more <i>labels</i> *separated by period characters ({@code '.'}), optionally followed by *a period character.Each label consists of <i>alphanum</i> characters *as well as hyphen characters ({@code '-'}), though hyphens never *occur as the first or last characters in a label. The rightmost *label of a domain name consisting of two or more labels, begins *with an <i>alpha</i> character. </li> * </ul> * * The host component of a URI cannot contain escaped octets, hence this * method does not perform any decoding. * * @returnThe host component of this URI, *or {@code null} if the host is undefined */ public String getHost() { return host; }
谷歌翻譯:
由一個或多個標籤組成的域名 由句點字元程式碼'.'分隔,可選地後跟 一個英文句號角色。 每個標籤由alphanum字元組成 以及連字元字元程式碼' - ',雖然連字元永遠不會 作為標籤中的第一個或最後一個字元出現。 最右邊包含最少長度最少兩個並且以英文字元開始的標籤
舉例如下:
www.baidu.com,這個域名包含三個標籤www、baidu、com;
www.baidu-zhidao.com,這個域名包含三個標籤www、baidu-zhidao、com;
這個例子就是說明每個標籤都可以使用-連線;
然後看一下,我的報錯的服務名稱zks_servers_1,這個名稱沒有以【.】分割,包含了非法字元【_】最後以單個數字結尾也不符合要求。
實際上測試發現zks-servers-1這樣也是不正確的,不知道是不是翻譯的有問題,這個結果和翻譯不太匹配。
總而言之,修改伺服器的hosts配置就行了。