SpringCloud学习笔记
一 从2.2.x和H版开始说起
1.1 微服务简介
1.2 SpringCloud 简介
1.3 SpringCloud技术栈
1.4 SpringBoot版本选择
1.4.1 git源码地址
git源码地址:https://github.com/spring-projects/spring-boot/releases/
为了稳定起见,建议用Spring boot2.x
1.4.2 SpringBoot2.0新特性
git源码地址:https:github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes
通过上面官网发现 Boot官方强烈建议你升级到2.X以上版本。
1.4.3 官网看Boot版本
- springboot(截止2019.10.26)
- springboot(截止2020.2.15)
1.5 SpringCloud版本选择
1.5.1 git源码地址
git源码地址:https://github.com/spring-projects/spring-cloud/releases/
1.5.2 官网
官网:https://spring.io/projects/spring-cloud
1.5.3 官网看Cloud版本
1.5.3.1 Cloud命名规则
SpringCloud采用了英国伦敦地铁站的名称来命名,并由地铁站名称字母A-Z依次类推的形式来发布迭代版本。
SpringCloud是一个由许多子项目组成的综合项目,各个项目有不同的发布节奏。为了管理SpringCloud与各子项目的版本依赖关系,发布了一个清单,其中包括了某个SpringCloud版本对应的子项目版本。为了避免SpringCloud版本号与子项目版本混乱,SpringCloud版本采用了名称而并非版本号的命名,这些版本的名字采用了伦敦地铁站的名字,根据字母表的顺序来对应版本时间顺序。例如Angel是第一个版本,Brixton是第二个版本。当SpringCloud的发布内容积累到列节点或者一个重大Bug被解决后,会发布一个’service releases’版本,简称SRX版本,比如Greenwich.SR2就是SpringCloud发布的Greenwich版本的第2个SRX版本。
1.5.3.2 springcloud(截止2019.10.26)
1.5.3.3 springboot(截止2020.2.15)
1.6 Springcloud和Springboot之间的依赖关系
1.6.1 官方文档
官方文档:https://spring.io/projects/spring-cloud#overview
1.6.2 依赖
1.6.3 更详细的版本对应查看方法
查询网址:https://start.spring.io/actuator/info
1.7 项目环境
工具 | 版本 |
---|---|
cloud | Hoxton.SR1 |
boot | 2.2.RELEASE |
cloud | alibaba 2.1.0.RELEASE |
java | Java8 |
Maven | 3.5及以上 |
1.8 题外话
- boot版已经到3.0.0为最新,为什么选2.2.2?
只用boot,可以直接用最新版,但是同时用boot和cloud,需要照顾,由cloud决定boot版本。
- 2.x版本常用软件pom
<dependencies>
<!-- springboot 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 2.2.9.RELEASE -->
<!-- SpringCloudAlibaba有关依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
二 关于Cloud各种组件的停更/升级/替换
2.1 由停更引发的"升级惨案"
2.1.1 停更不停用
- 被动修复bugs。
- 不再接受合并请求。
- 不再发布新版本。
2.1.2 明细条目
- 之前
- now
1) 服务注册中心:Eureka(重度患者)、Zookeeper、Consul、Nacos(推荐)。
2)服务调用: Ribbon(轻度患者)、LoadBalancer。
3)服务调用:Feign,OpenFeign。
4)服务降级:Hystrix、resilience4j(国外使用多)、alibaba Sentinel(国内使用多)。
5)服务网关:Zuul、Zuul2(胎死腹中)、gateway。
6)服务配置:Config、Nacos、apollo。
7)服务主线:Bus、Nacos。
2.1.3 参考资料见官网
Spring Cloud:https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/
Spring Cloud中文文档:https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md
Spring Boot:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/
三 微服务架构编码构建
3.1 IDEA新建project工作空间
3.1.1 父工程步骤
-
New Project
-
聚合总父工程名字
-
Maven选版本
-
字符编码
文件–>设置–>文本编码
-
注解生效激活
文件–>设置–>构建,执行,部署–>Compiler–>Annotation processors
-
java编译版本选8
文件–>设置–>构建,执行,部署–>Compiler–>Java Compiler
-
File Type过滤
文件–>设置–>编辑器–>文件类型
![在这里插入图片描述](https://img-blog.csdnimg.cn/359562f9ddc3402a8d73053ce3d33840.png
3.1.2 父工程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.tedu.java</groupId>
<artifactId>cloud2022</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>Maven</name>
<!-- FIXME change it to the project's website -->
<url>http://maven.apache.org/</url>
<inceptionYear>2001</inceptionYear>
<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.12</log4j.version>
<lombok.version>1.18.16</lombok.version>
<mysql.version>8.0.26</mysql.version>
<druid.version>1.2.11</druid.version>
<mybatis.spring.boot.version>2.1.4</mybatis.spring.boot.version>
</properties>
<!-- 子模块继承之后,提供作用:锁定版本+子模块不用写groupId和version -->
<dependencyManagement>
<dependencies>
<!-- springboot 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 2.2.9.RELEASE -->
<!-- SpringCloudAlibaba有关依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.7</version>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.1.3 Maven工程落地细节复习
- Maven中的DependencyManagement和Dependencies?
父项目中 不使用dependencyManagement,直接使用 dependencies,则子项目会继承引入父项目中的依赖。而父项目中使用dependencyManagement,则子项目不会引入依赖,需要显式的自行添加依赖。但可以不用添加版本号,直接继承父项目的版本号。
说明:dependencyManagement一般用在maven构建的聚合项目的父项目中,只是用来声明和锁定版本(通常用语有多个子项目,但是不是每个子项目都需要引入同一种依赖的场景),所以使用dependencyManagement元素提供了一种管理依赖版本号的方式,通常会在一个组织或者项目的最顶层父POM中看到dependencyManagement元素。 - maven中跳过单元测试?
3.1.4 父工程创建完成执行mvn:insall将父工程发布到仓库方便子工程继承
3.2 Rest微服务工程搭建
3.2.1 Cloud-provider-payment8001 微服务提供者Module模块
3.2.1.1 建module
创建完成后回到父工程查看pom文件变化?
3.2.1.2 改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">
<parent>
<artifactId>cloud2022</artifactId>
<groupId>com.tedu.java</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Cloud-provider-payment8001</artifactId>
<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.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>
3.2.1.3 写YML
application.yml
server:
port: 8001
spring:
application:
name: cloud-payment-service8001
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/db2022_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.tedu.java.pojo #所在pojo别名类所在包
3.2.1.4 主启动
package com.tedu.java;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author 47132
*/
@SpringBootApplication
public class PayMentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PayMentMain8001.class,args);
}
}
3.2.1.5 业务类
1) 建表SQL
在数据库中新增数据库db2022_cloud,在db2022_cloud新增表payment。
CREATE TABLE `payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`serial` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '支付流水号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '支付表' ROW_FORMAT = Dynamic;
2)pojo
主实体Payment:
package com.tedu.java.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author 47132
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private Long id;
private String serial;
}
Json封装体CommonResult类
package com.tedu.java.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 47132
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
//404 not_found
private Integer code;
private String message;
private T data;
public CommonResult(Integer code,String message){
this(code,message,null);
}
}
3)dao
PaymentDao 接口
package com.tedu.java.dao;
import com.tedu.java.pojo.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @author 47132
*/
@Mapper
public interface PaymentDao {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
mybatis的映射文件PaymentMapper.xml:
路径:src\main\resources\mapper\PaymentMapper.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.tedu.java.dao.PaymentDao">
<insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
insert into payment (serial) values (#{serial});
</insert>
<resultMap id="BaseResultMap" type="Payment">
<id column="id" property="id" jdbcType="BIGINT"></id>
<id column="serial" property="serial" jdbcType="VARCHAR"></id>
</resultMap>
<select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
select * from payment where id=#{id};
</select>
</mapper>
4)service
接口PaymentService
package com.tedu.java.service;
import com.tedu.java.pojo.Payment;
import org.apache.ibatis.annotations.Param;
/**
* @author 47132
*/
public interface PaymentService {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
实现类 PaymentServiceImpl
package com.tedu.java.service.impl;
import com.tedu.java.dao.PaymentDao;
import com.tedu.java.pojo.Payment;
import com.tedu.java.service.PaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PaymentServiceImpl implements PaymentService {
@Autowired
private PaymentDao paymentDao;
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
@Override
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
}
5)controller
PaymentController
package com.tedu.java.controller;
import com.tedu.java.pojo.Payment;
import com.tedu.java.service.PaymentService;
import com.tedu.java.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @author 47132
*/
@RestController
@Slf4j
public class PaymentController {
@Autowired
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
public CommonResult create(@RequestBody Payment payment) {
int result = paymentService.create(payment);
log.info("*******插入结果:" + result);
if (result > 0) {
return new CommonResult(200, "插入结果成功,serverPort:", result);
} else {
return new CommonResult(444, "插入结果失败!!serverPort:");
}
}
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id) {
Payment paymentResult = paymentService.getPaymentById(id);
log.info("*******插入结果为:" + paymentResult);
if (paymentResult != null) {
return new CommonResult(200, "查询结果成功,serverPort:"+serverPort, paymentResult);
} else {
return new CommonResult(444, "没有对应记录!!查询id为:"+id+",serverPort:"+serverPort);
}
}
}
3.2.1.6 测试
运行项目,先使用postman模拟post请求,添加数据,然后查询。
3.2.2 热部署Devtools
3.2.2.1 Adding devtools to your project(引入maven依赖)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
3.2.2.2 Adding plugin to your pom.xml(添加插件到pom)
<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>
3.2.2.3 Enabling automatic build(开启自动编译)
3.2.2.4 Update the value of(idea中快捷键:ctrl+shift+alt+/)
3.2.2.5 重启idea
3.2.3 cloud-consumer-order80 微服务消费者订单Module模块
3.2.3.1 新建cloud-consumer-order80
3.2.3.2 改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">
<parent>
<artifactId>cloud2022</artifactId>
<groupId>com.tedu.java</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-consumer-order80</artifactId>
<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-starter-test</artifactId>
<scope>test</scope>
</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>
</dependencies>
</project>
3.2.3.3 写YML
server:
port: 80
spring:
application:
name: cloud-comsumer-order80
3.2.3.4 主启动
package com.tedu.java;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author 47132
*/
@SpringBootApplication
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class,args);
}
}
3.2.3.5 业务类
- pojo
主实体Payment:
package com.tedu.java.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author 47132
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private Long id;
private String serial;
}
Json封装体CommonResult类
package com.tedu.java.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 47132
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
//404 not_found
private Integer code;
private String message;
private T data;
public CommonResult(Integer code,String message){
this(code,message,null);
}
}
- 首说RestTemplate
RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具类。
- config配置类
ApplicationContextConfig 类
package com.tedu.java.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author 47132
*/
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
- controller
OrderController 类
package com.tedu.java.controller;
import com.tedu.java.pojo.Payment;
import com.tedu.java.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author 47132
*/
@RestController
@Slf4j
public class OrderController {
public static final String PAYMENT_URL="HTTP://localhost:8001";
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment){
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment, CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
}
}
3.2.3.6 测试
先启动8001,再启动80,然后浏览器访问http://localhost/consumer/payment/get/1
3.2.4 工程重构
3.2.4.1 观察问题
系统中有重复部分,重构。
3.2.4.2 新建cloud-api-common
3.2.4.3 改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">
<parent>
<artifactId>cloud2022</artifactId>
<groupId>com.tedu.java</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-api-commons</artifactId>
<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>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.6</version>
</dependency>
</dependencies>
</project>
3.2.4.3 pojo
主实体Payment:
package com.tedu.java.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author 47132
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private Long id;
private String serial;
}
Json封装体CommonResult类
package com.tedu.java.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 47132
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
//404 not_found
private Integer code;
private String message;
private T data;
public CommonResult(Integer code,String message){
this(code,message,null);
}
}
3.2.4.4 maven命令clean install
3.2.4.5 订单80和支付8001分别改造
- 删除各自的原先的pojo和utils文件夹。
- 各自粘贴POM内容:
<dependency>
<groupId>com.tedu.java</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3.2.5 目前工程样图
四 Eureka服务注册与发现
4.1 Eureka基础知识
4.1.1 什么是服务治理
Spring Cloud封装了Netflix 公司开发的Eureka模块来实现服务治理。
在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
4.1.2 什么是服务注册
Erueka采用了CS的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server 来监控系统中各个微服务是否正常运行。
在微服务注册与发现中,有一个注册中心。当服务器启动的时候,就会把当前自己服务器的信息,比如服务地址通讯地址等以别名的形式注册到注册中心上。另一方(消费者|服务者提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想;在于注册中心,因为使用注册中心管理每一个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))。
4.1.3 Eureka两组件
- Eureka Server:提供服务注册功能。
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册列表将会存储所有可用服务节点的信息,服务节点的信息可以再界面中直观看到。 - EurekaClient:通过注册中心进行访问。
是一个java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮循(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)。
4.2 单机Eureka构建步骤
4.2.1 IDEA生成EurekaServer端服务注册中心
- 建Module(cloud-eureka-server7001)
- 改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">
<parent>
<artifactId>cloud2022</artifactId>
<groupId>com.tedu.java</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-eureka-server7001</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.tedu.java</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</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>
</dependencies>
</project>
- 写YML
server:
port: 7001
spring:
application:
name: cloud-eureka-server7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
#false表示自己断就是注册中心,职责就是维护服务实例,并不是区检索服务
fetch-registry: false #不注册自己
#fasle表示不向注册中心注册自己
register-with-eureka: false # 不检索自己
service-url:
#设置与eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7001.com:7001/eureka
- 启动类EurekaMain7001
package com.tedu.java;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @author 47132
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class,args);
}
}
- 修改host文件
- 启动7001测试
http://eureka7001.com:7001
No application available没有服务被发现 因为没有注册服务进来当前不可能有服务被发现。
4.2.2 EurekaClient端cloud-provider-payment8001 将注册进EurekaServer成为服务提供者provider
- 改POM
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 写YML
eureka:
client:
#表示是否将自己注册进eurekaServer,默认为true
register-with-eureka: true
#是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
#defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
defaultZone: http://eureka7001.com:7001/eureka
- 主启动类
@SpringBootApplication
@EnableEurekaClient
public class PayMentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PayMentMain8001.class,args);
}
}
- 测试
先启动EurekaServer,然后再浏览器输入:http://eureka7001.com:7001,然后再启动8001。
4.2.3 自我保护机制
4.3 集群Eureka构建步骤
4.3.1 Eureka集群原理说明
解决办法: 搭建Eureka注册中心集群,实现负载均衡+故障容错。
4.3.2 Eureka集群环境构建步骤
4.3.2.1 参考cloud-eureka-server7001新建cloud-eureka-server7002
4.3.2.2 改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">
<parent>
<artifactId>cloud2022</artifactId>
<groupId>com.tedu.java</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-eureka-server7002</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.tedu.java</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</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>
</dependencies>
</project>
4.3.2.3 修改映射配置
找到C:\Windows\System32\drivers\etc路径下的hosts文件:
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
刷新hosts文件:ipconfig /flushdns
4.3.2.4 写YMl
cloud-eureka-server7001:
server:
port: 7001
spring:
application:
name: cloud-eureka-server7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
#false表示自己断就是注册中心,职责就是维护服务实例,并不是区检索服务
fetch-registry: false #不注册自己
#fasle表示不向注册中心注册自己
register-with-eureka: false # 不检索自己
service-url:
#设置与eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7002.com:7002/eureka
cloud-eureka-server7002:
server:
port: 7002
spring:
application:
name: cloud-eureka-server7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
#false表示自己断就是注册中心,职责就是维护服务实例,并不是区检索服务
fetch-registry: false #不注册自己
#fasle表示不向注册中心注册自己
register-with-eureka: false # 不检索自己
service-url:
#设置与eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7001.com:7001/eureka
4.3.2.5 主启动
package com.tedu.java;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @author 47132
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7002 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7002.class,args);
}
}
4.3.3 将支付服务8001微服务发布到上面2台Eureka集群配置中
将Cloud-provider-payment8001中的application.yml修改:
server:
port: 8001
spring:
application:
name: cloud-payment-service8001
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/db2022_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.tedu.java.pojo #所在pojo别名类所在包
eureka:
client:
#表示是否将自己注册进eurekaServer,默认为true
register-with-eureka: true
#是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
#defaultZone: http://eureka7001.com:7001/eureka
4.3.4 将订单服务80微服务发布到上面2台Eureka集群配置中
将cloud-consumer-order80中的application.yml修改:
server:
port: 80
spring:
application:
name: cloud-comsumer-order80
eureka:
client:
#表示是否将自己注册进eurekaServer,默认为true
register-with-eureka: true
#是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
#defaultZone: http://eureka7001.com:7001/eureka
4.3.5 测试
先要启动EurekaServer,7001/7002服务,再要启动服务提供者provider8001,再要启动消费者80;在浏览器中输入http://localhost/consumer/payment/get/1,观察结果。
4.3.6 支付服务提供者8001集群环境搭建
4.3.6.1 参考cloud-provider-payment8001新建cloud-provider-payment8002
4.3.6.2 改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">
<parent>
<artifactId>cloud2022</artifactId>
<groupId>com.tedu.java</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-payment8002</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</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-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.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.tedu.java</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<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>
4.3.6.3 写YMl
server:
port: 8002
spring:
application:
name: cloud-payment-service8002
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/db2022_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.tedu.java.pojo #所在pojo别名类所在包
eureka:
client:
#表示是否将自己注册进eurekaServer,默认为true
register-with-eureka: true
#是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
#defaultZone: http://eureka7001.com:7001/eureka
4.3.6.4 主启动
package com.tedu.java;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @author 47132
*/
@SpringBootApplication
@EnableEurekaClient
public class PayMentMain8002 {
public static void main(String[] args) {
SpringApplication.run(PayMentMain8002.class,args);
}
}
4.3.6.5 业务类
直接从8001粘
4.3.6.6 修改8001/8002的controller
4.3.6.7 修改80的controller
package com.tedu.java.controller;
import com.tedu.java.pojo.Payment;
import com.tedu.java.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author 47132
*/
@RestController
@Slf4j
public class OrderController {
//public static final String PAYMENT_URL="HTTP://localhost:8001";
// 通过在eureka上注册过的微服务名称调用
public static final String PAYMENT_URL="http://CLOUD-PAYMENT-SERVICE";
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment){
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment, CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
}
}
4.3.6.8 使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
修改80端口的ApplicationContextConfig :
package com.tedu.java.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author 47132
*/
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
4.3.6.9 测试
先要启动EurekaServer,7001/7002服务,再要启动服务提供者provider,8001/8002服务再启动consumer;80,在浏览器输入:http://localhost/consumer/payment/get/1
修改8001和8002的application.yml,改为CLOUD-PAYMENT-SERVICE
结果:负载均衡效果达到,8001/8002端口交替出现。
因为Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号,且该服务还有负载功能了。
4.4 actuator微服务信息完善
4.4.1 主机名称:服务名称修改
- 当前问题
- 修改cloud-provoder-payment8001
yaml:
eureka:
client:
#表示是否将自己注册进eurekaServer,默认为true
register-with-eureka: true
#是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
#defaultZone: http://eureka7001.com:7001/eureka
instance:
instance-id: payment8001
8002和80也是如此。
4.5 服务发现Discovery
对于注册eureka里面的微服务,可以通过服务发现来获得该服务的信息。
4.5.1 修改cloud-provider-payment8001的Controller:
@Autowired
private DiscoveryClient discoveryClient;
/**
* 服务发现
*/
@GetMapping("/payment/discovery")
public Object discovery(){
List<String> services = discoveryClient.getServices();
for(String element : services){
log.info("*********element:"+element);
}
//一个微服务小的全部实例
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance:instances){
log.debug(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
}
return this.discoveryClient;
}
4.5.2 8001的启动类:@EnableDiscoveryClient
package com.tedu.java;
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;
/**
* @author 47132
*/
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class PayMentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PayMentMain8001.class,args);
}
}
4.5.3 测试
先要启动EurekaServer,再启动8001主启动类,需要稍等一会。在浏览器输入http://localhost:8001/payment/discovery
4.6 eureka自我保护
4.6.1 故障现象
概述:
保护模式主要用于一组客户端和Erueka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server 将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式:
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN
THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES
ARE NOT BEING EXPIRED JUST TO BE SAFE.
4.6.2 导致原因
- 为什么会产生Eureka自我保护机制?
为了防止EurekaClient可以正常运行,但是与EurekaServer网络不通情况下,EurekaServer不会立刻将EurekaClient服务剔除。 - 什么事自我保护模式?
默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurrekaServer之间无法正常通信,以上行为可能会变得非常危险----因为微服务本身其实时健康的,此时本不应该注销这个微服务。Eureka通过“自我保护机制”来解决这个问题----当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。
它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何一个可能健康的服务实例,
综上,自我保护模式是一种应对网络异常的安全保护措施。它的哲学架构是宁可同事保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目的注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。
一句话:某时刻 一个微服务不可用了,Eureka不会立刻清理,依旧会对该服务的信息进行保存,属于CAP里面的AP分支。
4.6.3 怎么禁止自我保护
4.6.3.1 注册中心eurekaServer端7001
出产默认,自我保护机制是开启的:eureka.server.enable-self-preservation=true,使用eureka.server.enable-self-preservation=false 可以禁用自我保护模式。
4.6.3.2 生产者客户端eurekaClient端8001
在默认情况下:
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
eureka.instance.lease-renewal-interval-in-seconds=30
#Eureka服务端在收到最后一次心跳后等待时间上限 ,单位为秒(默认是90秒),超时剔除服务
eureka.instance.lease-expiration-duration-in-seconds=90
配置:
eureka:
client:
#表示是否将自己注册进eurekaServer,默认为true
register-with-eureka: true
#是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
#defaultZone: http://eureka7001.com:7001/eureka
instance:
instance-id: payment8001
##Eureka服务端在收到最后一次心跳后等待时间上限 ,单位为秒(默认是90秒),超时剔除服务
lease-expiration-duration-in-seconds: 2
##Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal-interval-in-seconds: 1
4.6.3.3 测试
先启动EurekaServer,再启动8001,先关闭8001,看是否被删除。
五 Zookeeper服务注册与发现
Eureka停止更新了,你怎么办?
网址:https://github.com/Netflix/eureka/wiki
5.1 注册中心Zookeeper
Zookeeper是一个分布式协调工具,可以实现注册中心功能。
关闭Linux服务器防火墙后启动Zookeeper服务器。
5.2 服务提供者
5.2.1 新建cloud-provider-payment8004
5.2.2 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">
<parent>
<artifactId>cloud2022</artifactId>
<groupId>com.tedu.java</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-payment8004</artifactId>
<dependencies>
<dependency>
<groupId>com.tedu.java</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>
5.2.3 YML
#8004表示注册到zookeeper服务器的支付服务提供者端口号
server:
port: 8004
spring:
application:
name: cloud-provider-payment
cloud:
zookeeper:
connect-string: 192.168.43.128:2181
5.2.4 主启动类
package com.tedu.java;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author 47132
*/
@SpringBootApplication
//该注解用于向使用consul或者zookeeper作为注册中心时注册服务
@EnableDiscoveryClient
public class PaymentMain8004 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8004.class,args);
}
}
5.2.5 Controller
package com.tedu.java.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
@RestController
@Slf4j
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/payment/zk")
public String paymentZk(){
return "SpringCloud with Zookeeper:"+serverPort+"\t"+ UUID.randomUUID().toString();
}
}
5.2.6 启动8004注册进zookeeper
启动zk:
zkServer.sh start
启动后问题:
解决zookeeper版本jar包冲突问题:
排除zk冲突后的新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">
<parent>
<artifactId>cloud2022</artifactId>
<groupId>com.tedu.java</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-payment8004</artifactId>
<dependencies>
<dependency>
<groupId>com.tedu.java</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<!--先排除自带的zookeeper-->
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加zookeeper3.7.1-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.7.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>