咱們有了兩個服務。服務A的IP地址是192.168.0.1,端口9001,服務B的IP地址192.168.0.2,端口9002。咱們的客戶端須要調用服務A和服務B,咱們只須要在配置文件中寫上服務A和服務B的IP地址便可。html
此時,服務A的服務器負載有點高,咱們須要臨時增長服務A的實例,IP192.168.0.3,端口9001。可是咱們的客戶端要怎麼才能調用新的實例?node
常規來講,咱們能夠有如下幾種方法:nginx
網絡代理方式
若是是http方式通訊的服務,能夠增長一個nginx作反向代理,轉發到兩個服務A的實例上。
若是是RPC服務則能夠增長一個LVS或HAProxy或者ESB之類的網絡代理,客戶端配置網絡代理地址。
服務B咱們再來一套同樣的配置,這時候又來了服務C、服務D、服務E...,好吧咱們好還要再多維護一樣多的網絡代理。此外,全部的服務調用服務調用都必須通過網絡代理,咱們還必須保證代理的高可用。最後,陷入運維災難。web
DNS方式
給服務A配置一個域名,而後經過配置兩個A記錄分別指向兩個服務A的實例,客戶端只要配置服務A的域名便可。
這種方式也存在問題,首先DNS沒有辦法管理端口,咱們的端口仍是隻能寫在每一個客戶端的配置文件中。此外DNS輪詢負載均衡能力太弱,可能會致使客戶端負載的不均衡。redis
如今有了服務發現和註冊機制,咱們能夠更合理的解決這個問題。算法
服務發現和註冊,參考字面意思很容易理解,其核心部分能夠理解爲一個服務註冊表。服務啓動時,將本身的信息註冊到註冊表中。註冊表須要每必定時間訪問下已經註冊的服務,將沒有響應的服務從註冊表中刪除。最終讓客戶端拿到正常運行的服務地址。spring
此時,咱們的服務註冊表必須具有分佈式、高可用、強一致性等特色。api
目前,業界開源的服務發現和註冊產品有不少,比較流行的主要有:ZooKeeper,Etcd,Consul,Eureka等。服務器
下面介紹下今天的主角,Consul。網絡
Consul是一個服務發現和註冊的工具,其具備分佈式、高擴展性能特色。
Consul主要包含以下功能:
上圖是官網提供的一個事例系統圖,圖中的Server是consul服務端高可用集羣,Client是consul客戶端。consul客戶端不保存數據,客戶端將接收到的請求轉發給響應的Server端。Server之間經過局域網或廣域網通訊實現數據一致性。每一個Server或Client都是一個consul agent。Consul集羣間使用了GOSSIP協議通訊和raft一致性算法。
使用Consul也很是簡單,基本能夠作到開箱即用。
下載應用後能夠經過簡單的腳本啓動服務端和客戶端:
$ consul usage: consul [--version] [--help] <command> [<args>] Available commands are: agent Runs a Consul agent configtest Validate config file event Fire a new event exec Executes a command on Consul nodes force-leave Forces a member of the cluster to enter the "left" state info Provides debugging information for operators join Tell Consul agent to join cluster keygen Generates a new encryption key keyring Manages gossip layer encryption keys kv Interact with the key-value store leave Gracefully leaves the Consul cluster and shuts down lock Execute a command holding a lock maint Controls node or service maintenance mode members Lists the members of a Consul cluster monitor Stream logs from a Consul agent operator Provides cluster-level tools for Consul operators reload Triggers the agent to reload configuration files rtt Estimates network round trip time between nodes version Prints the Consul version watch Watch for changes in Consul
運行consul agent
加上相關的參數,就能夠啓動一個consul server 或者 client。
接着,咱們能夠經過http api註冊服務,向/v1/catalog/register發送PUT動做的JSON報文:
{ "Datacenter": "dc1", "Node": "foobar", "Address": "192.168.10.10", "Service": { //註冊的服務信息 "ID": "redis1", "Service": "redis", "Tags": [ "primary", "v1" ], "Address": "127.0.0.1", "Port": 8000 }, "Check": { //註冊健康檢查 "Node": "foobar", "CheckID": "service:redis1", "Name": "Redis health check", "Notes": "Script based health check", "Status": "passing", "ServiceID": "redis1" } }
註冊後,咱們能夠在consul自帶的WEB UI中看到剛剛註冊的服務:
若是你的服務正好使用spring boot構建,不妨試試Spring Cloud Consul。
Spring Cloud Consul經過幾個簡單的註解,就能夠集成諸多consul功能,讓你更方便的治理你的服務。
@SpringBootApplication @EnableDiscoveryClient //只要添加這個註解便可向配置號的consul註冊服務 @RestController public class Application { @RequestMapping("/") public String home() { return "Hello world"; } public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
同時咱們能夠配合spring boot actuator來註冊監控檢查:
spring: cloud: consul: discovery: healthCheckPath: ${management.contextPath}/health healthCheckInterval: 15s
Spring Cloud支持 Feign 或者 Spring RestTemplate 經過服務發現來調用服務,也可使用org.springframework.cloud.client.discovery.DiscoveryClient:
@Autowired //注入一個DiscoveryClient private DiscoveryClient discoveryClient; public String serviceUrl() { List<ServiceInstance> list = discoveryClient.getInstances("STORES"); if (list != null && list.size() > 0 ) { return list.get(0).getUri(); } return null; }
consul除了能夠用做服務治理的工具,還能夠利用其KV存儲能力,實現分佈式服務配置或分佈式鎖等功能。各位感興趣的童鞋能夠去consul官網,學習更多的內容。
最後,都看到這了,就順手點個贊吧~~~
參考資料: https://www.nginx.com/blog/service-discovery-in-a-microservices-architecture/ https://highops.com/insights/service-discovery-6-questions-to-4-experts/ https://www.consul.io/ http://cloud.spring.io/spring-cloud-consul/