概述
SpringCloud
约定 > 配置 > 编码
1. 父工程构建
1.1 创建微服务cloud整体聚合父工程Project步骤
1. New Project
2. 整体聚合父工程设置
3. 开启自动导入
4. 设置字符编码
5. 设置注解生效激活
6. java编译版本
7. File Type 过滤
1.2 父工程pom文件改造
- 删除src目录
- 设置打包方式为pom
<packaging>pom</packaging>
- 统一管理jar包版本
<!--统一管理jar包版本-->
<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>
<lombok.version>1.18.10</lombok.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>8.0.18</mysql.version>
<druid.version>1.1.20</druid.version>
<mybatis.spring.boot.version>1.3.2</mybatis.spring.boot.version>
</properties>
<!--子模块继承之后,提供作用:锁定版本+子module不用写groupId和version-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<!-- druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. REST微服务工程搭建
微服务工程搭建步骤
- 建module
- 改pom
- 写yml
- 主启动
- 业务类
- 测试
2.1 支付模块搭建
- 建module
父目录POM
- 改pom
添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
<!--子工程写了版本号,就使用子工程的版本号,如果没写版本,找父工程中规定的版本号-->
</dependency>
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- 写yml
在resources目录下创建application.yml配置文件
#微服务建议一定要写服务端口号和微服务名称
server:
#端口号
port: 8001
spring:
application:
#微服务名称
name: cloud-payment-service
#数据库配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
#mysql5.x的没有cj
driver-class-name: com.mysql.jdbc.Driver
#记得先创建数据库
url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
#mybatis配置
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.huan.springcloud.entities #所有Entity别名类所在包
- 主启动
在java包下创建主启动类com.huan.springcloud.PaymentMain8001
- 业务类
1. 建表
CREATE TABLE `payment`(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`serial` VARCHAR(200) DEFAULT '',
PRIMARY KEY(`id`)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO payment(`serial`)VALUES("张三");
2. 创建实体类
Payment实体类
CommonResult实体类,作为返回结果传给前端
3. 创建dao层接口
4. 创建sql映射文件
5. 编写service层接口
6. 编写controller接口
7. 测试
2.2 订单模块
- 创建module
cloud-consumer-order80
- 修改pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- 写yml
application.yml
#访问一个网站时,默认是80端口,给用户80端口,用户就可以不用加端口直接访问页面
server:
port: 80
- 主启动
OrderMain80
@SpringBootApplication public class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class, args); } }
- 业务类
1. 先将Payment类中的两个实体类复制到Order类中
2. 新建config.ApplicationContextConfig类
@Configuration
public class ApplicationContextConfig {
//往容器中添加一个RestTemplate
//RestTemplate提供了多种便捷访问远程http访问的方法
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
3. 新建controller.OrderController
@Controller
@Slf4j
@RequestMapping("/consumer/payment")
public class OrderController {
private static final String PAYMENT_URL = "http://localhost:8001";
@Resource
private RestTemplate restTemplate;
@GetMapping("/create")
public CommonResult create(Payment payment){
log.info("********插入的数据:" + payment);
//postForObject分别有三个参数:请求地址,请求参数,返回的对象类型
return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class);
}
@GetMapping("/get")
public CommonResult<Payment> getPayment(@RequestParam("id") Long id) {
log.info("********查询的id:" + id);
//getForObject两个参数:请求地址,返回的对象类型
return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
}
}
- 测试
3. 抽取重复结构,重构工程
观察到工程中有重复结构,com.huan.springCloud.entity.*,对该部分抽取重构
- 新建module,cloud-api-commons
- 修改pom
添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 一个Java工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
- 将重复结构(entities)拷贝到cloud-api-commons中(保持路径一致)
- 对cloud-api-commons进行打包
- 删除Payment和Order中的entities包
- 给Payment和Order两个模块引入cloud-api-commons依赖
<!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.huan.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
- 重新测试
4. Eureka服务注册与发现
4.1 Eureka基础知识
4.1.1 服务治理
Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理
在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
4.1.2 服务注册与发现
Eureka采用了CS的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息 (比如 服务地址通讯地址等)以别名方式注册到注册中心上。另一方(消费者|服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用
框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))
4.1.3 Eureka两组件
Eureka包括连个组件:Eureka Server 和 Eureka Client
Eureka Server 提供服务注册服务
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
Eureka Client 通过注册中心进行访问
是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)
4.2 单机Eureka搭建
- 建module
cloud-eureka-server7001
- 改pom
server端依赖对比
以前的老版本(当前使用2018)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
现在新版本(当前使用2020.2)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
添加依赖
<dependencies>
<!--eureka-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.huan.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--boot web actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--一般通用配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
- 写yml
application.yml
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己(想注册也可以,不过没必要)
register-with-eureka: false
#false表示自己端就是注册中心,职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与eurekaServer交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
- 主启动
- 测试
浏览器输入http://localhost:7001/
4.2.1 将EurekaClient端8001注册进EurekaServer成为服务提供者provider
client端版本依赖对比
以前老版本,别再使用
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
现在新版本,当前使用
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 改pom
将Eureka Client依赖引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 改yml
在yml文件中添加
eureka:
client:
#true表示向注册中心注册自己,默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
- 改主启动
在主启动类上添加@EnableEurekaClient注解,表示本工程为Eureka的客户端
- 启动项目,刷新Eureka界面
yml中配置的application name 即为注册进注册中心时的应用名
4.2.2 将EurekaClient端80注册进EurekaServer成为服务消费者consumer
- 引入依赖
<!-- eureka Client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 改yml
spring:
application:
name: cloud-order-service
eureka:
client:
# true表示向注册中心注册自己,默认为true
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
- 改主启动
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
- 测试
4.3 集群Eureka搭建
微服务RPC远程服务调用最核心的是什么
高可用,试想你的注册中心只有一个, 它出故障了会导致整个为服务环境不可用,所以
解决办法:搭建Eureka注册中心集群 ,实现负载均衡+故障容错
Eureka集群:相互注册,相互守望
4.3.1 构建eurekaServer集群环境
- 参照cloud-eureka-server7001新建cloud-eureka-server7002
- 修改host文件
127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com 127.0.0.1eureka7003.com
- 修改三个eurekaServer的yml文件
7001
# 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false
fetch-registry: false
service-url:
# 单机
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#集群版 相互注册,相互守望
defaultZone: http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/
# defaultZone是固定写法,如果想自定义,需要按以下写法才行:
# region: eureka-server
# availability-zones:
# eureka-server: server1,server2
# service-url:
# server1: http://eureka7002.com:7002/eureka/
# server2: http://eureka7003.com:7003/eureka/
7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false
fetch-registry: false
service-url:
#集群版 相互注册,相互守望
defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7003.com:7003/eureka/ #相互注册,相互守望
7003
eureka:
instance:
hostname: eureka7003.com #eureka服务端的实例名称
client:
register-with-eureka: false
fetch-registry: false
service-url:
#集群版 相互注册,相互守望
defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7002.com:7002/eureka/ #相互注册,相互守望
- 启动项目
- 将支付服务8001和订单服务80微服务发布到集群配置中
修改yml文件中的defaultZone
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka, http://eureka7003.com:7003/eureka
Tips:
- eureka.instance.hostname 值需要和host中配置的值保持一致,否则会报错,服务无法注册到集群中的所有机器
- defaultZone的值后需要加/eureka
4.3.2 构建支付服务提供者集群环境
- 按照8001新建8002、8003,除了需要修改yml中的端口号和主启动类外,其他保持一致
yml文件中的应用名不需要改,因为是集群,所以应用名需要一致
- 分别在所有的提供者的PaymentController中加入serverPort属性:(这个@Value是spring的注解)
- 修改消费者OrderController中的url:
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
- 然后在消费者的ApplicationContextConfig里的restTemplate方法上加上@LoadBalanced,开启负载均衡功能。
- 启动eurekaServer集群,启动提供者集群,启动消费者。
如果启动提供者后出现,这个错误:Public Key Retrieval is not allowed
请在yml文件中的datasource.datasource.url后加上&allowPublicKeyRetrieval=true即可解决。
- 测试
4.4 actuator微服务信息完善
修改几个微服务的yml
#######8001#######
# client:
# ...instance要和client对齐
instance:
instance-id: payment8001
prefer-ip-address: true #访问路径可以显示ip地址
#######8002#######
instance:
instance-id: payment8002 #修改显示的主机名
prefer-ip-address: true #访问路径可以显示ip地址
#######80#######
instance:
instance-id: consumer80 #修改显示的主机名
prefer-ip-address: true #访问路径可以显示ip地址
修改前:
修改后:
4.4 服务发现Discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息。
- 在主启动类上添加@EnableDiscoveryClient注解,启动发现客户端
- 在服务提供者的PaymentController中加入:
@Resource
private DiscoveryClient discoveryClient;//springframework的DiscoveryClient(不要导错包了)
@GetMapping("/discovery")
public Object discovery(){
//获取服务列表的信息
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("*******element:" + element);
}
//获取CLOUD-PAYMENT-SERVICE服务的所有具体实例
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance : instances) {
//getServiceId服务器id getHost主机名称 getPort端口号 getUri地址
log.info(instance.getServiceId() + "t" + instance.getHost() + "t" + instance.getPort() + "t" + instance.getUri());
}
return this.discoveryClient;
}
}
- 测试
4.5 Eureka自我保护
4.5.1 概述
保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
- 现象
如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式:
4.5.2 产生原因
防止在网络不通畅的情况下,EurekaClient可以正常运行,但是EurekaServer接收不到EurekaClient的心跳,而将EurekaClient服务剔除。
开启Eureka自我保护后,在某一时刻某个微服务不可用了,EurekaServer不会立即进行清理,而是依旧会对该微服务的信息进行保存
4.5.3 自我保护机制
默认情况下,EurekaClient会定时向EurekaServer端发送心跳包。如果EurekaServer端在一定时间内(默认90s)没有收到EurekaClient发来的心跳,就会直接把该服务从服务注册列表中删除。但是,在短时间内(默认90s)丢失了大量的服务实例心跳,这时EurekaServer就会自动开启自我保护机制,不会剔除这些服务。
该现象可能发生在网络分区故障发生(延时、卡顿、拥挤)时,但是EurekaClient并未宕机,如果将这些服务从服务注册列表中剔除,就会出现严重失误。
在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。
它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。
使用自我保护模式,可以让Eureka集群更加的健壮、稳定。
4.5.4 关闭自我保护
- EurekaServer自我保护机制默认开启
eureka.server.enable-self-preservation = true
- 将eureka.server.enable-self-preservation设为false,可以禁用自我保护模式
server端
服务端
- 关闭效果
- 关闭8001,模拟网络超时
在进行开发时,可以关闭自我保护机制,同时将心跳时间和超时时间设置的小一点,便于服务关闭时server端及时剔除失效服务。如果设置过大,容易造成短时间内失效服务达到阈值85%,从而自动开启自我保护机制。
学习视频:01_前言闲聊和课程说明_哔哩哔哩_bilibili
最后
以上就是虚幻缘分为你收集整理的SpringCloud笔记11. 父工程构建1.2 父工程pom文件改造2. REST微服务工程搭建3. 抽取重复结构,重构工程4. Eureka服务注册与发现的全部内容,希望文章能够帮你解决SpringCloud笔记11. 父工程构建1.2 父工程pom文件改造2. REST微服务工程搭建3. 抽取重复结构,重构工程4. Eureka服务注册与发现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复