1. 程式人生 > >SpringCloud微服務搭建詳解

SpringCloud微服務搭建詳解

具體關於SpringCloud介紹請參考其他文章,下面主要講解SpringCloud搭建微服務的步驟,其中用到了Eurake、Ribbon、Feign、Hystrix、Zuul、Config技術。
本次案例主要分為以下幾個微服務

  • 提供者服務用於操作user表,進行增刪改查;
  • 消費者服務用於請求提供者服務,進行增刪改查;
  • 公共模組微服務,用於提供其他微服務共同需要的功能;

本次案例用的工具版本如下
eclipse : Mars
JDK : 1.8
SpringCloud : Dalston
SpringBoot : 1.5.9

一、建立一個總工程

首先建立一個microservice-parent總工程,總工程中並不做什麼業務邏輯,總工程主要定義一個POM檔案,將後續各個微服公用的一些jar包在總工程的pom中進行匯入。為方便起見,建立一個working set用於歸類所有的微服務,命名為springcloudset。然後建立總工程
New -> Maven -> Maven Project
在這裡插入圖片描述


注意,Packaging模式要選擇pom模式,不要選擇jar模式。
POM檔案如下:

<?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.lzj.springcloud</groupId>
	<artifactId>microservice-parent</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<junit.version>4.12</junit.version>
		<log4j.version>1.2.17</log4j.version>
		<lombok.version>1.16.18</lombok.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Dalston.SR1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>1.5.9.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
			    <groupId>mysql</groupId>
			    <artifactId>mysql-connector-java</artifactId>
			    <version>5.1.46</version>
			</dependency>
			<dependency>
			    <groupId>com.alibaba</groupId>
			    <artifactId>druid</artifactId>
			    <version>1.1.0</version>
			</dependency>
			<dependency>
				<groupId>org.mybatis.spring.boot</groupId>
				<artifactId>mybatis-spring-boot-starter</artifactId>
				<version>1.3.0</version>
			</dependency>
			<dependency>
				<groupId>ch.qos.logback</groupId>
				<artifactId>logback-core</artifactId>
				<version>1.2.3</version>
			</dependency>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>
			<dependency>
				<groupId>log4j</groupId>
				<artifactId>log4j</artifactId>
				<version>${log4j.version}</version>
			</dependency>
		</dependencies>
	</dependencyManagement>
</project>

二、建立公共微服

然後建立一個microservice-com的公共模組,用於提供後續微服需要的公共的東西。建立好公共模組,其它微服務需要的話,不用再建立,直接引用該模組即可。
1、下面在總工程下,即microservice-parent下建立第一個微服務microservice-com模組。
New -> Maven -> Maven Module
這裡寫圖片描述

這裡寫圖片描述
注意,Packaging不要選擇pom模式,而應該選擇ja模式,後續的微服都是如此。
pom.xml內容為:

<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>
	<!-- 繼承父工程 -->
	<parent>
		<groupId>com.lzj.springcloud</groupId>
		<artifactId>microservice-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<!-- 當前工程的名字 -->
	<artifactId>microservice-com</artifactId>
	<dependencies><!-- 當前Module需要用到的jar包,按自己需求新增,如果父類已經包含了,可以不用寫版本號 -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
	</dependencies>
</project>

2、然後在該模組中建立一個User的bean,以供其它微服務進行呼叫。

package com.lzj.springcloud.entity;
public class User {
	private int id;
	private String name;
	private int age;
	
	public User() {
		super();
	}

	public User(int id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
	
}

3、建立完公共微服後,執行mvn clean install進行裝載。
建立完microservice-com模組後,在microservice-parent父工程中的pom.xml檔案中增加了

	<modules>
		<module>microservice-com</module>
	</modules>

microservice-com工程目錄如下;
這裡寫圖片描述
三、建立microservice-provider微服務

1、與建立microservice-com服務類似,建立一個microservice-provider微服務
2、該服務用於提供直接操作資料庫user表。首先在pom中配置依賴的包,操作資料庫需要的資料庫驅動、資料來源等。

<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>
	<parent>
		<groupId>com.lzj.springcloud</groupId>
		<artifactId>microservice-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<artifactId>microservice-provider</artifactId>

	<dependencies>
		<dependency>
			<groupId>com.lzj.springcloud</groupId>
			<artifactId>microservice-com</artifactId>
			<version>${project.version}</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-core</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jetty</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>
		</dependency>
		<!-- 修改後立即生效,熱部署 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>

</project>

在microservice-provider微服找那個需要引用microservice-com微服中User bean,所以在pom檔案中引入了microservice-com的依賴。

		<dependency>
			<groupId>com.lzj.springcloud</groupId>
			<artifactId>microservice-com</artifactId>
			<version>${project.version}</version>
		</dependency>

3、在microservice-provider需要操作資料庫,在application.yml中配置mybatis和資料來源如下:

server: 
  port: 8002

mybatis: 
  config-location: "classpath:mybatis/mybatis.cfg.xml"        # mybatis配置檔案所在路徑
  mapper-locations: 
    - "classpath:mybatis/mapper/**/*.xml"                     # mapper對映檔案
  type-aliases-package: com.lzj.springcloud.entity            # 別名類所在包

spring: 
  application: 
    name: microservicecloud-provider                          #微服務的名字
  datasource: 
    driver-class-name: org.gjt.mm.mysql.Driver                # mysql驅動包      
    type: com.alibaba.druid.pool.DruidDataSource              # 當前資料來源操作型別
    url: "jdbc:mysql://localhost:3306/lzj"                    # 資料庫名稱
    username: root
    password: lzjlzj
    dbcp2: 
      initial-size: 5                                         # 初始化連線數
      max-total: 5                                            # 最大連線數
      max-wait-millis: 200                                    # 等待連接獲取的最大超時時間
      min-idle: 5                                             # 資料庫連線池的最小維持連線數

4、在src/main/resources目錄下建立mybatis資料夾後新建mybatis.cfg.xml檔案,內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	<!-- 開啟二級快取 -->
	<settings> 
    	<setting name="cacheEnabled" value="true"/>  
	</settings> 

</configuration>

5、建立Dao介面,用於操作user表的介面

package com.lzj.springcloud.dao;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.lzj.springcloud.entity.User;

@Mapper
public interface UserDao {

	public boolean addUser(User user);
	
	public User getUser(int id);
	
	public List<User> getUsers();
}

6、在src/main/resources/mybatis目錄下建立mapper目錄,並在mapper目錄下建立UserMapper.xml檔案,內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzj.springcloud.dao.UserDao">

    <select id="getUser" resultType="User" parameterType="int">
        select * from user where ID=#{id}
    </select>
    
    <select id="getUsers" resultType="User">
    	select * from user
    </select>
    
    <insert id="addUser" parameterType="User">
    	insert into user(NAME, AGE) values(#{name}, #{age})
    </insert>
    
</mapper>

7、建立UserService服務介面

package com.lzj.springcloud.service;
import java.util.List;
import com.lzj.springcloud.entity.User;
public interface UserService {
	
	public boolean addUser(User user);
	
	public User getUser(int id);
	
	public List<User> getUsers();
}

8、建立UserServiceImpl介面的實現

package com.lzj.springcloud.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lzj.springcloud.dao.UserDao;
import com.lzj.springcloud.entity.User;
import com.lzj.springcloud.service.UserService;

@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserDao userDao;
	
	@Override
	public boolean addUser(User user) {
		boolean flag;
		flag = userDao.addUser(user);
		return flag;
	}

	@Override
	public User getUser(int id) {
		User user = userDao.getUser(id);
		return user;
	}

	@Override
	public List<User> getUsers() {
		List<User> users = userDao.getUsers();
		return users;
	}

}

9、建立Controller層,用於相應REST請求

package com.lzj.springcloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.lzj.springcloud.entity.User;
import com.lzj.springcloud.service.UserService;

@RestController
public class UserController {

	@Autowired
	private UserService service;
	
	@RequestMapping(value="/add", method=RequestMethod.POST)
	public boolean addUser(@RequestBody User user){
		boolean flag = service.addUser(user);
		return flag;
	}
	
	@RequestMapping(value="/get/{id}", method=RequestMethod.GET)
	public User getUser(@PathVariable("id") int id){
		User user = service.getUser(id);
		return user;
	}
	
	@RequestMapping(value="/getUser/list", method=RequestMethod.GET)
	public List<User> getUsers(){
		List<User> users = service.getUsers();
		return users;
	}
}

10、建立microservice-provider的啟動類

package com.lzj.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ProviderApplication {

	public static void main(String[] args) {

		SpringApplication.run(ProviderApplication.class, args);
	}

}

11、測試microservice-provider微服
啟動microservice-provider服務,然後在瀏覽器中傳送請求 http://localhost:8002/getUser/list,相應結果如下
這裡寫圖片描述
建立並配置完microservice-provider後,在microservice-parent的pom的檔案中,module標籤如下

	<modules>
		<module>microservice-com</module>
		<module>microservice-provider</module>
		<module>microservice-consumer</module>
	</modules>

microservice-provider工程目錄如下
這裡寫圖片描述

四、建立microservice-consumer微服務

microservice-consumer服務用於請求microservice-provicer
建立與microservice-com類似,在microservice-parent下建立microservice-consumer微服。
1、pom配置如下:

<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>
  <parent>
    <groupId>com.lzj.springcloud</groupId>
    <artifactId>microservice-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>microservice-consumer</artifactId>
  
	<dependencies>
		<!-- 依賴microservice-com模組 -->
		<dependency>
			<groupId>com.lzj.springcloud</groupId>
			<artifactId>microservice-com</artifactId>
			<version>${project.version}</version>
		</dependency>
				<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- 修改後立即生效,熱部署 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>
</project>

熱部署即為,工程每次修改完後,會重新部署。

2、application.yml配置檔案如下:
配置訪問埠

server: 
  port: 8003

3、配置RestTemplate的bean
RestTemplate用於模擬傳送REST的客戶端請求

package com.lzj.springcloud.configbean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ConfigBean {
	
	@Bean
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}
}

3、配置controller層

package com.lzj.springcloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.lzj.springcloud.entity.User;

@RestController
public class UserConsumerController {
	private static String REST_URL_PREFIX = "http://localhost:8002";
	
	@Autowired
	private RestTemplate restTemplate;
	
	@RequestMapping(value="/consumer/add")
	public boolean addUser(User user){
		Boolean flag = restTemplate.postForObject(REST_URL_PREFIX + "/add", user, Boolean.class);
		return flag;
	}
	
	@RequestMapping(value="/consumer/get/{id}")
	public User get(@PathVariable("id") int id){
		User user = restTemplate.getForObject(REST_URL_PREFIX + "/get" + "/id", User.class);
		return user;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@RequestMapping(value="/consumer/list")
	public List<User> getList(){
		List list = restTemplate.getForObject(REST_URL_PREFIX + "/getUser/list", List.class);
		return list;
	}
}

4、建立啟動類

package com.lzj.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConsumerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerApplication.class, args);
	}

}

傳送請求後,在資料庫user表中插入了一條資料
這裡寫圖片描述
至此需要的微服務已經全部建立完畢,在microservice-parent的pom檔案中可以看到總工程下有三個微服務。

 	<modules>
		<module>microservice-com</module>
		<module>microservice-provider</module>
		<module>microservice-consumer</module>
	</modules>

五、建立microservice-eurake1微服務

eureka微服務用於註冊和發現服務。
首先建立一個依賴於microservice-parent的microservice-eurake1工程,與上面建立方法一樣。
1、pom檔案配置如下:

<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>
	<parent>
		<groupId>com.lzj.springcloud</groupId>
		<artifactId>microservice-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	
	<artifactId>microservice-eurake1</artifactId>
  
	<dependencies>
		<!--eureka-server服務端 -->
		<dependency>
    		<groupId>org.springframework.cloud</groupId>
    		<artifactId>spring-cloud-netflix-eureka-server</artifactId>
		</dependency>
		<!-- 修改後立即生效,熱部署 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>
  
</project>

2、application.yml檔案配置如下

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      
server:
  port: 9001

3、建立啟動類

package com.lzj.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaApplication.class, args);
	}

}

注意,一定不要忘記@EnableEurekaServer註解,該註解用於啟用eureka的服務端。
現在可以啟動microservice-eureka微服務了
這裡寫圖片描述
正確建立eureka微服務後,啟動頁面如上圖所示,只是還沒有微服務註冊進來。

5、把microservice-provider微服務註冊進microservice-eureka服務中

  • 在microservice-provider微服務中的pom檔案加入下面依賴
		<!-- 將微服務microservice-provider側註冊進eureka -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>		

microservice-provider中的pom檔案如下:

<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>
	<parent>
		<groupId>com.lzj.springcloud</groupId>
		<artifactId>microservice-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<artifactId>microservice-provider</artifactId>

	<dependencies>
		<dependency>
			<groupId>com.lzj.springcloud</groupId>
			<artifactId>microservice-com</artifactId>
			<version>${project.version}</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-core</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jetty</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>
		</dependency>
		<!-- 將微服務microservice-provider側註冊進eureka -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>		
		<!-- 修改後立即生效,熱部署 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>

</project>
  • 在microservice-provider微服務中的application.yml檔案中加入如下配置
    表示把microservice-provider微服務註冊進http://localhost:9001/eureka指示的服務中,即microservice-eureka微服務中。
 eureka:
  client:
    service-url:
      defaultZone: http://localhost:9001/eureka

microservice-provider中application.yml配置檔案如下:

server: 
  port: 8002

mybatis: 
  config-location: "classpath:mybatis/mybatis.cfg.xml"        # mybatis配置檔案所在路徑
  mapper-locations: 
    - "classpath:mybatis/mapper/**/*.xml"                     # mapper對映檔案
  type-aliases-package: com.lzj.springcloud.entity            # 別名類所在包


spring: 
  application: 
    name: microservicecloud-provider                          #微服務的名字
  datasource: 
    driver-class-name: org.gjt.mm.mysql.Driver                # mysql驅動包      
    type: com.alibaba.druid.pool.DruidDataSource              # 當前資料來源操作型別
    url: "jdbc:mysql://localhost:3306/lzj"                    # 資料庫名稱
    username: root
    password: lzjlzj
    dbcp2: 
      initial-size: 5                                         # 初始化連線數
      max-total: 5                                            # 最大連線數
      max-wait-millis: 200                                    # 等待連接獲取的最大超時時間
      min-idle: 5                                             # 資料庫連線池的最小維持連線數

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9001/eureka
  • 在microservice-provider微服務中的啟動類上加入@EnableEurekaClient註解。表示microservice-provider微服務啟動時就啟動eureka的客戶端,該客戶端自動的把microservice-provider服務註冊進microservice-eureka1中。
package com.lzj.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient  //本服務啟動後會自動註冊進eureka服務中
public class ProviderApplication {

	public static void main(String[] args) {

		SpringApplication.run(ProviderApplication.class, args);
	}

}

6、測試microservice-provider服務已經註冊進了microservice-eureka1服務。
啟動microservice-eureka1微服務,然後再啟動microservice-provider微服務,
在瀏覽器中請求http://localhost:9001/,反饋網頁如下:
這裡寫圖片描述
可見網頁中Application那一欄多了一個MICROSERVICECLOUD-PROVIDER服務,此處顯示的服務名字是在microservice-provider服務中的application.yml檔案中配置的

spring: 
  application: 
    name: microservicecloud-provider                          #微服務的名字

為追求完美者,下面完善註冊服務的資訊,如果只是想達到功能,7、8、9可以不用看。
7、修改註冊服務的主機名稱
我們看到在上述的測試中,註冊進eureka中的MICROSERVICE-PROVIDER服務,在狀態一欄裡面顯示的是主機名稱:服務名稱的形式,主機預設是我本人主機名稱,如下圖所示。
這裡寫圖片描述

下面修改microservicecloud-provider中的application.yml檔案,關於eureka的部分改為如下:

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9001/eureka
  instance:
    instance-id: microservicecloud-provider8002

重啟服務,狀態列中顯示的即為配置的instance-id名稱。

對應關係如下
這裡寫圖片描述

8、eureka中顯示註冊微服務的ip資訊
當滑鼠放在註冊微服務的連結上,左下角顯示註冊微服務的ip資訊,如下所示
這裡寫圖片描述
左下角顯示了microservice-provider微服務的ip資訊,要想達到此效果,只需要microservice-provider服務中application.yml中eureka的配置改為如下

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9001/eureka
  instance:
    instance-id: microservicecloud-provider8002               #自定義服務名稱資訊
    prefer-ip-address: true                                   #訪問路徑可以顯示IP地址

9、點選註冊微服務連結,顯示微服務的info資訊
這裡寫圖片描述
當點選上圖劃紅線的連結處,顯示下面erro資訊
這裡寫圖片描述
下面定製當點選連結時,顯示指定資訊
首先在microservice-parent的pom中增加<build>的配置,pom如下所示

<?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.lzj.springcloud</groupId>
	<artifactId>microservice-parent</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<junit.version>4.12</junit.version>
		<log4j.version>1.2.17</log4j.version>
		<lombok.version>1.16.18</lombok.version>
	</properties>


	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Dalston.SR1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>1.5.9.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
			    <groupId>mysql</groupId>
			    <artifactId>mysql-connector-java</artifactId>
			    <version>5.1.46</version>
			</dependency>
			<dependency>
			    <groupId>com.alibaba</groupId>
			    <artifactId>druid</artifactId>
			    <version>1.1.0</version>
			</dependency>
			<dependency>
				<groupId>org.mybatis.spring.boot</groupId>
				<artifactId>mybatis-spring-boot-starter</artifactId>
				<version>1.3.0</version>
			</dependency>
			<dependency>
				<groupId>ch.qos.logback</groupId>
				<artifactId>logback-core</artifactId>
				<version>1.2.3</version>
			</dependency>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>
			<dependency>
				<groupId>log4j</groupId>
				<artifactId>log4j</artifactId>
				<version>${log4j.version}</version>
			</dependency>
		</dependencies>
	</dependencyManagement>
	
	<build>
		<finalName>microservicecloud</finalName>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<filtering>true</filtering>
			</resource>
		</resources>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<configuration>
					<delimiters>
						<delimit>$</delimit>
					</delimiters>
				</configuration>
			</plugin>
		</plugins>
	</build>	
	
	<modules>
		<module>microservice-com</module>
		<module>microservice-provider</module>
		<module>microservice-consumer</module>
		<module>microservice-eurake1</module>
	</modules>
</project>

然後再microservice-provider的服務中增加如下依賴

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>	

最後在microservice-provider中application.yml中配置顯示的info資訊

server: 
  port: 8002

mybatis: 
  config-location: "classpath:mybatis/mybatis.cfg.xml"        # mybatis配置檔案所在路徑
  mapper-locations: 
    - "classpath:mybatis/mapper/**/*.xml"                     # mapper對映檔案
  type-aliases-package: com.lzj.springcloud.entity            # 別名類所在包


spring: 
  application: 
    name: microservicecloud-provider                          #微服務的名字
  datasource: 
    driver-class-name: org.gjt.mm.mysql.Driver                # mysql驅動包      
    type: com.alibaba.druid.pool.DruidDataSource              # 當前資料來源操作型別
    url: "jdbc:mysql://localhost:3306/lzj"                    # 資料庫名稱
    username: root
    password: lzjlzj
    dbcp2: 
      initial-size: 5                                         # 初始化連線數
      max-total: 5                                            # 最大連線數
      max-wait-millis: 200                                    # 等待連接獲取的最大超時時間
      min-idle: 5                                             # 資料庫連線池的最小維持連線數

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9001/eureka
  instance:
    instance-id: microservicecloud-provider8002               #自定義服務名稱資訊
    prefer-ip-address: true                                   #訪問路徑可以顯示IP地址
    
info: 
  app.name: microservicecloud-provider
  company.name: www.lzj.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$

重啟microservice-eurake1和microservicecloud-provider微服務,點選註冊的微服務microservicecloud-provider的連結,顯示如下頁面
這裡寫圖片描述

10、eureka的自我保護
過段時間,微服務沒有用時,會出現下面紅色的警告資訊,即為eureka的自我保護。
這裡寫圖片描述

預設情況下,如果EurekaServer在一定時間內沒有接收到某個微服務例項的心跳,EurekaServer將會登出該例項(預設90秒)。但是當網路分割槽故障發生時,微服務與EurekaServer之間無法正常通訊,以上行為可能變得非常危險了——因為微服務本身其實是健康的,此時本不應該登出這個微服務。Eureka通過“自我保護模式”來解決這個問題——當EurekaServer節點在短時間內丟失過多客戶端時(可能發生了網路分割槽故障),那麼這個節點就會進入自我保護模式。一旦進入該模式,EurekaServer就會保護服務登錄檔中的資訊,不再刪除服務登錄檔中的資料(也就是不會登出任何微服務)。當網路故障恢復後,該Eureka Server節點會自動退出自我保護模式。

在自我保護模式中,Eureka Server會保護服務登錄檔中的資訊,不再登出任何服務例項。當它收到的心跳數重新恢復到閾值以上時,該Eureka Server節點就會自動退出自我保護模式。它的設計哲學就是寧可保留錯誤的服務註冊資訊,也不盲目登出任何可能健康的服務例項。

綜上,自我保護模式是一種應對網路異常的安全保護措施。它的架構哲學是寧可同時保留所有微服務(健康的微服務和不健康的微服務都會保留),也不盲目登出任何健康的微服務。使用自我保護模式,可以讓Eureka叢集更加的健壯、穩定。

在Spring Cloud中,可以使用eureka.server.enable-self-preservation = false 禁用自我保護模式。

六、建立eureka叢集

第五步只是建立了一個eureka的微服務,如果當這個微服務down掉了,那麼其它微服務就不能被註冊和發現,整個系統就會down掉,所以下面建立多個eureka微服務,配置eureka叢集,需要註冊的微服務要註冊到所有的eureka的微服務中,即註冊到整個叢集上,當一個eureka的微服務掛掉了,其它的eureka微服可以繼續工作。
首先修改host檔案,新增127.0.0.1的多個域名對映,方便後面模擬根據多個地址進行註冊服務。
分別複製microservice-eurake1工程為microservice-eurake2和microservice-eurake3,
把microservice-eurake2服務中pom檔案中的artifactId改為(因為之前該微服是複製過來的,如果是建立過來的就不用修改)<artifactId>microservice-eurake2</artifactId>
把microservice-eurake3服務中pom檔案中的artifactId改為<artifactId>microservice-eurake3</artifactId>
修改microservice-eureka1的application.yml檔案為

 eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/        #設定與Eureka Server互動的地址查詢服務和註冊服務都需要依賴這個地址。
      defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/
server:
  port: 9001

修改microservice-eureka2的application.yml檔案為

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9003.com:9003/eureka/
server:
  port: 9002

修改microservice-eureka3的application.yml檔案為

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/
      
server:
  port: 9003

然後修改microservice-provider微服務application.yml中的defaultZone配置,把該微服務同時註冊到三個eureka微服務中,即eureka叢集中。

server: 
  port: 8002

mybatis: 
  config-location: "classpath:mybatis/mybatis.cfg.xml"        # mybatis配置檔案所在路徑
  mapper-locations: 
    - "classpath:mybatis/mapper/**/*.xml"                     # mapper對映檔案
  type-aliases-package: com.lzj.springcloud.entity            # 別名類所在包


spring: 
  application: 
    name: microservicecloud-provider                          #微服務的名字
  datasource: 
    driver-class-name: org.gjt.mm.mysql.Driver                # mysql驅動包      
    type: com.alibaba.druid.pool.DruidDataSource              # 當前資料來源操作型別
    url: "jdbc:mysql://localhost:3306/lzj"                    # 資料庫名稱
    username: root
    password: lzjlzj
    dbcp2: 
      initial-size: 5                                         # 初始化連線數
      max-total: 5                                            # 最大連線數
      max-wait-millis: 200                                    # 等待連接獲取的最大超時時間
      min-idle: 5                                             # 資料庫連線池的最小維持連線數

eureka:
  client:
    service-url:
      #defaultZone: http://localhost:9001/eureka
      defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9003.com:9003/eureka/
  instance:
    instance-id: microservicecloud-provider8002               #自定義服務名稱資訊
    prefer-ip-address: true                                   #訪問路徑可以顯示IP地址
    
info: 
  app.name: microservicecloud-provider
  company.name: www.lzj.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$

測試:執行microservice-eurake1、microservice-eurake2、microservice-eurake3、microservice-provider
從瀏覽器中訪問eureka1的管理端http://localhost:9001/
這裡寫圖片描述
可以看出,兩個劃橫線的為microservice-eurake1的備份,microservice-provider為註冊上來的服務。eureka的3個微服務組成了一個服務註冊的叢集,只有有一個能工作,能保證業務的執行。

七、Ribbon負載均衡

Ribbon的負載均衡是應用於客戶端的,即呼叫一方的,在本案例中就是應用於microservice-consumer微服務的,下面就對microservice-consumer微服務使用負載均衡。
1、microservice-consumer進行Ribbon配置
下面進行修改microservice-consumer微服務的配置
pom檔案中增加Ribbon需要的依賴

		<!-- Ribbon相關 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-ribbon</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>

修改application.yml檔案,增加eureka的服務註冊功能,修改後的配置如下

server: 
  port: 8003

eureka:
  client:
    register-with-eureka: false
    service-url: 
      defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/

負載均衡實際是根據RestTemplate根據均衡演算法進行排程不同地址上的同一個微服務的部署。所以修改ConfigBean,在RestTemplate上加@LoadBalanced註解。

@Configuration
public class ConfigBean {
	
	@Bean
	@LoadBalanced
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}
}

把microservice-consumer也註冊到eureka服務中,需要在啟動類上加@EnableEurekaClient註解

@SpringBootApplication
@EnableEurekaClient
public class ConsumerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerApplication.class, args);
	}

}

修改controller層,不再通過地址和埠調取其它微服的應用,而是根據微服務的名來調取應用。修改後如下

@RestController
public class UserConsumerController {
//	private static String REST_URL_PREFIX = "http://localhost:8002";
	/*直接根據微服務名呼叫,而不再是根據地址和埠了,運用了eureka的發現功能*/
	private static String REST_URL_PREFIX = "http://microservicecloud-provider";
	
	@Autowired
	private RestTemplate restTemplate;
	
	@RequestMapping(value="/consumer/add")
	public boolean addUser(User user){
		Boolean flag = restTemplate.postForObject(REST_URL_PREFIX + "/add", user, Boolean.class);
		return flag;
	}
	
	@RequestMapping(value="/consumer/get/{id}")
	public User get(@PathVariable("id") int id){
		User user = restTemplate.getForObject(REST_URL_PREFIX + "/get/" + id, User.class);
		return user;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@RequestMapping(value="/consumer/list")
	public List<User> getList(){
		List list = restTemplate.getForObject(REST_URL_PREFIX + "/getUser/list", List.class);
		return list;
	}
}

測試:修改上述配置後,下面進行測試,啟動microservice-eurake1、microservice-eurake2、microservice-eurake3微服務,然後啟動microservice-provider提供者微服務,最後啟動帶Ribbon負載均衡配置的消費者(客戶端)微服務microservice-consumer。從瀏覽器中傳送請求http://localhost:8003/consumer/list,響應頁面如下
這裡寫圖片描述

說明可以從消費端通過微服務名找到提供者微服務,然後進行呼叫。

2、Ribbon負載均衡
上面在消費端microservice-consumer配置好了Ribbon,提供者微服務目前只有一個。為減小提供者微服務的壓力,現在再部署兩個提供者微服務,當客戶端傳送請求時,由三個微服務中的一個隨機的響應請求。
複製microservice-provider工程生成microservice-provider2和microservice-provider3
修改microservice-provider2的啟動類為ProviderApplication2
修改microservice-provider3的啟動類為ProviderApplication3
修改microservice-provider2的application.yml配置為

server: 
  port: 8003

mybatis: 
  config-location: "classpath:mybatis/mybatis.cfg.xml"        # mybatis配置檔案所在路徑
  mapper-locations: 
    - "classpath:mybatis/mapper/**/*.xml"                     # mapper對映檔案
  type-aliases-package: com.lzj.springcloud.entity            # 別名類所在包


spring: 
  application: 
    name: microservicecloud-provider                          #微服務的名字
  datasource: 
    driver-class-name: org.gjt.mm.mysql.Driver                # mysql驅動包      
    type: com.alibaba.druid.pool.DruidDataSource              # 當前資料來源操作型別
    url: "jdbc:mysql://localhost:3306/lzj"                    # 資料庫名稱
    username: root
    password: lzjlzj
    dbcp2: 
      initial-size: 5                                         # 初始化連線數
      max-total: 5                                            # 最大連線數
      max-wait-millis: 200                                    # 等待連接獲取的最大超時時間
      min-idle: 5                                             # 資料庫連線池的最小維持連線數

eureka:
  client:
    service-url:
      #defaultZone: http://localhost:9001/eureka
      defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9003.com:9003/eureka/
  instance:
    instance-id: microservicecloud-provider8003               #自定義服務名稱資訊
    prefer-ip-address: true                                   #訪問路徑可以顯示IP地址
    
info: 
  app.name: microservicecloud-provider
  company.name: www.lzj.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$

修改microservice-provider3的配置為

server: 
  port: 8004

mybatis: 
  config-location: "classpath:mybatis/mybatis.cfg.xml"        # mybatis配置檔案所在路徑
  mapper-locations: 
    - "classpath:mybatis/mapper/**/*.xml"                     # mapper對映檔案
  type-aliases-package: com.lzj.springcloud.entity            # 別名類所在包


spring: 
  application: 
    name: microservicecloud-provider                          #微服務的名字
  datasource: 
    driver-class-name: org.gjt.mm.mysql.Driver                # mysql驅動包      
    type: com.alibaba.druid.pool.DruidDataSource              # 當前資料來源操作型別
    url: "jdbc:mysql://localhost:3306/lzj"                    # 資料庫名稱
    username: root
    password: lzjlzj
    dbcp2: 
      initial-size: 5                                         # 初始化連線數
      max-total: 5                                            # 最大連線數
      max-wait-millis: 200                                    # 等待連接獲取的最大超時時間
      min-idle: 5                                             # 資料庫連線池的最小維持連線數

eureka:
  client:
    service-url:
      #defaultZone: http://localhost:9001/eureka
      defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9003.com:9003/eureka/
  instance:
    instance-id: microservicecloud-provider8004               #自定義服務名稱資訊
    prefer-ip-address: true                                   #訪問路徑可以顯示IP地址
    
info: 
  app.name: microservicecloud-provider
  company.name: www.lzj.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$

只是分別修改了server.port和eureka.instance.instance-id。

為方便觀察哪一個提供者微服務響應的客戶端請求,在提供者微服中分別列印兩條日誌,
microservice-provider微服務中UserServiceImpl類中getUser方法修改為如下:

	@Override
	public User getUser(int id) {
		User user = userDao.getUser(id);
		System.out.println("microservice-provider微服務在響應客戶端請求……");
		System.out.println("user : " + user);
		return user;
	}

microservice-provider2微服務中UserServiceImpl類中getUser方法修改為如下:

	@Override
	public User getUser(int id) {
		User user = userDao.getUser(id);
		System.out.println("microservice-provider2微服務在響應客戶端請求……");
		System.out.println("user : " + user);
		return user;
	}

microservice-provider3微服務中UserServiceImpl類中getUser方法修改為如下:

	@Override
	public User getUser(int id) {
		User user = userDao.getUser(id);
		System.out.println("microservice-provider3微服務在響應客戶端請求……");
		System.out.println("user : " + user);
		return user;
	}

測試:啟動3個eureka的微服務叢集,然後啟動3個上述提供者微服務,最後啟動消費者微服務microservice-consumer,分別從前端發起http://localhost:7001/consumer/get/{id}多筆請求,id用數字代替,發現分別在三個提供者服務的console中輸出如下內容:

microservice-provider3微服務在響應客戶端請求……
user : User [id=1, name=lzj1, age=20]

microservice-provider3微服務在響應客戶端請求……
user : User [id=2, name=lzj2, age=24]

microservice-provider微服務在響應客戶端請求……
user : User [id=4, name=lzj4, age=30]

microservice-provider2微服務在響應客戶端請求……
user : User [id=3, name=lzj3, age=26]
……

3個提供者微服務隨機的響應客戶端請求。

3、通過Ribbon的核心元件IRule定義查詢消費端呼叫提供端微服務的策略
如沒有指定輪詢策略,預設是消費端隨機呼叫提供端微服的策略,下面指定輪詢呼叫策略。只需要在microservice-consumer中的ConfigBean類新增如下宣告:

	@Bean
	public IRule myRule(){
		return new RoundRobinRule(); 	//輪詢策略
	}

重新啟動3個eureka微服務和3個提供者微服務,最後啟動消費者微服務,重新測試,可知消費者微服務是輪詢呼叫提供者的3個微服務的。

八、Feign負載均衡

Feign是一個宣告式WebService客戶端。使用Feign能讓編寫Web Service客戶端更加簡單。Feign是對Ribbon的包裝,Feign集成了Ribbon。
前面在使用Ribbon+RestTemplate時,利用RestTemplate對http請求的封裝處理,形成了一套模版化的呼叫方法。但是在實際開發中,由於對服務依賴的呼叫可能不止一處,往往一個介面會被多處呼叫,所以通常都會針對每個微服務自行封裝一些客戶端類來包裝這些依賴服務的呼叫。所以,Feign在此基礎上做了進一步封裝,由他來幫助我們定義和實現依賴服務介面的定義。在Feign的實現下,我們只需建立一個介面並使用註解的方式來配置它,即可完成對服務提供方的介面繫結,簡化了使用Spring cloud Ribbon時,自動封裝服務呼叫客戶端的開發量。
Feign既然是對Ribbon的包裝,那麼Feign也是用在客戶端的,即消費端的。下面建立整合Feign的消費端
複製microservice-consumer工程為microservice-consumer-feign
修改microservice-consumer-feign啟動類的名字為FeignConsumerApplication;
microservice-consumer-feign的pom檔案中增加對Feign的依賴:

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>

建立ConsumerService介面,用於包裝microservicecloud-provider微服務,以後要呼叫microservicecloud-provider服務中的方法,只需要呼叫介面中對應的方法即可:

package com.lzj.springcloud.service;
import java.util.List;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.lzj.springcloud.entity.User;

/*以後呼叫microservicecloud-provider微服務中的方法,只需要呼叫下面對應的介面既可以了*/
@FeignClient(value="microservicecloud-provider")
public interface ConsumerService {

	/*呼叫介面中的get方法,即可以向microservicecloud-provider微服務傳送/get/{id}請求*/
	@RequestMapping(value="/get/{id}", method=RequestMethod.GET)
	public User get(@PathVariable("id") int id);
	
	@RequestMapping(value="/add", method=RequestMethod.POST)
	public boolean add(User user);
	
	@RequestMapping(value="/getUser/list", method=RequestMethod.GET)
	public List<User> getAll();
}

修改microservice-consumer-feign中的controller層為

package com.lzj.springcloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.lzj.springcloud.entity.User;
import com.lzj.springcloud.service.ConsumerService;

@RestController
public class UserConsumerController {
//	private static String REST_URL_PREFIX = "http://localhost:8002";
	/*直接根據微服務名呼叫,而不再是根據地址和埠了,運用了eureka的發現功能*/
//	private static String REST_URL_PREFIX = "http://microservicecloud-provider";
//	@Autowired
//	private RestTemplate restTemplate;
	
	@Autowired
	private ConsumerService service;
	
	@RequestMapping(value="/consumer/add")
	public boolean addUser(User user){
		Boolean flag = service.add(user);
		return flag;
	}
	
	@RequestMapping(value="/consumer/get/{id}")
	public User get(@PathVariable("id") int id){
		User user = service.get(id);
		return user;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@RequestMapping(value="/consumer/list")
	public List<User> getList(){
		List list = service.getAll();
		return list;
	}
}

修改啟動類FeignConsumerApplication,在啟動類上加啟用Feign的註解:

package com.lzj.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages="com.lzj.springcloud.service")
public class FeignConsumerApplication {

	public static void main(String[] args) {
		SpringApplication.run(FeignConsumerApplication.class, args);
	}

}

測試,啟動microservice-eurake1、microservice-eurake2、microservice-eurake3叢集,然後啟動microservice-provider、microservice-provider2、microservice-provider3叢集,最後啟動microservice-consumer-feign微服務。
從瀏覽器中向消費端傳送請求http://localhost:7001/consumer/get/2,響應頁面如下
這裡寫圖片描述
Feign通過介面ConsumerService中的get方法呼叫Rest服務(之前是通過Ribbon+RestTemplate),並在eureka微服務中查詢microservicecloud-provider服務,找到後,把請求http://localhost:7001/consumer/get/2傳送到microservicecloud-provider微服務。

九、Hystrix斷路器

如果一個請求需要調起多個服務時,其中一個服務不通或失敗,當大量請求發生時,會導致請求延時和資源浪費。Hystrix是一個用於處理分散式系統的延遲和容錯的開源庫,在分散式系統裡,許多依賴不可避免的會呼叫失敗,比如超時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分散式系統的彈性。
當某個服務單元發生故障之後,通過斷路器的故障監控,向呼叫方返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者丟擲呼叫方無法處理的異常,這樣就保證了服務呼叫方的執行緒不會被長時間、不必要地佔用,從而避免了故障在分散式系統中的蔓延,乃至雪崩。
Hystrix可用於服務熔斷、服務降級、服務限流等作用。

1、服務熔斷
當某個服務出現異常時,熔斷該服務,快速返回指定的錯誤資訊,當服務正常時,恢復熔斷。
複製microservice-provider工程為microservice-provider-hystrix;
修改microservice-provider-hystrix的啟動類為HystrixProviderApplication;
pom檔案中新增hystrix的依賴

		<!--  hystrix -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>	

application.yml配置如下:

server: 
  port: 8005

mybatis: 
  config-location: "classpath:mybatis/mybatis.cfg.xml"        # mybatis配置檔案所在路徑
  mapper-locations: 
    - "classpath:mybatis/mapper/**/*.xml"                     # mapper對映檔案
  type-aliases-package: com.lzj.