| - | - | - |
|---|---|---|
| 01_前言闲聊和课程说明 | 02_零基础微服务架构理论入门 | 03_第二季Boot和Cloud版本选型 |
| 04_Cloud组件停更说明 | 05_父工程Project空间新建 | 06_父工程pom文件 |
| 07_复习DependencyManagement和Dependencies | 08_支付模块构建(上) | 09_支付模块构建(中) |
| 10_支付模块构建(下) | 11_热部署Devtools | 12_消费者订单模块(上) |
| 13_消费者订单模块(下) | 14_工程重构 | 15_Eureka基础知识 |
| 16_EurekaServer服务端安装 | 17_支付微服务8001入驻进EurekaServer | 18_订单微服务80入驻进EurekaServer |
| 19_Eureka集群原理说明 | 20_Eureka集群环境构建 | 21_订单支付两微服务注册进Eureka集群 |
| 22_支付微服务集群配置 | 23_actuator微服务信息完善 | 24_服务发现Discovery |
| 25_Eureka自我保护理论知识 | 26_怎么禁止自我保护 | 27_Eureka停更说明 |
| 28_支付服务注册进zookeeper | 29_临时还是持久节点 | 30_订单服务注册进zookeeper |
| 31_Consul简介 | 32_安装并运行Consul | 33_服务提供者注册进Consul |
| 34_服务消费者注册进Consul | 35_三个注册中心异同点 | 36_Ribbon入门介绍 |
| 37_Ribbon的负载均衡和Rest调用 | 38_Ribbon默认自带的负载规则 | 39_Ribbon负载规则替换 |
| 40_Ribbon默认负载轮询算法原理 | 41_RoundRobinRule源码分析 | 42_Ribbon之手写轮询算法 |
| 43_OpenFeign是什么 | 44_OpenFeign服务调用 | 45_OpenFeign超时控制 |
| 46_OpenFeign日志增强 | 47_Hystrix是什么 | 48_Hystrix停更进维 |
| 49_Hystrix的服务降级熔断限流概念初讲 | 50_Hystrix支付微服务构建 | 51_JMeter高并发压测后卡顿 |
| 52_订单微服务调用支付服务出现卡顿 | 53_降级容错解决的维度要求 | 54_Hystrix之服务降级支付侧fallback |
| 55_Hystrix之服务降级订单侧fallback | - | - |
教学视频
源码文件1、源码文件2
02_零基础微服务架构理论入门什么是微服务
In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.——James Lewis and Martin Fowler (2014)
- 微服务是一种架构风格
- 一个应用拆分为一组小型服务
- 每个服务运行在自己的进程内,也就是可独立部署和升级
- 服务之间使用轻量级HTTP交互
- 服务围绕业务功能拆分
- 可以由全自动部署机制独立部署
- 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术
手机
PC
智能家居
…
满足哪些维度?支撑起这些维度的具体技术?
-
服务调用
-
服务降级
-
服务注册与发先
-
服务熔断
-
负载均衡
-
服务消息队列
-
服务网关
-
配置中心管理
-
自动化构建部署
-
服务监控
-
全链路追踪
-
服务定时任务
-
调度操作
是什么?符合微服务技术维度
SpringCloud=分布式微服务架构的站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶
猜猜SpringCloud这个大集合里有多少种技术?
SpringCloud俨然已成为微服务开发的主流技术栈,在国内开发者社区非常火爆。
“微”力十足,互联网大厂微服务架构案例
京东的: 阿里的: 京东物流的: Spring Cloud技术栈 总结 03_第二季Boot和Cloud版本选型-
Spring Boot 2.X 版
- 源码地址
- Spring Boot 2 的新特性
- 通过上面官网发现,Boot官方强烈建议你升级到2.X以上版本
-
Spring Cloud H版
- 源码地址
- 官网
-
Spring Boot 与 Spring Cloud 兼容性查看
- 文档
- JSON接口
-
接下来开发用到的组件版本
- Cloud - Hoxton.SR1
- Boot - 2.2.2.RELEASE
- Cloud Alibaba - 2.1.0.RELEASE
- Java - Java 8
- Maven - 3.5及以上
- MySQL - 5.7及以上
-
停更引发的“升级惨案”
- 停更不停用
- 被动修复bugs
- 不再接受合并请求
- 不再发布新版本
-
Cloud升级
-
服务注册中心
- × Eureka
- √ Zookeeper
- √ Consul
- √ Nacos
-
服务调用
- √ Ribbon
- √ LoadBalancer
-
服务调用2
- × Feign
- √ OpenFeign
-
服务降级
- × Hystrix
- √ resilience4j
- √ sentienl
-
服务网关
- × Zuul
- ! Zuul2
- √ gateway
-
服务配置
- × Config
- √ Nacos
-
服务总线
- × Bus
- √ Nacos
-
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/
一、搭建总工程这一步最好选自己下载maven,高于3.5.2版本
删除 src 文件夹,pom加入 pom
设置编码
设置文件显示过滤(可做可不做这一步)
选择 java 8
勾上勾勾
二、父工程 pom 文件添加依赖配置 1.添加依赖 1.统一 管理 Jar 包版本2.子模块继承之后,提供作用: 锁定版本 + 子 modlue 不用写 groupId 和 versionUTF-8 1.8 1.8 4.12 1.2.17 1.16.18 5.1.47 1.1.16 1.3.0
dependencyManagement
3.pluginorg.springframework.boot spring-boot-dependencies 2.2.2.RELEASE pom import org.springframework.cloud spring-cloud-dependencies Hoxton.SR9 pom import com.alibaba.cloud spring-cloud-alibaba-dependencies 2.1.0.RELEASE pom import mysql mysql-connector-java ${mysql.version} com.alibaba druid ${druid.version} org.mybatis.spring.boot mybatis-spring-boot-starter ${mybatis.spring.boot.version}
2.添加完的 pom 文件代码org.springframework.boot spring-boot-maven-plugin true true
3. dependencyManagement 是什么4.0.0 com.atguigu.springcloud cloud2020 1.0-SNAPSHOT pom UTF-8 1.8 1.8 4.12 1.2.17 1.16.18 5.1.47 1.1.16 1.3.0 org.springframework.boot spring-boot-dependencies 2.2.2.RELEASE pom import org.springframework.cloud spring-cloud-dependencies Hoxton.SR9 pom import com.alibaba.cloud spring-cloud-alibaba-dependencies 2.1.0.RELEASE pom import mysql mysql-connector-java ${mysql.version} com.alibaba druid ${druid.version} org.mybatis.spring.boot mybatis-spring-boot-starter ${mybatis.spring.boot.version} org.springframework.boot spring-boot-maven-plugin true true
maven 使用 dependencyManagement 元素来提供了一种管理依赖版本号的方式。
通常会在一个组织或者项目的最顶层的 父POM 中看到 dependencyManagement 元素。
使用pom.xml中的dependencyManagement元素能让所有在子项目中引用一个依赖而不用显式的列出版本号。Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用这个dependencyManagement元素中指定的版本号。
这样做的好处就是:如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要一个一个子项目的修改;另外如果某个子项目需要另外的一个版本,只需要声明version就可。
dependencyManagement里只是声明依赖,并不实现引A,因此子项目需要显示的声明需要用的依赖。
如果不在子项目中声明依赖,是不会从父项中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;
如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
4.Maven 中跳过单元测试 三、建立子工程(支付模块) 1.父工程右键新建module 2.输入 ArtifactId :cloud-provider-payment8001 3.这里注意 Module name:默认会去除 -号 4. 子工程 pom 文件代码5.写 application.yml 配置文件cloud2020 com.atguigu.springcloud 1.0-SNAPSHOT 4.0.0 cloud-provider-payment8001 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.mybatis.spring.boot mybatis-spring-boot-starter com.alibaba druid-spring-boot-starter 1.1.10 mysql mysql-connector-java org.springframework.boot spring-boot-starter-jdbc org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver # mysql 驱动包
url: jdbc:mysql://localhost:3306/db2019?useUnicode-true&characterEncoding-utf-8&usessL=false
username: root
password: root
6.编写 子工程启动类 com.atguigu.springcloud.PaymentMain8001
6.1启动类代码
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
7.支付模块构建(中)
1.业务类
SQL:
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=utf8mb4
2.Entities:
实体类Payment:
package com.atguigu.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private Long id;
private String serial;
}
3.JSON封装体CommonResult:
package com.atguigu.springcloud.entities; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class CommonResult4.DAO:{ private Integer code; private String message; private T data; public CommonResult(Integer code, String message){ this(code, message, null); } }
接口PaymentDao:
package com.atguigu.springcloud.dao;
import com.atguigu.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface PaymentDao {
@Insert("insert into payment(serial) values(#{serial})")
public int create(Payment payment);
@Select("select * from payment where id=#{id}")
public Payment getPaymentById(@Param("id") Long id);
}
5.Service:
接口PaymentService
package com.atguigu.springcloud.service;
import com.atguigu.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
public interface PaymentService {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
6.实现类
PaymentServiceImpl
package com.atguigu.springcloud.service.impl;
import com.atguigu.springcloud.dao.PaymentDao;
import com.atguigu.springcloud.entities.Payment;
import com.atguigu.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
@Override
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
}
7.Controller
package com.atguigu.springcloud.controller;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import com.atguigu.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@Slf4j
public class PaymentController{
@Resource
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
public CommonResult create(Payment payment)
{
int result = paymentService.create(payment);
log.info("*****插入结果:"+result);
if(result > 0)
{
return new CommonResult(200,"插入数据库成功: ",result);
}else{
return new CommonResult(444,"插入数据库失败",null);
}
}
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id)
{
Payment payment = paymentService.getPaymentById(id);
if(payment != null)
{
return new CommonResult(200,"查询成功: ",payment);
}else{
return new CommonResult(444,"没有对应记录,查询ID: "+id,null);
}
}
}
8.支付模块构建(下)
1.测试
- 浏览器 - http://localhost:8001/payment/get/1
- http://localhost:8001/payment/create?serial=lun2
创建微服务模块套路:
- 建Module
- 改POM
- 写YML
- 主启动
- 业务类
开发时使用,生产环境关闭
1.Adding devtools to your project2.Adding plugin to your pom.xmlorg.springframework.boot spring-boot-devtools runtime true
下段配置复制到聚合父类总工程的pom.xml
3.Enabling automatic buildorg.springframework.boot spring-boot-maven-plugin true true
开启自动编译的选项
File -> Settings(New Project Settings->Settings for New Projects) ->Complier
下面项勾选
- Automatically show first error in editor
- Display notification on build completion
- Build project automatically
- Compile independent modules in parallel
键入Ctrl + Shift + Alt + / ,打开Registry,勾选:
- compiler.automake.allow.when.app.running
- actionSystem.assertFocusAccessFromEdt
注意:热部署会在 你修改代码后,过一小段时间重新运行
四、消费者订单模块 1.建Module
创建名为cloud-consumer-order80的maven工程。
2.改POM3.写YMLcloud2020 com.atguigu.springcloud 1.0-SNAPSHOT 4.0.0 cloud-consumer-order80 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test
server: port: 804.主启动
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderMain80
{
public static void main( String[] args ){
SpringApplication.run(OrderMain80.class, args);
}
}
5.业务类
实体类:
package com.atguigu.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private Long id;
private String serial;
}
package com.atguigu.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private Long id;
private String serial;
}
控制层:
package com.atguigu.springcloud.controller;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
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;
import javax.annotation.Resource;
@Slf4j
@RestController
public class OrderController {
// 采用 RestTemplate 调其他服务的接口,这里是调用 8001服务的接口
public static final String PAYMENT_URL = "http://localhost:8001";
@Resource
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult create(Payment payment){
// 8001 服务的 Post请求
return restTemplate.postForObject(PAYMENT_URL+"/payment/create", payment, CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult getPayment(@PathVariable("id") Long id){
// 8001 服务的Get 请求
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id, CommonResult.class);
}
}
配置类:
采用 RestTemplate 调其他服务的接口
package com.atguigu.springcloud.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
6.测试
打开 run Dashboard
可以看到我们启动的两个服务
运行cloud-consumer-order80与cloud-provider-payment8001两工程
浏览器 - http://localhost/consumer/payment/get/1
RestTemplate
RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集
官网地址 https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
使用:
- 使用restTemplate访问restful接口非常的简单粗暴无脑。
- (url, requestMap, ResponseBean.class)这三个参数分别代表。
- REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
浏览器 - http://localhost/consumer/payment/create?serial=lun3
虽然,返回成功,但是观测数据库中,并没有创建serial为lun3的行。
解决之道:在loud-provider-payment8001工程的PaymentController中添加@RequestBody注解。
public class PaymentController
{
@PostMapping(value = "/payment/create")
public CommonResult create(@RequestBody Payment payment){
...
}
}
通过修改idea的workspace.xml的方式来快速打开Run Dashboard窗口(这个用来显示哪些Spring Boot工程运行,停止等信息。我idea 2020.1版本在名为Services窗口就可以显示哪些Spring Boot工程运行,停止等信息出来,所以这仅作记录参考)。
- 开启Run DashBoard
去到本地文件夹
- 打开工程路径下的.idea文件夹的workspace.xml
- 在< component name=“RunDashboard”> 中修改或添加以下代码:
如果有就不管,没有就新增
由于idea版本差异,可能需要关闭重启。
五、工程重构
观察cloud-consumer-order80与cloud-provider-payment8001两工程有重复代码(entities包下的实体)(坏味道),重构。
1.新建 cloud-api-commons 公共子工程 2.POM3.entitiescloud2020 com.atguigu.springcloud 1.0-SNAPSHOT 4.0.0 cloud-api-commons org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true cn.hutool hutool-all 5.1.0
将cloud-consumer-order80与cloud-provider-payment8001两工程的公有entities包移至cloud-api-commons工程下。
删除cloud-consumer-order80与cloud-provider-payment8001两工程的公有entities包
4.maven clean、install cloud-api-commons工程,以供给cloud-consumer-order80与cloud-provider-payment8001两工程调用。
5.订单80和支付8001分别改造
将cloud-consumer-order80与cloud-provider-payment8001两工程的公有
- entities包移除
- 引入cloud-api-commons依赖
com.atguigu.springcloud
cloud-api-commons
${project.version}
6.测试
六、Eureka基础知识
什么是服务治理
Spring Cloud封装了Netflix 公司开发的Eureka模块来实现服务治理
在传统的RPC远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
什么是服务注册与发现Eureka采用了CS的设计架构,Eureka Sever作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何RPC远程框架中,都会有一个注册中心存放服务地址相关信息(接口地址)
Eureka包含两个组件:Eureka Server和Eureka Client
Eureka Server提供服务注册服务
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
EurekaClient通过注册中心进行访问
它是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)
EurekaServer服务端安装IDEA生成eurekaServer端服务注册中心,类似物业公司
1.创建名为cloud-eureka-server7001的Maven工程 2.修改pom.xml
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
POM 代码如下
3.添加application.ymlcloud2020 com.atguigu.springcloud 1.0-SNAPSHOT 4.0.0 cloud-eureka-server7001 org.springframework.cloud spring-cloud-starter-netflix-eureka-server com.atguigu.springcloud cloud-api-commons ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok org.springframework.boot spring-boot-starter-test test junit junit
server:
port: 7001
eureka:
instance:
hostname: locathost #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己。
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
4.主启动
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class, args);
}
}
5.测试运行EurekaMain7001,浏览器输入http://localhost:7001/回车,会查看到Spring Eureka服务主页。
6.支付微服务8001入驻进EurekaServer
EurekaClient端cloud-provider-payment8001将注册进EurekaServer成为服务提供者provider,类似学校对外提供授课服务。
1.修改cloud-provider-payment8001 2.改POM添加spring-cloud-starter-netflix-eureka-client依赖
3.写YML 修改org.springframework.cloud spring-cloud-starter-netflix-eureka-client
eureka:
client:
#表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
4.主启动 修改
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
5.测试
- 启动cloud-provider-payment8001和cloud-eureka-server7001工程。
- 浏览器输入 - http://localhost:7001/ 主页内的Instances currently registered with Eureka会显示cloud-provider-payment8001的配置文件application.yml设置的应用名cloud-payment-service
spring:
application:
name: cloud-payment-service
6.自我保护机制
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARELESSER THAN THRESHOLD AND HENCFT ARE NOT BEING EXPIRED JUST TO BE SAFE.
紧急情况!EUREKA可能错误地声称实例在没有启动的情况下启动了。续订小于阈值,因此实例不会为了安全而过期。
7.订单微服务80入驻进EurekaServerEurekaClient端cloud-consumer-order80将注册进EurekaServer成为服务消费者consumer,类似来上课消费的同学
1.cloud-consumer-order80 2.POM3.YMLorg.springframework.cloud spring-cloud-starter-netflix-eureka-client
server:
port: 80
spring:
application:
name: cloud-order-service
eureka:
client:
#表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
4.主启动 加入@EnableEurekaClient
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80
{
public static void main( String[] args ){
SpringApplication.run(OrderMain80.class, args);
}
}
5.测试
- 启动cloud-provider-payment8001、cloud-eureka-server7001和cloud-consumer-order80这三工程。
- 浏览器输入 http://localhost:7001 , 在主页的Instances currently registered with Eureka将会看到cloud-provider-payment8001、cloud-consumer-order80两个工程名。
注意,application.yml配置中层次缩进和空格,两者不能少,否则,会抛出异常Failed to bind properties under ‘eureka.client.service-url’ to java.util.Map
8.Eureka集群原理说明 1.Eureka集群原理说明 问题:微服务RPC远程服务调用最核心的是什么
服务注册:将服务信息注册进注册中心
服务发现:从注册中心上获取服务信息
实质:存key服务命取value闭用地址
1先启动eureka注主册中心
2启动服务提供者payment支付服务
3支付服务启动后会把自身信息(比服务地址L以别名方式注朋进eureka
4消费者order服务在需要调用接口时,使用服务别名去注册中心获取实际的RPC远程调用地址
5消去者导调用地址后,底屋实际是利用HttpClient技术实现远程调用
6消费者实癸导服务地址后会缓存在本地jvm内存中,默认每间隔30秒更新—次服务调用地址
高可用,试想你的注册中心只有一个only one,万一它出故障了,会导致整个为服务环境不可用。
解决办法:搭建Eureka注册中心集群,实现负载均衡+故障容错。
互相注册,相互守望。
9.Eureka集群环境构建 创建cloud-eureka-server7002工程,过程参考
EurekaServer服务端安装
基本配置跟7001一样就好
- 找到C:WindowsSystem32driversetc路径下的hosts文件,修改映射配置添加进hosts文件
127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com修改cloud-eureka-server7001配置文件
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eureka
defaultZone: http://eureka7002.com:7002/eureka/
#单机就是7001自己
#defaultZone: http://eureka7001.com:7001/eureka/
修改cloud-eureka-server7002配置文件
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eureka
defaultZone: http://eureka7001.com:7001/eureka/
#单机就是7002自己
#defaultZone: http://eureka7002.com:7002/eureka/
浏览器访问:
http://eureka7001.com:7001
或者 http://eureka7002.com:7002
实践的时候,遇到异常情况
在开启cloud-eureka-server7002时,开启失败,说7002端口被占用,然后在cmd中输入netstat -ano | find “7002”,查不到任何东西。
纳闷一阵,重启电脑,问题解决。
10.订单支付两微服务注册进Eureka集群
将支付服务8001微服务,订单服务80微服务发布到上面2台Eureka集群配置中
将它们的配置文件的eureka.client.service-url.defaultZone进行修改 8001 yml配置修改
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver # mysql 驱动包
url: jdbc:mysql://localhost:3306/db2019?allowMultiQueries=true&useAffectedRows=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull
username: root
password: root
eureka:
client:
#表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
#defaultZone: http://localhost:7001/eureka
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
80 yml 配置修改
server:
port: 80
spring:
application:
name: cloud-order-service
eureka:
client:
#表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
#defaultZone: http://localhost:7001/eureka
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka #集群版
- 测试01
-
先要启动EurekaServer,7001/7002服务
-
再要启动服务提供者provider,8001
-
再要启动消费者,80
-
浏览器输入 - http://localhost/consumer/payment/get/1
-
11.支付微服务集群配置
支付服务提供者8001集群环境构建
参考cloud-provicer-payment8001
1.新建cloud-provider-payment8002
2.改POM
3.写YML - 端口8002
4.主启动
5.业务类
6.修改8001/8002的Controller,添加serverPort



