consul 簡介
consul 具有以下性質:
- 服務發現:consul通過http 方式注冊服務,并且服務與服務之間相互感應。
- 服務健康監測
- key/value 存儲
- 多數據中心
consul可運行在mac windows linux 等機器上。
由于spring cloud對etcd的支持一直沒能從孵化器中出來,所以目前來說大多用戶還在使用eureka和consul,之前又因為eureka 2.0不在開源的消息,外加一些博眼球的標題黨媒體使得eureka的用戶有所減少,所以,相信在選擇spring cloud的用戶群體中,應該有不少用戶會選擇consul來做服務注冊與發現。
本文就來說一下,當我們使用spring cloud最新的finchley版 + consul 1.2.x時候最嚴重的一個坑:多實例注冊的問題。
問題解讀
問題:該問題可能在開發階段不一定會發現,但是在線上部署多實例的時候,將會發現consul中只有一個實例。
原因:造成該問題的主要原因是spring cloud consul在注冊的時候實例名(instanceid)采用了:“服務名-端口號”(即: {spring.application.name}-{server.port} )
的值,可以看到這個實例名如果不改變端口號的情況下,實例名都是相同的。如果熟悉spring cloud consul的讀者,可能會問老版本也是這個規則,怎么沒有這個問題呢?。主要是由于consul對實例唯一性的判斷標準也有改變,在老版本的consul中,對于實例名相同,但是服務地址不同,依然會認為是不同的實例。在consul 1.2.x中,服務實例名成為了集群中的唯一標識,所以,也就導致了上述問題。
解決方法
既然知道了原因,那么我們要解決它就可以有的放矢了。下面就來介紹兩個具體的解決方式:
方法一:通過配置屬性指定新的規則
下面舉個例子,通過 spring.cloud.consul.discovery.instance-id
參數直接來配置實例命名規則。這里比較粗暴的通過隨機數來一起組織實例名。當然這樣的組織方式并不好,因為隨機數依然有沖突的可能,所以您還可以用更負責的規則來進行組織實例名。
方法二:通過擴展 consulserviceregistry 來重設實例名
由于通過配置屬性的方式對于定義實例名的能力有限,所以我們希望可以用更靈活的方式來定義。這時候我們就可以通過重寫 consulserviceregistry
的 register
方法來修改。比如下面的實現:
1
2
3
4
5
6
7
8
9
10
11
12
|
public class myconsulserviceregistry extends consulserviceregistry { public myconsulserviceregistry(consulclient client, consuldiscoveryproperties properties, ttlscheduler ttlscheduler, heartbeatproperties heartbeatproperties) { super (client, properties, ttlscheduler, heartbeatproperties); } @override public void register(consulregistration reg) { reg.getservice().setid(reg.getservice().getname() + “-” + reg.getservice().getaddress() + “-” + reg.getservice().getport()); super .register(reg); } } |
上面通過拼接“服務名”-“ip地址”-“端口號”的方式,構造了一個絕對唯一的實例名,這樣就可以讓每個服務實例都能正確的注冊到consul上了。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.didispace.com/Spring-Cloud-Finchley-Consul-InstanceId/