精华内容
下载资源
问答
  • SpringCloud微服务搭建

    2019-06-07 18:26:39
    SpringCloud微服务搭建 具体关于SpringCloud介绍请参考其他文章,下面主要讲解SpringCloud搭建微服务的步骤,其中用到了Eurake、Ribbon、Feign、Hystrix、Zuul、Config技术。 本次案例主要分为以下几个微服务 提供...

    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);
    	}
    
    }
    

    5、测试
    在浏览器中发送 http://localhost:8003/consumer/add?name=lzj5&age=35
    相应如下:
    这里写图片描述

    发送请求后,在数据库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>
    

    如果出现“Failed to read artifact descriptor for org.springframework.cloud:spring-cloud-st”问题,请参考解决“Failed to read artifact descriptor for org.springframework.cloud:spring-cloud-st”

    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;
    	}
    }
    

    只是修改了private static String REST_URL_PREFIX = “http://microservicecloud-provider”;

    测试:修改上述配置后,下面进行测试,启动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和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.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-provider-hystrix           #自定义服务名称信息
        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;
    修改UserController内容为:

    package com.lzj.springcloud.controller;
    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.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import com.lzj.springcloud.entity.User;
    import com.lzj.springcloud.service.UserService;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    
    @RestController
    public class UserController {
    
    	@Autowired
    	private UserService service;
    	
    	@RequestMapping(value="/get/{id}", method=RequestMethod.GET)
    	@HystrixCommand(fallbackMethod="hystrixGetUser") //一旦服务调用失败,就调用hystrixGetUser方法
    	public User getUser(@PathVariable("id") int id){
    		User user = service.getUser(id);
    		if(user == null){
    			throw new RuntimeException("不存在id=" + id + "对应的用户信息");
    		}
    		return user;
    	}
    	
    	public User hystrixGetUser(@PathVariable("id") int id){
    		User user = new User(id, "不存在该用户", 0);
    		return user;
    	}
    
    }
    

    在启动类HystrixProviderApplication上添加注解@EnableCircuitBreaker;
    启动microservice-eurake1、microservice-eurake2、microservice-eurake3服务,然后启动microservice-provider-hystrix服务,然后启动microservice-consumer-feign服务。
    测试:从浏览器中发送请求:http://localhost:7001/consumer/get/18,响应如下:
    这里写图片描述

    说明熔断起作用了,调用服务失败,返回了熔断指定的错误信息。

    2、服务降级
    在一个分布式系统中,当访问高峰期或资源有限时,需要关掉某个服务,若有请求访问该服务,不能因为系统服务关掉了,就一直中断在该调用服务处,这时就需要请求返回指定的错误信息。例如在分布式系统中有A、B两个服务,因为资源有限,需要关掉B服务,A服务在调用B服务时,没有调通,此时A返回指定的错误信息,注意不是在B服务端返回的,是A客户端返回的错误信息。看示例
    复制microservice-consumer-feign服务为microservice-consumer-feign-hystrix;
    microservice-consumer-feign-hystrix的pom文件中添加依赖:

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

    microservice-consumer-feign-hystrix服务中新建实现FallbackFactory的ConsumerServiceFallbackFactory类,在类上添加@Component,并传入ConsumerService接口,当调用ConsumerService中对应的方法失败后,自动调用ConsumerServiceFallbackFactory 中对应实现的ConsumerService方法,并在对应方法中定制调用服务失败后显示的错误信息。

    package com.lzj.springcloud.service;
    import java.util.List;
    import org.springframework.stereotype.Component;
    import com.lzj.springcloud.entity.User;
    import feign.hystrix.FallbackFactory;
    
    @Component
    public class ConsumerServiceFallbackFactory implements FallbackFactory<ConsumerService> {
    
    	@Override
    	public ConsumerService create(Throwable arg0) {
    		// TODO Auto-generated method stub
    		return new ConsumerService() {
    			
    			@Override
    			public List<User> getAll() {
    				// TODO Auto-generated method stub
    				return null;
    			}
    			
    			@Override
    			public User get(int id) {
    				User user = new User(id, "该用户不存在", 0);
    				return user;
    			}
    			
    			@Override
    			public boolean add(User user) {
    				// TODO Auto-generated method stub
    				return false;
    			}
    		};
    	}
    
    }
    

    在microservice-consumer-feign-hystrix服务中ConsumerService的接口中@FeignClient中添加fallbackFactory属性。运用spring的AOP切面,当调用ConsumerService中方法失败后,执行fallbackFactory属性指定的ConsumerServiceFallbackFactory类中的对应方法,ConsumerService修改后如下:

    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", fallbackFactory=ConsumerServiceFallbackFactory.class)
    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-hystrix服务的application.yml文件为:

    server: 
      port: 7001
    
    feign: 
      hystrix: 
        enabled: true
    
    eureka:
      client:
        register-with-eureka: false
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
    

    测试:首先启动microservice-eurake1、microservice-eurake2、microservice-eurake3集群服务,然后启动microservice-provider提供者服务,最后启动microservice-consumer-feign-hystrix消费者服务。从浏览器中发送请求

    http://localhost:7001/consumer/get/2
    
    • 1

    响应正常如下:
    这里写图片描述

    下面模拟资源有限,关掉microservice-provider提供者服务,关掉提供者服务后,重新在浏览器中发送请求http://localhost:7001/consumer/get/2,响应如下:
    这里写图片描述
    响应过程如下:当发送请求后,调用microservice-consumer-feign-hystrix服务中的UserConsumerController的get方法,然后调用ConsumerService中的get方法,该方法向microservice-provider服务发送请求/get/{id},由于microservice-provider服务被关掉了,请求失败,转而调用ConsumerServiceFallbackFactory中实现的对应方法

    			@Override
    			public User get(int id) {
    				User user = new User(id, "该用户不存在", 0);
    				return user;
    			}
    

    因此,浏览器中得到的响应是指定的错误信息。

    3、服务监控
    hystrix除了应用于上述的服务熔断和降级,还可以应用于服务的实时监控。Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。示例如下
    创建microservice-consumer-hystrix-dashbord微服务;
    添加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>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-hystrix</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-hystrix-dashboard</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>
    

    application.yml配置文件如下:

    server: 
      port: 7002
    

    创建启动类HystrixDashbordConsumerApplication:

    package com.lzj.springcloud;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
    
    @SpringBootApplication
    @EnableHystrixDashboard
    public class HystrixDashbordConsumerApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(HystrixDashbordConsumerApplication.class, args);
    	}
    
    }
    

    然后启动微服务,响应页面如下,说明创建用于监控其它服务的微服务成功:
    这里写图片描述

    测试:
    首先启动microservice-eurake1、microservice-eurake2、microservice-eurake3集群服务,然后启动microservice-provider-hystrix服务,最后启动刚创建监控服务的服务microservice-consumer-hystrix-dashbord。
    本例要监听提供者microservice-provider-hystrix服务的访问情况,下面把监控提供者服务的链接填入豪猪监控客户端中,如下
    这里写图片描述
    填入完毕后,点击Monitor stream按钮,开启监控页面。
    从浏览器中连续的发送请求http://localhost:8005/get/1(不停的刷新即可),监控页面如下:
    这里写图片描述
    图中的实心圆的颜色为绿色,表示健康,健康程度排序绿色>黄色>橙色>红色,绿色表示最健康,红色表示最不健康。实心圆的大小表示了监控的服务访问量的大小,访问量越大,实心圆越大,反之,越小。图中每个颜色数字表示如下(从别处盗图)
    这里写图片描述

    十、Zuul路由

    Zuul路由包含了对请求的路由和过滤两个功能。
    路由:路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口;
    过滤:过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
    Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。Zuul服务最终也会注册进Eureka。

    1、路由配置
    建立一个microservice-zull微服务;
    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-zull</artifactId>
      
    	<dependencies>
    		<!-- zuul路由网关 -->
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-eureka</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-zuul</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>
    

    也要把Zuul微服务注册到Eureaka上面,application.yml文件配置如下:

    server: 
      port: 6001
    
    spring:
      application:
        name: microservice-zull
    eureka:
      client:
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
      instance: 
        instance-id: microservice-zull6001                        #自定义服务名称信息
        prefer-ip-address: true                                   #访问路径可以显示IP地址
        
    info: 
      app.name: microservice-zull
      company.name: www.lzj.com
      build.artifactId: $project.artifactId$
      build.version: $project.version$
    

    在host文件中添加127.0.0.1的映射,127.0.0.1 zull6001.com用zull6001.com表示Zuul微服务的域名;
    创建ZullApplication启动类,内容如下:

    package com.lzj.springcloud;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @SpringBootApplication
    @EnableZuulProxy //启动Zuul
    public class ZullApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(ZullApplication.class, args);
    	}
    
    }
    

    测试:
    在浏览器中发送http://localhost:8002/get/2请求,直接请求microservice-provider微服务,响应如下:
    这里写图片描述

    在浏览器中发送http://zull6001.com:6001/microservicecloud-provider/get/2请求,通过Zuul路由访问microservicecloud-provider服务,其中zull6001.com:6001为microservice-zull微服务的域名和端口,microservicecloud-provider为要访问的微服务名(在application.yml中配置的),响应如下:
    这里写图片描述
    结果正常。
    2、修改服务代理名称
    上面通过路由访问服务的请求为http://zull6001.com:6001/microservicecloud-provider/get/2,其中microservicecloud-provider为调用的服务名,向调用方暴露了具体的服务名。如果不想暴露服务名,可以为服务指定一个代号别名,例如可以通过发送请求http://zull6001.com:6001/provider/get/2访问microservicecloud-provider服务,那么provider即为microservicecloud-provider的别名,在application.yml中配置如下:

    server: 
      port: 6001
    
    spring:
      application:
        name: microservice-zull
    eureka:
      client:
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
      instance: 
        instance-id: microservice-zull6001                        #自定义服务名称信息
        prefer-ip-address: true                                   #访问路径可以显示IP地址
        
    zuul:
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    
    info: 
      app.name: microservice-zull
      company.name: www.lzj.com
      build.artifactId: $project.artifactId$
      build.version: $project.version$
    

    添加了关于zuul的配置,在浏览器中发送http://zull6001.com:6001/provider/get/2请求,响应如下:
    这里写图片描述
    响应正常,此时通过发送带调用的微服务名的请求也是可以访问的。

    3、忽略带真实服务名的请求
    如果想拒绝访问中带服务名的请求,例如http://zull6001.com:6001/microservicecloud-provider/get/2,使其不能再访问服务,只能通过指定的别名进行访问服务。
    在application.yml中关于zuul的配置修改为如下(增加了ignored-services):

    zuul:
      ignored-services: microservicecloud-provider
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    

    4、设置访问前缀
    当设置完忽略真实服务名访问后,只能通过路由代理别名的形式进行访问,例如http://zull6001.com:6001/provider/get/2,如果要在每次访问的时候,在代理服务名前面加一个前缀,例如http://zull6001.com:6001/MyDemo/provider/get/2,MyDemo即为前缀。在application.yml中关于zuul的配置修改为如下(只是添加了prefix的配置):

    zuul:
      prefix: /MyDemo
      ignored-services: microservicecloud-provider
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    

    浏览器中发送http://zull6001.com:6001/MyDemo/provider/get/2请求,响应如下:
    这里写图片描述

    十一、Config配置

    一个分布式系统有可能包括非常多微服务,每个微服务都有独自的配置文件,当系统变更时,有可能需要修改很多服务的配置文件,导致运维繁琐,容易出问题,所以需要一套集中式的、动态的配置管理设施。spring cloud提供了Config来解决该问题。

    1、建立Config服务端,与github通信
    在github上建立一个respository,此地名为microservice-config,地址为:https://github.com/shuniversity/microservice-config.git;
    把建立的respository 克隆到本地E:\demo\springcloud-config-repository

    >git clone https://github.com/shuniversity/microservice-config.git
    
    • 1

    在clone到本地的仓库E:\demo\springcloud-config-repository\microservice-config中新建一个application.yml文件,内容为:

    spring:
      profiles:
        active:
          - dev
    ---
    spring:
      profiles: dev                   #开发环境
      application:
        name: microservice-config-dev
        
    ---
    spring:
      profiles: test                  #测试环境
      application:
        name: microservice-config-test
    

    把新建的application.yml文件推送到github上的microservice-config仓库中:

        git add .
        git commit -m "init file" 
        git push origin master
    

    新建microservice-config-server服务,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-config-server</artifactId>
      
    	<dependencies>
    		<!-- 依赖microservice-com模块 -->
    		<dependency>
        		<groupId>org.springframework.cloud</groupId>
        		<artifactId>spring-cloud-config-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>
    
    •  

    application.yml配置为:
    server:
    port: 4001

    spring:
      application:
        name: microservice-config-server
      cloud:
        config:
          server:
            git:
              uri: https://github.com/shuniversity/microservice-config.git
    

    建立启动类ConfigServerApp

    package com.lzj.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.config.server.EnableConfigServer;
    
    @SpringBootApplication
    @EnableConfigServer
    public class ConfigServerApp {
    
    	public static void main(String[] args) {
    
    		SpringApplication.run(ConfigServerApp.class, args);
    	}
    
    }
    

    测试:
    创建完仓库和Config的服务端工程后,下面开始测试,首先启动创建好的Config服务工程,然后再浏览器中发送请求http://localhost:4001/application-test.yml,响应如下:
    在这里插入图片描述
    在浏览器中发送http://localhost:4001/application-dev.yml请求,响应如下:
    在这里插入图片描述
    可见通过Config的服务工程可以获取github上的配置内容。

    2、创建Config的客户端
    上面一步已经成功了创建服务端,并已能够与github进行通信,下面建立Config的客户端,与上一步创建的服务端通信,通过服务端获取github上的配置信息。目前已经创建的cousumer、provider、eurake等微服务都可以改成Config的客户端,然后修改后的微服务不用在各自的微服务中application.yml中配置独有的信息,统一的把配置放在github上,由运维人员统一进行配置。

    • 下面把前面已经创建的microservice-consumer微服务复制成microservice-consumer-config-clent.yml,然后把microservice-consumer-config-clent.yml修改成Config客户端;

    • 在本地仓库添加一个配置文件microservice-consumer-config-clent.yml,用户放到github上;

      spring:
      profiles:
      active:
      - dev


      server:
      port: 7001

      spring:
      profiles: dev
      application:
      name: microservice-consumer-config-clent

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

    • 把microservice-consumer-config-clent.yml配置文件放到github上
      在这里插入图片描述

    • 修改microservice-consumer-config-client中的pom文件,config的客户端需要下面的依赖,一定不能少:
      具体关于SpringCloud介绍请参考其他文章,下面主要讲解SpringCloud搭建微服务的步骤。
      本次案例主要分为以下几个微服务

    •  提供者服务用于操作user表,进行增删改查;

    • 消费者服务用于请求提供者服务,进行增删改查;

    • 公共模块微服务,用于提供其他微服务共同需要的功能;

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

    本系统源码全部上传至github,地址为:
    https://github.com/shuniversity/MySpringCloud

    原文来自:https://blog.csdn.net/u010502101/article/details/81989756

    展开全文
  • SpringCloud 微服务 搭建

    2020-07-31 16:09:27
    记录SpringCloud微服务 搭建 过程产生的 BUG - [ ] com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server client 连接 服务端 失败 : 排查问题 : (账号密码...

    微服务思想理解

    1. 单体横向架构思想:整个项目由一个大工程搞定。(采用分布式部署,做负载均衡。也能解决日活跃量百万级别项目;缺点:维护成本高,打包部署困难,新员工接手难度大。牵一发而动全身)

    2. SOA架构:面向服务的体系结构(Service-Oriented Architecture,SOA)是一个组件模型架构思想,经历过SOA架构的dubbo项目。采用服务注册中心管理服务;(针对活跃高的服务,可以进行分布式部署。服务之间的调用也有负载均衡,通过网关进行统一管理。跟微服务区别在,服务界限的划分)

    3. springcloud微服务 : 针对于类似springcloud微服务(当然dubbo也能做,但是没有springcloud方便,更加好维护);(在soa的基础上,做到服务的划分尽可能清晰,服务之间的耦合尽可能低。例如:每个服务都应该有自己服务的数据库服务)

    springcloud的访问模式 : 前端----网关----XXXX服务(内部调用feign。经过服务中心)

    记录SpringCloud微服务 搭建 过程产生的 BUG

    - [ ] com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server

    client 连接 server 服务端 失败 :
    排查问题 : (账号密码是否正确)(注册中心地址是否完全一致)(实在找不到原因,看下springboot的包是否导入全了,例如 web,core等一系列的包)

    展开全文
  • Spring Cloud 微服务搭建

    2018-11-12 10:41:54
    spring clode体系很大很多,要实现基本的微服务需要用到: 1、服务发现与注册(Eureka-Service、Eureka-Client) 2、客户端负载均衡(Ribbon) 3、服务容错(Hystrix) 4、服务网关(Zuul) 5、服务调用(Feign...

    spring clode体系很大很多,要实现基本的微服务需要用到:

    1、服务发现与注册(Eureka-ServiceEureka-Client

    2、客户端负载均衡(Ribbon)

    3、服务容错(Hystrix)

    4、服务网关(Zuul)

    5、服务调用(Feign)

    6、配置管理  (spring cloud config)

    7、APM全链接跟踪(Pinpoint)

    展开全文
  • SpringCloud微服务搭建详解

    万次阅读 多人点赞 2018-09-23 16:13:08
    具体关于SpringCloud介绍请参考其他文章,下面主要讲解SpringCloud搭建微服务的步骤。 本次案例主要分为以下几个微服务 提供者服务用于操作user表,进行增删改查; 消费者服务用于请求提供者服务,进行增删...

    具体关于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);
    	}
    
    }
    

    5、测试
    在浏览器中发送 http://localhost:8003/consumer/add?name=lzj5&age=35
    相应如下:
    这里写图片描述

    发送请求后,在数据库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>
    

    如果出现“Failed to read artifact descriptor for org.springframework.cloud:spring-cloud-st”问题,请参考解决“Failed to read artifact descriptor for org.springframework.cloud:spring-cloud-st”

    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;
    	}
    }
    

    只是修改了private static String REST_URL_PREFIX = “http://microservicecloud-provider”;

    测试:修改上述配置后,下面进行测试,启动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.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-provider-hystrix           #自定义服务名称信息
        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;
    修改UserController内容为:

    package com.lzj.springcloud.controller;
    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.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import com.lzj.springcloud.entity.User;
    import com.lzj.springcloud.service.UserService;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    
    @RestController
    public class UserController {
    
    	@Autowired
    	private UserService service;
    	
    	@RequestMapping(value="/get/{id}", method=RequestMethod.GET)
    	@HystrixCommand(fallbackMethod="hystrixGetUser") //一旦服务调用失败,就调用hystrixGetUser方法
    	public User getUser(@PathVariable("id") int id){
    		User user = service.getUser(id);
    		if(user == null){
    			throw new RuntimeException("不存在id=" + id + "对应的用户信息");
    		}
    		return user;
    	}
    	
    	public User hystrixGetUser(@PathVariable("id") int id){
    		User user = new User(id, "不存在该用户", 0);
    		return user;
    	}
    
    }
    

    在启动类HystrixProviderApplication上添加注解@EnableCircuitBreaker;
    启动microservice-eurake1、microservice-eurake2、microservice-eurake3服务,然后启动microservice-provider-hystrix服务,然后启动microservice-consumer-feign服务。
    测试:从浏览器中发送请求:http://localhost:7001/consumer/get/18,响应如下:
    这里写图片描述

    说明熔断起作用了,调用服务失败,返回了熔断指定的错误信息。

    2、服务降级
    在一个分布式系统中,当访问高峰期或资源有限时,需要关掉某个服务,若有请求访问该服务,不能因为系统服务关掉了,就一直中断在该调用服务处,这时就需要请求返回指定的错误信息。例如在分布式系统中有A、B两个服务,因为资源有限,需要关掉B服务,A服务在调用B服务时,没有调通,此时A返回指定的错误信息,注意不是在B服务端返回的,是A客户端返回的错误信息。看示例
    复制microservice-consumer-feign服务为microservice-consumer-feign-hystrix;
    microservice-consumer-feign-hystrix的pom文件中添加依赖:

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

    microservice-consumer-feign-hystrix服务中新建实现FallbackFactory的ConsumerServiceFallbackFactory类,在类上添加@Component,并传入ConsumerService接口,当调用ConsumerService中对应的方法失败后,自动调用ConsumerServiceFallbackFactory 中对应实现的ConsumerService方法,并在对应方法中定制调用服务失败后显示的错误信息。

    package com.lzj.springcloud.service;
    import java.util.List;
    import org.springframework.stereotype.Component;
    import com.lzj.springcloud.entity.User;
    import feign.hystrix.FallbackFactory;
    
    @Component
    public class ConsumerServiceFallbackFactory implements FallbackFactory<ConsumerService> {
    
    	@Override
    	public ConsumerService create(Throwable arg0) {
    		// TODO Auto-generated method stub
    		return new ConsumerService() {
    			
    			@Override
    			public List<User> getAll() {
    				// TODO Auto-generated method stub
    				return null;
    			}
    			
    			@Override
    			public User get(int id) {
    				User user = new User(id, "该用户不存在", 0);
    				return user;
    			}
    			
    			@Override
    			public boolean add(User user) {
    				// TODO Auto-generated method stub
    				return false;
    			}
    		};
    	}
    
    }
    

    在microservice-consumer-feign-hystrix服务中ConsumerService的接口中@FeignClient中添加fallbackFactory属性。运用spring的AOP切面,当调用ConsumerService中方法失败后,执行fallbackFactory属性指定的ConsumerServiceFallbackFactory类中的对应方法,ConsumerService修改后如下:

    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", fallbackFactory=ConsumerServiceFallbackFactory.class)
    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-hystrix服务的application.yml文件为:

    server: 
      port: 7001
    
    feign: 
      hystrix: 
        enabled: true
    
    eureka:
      client:
        register-with-eureka: false
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
    

    测试:首先启动microservice-eurake1、microservice-eurake2、microservice-eurake3集群服务,然后启动microservice-provider提供者服务,最后启动microservice-consumer-feign-hystrix消费者服务。从浏览器中发送请求

    http://localhost:7001/consumer/get/2
    

    响应正常如下:
    这里写图片描述

    下面模拟资源有限,关掉microservice-provider提供者服务,关掉提供者服务后,重新在浏览器中发送请求http://localhost:7001/consumer/get/2,响应如下:
    这里写图片描述
    响应过程如下:当发送请求后,调用microservice-consumer-feign-hystrix服务中的UserConsumerController的get方法,然后调用ConsumerService中的get方法,该方法向microservice-provider服务发送请求/get/{id},由于microservice-provider服务被关掉了,请求失败,转而调用ConsumerServiceFallbackFactory中实现的对应方法

    			@Override
    			public User get(int id) {
    				User user = new User(id, "该用户不存在", 0);
    				return user;
    			}
    

    因此,浏览器中得到的响应是指定的错误信息。

    3、服务监控
    hystrix除了应用于上述的服务熔断和降级,还可以应用于服务的实时监控。Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。示例如下
    创建microservice-consumer-hystrix-dashbord微服务;
    添加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>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-hystrix</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-hystrix-dashboard</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>
    

    application.yml配置文件如下:

    server: 
      port: 7002
    

    创建启动类HystrixDashbordConsumerApplication:

    package com.lzj.springcloud;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
    
    @SpringBootApplication
    @EnableHystrixDashboard
    public class HystrixDashbordConsumerApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(HystrixDashbordConsumerApplication.class, args);
    	}
    
    }
    

    然后启动微服务,响应页面如下,说明创建用于监控其它服务的微服务成功:
    这里写图片描述

    测试:
    首先启动microservice-eurake1、microservice-eurake2、microservice-eurake3集群服务,然后启动microservice-provider-hystrix服务,最后启动刚创建监控服务的服务microservice-consumer-hystrix-dashbord。
    本例要监听提供者microservice-provider-hystrix服务的访问情况,下面把监控提供者服务的链接填入豪猪监控客户端中,如下
    这里写图片描述
    填入完毕后,点击Monitor stream按钮,开启监控页面。
    从浏览器中连续的发送请求http://localhost:8005/get/1(不停的刷新即可),监控页面如下:
    这里写图片描述
    图中的实心圆的颜色为绿色,表示健康,健康程度排序绿色>黄色>橙色>红色,绿色表示最健康,红色表示最不健康。实心圆的大小表示了监控的服务访问量的大小,访问量越大,实心圆越大,反之,越小。图中每个颜色数字表示如下(从别处盗图)
    这里写图片描述

    十、Zuul路由

    Zuul路由包含了对请求的路由和过滤两个功能。
    路由:路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口;
    过滤:过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
    Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。Zuul服务最终也会注册进Eureka。

    1、路由配置
    建立一个microservice-zull微服务;
    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-zull</artifactId>
      
    	<dependencies>
    		<!-- zuul路由网关 -->
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-eureka</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-zuul</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>
    

    也要把Zuul微服务注册到Eureaka上面,application.yml文件配置如下:

    server: 
      port: 6001
    
    spring:
      application:
        name: microservice-zull
    eureka:
      client:
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
      instance: 
        instance-id: microservice-zull6001                        #自定义服务名称信息
        prefer-ip-address: true                                   #访问路径可以显示IP地址
        
    info: 
      app.name: microservice-zull
      company.name: www.lzj.com
      build.artifactId: $project.artifactId$
      build.version: $project.version$
    

    在host文件中添加127.0.0.1的映射,127.0.0.1 zull6001.com用zull6001.com表示Zuul微服务的域名;
    创建ZullApplication启动类,内容如下:

    package com.lzj.springcloud;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @SpringBootApplication
    @EnableZuulProxy //启动Zuul
    public class ZullApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(ZullApplication.class, args);
    	}
    
    }
    

    测试:
    在浏览器中发送http://localhost:8002/get/2请求,直接请求microservice-provider微服务,响应如下:
    这里写图片描述

    在浏览器中发送http://zull6001.com:6001/microservicecloud-provider/get/2请求,通过Zuul路由访问microservicecloud-provider服务,其中zull6001.com:6001为microservice-zull微服务的域名和端口,microservicecloud-provider为要访问的微服务名(在application.yml中配置的),响应如下:
    这里写图片描述
    结果正常。
    2、修改服务代理名称
    上面通过路由访问服务的请求为http://zull6001.com:6001/microservicecloud-provider/get/2,其中microservicecloud-provider为调用的服务名,向调用方暴露了具体的服务名。如果不想暴露服务名,可以为服务指定一个代号别名,例如可以通过发送请求http://zull6001.com:6001/provider/get/2访问microservicecloud-provider服务,那么provider即为microservicecloud-provider的别名,在application.yml中配置如下:

    server: 
      port: 6001
    
    spring:
      application:
        name: microservice-zull
    eureka:
      client:
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
      instance: 
        instance-id: microservice-zull6001                        #自定义服务名称信息
        prefer-ip-address: true                                   #访问路径可以显示IP地址
        
    zuul:
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    
    info: 
      app.name: microservice-zull
      company.name: www.lzj.com
      build.artifactId: $project.artifactId$
      build.version: $project.version$
    

    添加了关于zuul的配置,在浏览器中发送http://zull6001.com:6001/provider/get/2请求,响应如下:
    这里写图片描述
    响应正常,此时通过发送带调用的微服务名的请求也是可以访问的。

    3、忽略带真实服务名的请求
    如果想拒绝访问中带服务名的请求,例如http://zull6001.com:6001/microservicecloud-provider/get/2,使其不能再访问服务,只能通过指定的别名进行访问服务。
    在application.yml中关于zuul的配置修改为如下(增加了ignored-services):

    zuul:
      ignored-services: microservicecloud-provider
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    

    4、设置访问前缀
    当设置完忽略真实服务名访问后,只能通过路由代理别名的形式进行访问,例如http://zull6001.com:6001/provider/get/2,如果要在每次访问的时候,在代理服务名前面加一个前缀,例如http://zull6001.com:6001/MyDemo/provider/get/2,MyDemo即为前缀。在application.yml中关于zuul的配置修改为如下(只是添加了prefix的配置):

    zuul:
      prefix: /MyDemo
      ignored-services: microservicecloud-provider
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    

    浏览器中发送http://zull6001.com:6001/MyDemo/provider/get/2请求,响应如下:
    这里写图片描述

    十一、Config配置

    一个分布式系统有可能包括非常多微服务,每个微服务都有独自的配置文件,当系统变更时,有可能需要修改很多服务的配置文件,导致运维繁琐,容易出问题,所以需要一套集中式的、动态的配置管理设施。spring cloud提供了Config来解决该问题。

    1、建立Config服务端,与github通信
    在github上建立一个respository,此地名为microservice-config,地址为:https://github.com/shuniversity/microservice-config.git;
    把建立的respository 克隆到本地E:\demo\springcloud-config-repository

    >git clone https://github.com/shuniversity/microservice-config.git
    

    在clone到本地的仓库E:\demo\springcloud-config-repository\microservice-config中新建一个application.yml文件,内容为:

    spring:
      profiles:
        active:
          - dev
    ---
    spring:
      profiles: dev                   #开发环境
      application:
        name: microservice-config-dev
        
    ---
    spring:
      profiles: test                  #测试环境
      application:
        name: microservice-config-test
    

    把新建的application.yml文件推送到github上的microservice-config仓库中:

        git add .
        git commit -m "init file" 
        git push origin master
    

    新建microservice-config-server服务,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-config-server</artifactId>
      
    	<dependencies>
    		<!-- 依赖microservice-com模块 -->
    		<dependency>
        		<groupId>org.springframework.cloud</groupId>
        		<artifactId>spring-cloud-config-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>
    

    application.yml配置为:
    server:
    port: 4001

    spring:
      application:
        name: microservice-config-server
      cloud:
        config:
          server:
            git:
              uri: https://github.com/shuniversity/microservice-config.git
    

    建立启动类ConfigServerApp

    package com.lzj.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.config.server.EnableConfigServer;
    
    @SpringBootApplication
    @EnableConfigServer
    public class ConfigServerApp {
    
    	public static void main(String[] args) {
    
    		SpringApplication.run(ConfigServerApp.class, args);
    	}
    
    }
    

    测试:
    创建完仓库和Config的服务端工程后,下面开始测试,首先启动创建好的Config服务工程,然后再浏览器中发送请求http://localhost:4001/application-test.yml,响应如下:
    在这里插入图片描述
    在浏览器中发送http://localhost:4001/application-dev.yml请求,响应如下:
    在这里插入图片描述
    可见通过Config的服务工程可以获取github上的配置内容。

    2、创建Config的客户端
    上面一步已经成功了创建服务端,并已能够与github进行通信,下面建立Config的客户端,与上一步创建的服务端通信,通过服务端获取github上的配置信息。目前已经创建的cousumer、provider、eurake等微服务都可以改成Config的客户端,然后修改后的微服务不用在各自的微服务中application.yml中配置独有的信息,统一的把配置放在github上,由运维人员统一进行配置。

    • 下面把前面已经创建的microservice-consumer微服务复制成microservice-consumer-config-clent.yml,然后把microservice-consumer-config-clent.yml修改成Config客户端;

    • 在本地仓库添加一个配置文件microservice-consumer-config-clent.yml,用户放到github上;

      spring:
      profiles:
      active:
      - dev


      server:
      port: 7001

      spring:
      profiles: dev
      application:
      name: microservice-consumer-config-clent

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

    • 把microservice-consumer-config-clent.yml配置文件放到github上
      在这里插入图片描述

    • 修改microservice-consumer-config-client中的pom文件,config的客户端需要下面的依赖,一定不能少:
      具体关于SpringCloud介绍请参考其他文章,下面主要讲解SpringCloud搭建微服务的步骤。
      本次案例主要分为以下几个微服务

    • 提供者服务用于操作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模式要选择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模式,后续的微服都是如此。
    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);
    	}
    
    }
    

    5、测试
    在浏览器中发送 http://localhost:8003/consumer/add?name=lzj5&age=35
    相应如下:
    这里写图片描述

    发送请求后,在数据库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>
    

    如果出现“Failed to read artifact descriptor for org.springframework.cloud:spring-cloud-st”问题,请参考解决“Failed to read artifact descriptor for org.springframework.cloud:spring-cloud-st”

    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;
    	}
    }
    

    只是修改了private static String REST_URL_PREFIX = “http://microservicecloud-provider”;

    测试:修改上述配置后,下面进行测试,启动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.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-provider-hystrix           #自定义服务名称信息
        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;
    修改UserController内容为:

    package com.lzj.springcloud.controller;
    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.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import com.lzj.springcloud.entity.User;
    import com.lzj.springcloud.service.UserService;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    
    @RestController
    public class UserController {
    
    	@Autowired
    	private UserService service;
    	
    	@RequestMapping(value="/get/{id}", method=RequestMethod.GET)
    	@HystrixCommand(fallbackMethod="hystrixGetUser") //一旦服务调用失败,就调用hystrixGetUser方法
    	public User getUser(@PathVariable("id") int id){
    		User user = service.getUser(id);
    		if(user == null){
    			throw new RuntimeException("不存在id=" + id + "对应的用户信息");
    		}
    		return user;
    	}
    	
    	public User hystrixGetUser(@PathVariable("id") int id){
    		User user = new User(id, "不存在该用户", 0);
    		return user;
    	}
    
    }
    

    在启动类HystrixProviderApplication上添加注解@EnableCircuitBreaker;
    启动microservice-eurake1、microservice-eurake2、microservice-eurake3服务,然后启动microservice-provider-hystrix服务,然后启动microservice-consumer-feign服务。
    测试:从浏览器中发送请求:http://localhost:7001/consumer/get/18,响应如下:
    这里写图片描述

    说明熔断起作用了,调用服务失败,返回了熔断指定的错误信息。

    2、服务降级
    在一个分布式系统中,当访问高峰期或资源有限时,需要关掉某个服务,若有请求访问该服务,不能因为系统服务关掉了,就一直中断在该调用服务处,这时就需要请求返回指定的错误信息。例如在分布式系统中有A、B两个服务,因为资源有限,需要关掉B服务,A服务在调用B服务时,没有调通,此时A返回指定的错误信息,注意不是在B服务端返回的,是A客户端返回的错误信息。看示例
    复制microservice-consumer-feign服务为microservice-consumer-feign-hystrix;
    microservice-consumer-feign-hystrix的pom文件中添加依赖:

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

    microservice-consumer-feign-hystrix服务中新建实现FallbackFactory的ConsumerServiceFallbackFactory类,在类上添加@Component,并传入ConsumerService接口,当调用ConsumerService中对应的方法失败后,自动调用ConsumerServiceFallbackFactory 中对应实现的ConsumerService方法,并在对应方法中定制调用服务失败后显示的错误信息。

    package com.lzj.springcloud.service;
    import java.util.List;
    import org.springframework.stereotype.Component;
    import com.lzj.springcloud.entity.User;
    import feign.hystrix.FallbackFactory;
    
    @Component
    public class ConsumerServiceFallbackFactory implements FallbackFactory<ConsumerService> {
    
    	@Override
    	public ConsumerService create(Throwable arg0) {
    		// TODO Auto-generated method stub
    		return new ConsumerService() {
    			
    			@Override
    			public List<User> getAll() {
    				// TODO Auto-generated method stub
    				return null;
    			}
    			
    			@Override
    			public User get(int id) {
    				User user = new User(id, "该用户不存在", 0);
    				return user;
    			}
    			
    			@Override
    			public boolean add(User user) {
    				// TODO Auto-generated method stub
    				return false;
    			}
    		};
    	}
    
    }
    

    在microservice-consumer-feign-hystrix服务中ConsumerService的接口中@FeignClient中添加fallbackFactory属性。运用spring的AOP切面,当调用ConsumerService中方法失败后,执行fallbackFactory属性指定的ConsumerServiceFallbackFactory类中的对应方法,ConsumerService修改后如下:

    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", fallbackFactory=ConsumerServiceFallbackFactory.class)
    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-hystrix服务的application.yml文件为:

    server: 
      port: 7001
    
    feign: 
      hystrix: 
        enabled: true
    
    eureka:
      client:
        register-with-eureka: false
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
    

    测试:首先启动microservice-eurake1、microservice-eurake2、microservice-eurake3集群服务,然后启动microservice-provider提供者服务,最后启动microservice-consumer-feign-hystrix消费者服务。从浏览器中发送请求

    http://localhost:7001/consumer/get/2
    

    响应正常如下:
    这里写图片描述

    下面模拟资源有限,关掉microservice-provider提供者服务,关掉提供者服务后,重新在浏览器中发送请求http://localhost:7001/consumer/get/2,响应如下:
    这里写图片描述
    响应过程如下:当发送请求后,调用microservice-consumer-feign-hystrix服务中的UserConsumerController的get方法,然后调用ConsumerService中的get方法,该方法向microservice-provider服务发送请求/get/{id},由于microservice-provider服务被关掉了,请求失败,转而调用ConsumerServiceFallbackFactory中实现的对应方法

    			@Override
    			public User get(int id) {
    				User user = new User(id, "该用户不存在", 0);
    				return user;
    			}
    

    因此,浏览器中得到的响应是指定的错误信息。

    3、服务监控
    hystrix除了应用于上述的服务熔断和降级,还可以应用于服务的实时监控。Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。示例如下
    创建microservice-consumer-hystrix-dashbord微服务;
    添加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>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-hystrix</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-hystrix-dashboard</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>
    

    application.yml配置文件如下:

    server: 
      port: 7002
    

    创建启动类HystrixDashbordConsumerApplication:

    package com.lzj.springcloud;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
    
    @SpringBootApplication
    @EnableHystrixDashboard
    public class HystrixDashbordConsumerApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(HystrixDashbordConsumerApplication.class, args);
    	}
    
    }
    

    然后启动微服务,响应页面如下,说明创建用于监控其它服务的微服务成功:
    这里写图片描述

    测试:
    首先启动microservice-eurake1、microservice-eurake2、microservice-eurake3集群服务,然后启动microservice-provider-hystrix服务,最后启动刚创建监控服务的服务microservice-consumer-hystrix-dashbord。
    本例要监听提供者microservice-provider-hystrix服务的访问情况,下面把监控提供者服务的链接填入豪猪监控客户端中,如下
    这里写图片描述
    填入完毕后,点击Monitor stream按钮,开启监控页面。
    从浏览器中连续的发送请求http://localhost:8005/get/1(不停的刷新即可),监控页面如下:
    这里写图片描述
    图中的实心圆的颜色为绿色,表示健康,健康程度排序绿色>黄色>橙色>红色,绿色表示最健康,红色表示最不健康。实心圆的大小表示了监控的服务访问量的大小,访问量越大,实心圆越大,反之,越小。图中每个颜色数字表示如下(从别处盗图)
    这里写图片描述

    十、Zuul路由

    Zuul路由包含了对请求的路由和过滤两个功能。
    路由:路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口;
    过滤:过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
    Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。Zuul服务最终也会注册进Eureka。

    1、路由配置
    建立一个microservice-zull微服务;
    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-zull</artifactId>
      
    	<dependencies>
    		<!-- zuul路由网关 -->
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-eureka</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-zuul</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>
    

    也要把Zuul微服务注册到Eureaka上面,application.yml文件配置如下:

    server: 
      port: 6001
    
    spring:
      application:
        name: microservice-zull
    eureka:
      client:
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
      instance: 
        instance-id: microservice-zull6001                        #自定义服务名称信息
        prefer-ip-address: true                                   #访问路径可以显示IP地址
        
    info: 
      app.name: microservice-zull
      company.name: www.lzj.com
      build.artifactId: $project.artifactId$
      build.version: $project.version$
    

    在host文件中添加127.0.0.1的映射,127.0.0.1 zull6001.com用zull6001.com表示Zuul微服务的域名;
    创建ZullApplication启动类,内容如下:

    package com.lzj.springcloud;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @SpringBootApplication
    @EnableZuulProxy //启动Zuul
    public class ZullApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(ZullApplication.class, args);
    	}
    
    }
    

    测试:
    在浏览器中发送http://localhost:8002/get/2请求,直接请求microservice-provider微服务,响应如下:
    这里写图片描述

    在浏览器中发送http://zull6001.com:6001/microservicecloud-provider/get/2请求,通过Zuul路由访问microservicecloud-provider服务,其中zull6001.com:6001为microservice-zull微服务的域名和端口,microservicecloud-provider为要访问的微服务名(在application.yml中配置的),响应如下:
    这里写图片描述
    结果正常。
    2、修改服务代理名称
    上面通过路由访问服务的请求为http://zull6001.com:6001/microservicecloud-provider/get/2,其中microservicecloud-provider为调用的服务名,向调用方暴露了具体的服务名。如果不想暴露服务名,可以为服务指定一个代号别名,例如可以通过发送请求http://zull6001.com:6001/provider/get/2访问microservicecloud-provider服务,那么provider即为microservicecloud-provider的别名,在application.yml中配置如下:

    server: 
      port: 6001
    
    spring:
      application:
        name: microservice-zull
    eureka:
      client:
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
      instance: 
        instance-id: microservice-zull6001                        #自定义服务名称信息
        prefer-ip-address: true                                   #访问路径可以显示IP地址
        
    zuul:
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    
    info: 
      app.name: microservice-zull
      company.name: www.lzj.com
      build.artifactId: $project.artifactId$
      build.version: $project.version$
    

    添加了关于zuul的配置,在浏览器中发送http://zull6001.com:6001/provider/get/2请求,响应如下:
    这里写图片描述
    响应正常,此时通过发送带调用的微服务名的请求也是可以访问的。

    3、忽略带真实服务名的请求
    如果想拒绝访问中带服务名的请求,例如http://zull6001.com:6001/microservicecloud-provider/get/2,使其不能再访问服务,只能通过指定的别名进行访问服务。
    在application.yml中关于zuul的配置修改为如下(增加了ignored-services):

    zuul:
      ignored-services: microservicecloud-provider
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    

    4、设置访问前缀
    当设置完忽略真实服务名访问后,只能通过路由代理别名的形式进行访问,例如http://zull6001.com:6001/provider/get/2,如果要在每次访问的时候,在代理服务名前面加一个前缀,例如http://zull6001.com:6001/MyDemo/provider/get/2,MyDemo即为前缀。在application.yml中关于zuul的配置修改为如下(只是添加了prefix的配置):

    zuul:
      prefix: /MyDemo
      ignored-services: microservicecloud-provider
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    

    浏览器中发送http://zull6001.com:6001/MyDemo/provider/get/2请求,响应如下:
    这里写图片描述

    十一、Config配置

    一个分布式系统有可能包括非常多微服务,每个微服务都有独自的配置文件,当系统变更时,有可能需要修改很多服务的配置文件,导致运维繁琐,容易出问题,所以需要一套集中式的、动态的配置管理设施。spring cloud提供了Config来解决该问题。

    1、建立Config服务端,与github通信
    在github上建立一个respository,此地名为microservice-config,地址为:https://github.com/shuniversity/microservice-config.git;
    把建立的respository 克隆到本地E:\demo\springcloud-config-repository

    >git clone https://github.com/shuniversity/microservice-config.git
    

    在clone到本地的仓库E:\demo\springcloud-config-repository\microservice-config中新建一个application.yml文件,内容为:

    spring:
      profiles:
        active:
          - dev
    ---
    spring:
      profiles: dev                   #开发环境
      application:
        name: microservice-config-dev
        
    ---
    spring:
      profiles: test                  #测试环境
      application:
        name: microservice-config-test
    

    把新建的application.yml文件推送到github上的microservice-config仓库中:

        git add .
        git commit -m "init file" 
        git push origin master
    

    新建microservice-config-server服务,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-config-server</artifactId>
      
    	<dependencies>
    		<!-- 依赖microservice-com模块 -->
    		<dependency>
        		<groupId>org.springframework.cloud</groupId>
        		<artifactId>spring-cloud-config-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>
    

    application.yml配置为:
    server:
    port: 4001

    spring:
      application:
        name: microservice-config-server
      cloud:
        config:
          server:
            git:
              uri: https://github.com/shuniversity/microservice-config.git
    

    建立启动类ConfigServerApp

    package com.lzj.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.config.server.EnableConfigServer;
    
    @SpringBootApplication
    @EnableConfigServer
    public class ConfigServerApp {
    
    	public static void main(String[] args) {
    
    		SpringApplication.run(ConfigServerApp.class, args);
    	}
    
    }
    

    测试:
    创建完仓库和Config的服务端工程后,下面开始测试,首先启动创建好的Config服务工程,然后再浏览器中发送请求http://localhost:4001/application-test.yml,响应如下:
    在这里插入图片描述
    在浏览器中发送http://localhost:4001/application-dev.yml请求,响应如下:
    在这里插入图片描述
    可见通过Config的服务工程可以获取github上的配置内容。

    2、创建Config的客户端
    上面一步已经成功了创建服务端,并已能够与github进行通信,下面建立Config的客户端,与上一步创建的服务端通信,通过服务端获取github上的配置信息。目前已经创建的cousumer、provider、eurake等微服务都可以改成Config的客户端,然后修改后的微服务不用在各自的微服务中application.yml中配置独有的信息,统一的把配置放在github上,由运维人员统一进行配置。

    • 下面把前面已经创建的microservice-consumer微服务复制成microservice-consumer-config-clent.yml,然后把microservice-consumer-config-clent.yml修改成Config客户端;

    • 在本地仓库添加一个配置文件microservice-consumer-config-clent.yml,用户放到github上;

      spring:
      profiles:
      active:
      - dev


      server:
      port: 7001

      spring:
      profiles: dev
      application:
      name: microservice-consumer-config-clent

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

    • 把microservice-consumer-config-clent.yml配置文件放到github上
      在这里插入图片描述

    • 修改microservice-consumer-config-client中的pom文件,config的客户端需要下面的依赖,一定不能少:

    ‘’’
    具体关于SpringCloud介绍请参考其他文章,下面主要讲解SpringCloud搭建微服务的步骤。
    本次案例主要分为以下几个微服务

    • 提供者服务用于操作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模式要选择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模式,后续的微服都是如此。
    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);
    	}
    
    }
    

    5、测试
    在浏览器中发送 http://localhost:8003/consumer/add?name=lzj5&age=35
    相应如下:
    这里写图片描述

    发送请求后,在数据库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>
    

    如果出现“Failed to read artifact descriptor for org.springframework.cloud:spring-cloud-st”问题,请参考解决“Failed to read artifact descriptor for org.springframework.cloud:spring-cloud-st”

    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;
    	}
    }
    

    只是修改了private static String REST_URL_PREFIX = “http://microservicecloud-provider”;

    测试:修改上述配置后,下面进行测试,启动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.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-provider-hystrix           #自定义服务名称信息
        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;
    修改UserController内容为:

    package com.lzj.springcloud.controller;
    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.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import com.lzj.springcloud.entity.User;
    import com.lzj.springcloud.service.UserService;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    
    @RestController
    public class UserController {
    
    	@Autowired
    	private UserService service;
    	
    	@RequestMapping(value="/get/{id}", method=RequestMethod.GET)
    	@HystrixCommand(fallbackMethod="hystrixGetUser") //一旦服务调用失败,就调用hystrixGetUser方法
    	public User getUser(@PathVariable("id") int id){
    		User user = service.getUser(id);
    		if(user == null){
    			throw new RuntimeException("不存在id=" + id + "对应的用户信息");
    		}
    		return user;
    	}
    	
    	public User hystrixGetUser(@PathVariable("id") int id){
    		User user = new User(id, "不存在该用户", 0);
    		return user;
    	}
    
    }
    

    在启动类HystrixProviderApplication上添加注解@EnableCircuitBreaker;
    启动microservice-eurake1、microservice-eurake2、microservice-eurake3服务,然后启动microservice-provider-hystrix服务,然后启动microservice-consumer-feign服务。
    测试:从浏览器中发送请求:http://localhost:7001/consumer/get/18,响应如下:
    这里写图片描述

    说明熔断起作用了,调用服务失败,返回了熔断指定的错误信息。

    2、服务降级
    在一个分布式系统中,当访问高峰期或资源有限时,需要关掉某个服务,若有请求访问该服务,不能因为系统服务关掉了,就一直中断在该调用服务处,这时就需要请求返回指定的错误信息。例如在分布式系统中有A、B两个服务,因为资源有限,需要关掉B服务,A服务在调用B服务时,没有调通,此时A返回指定的错误信息,注意不是在B服务端返回的,是A客户端返回的错误信息。看示例
    复制microservice-consumer-feign服务为microservice-consumer-feign-hystrix;
    microservice-consumer-feign-hystrix的pom文件中添加依赖:

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

    microservice-consumer-feign-hystrix服务中新建实现FallbackFactory的ConsumerServiceFallbackFactory类,在类上添加@Component,并传入ConsumerService接口,当调用ConsumerService中对应的方法失败后,自动调用ConsumerServiceFallbackFactory 中对应实现的ConsumerService方法,并在对应方法中定制调用服务失败后显示的错误信息。

    package com.lzj.springcloud.service;
    import java.util.List;
    import org.springframework.stereotype.Component;
    import com.lzj.springcloud.entity.User;
    import feign.hystrix.FallbackFactory;
    
    @Component
    public class ConsumerServiceFallbackFactory implements FallbackFactory<ConsumerService> {
    
    	@Override
    	public ConsumerService create(Throwable arg0) {
    		// TODO Auto-generated method stub
    		return new ConsumerService() {
    			
    			@Override
    			public List<User> getAll() {
    				// TODO Auto-generated method stub
    				return null;
    			}
    			
    			@Override
    			public User get(int id) {
    				User user = new User(id, "该用户不存在", 0);
    				return user;
    			}
    			
    			@Override
    			public boolean add(User user) {
    				// TODO Auto-generated method stub
    				return false;
    			}
    		};
    	}
    
    }
    

    在microservice-consumer-feign-hystrix服务中ConsumerService的接口中@FeignClient中添加fallbackFactory属性。运用spring的AOP切面,当调用ConsumerService中方法失败后,执行fallbackFactory属性指定的ConsumerServiceFallbackFactory类中的对应方法,ConsumerService修改后如下:

    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", fallbackFactory=ConsumerServiceFallbackFactory.class)
    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-hystrix服务的application.yml文件为:

    server: 
      port: 7001
    
    feign: 
      hystrix: 
        enabled: true
    
    eureka:
      client:
        register-with-eureka: false
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
    

    测试:首先启动microservice-eurake1、microservice-eurake2、microservice-eurake3集群服务,然后启动microservice-provider提供者服务,最后启动microservice-consumer-feign-hystrix消费者服务。从浏览器中发送请求

    http://localhost:7001/consumer/get/2
    

    响应正常如下:
    这里写图片描述

    下面模拟资源有限,关掉microservice-provider提供者服务,关掉提供者服务后,重新在浏览器中发送请求http://localhost:7001/consumer/get/2,响应如下:
    这里写图片描述
    响应过程如下:当发送请求后,调用microservice-consumer-feign-hystrix服务中的UserConsumerController的get方法,然后调用ConsumerService中的get方法,该方法向microservice-provider服务发送请求/get/{id},由于microservice-provider服务被关掉了,请求失败,转而调用ConsumerServiceFallbackFactory中实现的对应方法

    			@Override
    			public User get(int id) {
    				User user = new User(id, "该用户不存在", 0);
    				return user;
    			}
    

    因此,浏览器中得到的响应是指定的错误信息。

    3、服务监控
    hystrix除了应用于上述的服务熔断和降级,还可以应用于服务的实时监控。Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。示例如下
    创建microservice-consumer-hystrix-dashbord微服务;
    添加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>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-hystrix</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-hystrix-dashboard</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>
    

    application.yml配置文件如下:

    server: 
      port: 7002
    

    创建启动类HystrixDashbordConsumerApplication:

    package com.lzj.springcloud;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
    
    @SpringBootApplication
    @EnableHystrixDashboard
    public class HystrixDashbordConsumerApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(HystrixDashbordConsumerApplication.class, args);
    	}
    
    }
    

    然后启动微服务,响应页面如下,说明创建用于监控其它服务的微服务成功:
    这里写图片描述

    测试:
    首先启动microservice-eurake1、microservice-eurake2、microservice-eurake3集群服务,然后启动microservice-provider-hystrix服务,最后启动刚创建监控服务的服务microservice-consumer-hystrix-dashbord。
    本例要监听提供者microservice-provider-hystrix服务的访问情况,下面把监控提供者服务的链接填入豪猪监控客户端中,如下
    这里写图片描述
    填入完毕后,点击Monitor stream按钮,开启监控页面。
    从浏览器中连续的发送请求http://localhost:8005/get/1(不停的刷新即可),监控页面如下:
    这里写图片描述
    图中的实心圆的颜色为绿色,表示健康,健康程度排序绿色>黄色>橙色>红色,绿色表示最健康,红色表示最不健康。实心圆的大小表示了监控的服务访问量的大小,访问量越大,实心圆越大,反之,越小。图中每个颜色数字表示如下(从别处盗图)
    这里写图片描述

    十、Zuul路由

    Zuul路由包含了对请求的路由和过滤两个功能。
    路由:路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口;
    过滤:过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
    Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。Zuul服务最终也会注册进Eureka。

    1、路由配置
    建立一个microservice-zull微服务;
    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-zull</artifactId>
      
    	<dependencies>
    		<!-- zuul路由网关 -->
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-eureka</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-zuul</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>
    

    也要把Zuul微服务注册到Eureaka上面,application.yml文件配置如下:

    server: 
      port: 6001
    
    spring:
      application:
        name: microservice-zull
    eureka:
      client:
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
      instance: 
        instance-id: microservice-zull6001                        #自定义服务名称信息
        prefer-ip-address: true                                   #访问路径可以显示IP地址
        
    info: 
      app.name: microservice-zull
      company.name: www.lzj.com
      build.artifactId: $project.artifactId$
      build.version: $project.version$
    

    在host文件中添加127.0.0.1的映射,127.0.0.1 zull6001.com用zull6001.com表示Zuul微服务的域名;
    创建ZullApplication启动类,内容如下:

    package com.lzj.springcloud;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @SpringBootApplication
    @EnableZuulProxy //启动Zuul
    public class ZullApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(ZullApplication.class, args);
    	}
    
    }
    

    测试:
    在浏览器中发送http://localhost:8002/get/2请求,直接请求microservice-provider微服务,响应如下:
    这里写图片描述

    在浏览器中发送http://zull6001.com:6001/microservicecloud-provider/get/2请求,通过Zuul路由访问microservicecloud-provider服务,其中zull6001.com:6001为microservice-zull微服务的域名和端口,microservicecloud-provider为要访问的微服务名(在application.yml中配置的),响应如下:
    这里写图片描述
    结果正常。
    2、修改服务代理名称
    上面通过路由访问服务的请求为http://zull6001.com:6001/microservicecloud-provider/get/2,其中microservicecloud-provider为调用的服务名,向调用方暴露了具体的服务名。如果不想暴露服务名,可以为服务指定一个代号别名,例如可以通过发送请求http://zull6001.com:6001/provider/get/2访问microservicecloud-provider服务,那么provider即为microservicecloud-provider的别名,在application.yml中配置如下:

    server: 
      port: 6001
    
    spring:
      application:
        name: microservice-zull
    eureka:
      client:
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
      instance: 
        instance-id: microservice-zull6001                        #自定义服务名称信息
        prefer-ip-address: true                                   #访问路径可以显示IP地址
        
    zuul:
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    
    info: 
      app.name: microservice-zull
      company.name: www.lzj.com
      build.artifactId: $project.artifactId$
      build.version: $project.version$
    

    添加了关于zuul的配置,在浏览器中发送http://zull6001.com:6001/provider/get/2请求,响应如下:
    这里写图片描述
    响应正常,此时通过发送带调用的微服务名的请求也是可以访问的。

    3、忽略带真实服务名的请求
    如果想拒绝访问中带服务名的请求,例如http://zull6001.com:6001/microservicecloud-provider/get/2,使其不能再访问服务,只能通过指定的别名进行访问服务。
    在application.yml中关于zuul的配置修改为如下(增加了ignored-services):

    zuul:
      ignored-services: microservicecloud-provider
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    

    4、设置访问前缀
    当设置完忽略真实服务名访问后,只能通过路由代理别名的形式进行访问,例如http://zull6001.com:6001/provider/get/2,如果要在每次访问的时候,在代理服务名前面加一个前缀,例如http://zull6001.com:6001/MyDemo/provider/get/2,MyDemo即为前缀。在application.yml中关于zuul的配置修改为如下(只是添加了prefix的配置):

    zuul:
      prefix: /MyDemo
      ignored-services: microservicecloud-provider
      routes:
        mydept.serviceId: microservicecloud-provider
        mydept.path: /provider/**
    

    浏览器中发送http://zull6001.com:6001/MyDemo/provider/get/2请求,响应如下:
    这里写图片描述

    十一、Config配置

    一个分布式系统有可能包括非常多微服务,每个微服务都有独自的配置文件,当系统变更时,有可能需要修改很多服务的配置文件,导致运维繁琐,容易出问题,所以需要一套集中式的、动态的配置管理设施。spring cloud提供了Config来解决该问题。Config的Server端用来连接github,Config的Client端通过Server端去github请求相关的配置信息。

    1、建立Config服务端,与github通信
    在github上建立一个respository,此地名为microservice-config,地址为:https://github.com/shuniversity/microservice-config.git;
    把建立的respository 克隆到本地E:\demo\springcloud-config-repository

    >git clone https://github.com/shuniversity/microservice-config.git
    

    在clone到本地的仓库E:\demo\springcloud-config-repository\microservice-config中新建一个application.yml文件,内容为:

    spring:
      profiles:
        active:
          - dev
    ---
    spring:
      profiles: dev                   #开发环境
      application:
        name: microservice-config-dev
        
    ---
    spring:
      profiles: test                  #测试环境
      application:
        name: microservice-config-test
    

    把新建的application.yml文件推送到github上的microservice-config仓库中:

        git add .
        git commit -m "init file" 
        git push origin master
    

    新建microservice-config-server服务,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-config-server</artifactId>
      
    	<dependencies>
    		<!-- 依赖microservice-com模块 -->
    		<dependency>
        		<groupId>org.springframework.cloud</groupId>
        		<artifactId>spring-cloud-config-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>
    

    application.yml配置为:
    server:
    port: 4001

    spring:
      application:
        name: microservice-config-server
      cloud:
        config:
          server:
            git:
              uri: https://github.com/shuniversity/microservice-config.git
    

    建立启动类ConfigServerApp

    package com.lzj.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.config.server.EnableConfigServer;
    
    @SpringBootApplication
    @EnableConfigServer
    public class ConfigServerApp {
    
    	public static void main(String[] args) {
    
    		SpringApplication.run(ConfigServerApp.class, args);
    	}
    
    }
    

    测试:
    创建完仓库和Config的服务端工程后,下面开始测试,首先启动创建好的Config服务工程,然后再浏览器中发送请求http://localhost:4001/application-test.yml,响应如下:
    在这里插入图片描述
    在浏览器中发送http://localhost:4001/application-dev.yml请求,响应如下:
    在这里插入图片描述
    可见通过Config的服务工程可以获取github上的配置内容。

    2、创建Config的客户端
    上面一步已经成功了创建服务端,并已能够与github进行通信,下面建立Config的客户端,与上一步创建的服务端通信,通过服务端获取github上的配置信息。目前已经创建的cousumer、provider、eurake等微服务都可以改成Config的客户端,然后修改后的微服务不用在各自的微服务中application.yml中配置独有的信息,统一的把配置放在github上,由运维人员统一进行配置。

    • 下面把前面已经创建的microservice-consumer微服务工程复制成microservice-consumer-config-clent微服务工程,然后把microservice-consumer-config-clent修改成Config客户端;
    • 在本地仓库添加一个配置文件microservice-consumer-config-clent.yml,用户放到github上;
    spring:
      profiles:
        active:
          - dev
    
    ---
    server: 
      port: 7003
    
    spring:
      profiles: dev
      application:
        name: microservice-consumer-config-clent
    
    eureka:
      client:
        register-with-eureka: false
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
    
    ---
    server: 
      port: 7004
    
    spring:
      profiles: test
      application:
        name: microservice-consumer-config-clent
    
    eureka:
      client:
        register-with-eureka: false
        service-url: 
          defaultZone: http://eureka9003.com:9003/eureka/,http://eureka9002.com:9002/eureka/,http://eureka9001.com:9001/eureka/
    
    • 把microservice-consumer-config-clent.yml配置文件放到github上
      在这里插入图片描述

    • 修改microservice-consumer-config-client中的pom文件,config的客户端需要下面的依赖,一定不能少:

       <dependency>
       	<groupId>org.springframework.cloud</groupId>
       	<artifactId>spring-cloud-starter-config</artifactId>
       </dependency>
      
    • 在microservice-consumer-config-client工程中添加bootstrap.yml配置文件,bootstrap.yml为系统级的配置文件,application.yml为用户级的配置文件,bootstrap.yml的优先级高,服务启动时会优先加载。bootstrap中主要配置了通过Config服务端从github上获取配置信息,bootstrap.yml内容为:

      spring:
      cloud:
        config:
          name: microservice-consumer-config-client #需要从github上读取的资源名,没有yml后缀;microservice-consumer-config-client.yml为已经长传到github的配置文件
          profile: dev
          label: master
          uri: http://127.0.0.1:4001 #config的服务端地址,等config的客户端和服务端启动后,客户端去查找这个指定的config的服务端,通过服务端获取github上配置文件信息
    
    • application.yml可配置可不配置,把application.yml修改为如下:
     spring:
      profiles: dev
      application:
        name: microservice-consumer-config-clent
    
    • 测试
      环境搭载完毕,开始测试,首先启动microservice-eurake1、microservice-eurake2、microservice-eurake3集群,然后启动microservice-provider服务,然后启动microservice-config-server微服务,最后启动刚创建的microservice-consumer-config-client微服务。从浏览器中发送http://127.0.0.1:7003/consumer/get/2请求,响应如下:
      在这里插入图片描述

    解析:上述微服务都启动后,microservice-consumer-config-client通过microservice-config-server微服务获取github上的microservice-consumer-config-clent.yml中的dev配置信息,获取后的配置信息把microservice-consumer-config-client微服务的端口配置成了7003,然后从浏览器中发送http://127.0.0.1:7003/consumer/get/2请求后,microservice-consumer-config-client微服务中的controller层截获请求后,然后去eurake集群上去查找要调用的microservice-provider微服务,然后调用microservice-provider中的对应接口方法,接口方法中操作数据库。

    至此,目前一个简单的分布式微服务系统构建而成,整个系统服务如下:
    在这里插入图片描述

    本系统源码全部上传至github,地址为:
    https://github.com/shuniversity/MySpringCloud

    展开全文
  • cloud-starter-eureka 1.4.6.RELEASE org.springframework.cloud spring-cloud-starter-netflix-eureka-client 2.0.2.RELEASE org.springframework.cloud spring-cloud-config-client 2.1.2.RELEASE org.spring...
  • 微服务搭建微服务常用几大组件微服务搭建步骤搭建SpringBoot项目搭建注册中心Eureka搭建提供者搭建消费者Feign搭建zuul搭建熔断器Hystrix运行测试 微服务常用几大组件 服务治理: Spring Cloud Eureka 客户端负载...
  • Spring Cloud 微服务搭建 (一)注册中心创建之eureka_server 1、添加依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=...
  • Spring Cloud 微服务搭建 (一)注册中心创建之eureka 1、在pom文件中添加依赖。 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=...
  • springboot springcloud微服务搭建测试 1)step 1 https://blog.csdn.net/csuzxm2000/article/details/86511847 2) step 2 创建Eureka注册中心https://blog.csdn.net/csuzxm2000/article/details/86509088 注意:...
  • 接上一篇:Spring cloud微服务搭建(七)——Feign面向接口编程 服务熔断,是指某个服务超时或异常,引起熔断,起到保险丝的作用。 针对服务方而言,只涉及修改服务提供方。 Maven依赖 <!-- ...
  • SpringCloud微服务搭建(一)和(二)中,说白了就是建了一个eurekaServer而已 既没用到maven的聚合工程,也没真正地开始注册服务。接下来给大家带点干货! 想要了解微服务的注册,首先要了解什么是消费者和提供者...
  • 接上一篇:Spring cloud微服务搭建(五)——Eureka注册服务 Ribbon是Netflix发布的开源项目,提供客户端的软件负载均衡算法。 Ribbon属于进程内负载均衡,作为一个类库,集成于消费方进程中。消费方通过ribbon连接到...
  • 接上一篇:Spring cloud微服务搭建(六)——Ribbon负载均衡 在微服务中,有两种调用方式: Ribbon+RestTemplate Feign Feign是社区产品,符合Java面向接口编程的开发风格。Feign内置了Ribbon,本质上还是通过Ribbon...
  • springCloud微服务搭建实例

    千次阅读 2019-02-01 11:19:09
    springCloud微服务搭建简单实例IDEA创建项目Eureka服务注册中心的创建创建实体类model的module创建一个springboot+mybatis的module创建eureka-client 项目目录结构 springboot+mybatis+mysql ![在这里插入图片...
  • 【例子】springcloud微服务搭建(一)注册中心+生产者+消费者+feign+负载均衡+熔断器 feign分布式事务 这次加上网关zuul。 概念:正向代理,即vpn这种,客户需要提交代理服务器和目标的地址,由代理去访问返回;...
  • SpringCloud是什么? SpringCloud是分布式一站式的解决方案。 SpringCloud微服务技术的...2.SpringCloud是关注全局的微服务协调整理治理框架以及一整套的落地解决方案,它将SpringBoot开发的一个个单体微服务整合...
  • 搭建SpringCloud微服务首先要知道SpringCloud的基本概念与核心组件 springcloud是微服务架构的集大成者,将一系列优秀的组件进行了整合。就像maven整合了所有的jar包,springboot整合了所有的web组件,springcloud...
  • SpringCloud微服务搭建实战

    千次阅读 2018-03-22 13:51:57
    SpringCloud微服务架构搭建   什么是微服务?  '微',顾名思义,就是小的意思。意指将一个模块按其业务功能来拆分为多个模块,每个模块之间相互独立,各司其职,类似于单一职责原则。每个模块就是一个服务,...
  •   SpringCloud微服务架构落地的一套技术栈。   SpringCloud 的八个技术点。   Eureka,服务的注册与发现;   Robbin,服务之间的负载均衡;   Feign,服务之间的通讯;   Hystrix,服务的线程隔离...
  • 关于springcloud微服务中使用注册中心eureka的简单配置,服务提供与调用的流程说明,熔断机制的配置。 【1】注册中心eureka application.properties配置文件 spring.application.name=spring-cloud-eureka server...
  • SpringCloud微服务搭建过程记录

    千次阅读 2019-04-25 11:16:59
    公司为了微服务技术落地,采用SpringCloud搭建,但网上好多搭建过程真正使用的很少,所以自己记录了下来。方便后期查看, 微服务主要包含服务注册,服务发现,服务路由,服务配置,服务熔断,服务降级等一系列的...
  • 接上一篇:Spring cloud开发...springcloud-api:pojo实体类所在jar包 spring-boot-starter-web:web应用 spring-boot-devtools:支持热部署 <!--需要引入实体类和web--> <dependencies> <dependenc
  • 0000-SpringCloud微服务搭建

    千次阅读 2020-04-17 09:13:29
    这篇文章整理的是SpringCloud的全家桶中的技术 Demo采用的是SpringCloud F版 所有的Dmeo代码在GitHup上都有 传送门 SpringCloud目前很多项目已经停更,但这里不会出现替代技术解决方案 2. 目录 1. Eureka 0010-...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,634
精华内容 2,653
关键字:

springcloud微服务搭建

spring 订阅