SpringCloud的服務註冊和服務發現是由Eureka來完成的。
使用IDEA來做demo(包含:高可用註冊中心,服務註冊與發現,服務調用,負載均衡)
*注:創建項目細節不貼圖了
總體項目結構:
一、啓動服務註冊中心
1、創建SpringCloud項目
項目pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zbb</groupId>
<artifactId>spring-cloud</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>springclouddemo</name>
<description>Demo project for Spring Cloud</description>
<modules>
<module>eurekaservice</module>
<module>helloservice</module>
<module>hellocustomer</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Dalston.SR4</spring-cloud.version>
</properties>
<dependencies>
<!--服務註冊中心必要依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、在項目下創建服務註冊中心子項目 eurekaservice
子項目(服務註冊中心)pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud</artifactId>
<groupId>com.zbb</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.zbb</groupId>
<artifactId>eureka-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--服務註冊中心必要依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3、設置該子項目爲服務註冊中心
想要開啓一個註冊中心只需要兩步
(1)在啓動類(xxxxApplication.java))上添加一條註解@EnableEurekaServer
package com.zbb.eurekaservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer //開啓服務註冊中心
@SpringBootApplication
public class EurekaServiceApplication {
public static void main(String[] args)
{
SpringApplication.run(EurekaServiceApplication.class, args);
}
}
(2) 在application.properties中設置註冊中心的配置
#註冊中心端口
server.port=1111
#主機名
eureka.instance.hostname=localhost
#表示本應用是否是向註冊中心註冊自己(配置高可用的時候需要設置爲true,也就是默認值)
eureka.client.register-with-eureka=false
#是否去檢索服務
eureka.client.fetch-registry=false
#eureka服務地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
4、如圖啓動成功
打開瀏覽器輸入:http://localhost:1111/
這時頁面會顯示Eureka的管理界面
Instances currently registered with Eureka下面表示的就是發現的服務,因爲現在還沒有服務註冊,所以沒有發現服務。
注:出現一行紅色大字EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
這是一種自我保護機制。Eureka Server在運行期間,會統計心跳失敗的比例在15分鐘之內是否低於85%,如果出現低於的情況(在單機調試的時候很容易滿足,實際在生產環境上通常是由於網絡不穩定導致),Eureka Server會將當前的實例註冊信息保護起來,同時提示這個警告。
二、註冊服務提供者
1、創建一個服務提供者的子項目helloservice。(略)
2、添加依賴(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud</artifactId>
<groupId>com.zbb</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>helloservice</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
</project>
3、創建Controller
package com.zbb.controller;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
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;
@RestController
public class HelloServiceController {
private final Logger logger = Logger.getLogger(getClass());
@Autowired
DiscoveryClient discoveryClient; //自動注入DiscoveryClinet
@RequestMapping(value = "/hello" , method = RequestMethod.GET)
public String sayHello(){
ServiceInstance serviceInstance = discoveryClient.getLocalServiceInstance(); //獲得service實例
logger.info("/hello , host:"+serviceInstance.getHost()+"/n"+"/service_id:"+serviceInstance.getServiceId());
return "成功訪問服務";
}
}
4、激活DiscoveryClient實現
在啓動類添加註解:@EnableDiscoveryClient
package com.zbb.helloservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan("com.zbb.*") //組件掃描
@EnableDiscoveryClient //激活DiscoveryClient實現
@SpringBootApplication
public class HelloServiceApplication {
public static void main(String[] args){
SpringApplication.run(HelloServiceApplication.class,args);
}
}
注:激活DiscoveryClient實現(自動化配置,創建DiscoveryClient接口的實現EnableDiscoveryClient)
5、修改application.properties,指定註冊中心
#設置服務名
spring.application.name=hello-service
#指定服務註冊中心地址
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka
6、啓動
先啓動註冊中心,再啓動本服務。
訪問:http://localhost:1111/
7、訪問http://localhost:8080/hello
查看控制檯會發現打印出以下信息:
這裏打印的信息就是剛剛在HelloServiceController中注入的DiscoveryClient接口對象從服務註冊中心獲取的服務信息。
* 三、高可用註冊中心搭建*
EurekaServer在設計的時候就開始考慮高可用的問題,在Eureka的服務治理設計中,所有的節點即是服務提供方,也是服務消費方,註冊中心也不會例外。
簡單點來講就是使多個註冊中心相註冊服務,我們以上面eurekaservice爲基礎進行搭建
1、創建兩個properties文件(3個)
application-peer1.properties
#服務名
spring.application.name=eureka-server
#註冊中心-01 端口
server.port=1111
#註冊中心主機名
eureka.instance.hostname=peer1
#指定另外的註冊中心
eureka.client.serviceUrl.defaultZone=http://peer2:1112/eureka/,http://peer3:1113/eureka/
application-peer2.properties
#服務名
spring.application.name=eureka-server
#註冊中心-01 端口
server.port=1112
#註冊中心主機名
eureka.instance.hostname=peer2
#指定另外的註冊中心
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer3:1113/eureka/
application-peer3.properties
#服務名
spring.application.name=eureka-server
#註冊中心-01 端口
server.port=1113
#註冊中心主機名
eureka.instance.hostname=peer3
#指定另外的註冊中心
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/
2、修改服務生產者(helloservice)的配置文件application.properties
#設置服務名
spring.application.name=hello-service
#指定服務註冊中心地址
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/,http://peer3:1113/eureka/
3、添加對register1、register2、register3的轉換
需要在/etc/host文件中添加對應關係
windows系統host文件路徑C:\Windows\System32\drivers\etc
修改完成後的host如下:
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
127.0.0.1 peer1
127.0.0.1 peer2
127.0.0.1 peer3
4、通過spring.profiles.active來指定啓動註冊中心
java -jar eureka-server-0.0.1-SNAPSHOT.jar - -spring.profiles.active=peer1
java -jar eureka-server-0.0.1-SNAPSHOT.jar - -spring.profiles.active=peer1
java -jar eureka-server-0.0.1-SNAPSHOT.jar - -spring.profiles.active=peer1
啓動成功後訪問http://localhost:1111/或http://localhost:1112/或http://localhost:1113/
這裏只截圖http://localhost:1111/的
可以明顯看到發現服務EUREKA-SERVER
Application AMIs Availability Zones Status
EUREKA-SERVER n/a (3) (3) UP (3) - a-PC:eureka-server:1111 , a-PC:eureka-server:1112 , a-PC:eureka-server:1113
5、通過server.port來指定啓動註冊中心
分別啓動兩個生產者
java -jar helloservice-1.0-SNAPSHOT.jar –server.port=8081
java -jar helloservice-1.0-SNAPSHOT.jar –server.port=8082
完成後發現,EUREKA-SERVER三個,HELLO-SERVICE兩個。
四、註冊服務消費
1、創建服務消費子項目 hellocustomer(略)
2、添加依賴(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud</artifactId>
<groupId>com.zbb</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>hellocustomer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.3.4.RELEASE</version>
</dependency>
</dependencies>
</project>
3、開啓eureka客戶端
在HelloCustomerApplication.java中添加@EnableDiscoveryClient
package com.zbb.hellocustomer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;
@ComponentScan("com.zbb.*")
@EnableDiscoveryClient //讓該應用註冊成爲eureka客戶端,以獲得服務發現的能力
@SpringBootApplication
public class HelloCustomerApplication {
@Bean
@LoadBalanced //開啓客戶端負載均衡
RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args){
SpringApplication.run(HelloCustomerApplication.class, args);
}
}
4、創建Controller (CustomerController.java)
package com.zbb.contorller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class CustomerController {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/hello-customer" , method = RequestMethod.GET)
public String HelloController(){
return restTemplate.getForEntity("http://hello-service/hello" , String.class).getBody();
}
}
5、修改配置文件 application.properties
#服務名
spring.application.name=ribbon-consumer
#註冊中心-01 端口
server.port=9000
#指定另外的註冊中心
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/,http://peer3:1113/eureka/
6、啓動消費者服務
我們會發現有三個註冊中心服務可用域有三個,生產者服務可用域兩個,消費者服務一個
7、訪問消費者服務
http://localhost:9000/hello-customer
我們發現成功的訪問了生產者服務。
現在我停止一個註冊中心,看看會有什麼效果,停止peer1
我們發現peer1狀態變爲down。再次調用生產者服務發現依然可以調用成功!
end