這是一個(gè)從零開(kāi)始的springcloud的系列教程,如果你從中間開(kāi)始看,可能會(huì)看不明白.請(qǐng)進(jìn)入我的系列教程開(kāi)始從頭開(kāi)始學(xué)習(xí).spring-cloud教程
服務(wù)發(fā)現(xiàn)
在框架中,服務(wù)之間的相互調(diào)用不再通過(guò)傳統(tǒng)的ip地址來(lái)尋找到對(duì)方.而是通過(guò)服務(wù)名稱(chēng),然后向服務(wù)注冊(cè)中心獲取服務(wù)ip地址,然后再進(jìn)行調(diào)用,達(dá)到動(dòng)態(tài)化增加服務(wù)和自動(dòng)化發(fā)現(xiàn)服務(wù)的目的.
傳統(tǒng)方式調(diào)用:
服務(wù)A -> http請(qǐng)求(服務(wù)B的ip地址192.168.0.100:8001)->服務(wù)B收到
傳統(tǒng)方式調(diào)用依賴(lài)靜態(tài)配置,服務(wù)A有個(gè)配置文件,里面配置了服務(wù)B的ip地址
治理框架下調(diào)用:
服務(wù)A -> 向注冊(cè)中心咨詢(xún)服務(wù)B的地址或從緩存中獲取 -> 得到地址后發(fā)起http請(qǐng)求(服務(wù)B集群狀況下,是一組地址,根據(jù)輪詢(xún)策略來(lái)決定使用哪個(gè)ip地址) -> 服務(wù)B收到
在使用服務(wù)治理框架來(lái)發(fā)現(xiàn)服務(wù),使用者不再關(guān)心服務(wù)B的具體位置,只需要關(guān)心我想使用服務(wù)名稱(chēng)叫B的服務(wù),哪怕服務(wù)B的ip變更也不影響服務(wù)A的調(diào)用.大大降低了維護(hù)成本.
發(fā)現(xiàn)服務(wù)
之前我們已經(jīng)掌握了一個(gè)微服務(wù)如何將自己注冊(cè)到服務(wù)治理中心(eureka-sevrer),將eureka-client2工程進(jìn)行啟動(dòng)注冊(cè),服務(wù)名稱(chēng)為eureka-client2,端口為7772
Spring-Cloud通過(guò)DiscoveryClient來(lái)進(jìn)行發(fā)現(xiàn)服務(wù)的操作,修改eureka-client工程的EurekaClientApplication類(lèi)
package com.jack.eureka_client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@SpringBootApplication
@RestController
//@EnableEurekaClient (Finchley.SR2已經(jīng)不需要該配置了,你只需要在配置文件中含有eureka.client.enabled的配置即可)
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
private DiscoveryClient discoveryClient;
// 得到DiscoveryClient
@Autowired
public void setDiscoveryClient(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
@RequestMapping(value = "/discovery", method = RequestMethod.GET)
public Object discovery() {
// 獲取服務(wù)名稱(chēng)列表
List<String> names = discoveryClient.getServices();
System.out.println("*******************" + names);
StringBuilder builder = new StringBuilder();
for (String name : names) {
// 根據(jù)服務(wù)名稱(chēng)獲取服務(wù)實(shí)例列表,可能是多個(gè)實(shí)例.
List<ServiceInstance> instances = discoveryClient.getInstances(name);
for (ServiceInstance instance : instances) {
String info = instance.getServiceId() + "," +
instance.getHost() + "," +
instance.getPort() + "," +
instance.getUri() + "<br/>";
System.out.println(info);
builder.append(info);
}
}
return builder.toString();
}
}
http請(qǐng)求localhost:7771/discovery,得到兩個(gè)服務(wù)實(shí)例信息,EUREKA-CLIENT,EUREKA-CLIENT2.

通過(guò)服務(wù)的詳細(xì)信息動(dòng)態(tài)的獲取服務(wù)的ip地址,然后發(fā)送http請(qǐng)求.如果一個(gè)服務(wù)名稱(chēng)有多個(gè)實(shí)例,需要根據(jù)輪詢(xún)策略來(lái)決定請(qǐng)求哪個(gè)具體實(shí)例,為此需要寫(xiě)代碼去做這方面的處理.幸運(yùn)的是spring-cloud已準(zhǔn)備了工具,不需要再進(jìn)行編寫(xiě)了.
總結(jié)
經(jīng)過(guò)上面的講解,已經(jīng)了解服務(wù)發(fā)現(xiàn)的概念,以及如何用代碼來(lái)發(fā)現(xiàn)服務(wù).不過(guò)以上還不足以讓我們方便的進(jìn)行服務(wù)之間的調(diào)用.SpringCloud提供兩種服務(wù)調(diào)用方式,一種是ribbon+restTemplate,另一種是feign。接下來(lái)我們會(huì)對(duì)兩種方法進(jìn)行深入的講解.