按照下图创建工程:

首先先创建一个工作集,方便项目管理,在工作集下面创建分布式集群项目。这里有个工程名命名规范,参照工程名图的命名规范,这样方便管理。

创建父工程:

  1. 创建一个maven空项目的父工程,注意这里的父工程是pom类型的,图1所示,在按照图2步骤创建。图3是创建父工程的操作步骤,在父工程里主要定义版本信息,供它的子模块使用,父工程如果定义了一些依赖的版本信息,那么它的子模块只需要添加依赖就行了,不需要写版本信息,父工程里没有的依赖或者没有定义的依赖版本信息,子模块又需要用的话,可以在子模块里自己定义版本信息和添加依赖,


<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.lyj.springcloud</groupId>
	<artifactId>microservicecloud</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>
	<!-- 新建父工程microservicecloud,切记是packageing是pom模式 主要是定义pom文件,将后续的各个子模块公用的jar包统一提出来, 类似一个抽象父类 -->
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<!--指定每次编译的时候都是以java8版本进行编译 ====start -->
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<!--指定每次编译的时候都是以java8版本进行编译 ====end -->
		<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.0.4</version>
				<scope>runtime</scope>
			</dependency>
			<dependency>
				<groupId>com.alibaba</groupId>
				<artifactId>druid</artifactId>
				<version>1.0.31</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>
			</dependency>
			<dependency>
				<groupId>log4j</groupId>
				<artifactId>log4j</artifactId>
				<version>${log4j.version}</version>
			</dependency>


		</dependencies>
	</dependencyManagement>
	<build>
	<!-- 这里的 配置是使在Eureka的web界面能够访问服务的info界面(服务的详细信息)==start -->
	<!-- finalName指父工程的名字 -->
		<finalName>microservicecloud</finalName>
		<!-- resources:资源,允许你访问的资源 directory:允许你访问这个路径下的资源 filtering:访问过滤开启-->
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<filtering>true</filtering>
			</resource>
		</resources>
		<plugins>
		<!-- plugins:引入插件的意思, <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> 上面的插件是负责解析和解读的-->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<!-- configuration:解析配置的意思, <delimiter>$</delimiter>:意思就是以$开头和以$结尾的 在<directory>src/main/resources</directory>路径下面 的信息,我就能读取,即要显示的信息-->
				<configuration>
					<delimiters>
						<delimiter>$</delimiter>
					</delimiters>
				</configuration>
			</plugin>

		</plugins>
<!-- 这里的 配置是使在Eureka的web界面能够访问服务的info界面(服务的详细信息)==end -->
	</build>




	<!-- 创建microservice-api服务,自动在父工程pom文件里引进module配置 -->
	<modules>
		<module>microservicecloud-api</module>
		<module>microservicecloud-provider-dept-8001</module>
		<module>microservicecloud-consumer-dept-80</module>
		<module>microservicecloud-eureka-7001</module>
		<module>microservicecloud-eureka-7002</module>
		<module>microservicecloud-eureka-7003</module>
	</modules>
</project>

创建公共子模块(Module):

除了父工程是pom类型的工程,后面的公共子模块和服务提供者工程和服务消费者工程都是jar包类型。并且创建都是在父工程下创建module模块,创建完成后检查父工程中的pom文件是否添加了创建的module,如果自动添加了,则创建正确。

<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>
  <!-- 本Module开发步骤 1、新建microservicecloud-api创建完成后查看pom文件变化 2、修改pom 3、新建Entity且配合lombok使用 4、mvn clean&install(打成jar包)后给其他模块引用,达到通用的目的。 也即需要用到部门实体的话,不用每个工程都定义一份,直接引用本模块即可 -->
  <parent>
  <!-- 子类里面显示声明才能有明确的继承表现, 无意外就是父类的默认版本否则自己定义-->
    <groupId>com.lyj.springcloud</groupId>
    <artifactId>microservicecloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <!-- 当前Module,就是我自己叫什么名字 -->
  <artifactId>microservicecloud-api</artifactId>
  
  <!-- 当前Module需要用的jar包,按自己需求添加, 入股父类已经包含了,可以不用 写版本号-->
  <dependencies>
  <dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  </dependency>
  </dependencies>
</project>

这里添加了一个lombok依赖主要是用来简化和方便写我们的Javabean,添加这个依赖,可以不用写getter和setter方法、构造方法、toString()等。直接在相应的Javabean上面添加相应的注解即可。

图4是公共子模块的架构图:

在这里创建了一个公共的Javabean,供后面服务提供者和服务消费者使用。如下:

package com.lyj.springcloud.entities;

import java.io.Serializable;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@SuppressWarnings("serial")//如果有类上或者方法上或者参数上有警告。添加此注解可以选择压制
//@AllArgsConstructor//添加传参构造函数的注解,依赖于lombok(俗称小辣椒)的依赖
@NoArgsConstructor//添加构造空构造函数的注解
@Data//添加使每个参数都生成getter和setter方法
@Accessors(chain=true)//添加链式风格访问的注解
public class Dept implements Serializable//Dept(Entity) ORM mysql->Dept(table) 类关系映射
{		//必须序列化
	
	private Long 	deptno;//主键

	private String 	dname;//部门名称

	/** * 来自哪个数据库,因为微服务架构可以一个服务对应一个数据库, * 同一个信息被存在不同的数据库 */

	private String 	db_source;

	
// 检测是否能够自定义构造函数
// public Dept(String dname) {
// super();
// this.dname = dname;
// }
// 
// //检测链式风格访问是否起作用
// public static void main(String[] args) {
// Dept dept=new Dept();
//// 这里下面是检测
// dept.setDeptno(11l).setDname("RD").setDb_source("DB01");
// }
	

}

创建服务注册模块(cloud-server):

架构图5:

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.lyj.springcloud</groupId>
		<artifactId>microservicecloud</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<groupId>microservicecloud</groupId>
	<artifactId>microservicecloud-eureka-7001</artifactId>

	<dependencies>
		<!-- eureka-server服务端配置 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka-server</artifactId>
		</dependency>
		<!-- 修改后立即生效,热部署 ===start-->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		<!--修改后立即生效,热部署===end-->
	</dependencies>

</project>

创建application主程序:
记得在主程序上添加@EnableEurekaServer注解,开启服务,用来接收服务的注册。

package com.lyj.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer // Eureka服务器端启动类,接收其他微服务注册进来
public class EurekaServer7001_App {

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

}

创建application.yml文件:

单机版的Eureka配置
server:
  port: 7001

eureka:
# server:
# enable-self-preservation: false #禁用自我保护机制
  instance:
    hostname: localhost #eureka服务端的实例名称
  client:
    register-with-eureka: false #false 表示不向注册中心注册自己
     #false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
    #设置与Eureka Server交互的地址查询服务和注册服务都需要这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    

创建服务提供者工程

服务提供者开发流程图:

架构图:

配置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.lyj.springcloud</groupId>
		<artifactId>microservicecloud</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>microservicecloud-provider-dept-8001</artifactId>
	<dependencies>
		<!-- 引入自定义的api通用包,可以使用Dept部门的Entity -->
		<dependency>
			<groupId>com.lyj.springcloud</groupId>
			<artifactId>microservicecloud-api</artifactId>
			<!-- 下面指定的版本是活的,相当于,api通用包随意怎么变,这里都会自动更新,不影响 -->
			<version>${project.version}</version>
		</dependency>
		<!-- 将微服务注册provider到Eureka注册中心中 ==start -->
		<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>
		<!-- 将微服务注册provider到Eureka注册中心中 ==end -->
		<!-- 引入监控信息完善的依赖==start -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<!-- 引入监控信息完善的依赖==end -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</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>
		<!-- 引入热部署,修改后立即生效===start -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		<!-- 引入热部署,修改后立即自动发布和构建生效===end -->
	</dependencies>


</project>

配置application.yml 文件:

server:
#指定服务器端口号8001
  port: 8001
  
mybatis:
#mybatis配置文件所在路径
  config-location: classpath:mybatis/mybatis.cfg.xml
   #所有Entity别名类所在包
  type-aliases-package: com.lyj.springcloud.entities
   #mapper映射文件所在路径
  mapper-locations:
  - classpath:mybatis/mapper/**/*.xml
  
spring:
  application:
   # 当前应用(服务)起的名字
    name: microservicecloud-dept       
  datasource:
  #当前数据源操作类型
    type: com.alibaba.druid.pool.DruidDataSource
    #mysql驱动包
    driver-class-name: com.mysql.jdbc.Driver
     #数据库名称
    url: jdbc:mysql://localhost:3306/cloudDB01
    username: mysql
    password: 15827318595
    dbcp2: 
       min-idle: 5 #数据库连接池的最小维持连接数
       initial-size: 5 #初始化连接数5个
       max-total: 5 #设置最大连接数
       max-wait-millis: 200 #s等待连接获取的最大超时时间
      

#配置Eureka
eureka:
#客户端注册进Eureka服务列表内
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka #(单机版服务器)

服务提供者详细架构图如下:

  1. 创建DeptDao访问数据库的接口:
package com.lyj.springcloud.dao;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import com.lyj.springcloud.entities.Dept;

@Mapper // 添加mybatis注解(mapper文件)
public interface DeptDao {

    public boolean addDept(Dept dept);

    public Dept findById(Long id);

    public List < Dept > findAll();
}

  1. 创建DeptService接口:
package com.lyj.springcloud.service;

import java.util.List;

import com.lyj.springcloud.entities.Dept;

public interface DeptService {

    /** * 这里是对数据库访问的函数,比较靠近底层,为了比较符合rest的风格, 这里的函数名都是以靠近底层的命名方式命名 * * @param dept * @return */
    public boolean add(Dept dept);

    public Dept get(Long id);

    public List < Dept > list();
}

  1. 创建接口实现类DeptServiceImpl:
package com.lyj.springcloud.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.lyj.springcloud.dao.DeptDao;
import com.lyj.springcloud.entities.Dept;
import com.lyj.springcloud.service.DeptService;

@Service("deptService")
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptDao deptDao;

    @Override
    public boolean add(Dept dept) {

        return deptDao.addDept(dept);
    }

    @Override
    public Dept get(Long id) {

        return deptDao.findById(id);
    }

    @Override
    public List < Dept > list() {

        return deptDao.findAll();
    }

}

  1. 创建控制器:
package com.lyj.springcloud.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.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.lyj.springcloud.entities.Dept;
import com.lyj.springcloud.service.DeptService;

@RestController
public class DeptController {

    @Autowired
    private DeptService service;

    /** * 这里是引入服务发现的DiscoveryClient 注意这里的DiscoveryClient是引用这个 org.springframework.cloud.client.discovery.DiscoveryClient; * 还需要在application的主程序中添加@EnableDiscoveryClient注解,开启服务发现功能 */
    @Autowired
    private DiscoveryClient client;

    @RequestMapping(value = "/dept/add", method = RequestMethod.POST)
    public boolean add(@RequestBody Dept dept) {

        return service.add(dept);
    }

    @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
    public Dept get(@PathVariable("id") Long id) {

        return service.get(id);
    }

    @RequestMapping(value = "/dept/list", method = RequestMethod.GET)
    public List < Dept > list() {

        return service.list();
    }

    @RequestMapping(value = "/dept/discovery", method = RequestMethod.GET)
    public Object discovery() {
        List < String > list = client.getServices();
        System.out.println("************" + list);

        List < ServiceInstance > srvList = client.getInstances("MICROSERVICECLOUD-DEPT");
        for (ServiceInstance eInstance : srvList) {
            System.out.println(eInstance.getServiceId() + "\t" + eInstance.getHost() + "\t" + eInstance.getPort() + "\t"
                    + eInstance.getUri());
        }
        return this.client;
    }

}

  1. 创建application主程序 这里面配置了服务发现(服务发现用用的不多,主要是服务注册)
package com.lyj.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableDiscoveryClient // 开启服务发现功能,控制器里的服务发现方法能正常运行。
@EnableEurekaClient // 本服务启动后会自动将服务注册进Eureka服务中心中
@SpringBootApplication
public class DeptProvider8001_App {

    /** * 使用服务发现功能步骤: 1、先要启动EurekaServer 2、再启动DeptProvider8001_App主启动类,需要 稍等一会 3、访问http://localhost:8001/dept/discovery * * @param args */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        SpringApplication.run(DeptProvider8001_App.class, args);

    }

}

下图是数据访问的路径,mapper.xml文件路径:

配置DeptMapper.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.lyj.springcloud.dao.DeptDao">
	<select id="findById" resultType="Dept" parameterType="Long">
		select deptno dname,db_source from dept where deptno=#{deptno};
	</select>
	<select id="findAll" resultType="Dept">
		select deptno,dname,db_source from dept;
	</select>
	<insert id="addDept" parameterType="Dept">
		<!-- database()mysql自带的查询数据源的名字的()数据库的名字 -->
		INSERT INTO dept(dname,db_source) VALUES(#{dname},DATABASE());
	</insert>

</mapper>

配置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>

服务消费者配置:

服务消费者的开发流程图:

架构图:

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.lyj.springcloud</groupId>
		<artifactId>microservicecloud</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>microservicecloud-consumer-dept-80</artifactId>
	<description>部门微服务消费者</description>

	<dependencies>
	<!-- 引入自己定义的api -->
		<dependency>
			<groupId>com.lyj.springcloud</groupId>
			<artifactId>microservicecloud-api</artifactId>
			<version>${project.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- 引入热部署,修改后立即生效===start -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		<!-- 引入热部署,修改后立即自动发布和构建生效===end -->

	</dependencies>
</project>

配置application.yml文件

server:
  port: 80 #访问时不用加端口号,因为浏览器的默认端口就是80,所以访问:localhosst/xxxxx

创建application主程序:

package com.lyj.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DeptConsumer80_App {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

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

}

创建Config.java 文件:

package com.lyj.springcloud.cfgbeans;

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 geRestTemplate() {
        return new RestTemplate();
    }

}
// boot--spring applicationContext.xml
//--@Configuration配置 ConfigBean=applicationContext.xml
//public UserService getUserService() {
// return new UserServiceImpl();
//}
/** * applicationContext.xml==ConfigBean(@Configuration) <bean id="userService" class="com.lyj.tmall.UserServiceImpl"> * 这里的id相当于上面的方法类型UserService,class就相当于return的返回值, */

创建控制器:

package com.lyj.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.lyj.springcloud.entities.Dept;

@RestController
public class DeptController_consumer {
    /** * RestTemplate提供了多种便捷访问远程Http服务的方法, 是一种简单便捷的访问restful服务模板类, 是spring提供的用于访问Rest服务的客户端模板工具集 用法: * 使用restTemplate访问restful接口非常的简单粗暴无脑。 (url,requestMap,ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。 * */
    @Autowired
    private RestTemplate restTemplate;

    private static final String TEST_URL_PREFIX = "http://localhost:8001";

    @RequestMapping(value = "/consumer/dept/add")
    public boolean add(Dept dept) {
        return restTemplate.postForObject(TEST_URL_PREFIX + "/dept/add", dept, boolean.class);
// return restTemplate.getForObject(TEST_URL_PREFIX + "/dept/add", boolean.class, dept);

    }

    @RequestMapping(value = "/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
        return restTemplate.getForObject(TEST_URL_PREFIX + "/dept/get/" + id, Dept.class);
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/consumer/dept/list")
    public List < Dept > list(Dept dept) {
        return restTemplate.getForObject(TEST_URL_PREFIX + "/dept/list", List.class);
    }

    // 测试@EnableDiscoveryClient,消费者可以调用服务发现,消费者的application主程序不用添加@EnableDiscoveryClient
    @RequestMapping(value = "/consumer/dept/discovery")
    public Object discovery() {
        return restTemplate.getForObject(TEST_URL_PREFIX + "/dept/discovery", Object.class);
    }

}

数据库执行脚本:

-- drop database if exists cloudDB01;
CREATE DATABASE cloudDB01 CHARACTER SET UTF-8;
USE cloudDb01;
CREATE TABLE dept
( 
   deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
   dname VARCHAR(60),
   db_source VARCHAR(60)
);
-- DATABASE()查询获取当前数据源(数据库)的名字
INSERT INTO dept(dname,db_source) VALUES('开发部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('市场部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE());
SELECT * FROM dept;   

INSERT INTO dept(dname,db_source) VALUES(123,DATABASE());

测试:

一上操作都是一个Eureka-server服务器的运行。
下面讲一下集群分布式开发:

集群开发步骤:

Eureka集群开发流程图:


集群配置,也就是服务消费者不动,只用增加服务器子模块的配置的数量即可。在父工程下创建服务器工程子模块
如下:
架构图:
配置7002工程和7003工程的pom文件,与7001pom文件一样,直接copy过来。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.lyj.springcloud</groupId>
    <artifactId>microservicecloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>microservicecloud-eureka-7002</artifactId>
  
<dependencies>
		<!-- eureka-server服务端配置 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-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>

修改7002工程和7003工程的application主程序配置:
主程序配置一样,只不过类名不一样而已

package com.lyj.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer // Eureka服务器端启动类,接收其他微服务注册进来
public class EurekaServer7002_App {

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

}

修改7001工程的application.yml配置文件,改为集群配置:

#单机版的Eureka配置
#server:
# port: 7001
#
#eureka:
## server:
## enable-self-preservation: false #禁用自我保护机制
# instance:
# hostname: localhost #eureka服务端的实例名称
# client:
# register-with-eureka: false #false 表示不向注册中心注册自己
# #false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
# fetch-registry: false
# service-url:
# #设置与Eureka Server交互的地址查询服务和注册服务都需要这个地址
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# 

#集群Eureka配置,即把相同的服务部署到不同的服务器上运行,避免由于一台服务器异常而终止程序,
#集群配置可以在一台服务器发生异常的情况下,还能保持程序的正常运行
server:
  port: 7001

eureka:
# server:
# enable-self-preservation: false #禁用自我保护机制
  instance:
    hostname: eureka7001.com #eureka服务端的实例名称
  client:
    register-with-eureka: false #false 表示不向注册中心注册自己
     #false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
# defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ 
      defaultZone: http://eureka7002.com:7002,http://eureka7003.com:7003
    
    #设置与Eureka Server交互的地址查询服务和注册服务都需要这个地址
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #(单机)
# defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    
    
    

7002application.yml文件配置:

#集群Eureka配置,即把相同的服务部署到不同的服务器上运行,避免由于一台服务器异常而终止程序,
#集群配置可以在一台服务器发生异常的情况下,还能保持程序的正常运行
server:
  port: 7002

eureka:
# server:
# enable-self-preservation: false #禁用自我保护机制
  instance:
    hostname: eureka7002.com #eureka服务端的实例名称
  client:
    register-with-eureka: false #false 表示不向注册中心注册自己
     #false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
    #设置与Eureka Server交互的地址查询服务和注册服务都需要这个地址
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #(单机)
# defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
      defaultZone: http://eureka7001.com:7001,http://eureka7003.com:7003
 
    

7003application.yml文件配置:

#集群Eureka配置,即把相同的服务部署到不同的服务器上运行,避免由于一台服务器异常而终止程序,
#集群配置可以在一台服务器发生异常的情况下,还能保持程序的正常运行
server:
  port: 7003

eureka:
# server:
# enable-self-preservation: false #禁用自我保护机制
  instance:
    hostname: eureka7003.com #eureka服务端的实例名称
  client:
    register-with-eureka: false #false 表示不向注册中心注册自己
     #false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
    #设置与Eureka Server交互的地址查询服务和注册服务都需要这个地址
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #(单机)
# defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
      defaultZone: http://eureka7001.com:7001,http://eureka7002.com:7002
 
    

最重要的一点==修改映射文件:==打开C盘,找到这个路径下的hosts文件:C:\Windows\System32\drivers\etc
编辑hosts文件添加映射配置:


host文件中的Eureka


修改8001工程的application.yml文件里的defaultZone服务注册路径,具体配置如下:

server:
#指定服务器端口号8001
  port: 8001
  
mybatis:
#mybatis配置文件所在路径
  config-location: classpath:mybatis/mybatis.cfg.xml
   #所有Entity别名类所在包
  type-aliases-package: com.lyj.springcloud.entities
   #mapper映射文件所在路径
  mapper-locations:
  - classpath:mybatis/mapper/**/*.xml
  
spring:
  application:
   # 当前应用(服务)起的名字
    name: microservicecloud-dept       
  datasource:
  #当前数据源操作类型
    type: com.alibaba.druid.pool.DruidDataSource
    #mysql驱动包
    driver-class-name: com.mysql.jdbc.Driver
     #数据库名称
    url: jdbc:mysql://localhost:3306/cloudDB01
    username: mysql
    password: 15827318595
    dbcp2: 
       min-idle: 5 #数据库连接池的最小维持连接数
       initial-size: 5 #初始化连接数5个
       max-total: 5 #设置最大连接数
       max-wait-millis: 200 #s等待连接获取的最大超时时间
      

#配置Eureka
eureka:
#客户端注册进Eureka服务列表内
  client:
    service-url:
# defaultZone: http://localhost:7001/eureka #(单机版服务器)
# 集群配置(多台服务器共同使用)
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
      
  #自定义实例的statusIP地址名字(主机名字:服务名称修改,不采用默认的名字)
  instance:
    instance-id: microservicecloud-dept8001
    prefer-ip-address: true #访问路径可以显示IP地址
    
    
#配置Eurekaweb界面访问各个服务的的详细信息的info界面
info:
  app.name: lyj-microservicecloud
  company.name: www.lyj.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$
    

最后依次启动服务器7001、7002、7003工程,和服务提供者工程。
测试:
依次访问:http://eureka7001.com:7001/
http://eureka7002.com:7002/
http://eureka7003.com:7003/
并且可以在这个三个界面里按照下图:可以点击1查看该服务的我们自己自定义的信息。
点击2或者3可以跳转到7002或者7003服务器,并且都可以正常操作。

<mark>面试常考题</mark>:

1.<mark>Eureka是什么?</mark>

Eureka是Netflix的一个子模块,也是核心模块之一,Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册于发现对于微服务架构来说是非常重要,有了服务发现与注册,<mark>只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件</mark>,功能类似dubbo的注册中心,比如zookeeper。

2.<mark>传统的ACID什么?&CAP是什么</mark>

<mark>ACID</mark>:原子性(Atomicity)、一致性(Consistency)、独立性(lsolation)、持久性(Durability)
<mark>原子性</mark>:事务里的所有操作要么做,要么都不做,事务成功的条件是事务里所有操作都成功,只要有一个操作失败、整个事务失败。
<mark>一致性</mark>:数据库要一直处于一致状态,事务运行不会改变数据库原本的一致性约束
<mark>独立性</mark>:并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。
<mark>持久性</mark>:一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。

<mark>CAP</mark>:一致性(Consistency)、可用性(Availability)、分区容错性(Partition Tolerance)
<mark>经典CAP图</mark>

CAP理论图:
在现在集群分布式的开发过程中,<mark>CAP三个条件最多只能同时较好的满足两个</mark>。
CAP理论的核心:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,因此,根据CAP原理将NOSQL数据库分成了满足CA原则、满足CP原则、满足AP原则三大类:
<mark>CA</mark>-单点集群,满足一致性、可用性的系统,通常在可扩展上不太强大
<mark>CP</mark>-满足一致性,分区容错性的系统,通常性能不是很高。
<mark>AP</mark>-满足可用性、分区容错性的系统,通常可能对一致性要求低一些。
<mark>CAP的3进2</mark>:
CAP理论就是说再分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以<mark>分区容错性是我们必须需要实现的</mark>。
所以我们只能在<mark>一致性</mark>和可用性之间进行权衡,没有NOSQL系统能同时保证这三点。
<mark>CA</mark>传统的Oracle数据库
<mark>AP</mark>大多数网站架构的选择
<mark>CP</mark>Redis、MongoDB
注意:分布式架构的时候必须做出取舍

3.<mark>Netflix在设计Eureka时遵守的就是AP原则,啥是AP原则</mark>?

面试必问:
Eureka与zookeeper的区别?
答:Eureka遵守AP,zookeeper遵守CP

4. <mark>作为服务注册中心,Eureka比zookeeper好在哪里?</mark>