java-spring-Cloud


java-spring-Cloud

  • 集成了服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件
  • SpringCloud屏蔽掉了复杂的配置和实现原理,最终给开发者流出了一套简单易懂,易于部署和维护的分布式系统开发工具包

SpringBoot 和SpringCloud关系

  • 专注于快速开发
  • 集成了服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件
  • SpringCloud离不开SpringBoot
  • SpringBoot专注于快速、方便的开发当个个体微服务,springcloud关注全局的服务制里框架

https://springcloud.cc/spring-cloud-netflix.html

中文api:https://springcloud.cc/spring-cloud-dalston.html

springcloud中国社区:http://springcloud.cn

SpringCloud 中文网: https://springcloud.cc

版本对应关系

Spring Cloud Spring Boot
Angel版本 兼容Spring Boot 1.2.x
Brixton版本 兼容Spring Boot 1.3.x,也兼容Spring Boot 1.4.x
Camden版本 兼容Spring Boot 1.4.x,也兼容Spring Boot 1.5.x
Dalston版本、Edgware版本 兼容Spring Boot 1.5.x,不兼容Spring Boot 2.0.x
Finchley版本 兼容Spring Boot 2.0.x,不兼容Spring Boot 1.5.x
Greenwich版本 兼容Spring Boot 2.1.x
Hoxtonl版本 兼容Spring Boot 2.2.x

更详细

Spring Boot Spring Cloud
1.5.2.RELEASE Dalston.RC1
1.5.9.RELEASE Edgware.RELEASE
2.0.2.RELEASE Finchley.BUILD-SNAPSHOT
2.0.3.RELEASE Finchley.RELEASE
2.1.0.RELEASE-2.1.14.RELEASE Greenwich.SR5
2.2.0.M4 Hoxton.SR4

项目 Hello springcloud

  • 了解下微服务的基本配置
  • 这里搭建两个类,分别对应 不同模块

依赖关系处理

核心:https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies

  1. 创建普通的maven项目,删除src目录
  2. 导入依赖,注意<scope>import</scope>
<?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>org.example</groupId>
	<artifactId>springcloud</artifactId>
	<version>1.0-SNAPSHOT</version>

	<!--版本控制-->
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>8</maven.compiler.source>
		<maven.compiler.target>8</maven.compiler.target>
		<junit.version>4.13.2</junit.version>
		<lombok.version>1.18.20</lombok.version>
	</properties>

	<!--打包方式-->
	<packaging>pom</packaging>

	<!-- 多服务依赖管理(这是父级) -->
	<dependencyManagement>
		<dependencies>
			<!--springCloud 依赖-->
			<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>2020.0.2</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<!--SpringBoot 依赖-->
			<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies -->
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>2.4.4</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<!--数据库-->
			<dependency>
				<groupId>mysql</groupId>
				<artifactId>mysql-connector-java</artifactId>
				<version>5.1.47</version>
			</dependency>
			<!--数据源-->
			<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
			<dependency>
				<groupId>com.alibaba</groupId>
				<artifactId>druid</artifactId>
				<version>1.2.5</version>
			</dependency>
			<!--SpringBoot 启动器-->
			<dependency>
				<groupId>org.mybatis.spring.boot</groupId>
				<artifactId>mybatis-spring-boot-starter</artifactId>
				<version>2.1.4</version>
			</dependency>
			<!-- 日志相关 -->
			<dependency>
				<groupId>ch.qos.logback</groupId>
				<artifactId>logback-core</artifactId>
				<version>1.2.3</version>
			</dependency>
			<!--log4j-->
			<dependency>
				<groupId>log4j</groupId>
				<artifactId>log4j</artifactId>
				<version>1.2.9</version>
			</dependency>
			<!-- 版本不写死。留空 -->
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
			</dependency>
				<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
			<dependency>
				<groupId>org.projectlombok</groupId>
				<artifactId>lombok</artifactId>
				<version>${lombok.version}</version>
			</dependency>

		</dependencies>
	</dependencyManagement>
	<!--打包插件-->
	<build>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<includes>
					<include>**/*.properties</include>
					<include>**/*.xml</include>
				</includes>
				<filtering>true</filtering>
			</resource>

			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.properties</include>
					<include>**/*.xml</include>
				</includes>
				<filtering>true</filtering>
			</resource>
		</resources>
	</build>

</project>

创建初始数据库

  • db_source:记录数据源的位置,后续用于分布式数据库读取
create table dept
(
    deptno    bigint auto_increment
        primary key,
    dname     varchar(60) null,
    db_source varchar(60) null
)
    comment '部门表';
    
insert into db01.dept (dname, db_source) values ("开发部","db01");
insert into db01.dept (dname, db_source) values ("人事部","db01");
insert into db01.dept (dname, db_source) values ("财务部","db01");
insert into db01.dept (dname, db_source) values ("市场部","db01");
insert into db01.dept (dname, db_source) values ("运维部","db01");

实体类编写(模块1)

1、依赖

  • springcloudapi->pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>springcloud</artifactId>
		<groupId>org.example</groupId>
		<version>1.0-SNAPSHOT</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>

	<artifactId>spingcloud-api</artifactId>

	<properties>
		<maven.compiler.source>8</maven.compiler.source>
		<maven.compiler.target>8</maven.compiler.target>
	</properties>
	<!-- 自己需要使用到的包 -->
	<dependencies>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
	</dependencies>

</project>

2、实体类

  • springcloudapi->com.hui.springcloud.pojo
  • Serializable 实现改类实现通信
  • @Accessors(chain = true):开启链式写法
    • Dept dept = new Dept();
    • 允许这么写dept.setxxx(1).setxxx(2).setxxx(3)
package com.hui.pojo;
...
/**
 * @author Hui3c
 * @program: springcloud
 * @description: 数据库实体类
 * @date 2021-04-06 14:06:14
 */
// 实现序列化
@Data
@NoArgsConstructor
@Accessors(chain = true)  // 链式写法
public class Dept implements Serializable {
    private Long deptno;
    private String dname;

    // 记录数据源的位置,后续用于分布式数据库读取
    // 同一个数据可能来自不同的数据库
    private String db_source;

    public Dept(String dname) {
        this.dname = dname;
    }

}

服务提供者(模块2)

  • 创建springcloud-provider-dept-8001
    • 通常把端口写在最后面

1、依赖

  • 依赖会继承父类的版本
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>springcloud</artifactId>
		<groupId>org.example</groupId>
		<version>1.0-SNAPSHOT</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>

	<artifactId>springcloud-provider-dept-8001</artifactId>

	<properties>
		<maven.compiler.source>8</maven.compiler.source>
		<maven.compiler.target>8</maven.compiler.target>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.example</groupId>
			<artifactId>springcloud-api</artifactId>
			<version>1.0-SNAPSHOT</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>
		<!--springboot test-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-test</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!--jetty-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jetty</artifactId>
		</dependency>
		<!--热部署-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>
</project>

2、该模块的配置

application.yml

  • 配置别名
  • resources->application.yml
server:
  port: 8001

mybatis:
  type-aliases-package: com.hui.pojo
  # mybatis 的核心配置
  config-location: classpath:mybatis/mybatis-config.xml
  # mapper 文件
  mapper-locations: classpath:mybatis/mapper/*.xml

# spring 配置
spring:
  application:
    name: springcloud-provider-dept
  # 数据源配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=true
    username: root
    password: 123456

mybatis 配置

  • mybatis核心配置一般放于:resources->mybatis.mybatis-config.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>

3、接口层

  • com.hui.springcloud.dao.DeptDao
@Mapper
@Repository
public interface DeptDao {
    boolean addDept(Dept dept);
    Dept queryById(Long id);
    List<Dept> queryAll();
}

编写Mapper文件

  • resources->mybatis.mapper.DeptMapper.xml
  • 注意要绑定命名空间
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 核心配置文件 -->
<mapper namespace="com.hui.springcloud.dao.DeptDao">
	<insert id="addDept" parameterType="Dept">
		insert into db01.dept (dname, db_source)
		VALUES (#{dname}, DATABASE())
	</insert>

	<select id="queryById" resultType="Dept" parameterType="Long">
		select * from db01.dept where deptno = #{deptno}
	</select>

	<select id="queryAll" resultType="Dept">
		select * from db01.dept
	</select>
</mapper>

4、service层

service 接口

  • com.hui.springcloud.service.DeptService
  • 与dao层一致
public interface DeptService {
    boolean addDept(Dept dept);
    Dept queryById(Long id);
    List<Dept> queryAll();
}

接口实现类

  • com.hui.springcloud.service.DeptServiceImpl
@Service
public class DeptServiceImpl implements DeptService{
    @Autowired
    private DeptDao deptDao;
    @Override
    public boolean addDept(Dept dept) {
        return deptDao.addDept(dept);
    }
    @Override
    public Dept queryById(Long id) {
        return deptDao.queryById(id);
    }
    @Override
    public List<Dept> queryAll() {
        return deptDao.queryAll();
    }
}

5、Restful 服务控制器

  • com.hui.springcloud.controller.DeptController
@RestController
public class DeptController {
    // controller 层调用 service 层
    @Autowired
    private DeptService deptService;
    // 添加部门
    @PostMapping("/dept/add")
    public boolean addDept(Dept dept) {
        return deptService.addDept(dept);
    }
    // 通过id查询部门
    @GetMapping("/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
        return (Dept) deptService.queryById(id);
    }
    // 查询所有
    @GetMapping("/dept/list")
    public List<Dept> queryAll(Dept dept) {
        return deptService.queryAll();
    }
}

6、主启动类

  • com.hui.springcloud.DeptProvider_8001
@SpringBootApplication
public class DeptProvider_8001 {
    public static void main(String[] args) {
        // 运行该类,传入参数
        SpringApplication.run(DeptProvider_8001.class, args);
    }
}

消费者层

  • 主要负责接口,与前端打交道

springcloud-consumer-dept-80

1、导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>springcloud</artifactId>
		<groupId>org.example</groupId>
		<version>1.0-SNAPSHOT</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<artifactId>springcloud-consumer-dept-80</artifactId>
	<properties>
		<maven.compiler.source>8</maven.compiler.source>
		<maven.compiler.target>8</maven.compiler.target>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.example</groupId>
			<artifactId>springcloud-api</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>
</project>

2、配置文件

server:
  port: 80

3、RestTemplate装载入 bean

  • com.hui.springcloud.config.ConfigBean
@Configuration
public class ConfigBean {
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

4、控制层

  • RestTemplate:提供多种便捷访问远程http服务的方法,简单的Restful服务模板

  • com.hui.springcloud.controller.DeptConsumerController

@RestController
public class DeptConsumerController {
    // 消费者,不应该拥有service层!
    // 需要使用 RestTemplate 请求,
    @Autowired
    private RestTemplate restTemplate;

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

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

    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept) {
        return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class);
    }
    @RequestMapping("/consumer/dept/list")
    public List<Dept> list() {
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class);
    }
}

5、主启动类

  • com.hui.springcloud.DeptConsumer_80
@SpringBootApplication
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class, args);
    }
}

访问时访问:http://localhost/consumer/dept/get/2

Eureka 服务注册发现

  • 是Netflix子模块,是基于REST服务,用于定位服务,以实现云端中间层服务发现和故障转义
  • 有了该模块只需要使用服务的标识符,就可以访问到服务,不需要修改服务调用的配置文件了
  • 类似于Dubbo的注册中心,比如Zookeeeper
  • 使用C/S 架构,EurekaServer作为服务注册功能的服务器,是服务注册中心(手动写)

三大角色

  • Eureka Server:提供服务的注册用于发现
  • Service Provider:自身服务注册到Eureka中,使消费方能找到
  • Service Consumer:服务消费从Eureka中获取注册服务列表,从而找到消费服务

Hello Eureka

1、导入依赖

  • springcloud-eureka-7001项目
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    <version>3.0.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

编写配置文件

  • 注册中心需要配置:
    • register-with-eureka:false
    • fetch-registry: false
server:
  port: 7001

eureka:
  instance:
    hostname: localhost # 服务端的实例名称
  client:
    register-with-eureka: false # 表示是否向eureka 中心注册自己
    fetch-registry: false # 值为false表示自己为注册中心
    service-url: # 监控的页面
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

分析源码后,需要重写eureka 的服务地址

开启服务

  • 在主启动类加上注解
@EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer_7001 {
    ...

2、client加入eureka server

  • client:springcloud-provider-dept-8001

导入client依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

配置文件

# Eureka 配置,服务注册到哪里
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/

主启动类添加注解

@SpringBootApplication
@EnableEurekaClient  // 客户端自动注册到服务端
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class, args);
    }
}

备注类 ,监控信息

备注类主要用于首页点击接口进去后的描述

1. 导入依赖

<!--actuator 完善监控信息-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2. 配置

  • 这里info内的信息随便写,xxxx.name
info:
  app.name: 123
  compny.name: hhhhh

3.添加注解

  • 在主启动类添加注解@EnableDiscoveryClient
@SpringBootApplication
@EnableEurekaClient  // 客户端自动注册到服务端
@EnableDiscoveryClient
public class DeptProvider_8001 {
    public static void main(String[] args) {
        // 运行该类,传入参数
        SpringApplication.run(DeptProvider_8001.class, args);
    }
}

备注一个拿到当前运行类关键信息的方法:

import org.springframework.cloud.client.discovery.DiscoveryClient;

@Autowired
private DiscoveryClient client;
@GetMapping("/info")
public Object discovery() {
    List<String> services = client.getServices();
    System.out.println(services);

    List<ServiceInstance> instances = client.getInstances("springcloud-provider-dept");
    for (ServiceInstance instance : instances) {
        System.out.println("1111=>"+instance);
    }
    return instances;
} 

网关api Zuul

  • 用户访问微服务时:最先通过网关
  • 提供路由过滤两个功能
  • Zuul 服务最终会注册进Eureka
  • 实现外部访问统一入口

依赖!!最好全部最新版本!!大坑

否则会出现xxxxx.xml cannot be opened because it does not exist

依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>springcloud</artifactId>
		<groupId>org.example</groupId>
		<version>1.0-SNAPSHOT</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>

	<artifactId>springcloud-zuul-9528</artifactId>

	<properties>
		<maven.compiler.source>8</maven.compiler.source>
		<maven.compiler.target>8</maven.compiler.target>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
			<version>2.2.7.RELEASE</version>
		</dependency>

		<!--Hystarix 依赖 和它的监控-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
			<version>2.2.7.RELEASE</version>
		</dependency>

		<!--Ribbon-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-ribbon</artifactId>
			<version>1.4.7.RELEASE</version>
		</dependency>
		<!--erueka-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
			<version>1.4.7.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.example</groupId>
			<artifactId>springcloud-api</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>
</project>

文章作者: Hui3c
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-ND 4.0 许可协议。转载请注明来源 Hui3c !
  目录