版本选型:
Release Train Version: 2020.0.2
Supported Boot Version: 2.4.3
和 Release Train Version: Hoxton.SR11
Supported Boot Version: 2.3.10.RELEASE
注意:若pom.xml导入依赖一直报红可能是存在版本更迭问题,查看早些的项目更换版本,一直等待没有效果
建议:微服务一定要有服务端口号和微服务名称
对前端传数据用的是CommonResult,自己写用Payment。CommonResult是为了和前端进行交互的
在PaymentService中的内容和PaymentDao是一样的
dao接口要加上@Mapper;service的impl要有@Service
@Autowired是spring的,@Resource是java的
在完成第一个controller后运行出错了,随意修改居然可以运行了。同时要注意.yml文件的排版,空格,等细节。
当运行后返回的一个json字符串,这正是前端想要的,也解释了为什么controller的写法与以前不同,
然而当添加时出错了【http://localhost:8001/payment/create?serial=atguigu002】因为大部分浏览器不支持post请求,需要使用postman软件模拟。【http://localhost:8001/payment/get/31】
支付模块8001中:
1.【http://localhost:8001/payment/get/31】 成功
{"code":200,"message":"查询成功","data":{"id":31,"serial":"尚硅谷001"}}
2.【http://localhost:8001/payment/create?serial=atguigu002】 失败
解决:需要在postman才能成功
开发阶段必须开热部署,生产阶段必须关闭
消费者订单模块80调用支付模块8001成功,80端口调用8001端口的方法。端口默认为80不用在地址栏输入
消费者订单模块80中:
1.【http://localhost/consumer/payment/get/31】 成功
【{"code":200,"message":"出入数据库成功","data":1}】
2.【http://localhost/consumer/payment/create?serial=111】 失败
【{"code":200,"message":"查询成功","data":{"id":31,"serial":"尚硅谷001"}}】
插入显示成功,但数据库没有数据
解决:8001端口的PaymentController中一个方法改为:【public CommonResult create(@RequestBody Payment payment) {】,也就是加一个@RequestBody。
解决后的再次测试:此时数据库有了数据
【http://localhost/consumer/payment/create?serial=11111】
【{"code":200,"message":"出入数据库成功","data":1}】
以前的RunDashBoard:IDEA2020.1: 1. View -> Tool Window -> Services; 2. + -> Run Configeration Type -> Spring Boot;8
微服务模块:
1.建module
2.改pom
3.写yml
4.主启动
5.业务类
cloud-api-commons模块中:抽取80和8001端口的entities类
--------------------------------服务注册中心---------------------------------------------
eureka:直接使用
cloud-eureka-server7001单机版:与eureka注册中心相关的配置
1.pom.xml中:【
spring-cloud-starter-netflix-eureka-server
2.yml文件中:【
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己。
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
】
3.其主程序中加上@EnableEurekaServer注解,标记这个是服务注册中心
80和8001注册到eureka中的配置:
1.pom.xml中【
spring-cloud-starter-netflix-eureka-client
】
2.yml文件中:【
order80另加一个【
spring:
application:
name: cloud-order-service #入住注册中心的名称
】 下面为都添加,上面这个8001之前已添加
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true。
register-with-eureka: true #若改为false就是不入住到注册中心
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
】
3.其主程序中加上@EnableEurekaClient注解,使被注册到注册中心
注意:尽量先启动注册中心7001
之后为eureka集群:
集群中各eureka互相注册,相互守望
eureka集群:
改变映射:
C:WindowsSystem32driversetc中在hosts文件中添加:【
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
】
创建7002使其与7001实现集群效果,7002中:
1.pom.xml,与7001相同
2.yml文件中:
7001改为:【
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7002.com:7002/eureka/
】
7002改为:【
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
】
3.主启动类添加@EnableEurekaServer //标记这个是服务注册中心
注意:单机版的eureka我们浏览器地址 输入:http://localhost:7001/
集群后由于在hosts文件中配置了映射,浏览器地址栏输入:http://eureka7001.com:7001/和http://eureka7002.com:7002/
接下来将80和8001注册到集群eureka中,进行以下修改,只需要修改yml文件【
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 # 集群版
】
注意:先启动7001和7002,再启动8001,在启动80
同时启动:http://localhost/consumer/payment/get/31 等操作依然成功
上面是eruka注册中心集群,下面是服务提供者8001集群
创建服务提供者集群:
创建8002:
1.pom.xml文件:与8001相同
2.yml文件:与8001相同,并修改server的port为8002
3.mapper相同
4.java下的目录相同,主启动类名为Payment8002
5.8001和8002的PaymentController修改:【
添加:@Value("${server.port}")
private String serverport;
修改: if (result > 0) {
return new CommonResult(200,"出入数据库成功,serverport:"+serverport,result);
}else {
return new CommonResult(444,"插入数据库失败",null);
}
修改: if (payment != null) {
return new CommonResult(200,"查询成功,serverport:"+serverport,payment);
}else {
return new CommonResult(444,"没有对应记录,查询ID:"+id,null);
}
】
进行上述修改后在浏览器地址栏访问:
http://eureka7001.com:7001/ 可以进入eureka集群的web图形化界面
http://eureka7002.com:7002/ 可以进入eureka集群的web图形化界面
http://localhost:8001/payment/get/31
{"code":200,"message":"查询成功,serverport:8001","data":{"id":31,"serial":"尚硅谷001"}}
http://localhost:8002/payment/get/31 {"code":200,"message":"查询成功,serverport:8002","data":{"id":31,"serial":"尚硅谷001"}}
http://localhost/consumer/payment/get/31
{"code":200,"message":"查询成功,serverport:8001","data":{"id":31,"serial":"尚硅谷001"}}
上述都成功,但我们设置的集群,因此在consumer80调用服务提供者时,应该是8001和8002都会有显示,然而
http://localhost/consumer/payment/get/31 多次刷新始终为上述结果。也就是集群的负载均衡效果没有
实现,因此需要注意consumer80里面要修改,即OrderController里面要修改。修改内容:【
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
//CLOUD-PAYMENT-SERVICE为注册中心中注册的名称,没有加端口号
】。在同一模块中的ApplicationContextConfig中唯一的一个方法上加上注解@LoadBalanced(轮询负载均衡),若没有此步,会出错,也就是必须指定负载均衡机制。之后重启80,访问 http://localhost/consumer/payment/get/31 可以运行,实现负载均衡,不断刷新,显示内容有以下两种情况,如下:【
{"code":200,"message":"查询成功,serverport:8001","data":{"id":31,"serial":"尚硅谷001"}}
{"code":200,"message":"查询成功,serverport:8002","data":{"id":31,"serial":"尚硅谷001"}}
】
下列为actuator微服务信息完善:
8001和8002的yml文件添加【
instance:
instance-id: payment8001/8002
】这个instance与client是同级的
之后再次进入http://eureka7002.com:7002/ 或 http://eureka7001.com:7001/
点击payment8001或payment8002会进入地址: http://laptop-ehkt246n:8002/actuator/info
改变地址为: http://laptop-ehkt246n:8002/actuator/health 显示【{"status":"UP"}】,这显示
如果是把鼠标放到payment8001或payment8002上显示: laptop-ehkt246n:8001/actuator/info或
laptop-ehkt246n:8002/actuator/info
上述配置成功
之后两个yml文件中再添加:【 prefer-ip-address: true #访问路径可以显示IP地址】,这是与上面的
instance-id同级的
完成这个后刷新进入http://eureka7002.com:7002/ 和 http://eureka7001.com:7001/
把鼠标放到payment8001或payment8002上显示: http://118.251.151.168:8001/actuator/info 或
http://118.251.151.168:8002/actuator/info
注意:laptop-ehkt246n为默认eureka主机名称,118.251.151.168(这个是无线网的地址,windows下的ipconfig)为添加prefer-ip-address: true后替代主机名称显示的ip地址
下面是服务发现Discovery:通过服务发现来获得eureka里面的微服务的信息
在8001中的PaymentController中: 8002就不演示了,与此相同
添加【
@Resource
private DiscoveryClient discoveryClient;
@GetMapping(value = "/payment/discovery")
public Object discovery() {
List
for (String element : services) {
log.info("****element:"+element);
}
List
for (ServiceInstance instance:instances) {
log.info(instance.getInstanceId()+"t"+instance.getHost()+"t"
+instance.getPort()+"t"+instance.getUri());
}
return this.discoveryClient;
}
】
在主程序中加上注解@EnableDiscoveryClient
运行:http://localhost:8001/payment/discovery
会显示【{"services":["cloud-payment-service","cloud-order-service"],"order":0}】,多次刷新,在控制台会显示【
2021-05-22 22:25:37.444 INFO 10020 --- [nio-8001-exec-6] c.a.s.controller.PaymentController : ****element:cloud-payment-service
2021-05-22 22:25:37.444 INFO 10020 --- [nio-8001-exec-6] c.a.s.controller.PaymentController : ****element:cloud-order-service
2021-05-22 22:25:37.444 INFO 10020 --- [nio-8001-exec-6] c.a.s.controller.PaymentController : payment8001 118.251.151.168 8001 http://118.251.151.168:8001
2021-05-22 22:25:37.444 INFO 10020 --- [nio-8001-exec-6] c.a.s.controller.PaymentController : payment8002 118.251.151.168 8002 http://118.251.151.168:8002
】这里只是在8001演示,80想要访问,只需要像8001里添加相似,不过把
@GetMapping(value = "/payment/discovery")里的value修改掉
下面是自我保护内容:
禁用自我保护,这里仅用eureka集群中的7001和8001演示
在7001的yml中:【
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7002.com:7002/eureka/
server:
#关闭自我保护机制,保证不可用服务被及时剔除
enable-self-preservation: false
#返回心跳时间在2s内
eviction-interval-timer-in-ms: 2000
】后面的server到底是新增的。之后刷新进入 http://eureka7001.com:7001/
进入 http://eureka7001.com:7001/ 如果自我保护开启是这段红字:【
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.
】
自我保护关闭了显示这个红字:【
THE SELF PRESERVATION MODE IS TURNED OFF. THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.
】
8001中:
yml中修改:【
instance:
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal-interval-in-seconds: 1
#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
lease-expiration-duration-in-seconds: 2
】
完成上述后,再重新进入 http://eureka7001.com:7001/ ,当关闭8001后,在eureka的7001和
7002web界面发现8001已不在
上述的eureka已结束
下面是其他的服务注册中心
zookeep:有zookeeper+dubbo和zookeeper+springcloud的搭配。需要安装,已经安装在linux中
在/opt/zookeeper
使用zookeeper新建了8004.8001和8002为eureka的测试。下面只启动8004
8004中:
1.pom.xml
2.yml文件
3.主启动类
4.controller创建。
注:其他就不配置了,这里主要研究注册中心,不是业务逻辑的实现
在linux中开启zookeeper:进入/opt/zookeeper.版本号/bin
./zkServer.sh start 开启zookeeper服务,./zkCli.sh 连接zookeeper。zookeeeper默认端口为2181
之后运行8004主启动类,会报错:【
at org.apache.zookeeper.KeeperException.create(KeeperException.java:103) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
at org.apache.zookeeper.KeeperException.create(KeeperException.java:51) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
at org.apache.zookeeper.ZooKeeper.create(ZooKeeper.java:1525) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
】这代表着idea和系统装的zookeeper的版本不一样,改动以下pom.xml,再次运行,显示成功。
linux中在连接zookeeper的前提下:ls /。会有[services,zookeeper]。ls /services。会有
[cloud-provider-payment]表示成功
浏览器地址栏输入:http://localhost:8004/payment/zk
显示【springcloud with zookeeper: 8004 12f63207-6de0-4a8e-8913-fc4996b43bea】类似的表示成功
当关闭8004后,linux中 ls/services/cloud-provider 有[*********************]一段时间后没有了
显示[],证明这是临时结点
在又开启后 linux中 ls/services/cloud-provider 又有了[*******************]。
下面是订单服务注册进zookeeper。新建cloud-consumerzk-order80,这个依然是80端口,但与上面80不是一个
在cloud-consumerzk-order80中:
1.pom.xml
2.yml文件
3.主启动类
4.config
5.controller
之后启动8004和cloud-consumerzk-order80。在复制粘贴pom和yml时注意修改与本机相搭配的配置
一个错误:【
java.net.ConnectException: Connection refused: no further information
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ~[na:1.8.0_131]
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) ~[na:1.8.0_131]
at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:361) ~[zookeeper-3.4.10.jar:3.4.10-39d3a4f269333c922ed3db283be479f9deacaa0f]
at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1141) ~[zookeeper-3.4.10.jar:3.4.10-39d3a4f269333c922ed3db283be479f9deacaa0f]
】若出现此错误,是yml文件空格问题
linux中:ls /services 显示了两个服务,代表成功了
浏览器地址输入: http://localhost/consumer/payment/zk
显示【
springcloud with zookeeper: 8004 3fb2fc42-6619-4860-a8ac-9f9392b8943c
】表示已经成功了
注:zookeeper没有好的图形化界面,eureka,consul,nacos都有很好的图形化界面
下面是服务注册中心的consul:要下载。本机装在windows下的
consul目录下进入cmd输入:consul agent -dev运行。下面运行的条件是这个必须打开的
运行后浏览器地址栏输入:http://localhost:8500 进入图形化界面
下面创建cloud-providerconsul-payment8006这个服务提供者:
1.pom
2.yml
3.主启动类
4.controller。复制粘贴8004的controller,并进行修改
之后启动:进入 http://localhost:8500 会显示:【
consul
consul-provider-payment
】
进入: http://localhost:8006/payment/consul 会显示:【
springcloud with consul: 8006 119f4f0c-5cb6-42cd-af46-828ea8384c34
】说明运行成功了
下面是创建服务消费者cloud-consumerconsul-order80:
1.pom
2.yml
3.主启动类
4.配置bean,创建config类
5.controller。
注:服务提供者没有配置bean,即创建config这步骤,而服务消费者有这步
当服务提供者和消费者都有的时候,先运行服务提供者再运行服务消费者
运行两者后:
进入 http://localhost:8500/ 显示:【
consul
cloud-consumer-order80
consul-provider-payment
】
进入 http://localhost:8006/payment/consul 显示【
springcloud with consul: 8006 91bfe6b6-0c38-4c00-abad-e74a5a954187
】
进入 http://localhost/consumer/payment/consul 显示【
springcloud with consul: 8006 3fe9231f-7706-48f2-88d3-f5cc263327c1
】
上述三个注册中心为springcloud,nacos为springcloud alibaba,暂不提
上述三个注册中心的异同点:见脑图或截屏 AP适用于淘宝秒杀等
下面是ribbon:
先重启以下环境,打开7001,7002,8001,8002,OrderMain80
nginx相当于指引到医院的哪个科室,口腔科,骨科,耳科等 这是集中式的LB
ribbon相当于具体某个科室内的人员轮班 这是进程内的LB
ribbon就是负载均衡+RestTemplate调用
我们会发现pom文件没引入ribbon,却实现了负载均衡,因为eureka附带了ribbon,见
cloud-consumer-order80的pom.xml【
spring-cloud-starter-netflix-eureka-client
】
在cloud-consumer-order80的OrderController中新增了:【
//ribbon的其他测试
@GetMapping("/consumer/payment/getForEntity/{id}")
public CommonResult
ResponseEntity
if (entity.getStatusCode().is2xxSuccessful()) {
return entity.getBody();
}else {
return new CommonResult<>(444,"操作失败");
}
}
】这是在ribbon中二说服务注册中心谈到的restRemplate,这是restTempalte的另一个操作
地址栏输入: http://localhost/consumer/payment/getForEntity//31
显示:【
{"code":200,"message":"查询成功,serverport:8001","data":{"id":31,"serial":"尚硅谷001"}}】
ribbon的负载均衡算法默认是轮询的
下面是ribbon中修改负载均衡算法:
1.注意:必须和创建一个包不与主程序在同一包下,此处在cloud-consumer-order80的java目录下另建
com.atguigu.myrule,并创建了类MySelfRule,在这里制定负载均衡算法。
2.主启动类上添加注解
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration= MySelfRule.class)
之后可以运行了。地址栏输入: http://localhost/consumer/payment/get/31
显示:【
{"code":200,"message":"查询成功,serverport:8002","data":{"id":31,"serial":"尚硅谷001"}}
】其中serverport:有时显示8001有时8002,这两个随机,代表配置成功了
***********JUC(CAS+自旋锁)知识??*************
手写算法:用到了8001和8002和cloud-consumer-order80
步骤:
1.在8001和8002的controller中新增:【
//手写算法用到的
@GetMapping(value = "/payment/lb")
public String getPaymentLB() {
return serverport;
}
】
2.cloud-consumer-order80的ApplicationContextConfig中注释掉@LoadBalanced
3.com.atguigu.springcloud下创建包lb,lb下创建类LoadBalancer和实现类MyLB
4.cloud-consumer-order80的OrderController添加:【
//自写算法用到的其一
@Resource
private LoadBalancer loadBalancer;
//自写算法用到的其二
@Resource
private DiscoveryClient discoveryClient;
//自写算法用到的
@GetMapping(value = "/consumer/payment/lb")
public String getPaymentLB() {
List
if (instances==null || instances.size() <= 0) {
return null;
}
ServiceInstance serviceInstance=loadBalancer.instances(instances);
URI uri = serviceInstance.getUri();
return restTemplate.getForObject(uri+"/payment/lb",String.class);
}
】
之后运行,在地址栏输入:http://localhost/consumer/payment/lb 。页面会交替显示【8001和8002】
下面是第二个服务调用openfeign,第一个是上面的ribbon
新建cloud-consumer-feign-order80。这里面的service复制粘贴8001端口的service,并加上注解,注解为8001
端口的同名的方法上的注解(这里定义为service和controller方法名对应相同),这里面的controller上的注解
地址加了一个/feign
1.pom。附带了ribbon
2.yml。
3.主启动
4.其他
之后进入 http://localhost/consumer/payment/get/31 显示:【
{"code":200,"message":"查询成功,serverport:8001","data":{"id":31,"serial":"尚硅谷001"}}
】多次刷新serverport:****"其中8001和8002交替显示,代表成功
再次添加了超时: openfeign默认等待1s
访问: http://localhost:8001/payment/feign/timeout 显示【8001】,不过等了3秒钟,和设定的一样
访问: http://localhost/comsumer/payment/feign/timeout 报错【500】
在 cloud-consumer-feign-order80的yml文件添加了配置:【
#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ReadTimeout: 5000
#指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 5000
】之后就可以运行了 : http://localhost/comsumer/payment/feign/timeout
下面是openfeign日志增强:
1.新建包config,并在里面创建类,对于日志增强的配置在这个类里面写
2.yml文件添加【
logging:
level:
# feign日志以什么级别监控哪个接口
com.atguigu.springcloud.service.PaymentFeignService: debug
】
然后访问:http://localhost/consumer/payment/get/31
控制台有详细的信息:【
2021-05-24 13:35:01.917 DEBUG 11568 --- [p-nio-80-exec-4] c.a.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] keep-alive: timeout=60
2021-05-24 13:35:01.917 DEBUG 11568 --- [p-nio-80-exec-4] c.a.s.service.PaymentFeignService : [PaymentFeignService#getPaymentById] transfer-encoding: chunked
】代表上述配置成功
下面是服务降级:这一章是分水岭
fallback:服务降级:
break:服务熔断:
flowlimit:服务限流:
下面是Hystrix支付微服务构建: 下面是正常的
1.新建cloud-provider-hystrix-payment8001(下面所说的8001是这个)
2.pom
3.yml
4.主启动
5.其他配置
之后运行: http://localhost:8001/payment/hystrix/ok/31 显示:【
线程池:http-nio-8001-exec-2paymentInfo_OK,id:31
】
运行: http://localhost:8001/payment/hystrix/timeout/31 显示:【
线程池:http-nio-8001-exec-1paymentInfo_Timeout,id:31 耗时3s钟
】
下面在上面正常的状况下模拟错误:JMeter软件下载,暂时没下载
下面创建又一个模块cloud-consumer-feign-hystrix-order80
注:hystrix既可以放在服务提供者,也可以放在服务消费者。但一般放在服务消费者
创建后配置pom,yml,主启动和其他
之后运行: http://localhost/consumer/payment/hystrix/ok/31 显示:【
线程池:http-nio-8001-exec-6paymentInfo_OK,id:31
】
之后使用JMeter高压测试,会使得 http://localhost/consumer/payment/hystrix/ok/31
运行缓慢。
下面进行服务降级:
cloud-provider-hystrix-payment8001的service中给已有方法添加注解【
@HystrixCommand(fallbackMethod = "paymentInfo_TimeoutHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
//这个注解设定生效时间为3秒钟,结合注解下面的方法来看,在3s内正常逻辑,3s后使用兜底的方法
//paymentInfo_TimeoutHandler
})
】,并新建方法【
public String paymentInfo_TimeoutHandler(Integer id)
】
同时该模块的主程序添加注解:@EnableCircuitBreaker
之后运行: http://localhost:8001/payment/hystrix/timeout/31 显示:【
线程池:HystrixTimer-1系统繁忙,请稍后再试。paymentInfo_TimeoutHandler,id:31
】 同时后台会显示:【java.lang.InterruptedException: sleep interrupted】
****服务降级在int age=10/0;计算异常和超时异常时都能生效
这代表着成功。
服务降级既可以放在消费端也可以放在支付端,一般放在客户端(消费端)
下面是cloud-consumer-feign-hystrix-order80端的服务降级(消费者,上面是生产者的)
修改:
1.yml
2.主启动
3.业务类
然后运行: http://localhost/consumer/payment/hystrix/timeout/31 显示:【
我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o
】表示配置成功
上面是服务提供者和服务消费者的服务降级功能各自写在各自的模块中
下面是寻求把服务降级功能从两个模块的正常运行逻辑中剥离出来,此处把服务降级功能与运行逻辑分开。
修改:
1.cloud-consumer-feign-hystrix-order80的controller新增:【
//下面是全局fallback方法
public String payment_Global_FallbackMethod() {
return "Global异常处理信息,请稍后再试";
}
】
2.controller类上面加上注解:【
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
】
3.注释掉:【
// @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
// @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
// })//1.5s以内正常执行逻辑,1.5s以后使用paymentTimeOutFallbackMethod方法返回
】
4.添加注解: @HystrixCommand在注释掉的下方
注意:方法上添加@HystrixCommand的地方,若@HystrixCommand(fallbackMethod =.....)则使用
fallbackMethod =....的,若没有,使用@DefaultProperties(defaultFallback = "")双引号里的。
之后运行: http://localhost/consumer/payment/hystrix/timeout/31 显示:【
Global异常处理信息,请稍后再试
】表示配置成功
下面是给service所有方法同意设定服务降级: 这种方法最好
1.创建cloud-consumer-feign-hystrix-order80的PaymentHystrixService接口的实现类
PaymentFallbackService
2.PaymentHystrixService的@FeignClient注解里添加属性
fallback = PaymentFallbackService.class
3.yml:【
feign:
hystrix:
enabled: true
】此处上面已添加过
之后运行: http://localhost/consumer/payment/hystrix/ok/31 显示:【
线程池:http-nio-8001-exec-9paymentInfo_OK,id:31
】然后关闭服务cloud-provider-hystrix-payment8001
继续访问: http://localhost/consumer/payment/hystrix/ok/31 显示:【
------PaymentFallbackService fall back-paymentInfo_OK
】表明配置成功
下面是服务熔断:
cloud-provider-hystrix-payment8001的:
1.service新增方法
2.controller新增方法
之后访问: http://localhost:8001/payment/circuit/31 显示:【
hystrix-PaymentService-2 调用成功,流水号: 826c50dbb5d04f139a86039937796e96
】
访问 http://localhost:8001/payment/circuit/-31 显示:【
id 不能负数,请稍后再试,/(ㄒoㄒ)/~~ id: -31
】如果多次刷新【访问至少10次,且60%失败】
http://localhost:8001/payment/circuit/-31 然后访问
http://localhost:8001/payment/circuit/31 那么显示结果也是:【
id 不能负数,请稍后再试,/(ㄒoㄒ)/~~ id: -31
】如果在访问 http://localhost:8001/payment/circuit/-31 后不是多次刷新就访问
http://localhost:8001/payment/circuit/31 那么结果就是:【
hystrix-PaymentService-2 调用成功,流水号: 826c50dbb5d04f139a86039937796e96
】符合上述代表服务熔断配置成功。一些笔记,注释见模块cloud-provider-hystrix-payment8001中的service和
controller方法
服务限流在springcloud的Sentinel说明
下面是hystrix的web端的可视化界面dashboard(仪表盘)(这个不需要下载):新建模块
cloud-provider-hystrix-dashboard9101(视频是9001,本机此端口被其他的设置过了,故换一个)
1.pom
2.yml
3.主启动类
4.其他
注意:actutor与支持图形化展现有关
之后进入:http://localhost:9101/hystrix 显示可视化界面,表示成功
然后因为版本更新的问题:要在被监控模块(此处为cloud-provider-hystrix-payment8001)的主程序加上
:【
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadonStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
】
重启8001,9101
访问:http://localhost:8001/payment/circuit/31 和 http://localhost:8001/payment/circuit/-31
访问:http://localhost:9101/hystrix 并输入一些信息后进入可视化界面。然后测试点击上面两个链接
可以在这个可视化界面中看到其反应(因为上面两个都是8001,而9101监控了8001端口)。
**这个反应很有意思,很有用**
***此处需要自己搭建一个监控测试平台9101,而后面的Sentinel会有一个配置好的网站给予使用。***
下面是服务网关的内容:主要使用zuul和Gateway。此处只谈Gateway,zuul自己从脑图学习如果时间充裕
gateway:(可以隐藏真实端口)
predicate(断言):判断,返回true或false
新建模块cloud-gateway-gateway9527:基本创建。给yml文件新增网关配置。yml文件中指定【
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes: //路由
- id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
- id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** # 断言,路径相匹配的进行路由
】跟gateway相关的配置都在cloud-gateway-gateway9527的yml文件中
之后启动7001,7002,cloud-provider-payment8001和cloud-gateway-gateway9527
注意:最好7001,7002都启动,不然 cloud-provider-payment8001可能会出错,因为配置了集群的原因
注意:gateway网关不要引入starter-web和actuator依赖
*********************************注意:如果出现这个错误**************************
【spring-cloud-starter-gateway-2.2.1.RELEASE.jar: error in opening zip file】解决方案【
找到目的地jat包,删除,然后maven点击install
】
运行上述之后:进入:【http://localhost:8001/payment/get/31】 显示【
{"code":200,"message":"查询成功,serverport:8001","data":{"id":31,"serial":"尚硅谷001"}}
】
进入:http://localhost:9527/payment/get/31 显示:【
{"code":200,"message":"查询成功,serverport:8001","data":{"id":31,"serial":"尚硅谷001"}}
】这代表上述配置成功
Gateway网关路由的两种配置方式:一是yml中,二是代码注入RouteLocator
下面是代码注入RouteLocator:新建config
第一种方法的【predicates:
- Path=/payment/lb/**】是要路径相匹配
第二种方法的【
routes.route("path_route_atguigu",r -> r.path("/guonei").
uri("http://news.baidu.com/guonei")).build();
】 r -> r.path("/guonei")与 uri("http://news.baidu.com/guonei"))似乎可以没关系
当新建config后:
访问:http://localhost:9527/guonei 跳转到了 http://news.baidu.com/guonei ,但是地址栏还是http://localhost:9527/guonei。
这就实现了用编码方式实现gateway网关尽心路由映射配置的方法
下面是配置动态路由的内容:
1.打开8001和8002,7001
2.修改yml。添加【
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
uri: lb://cloud-payment-service
】
访问:http://localhost:9527/payment/lb 显示【8001/8002】代表成功
下面是常用的predicate(符合predicate要求的才允许访问,否则报错):下面用到了curl测试
1.#- After=2021-05-25T16:22:57.745+08:00[Asia/Shanghai] #在这个时间之后访问才有效果
2.- cookie=username,zzyy。
cmd访问输入: 【相当于发了get请求
curl http://localhost:9527/payment/lb 】
在一大串子母中第一行有【status":404,"error":"Not Found"】
cmd访问: 【curl http://localhost:9527/payment/lb --cookie "username=zzyy"】
返回【8001/8002】
3.- Header=X-Request-Id, d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
curl访问: 【curl http://localhost:9527/payment/lb -H "X-Request-Id:123"
】返回【8001/8002】
curl访问: 【curl http://localhost:9527/payment/lb -H "X-Request-Id:-123"
】返回【"status":404,"error":"Not Found"】 这代表运行成功
注意: 计算当前时间的方法【
import java.time.ZonedDateTime;
public class T2 {
public static void main(String[] args) {
ZonedDateTime zbj=ZonedDateTime.now();
System.out.println(zbj);
}
}
】
下面是gateway的filter:
新建controller
访问: http://localhost:9527/payment/lb?uname=z3
显示:【8001/8002】
之后地址栏只要带有uname=***,就可以访问,但没有unmae不可以访问
下面是分布式配置中心和消息总线
分布式配置中心:
config配置总控中心搭建:
github上创建仓库,并在仓库中创建了一些文件,并clone到文件夹FromGitHub
新建模块cloud-config-center-3344(服务端的):基本搭建
其中的yml:【
server:
port: 3344
spring:
application:
name: cloud-config-center #注册进Eureka服务器的微服务名
cloud:
config:
server:
git:
#uri: git@github.com:SunlightOk/Springcloud-config.git #GitHub上面的git仓库名字
uri: https://github.com/SunlightOk/Springcloud-config.git
####搜索目录
search-paths:
- springcloud-config
####读取分支
label: main
#服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
】
hosts配置了映射
之后启动7001和7002,然后3344
访问 http://config-3344.com:3344/main/config-dev.yml
main为分支,后面的为文件,config为配置过的,-后面的如果不存在返回【{}】
配置读取规则有五种,也就是链接uri可以写5中,当然有一总为返回json串
显示 【
config: from main branch,springcloud-config/config.yml version=1
】
下面是服务端的
死于这里,对应76集-82集
curl -X POST "url":使用非get方式
下面是消息驱动Stream:
消费驱动的生产者
新建模块:cloud-stream-rabbitmq-provider8801。配置
其中的service的实现类不用@Service注解,因为这不是与数据库打交道,这是在操作rabbitmq消息中间件
其中的yml不能采用脑图里的。
注意:连接rabbitmq的操作:linux中任意目录下:systemctl start/stop rabbitmq-server
运行7001.7002,和cloud-stream-rabbitmq-provider8801
访问:http://192.168.23.133:15672/ 的exchanges能看到
访问:http://localhost:8801/sendMessage 不断刷新控制台也能看到输出
消费驱动的消费者:新建模块cloud-stream-rabbitmq-consumer8802。配置以下
然后启动8802。
访问 http://localhost:8801/sendMessage 连续刷新。可在后台发现8801和8802都有输出
clone一份8803仿照8802
下面是给8802和8803配置分组:修改yml文件
之后访问: http://192.168.23.133:15672/ 到exchanges可发现不同
配置同样的组不会重复消费,配置不一样的组会重复消费(
刷新几次 http://localhost:8801/sendMessage
可从8802和8803的控制台输出判断是否重复消费)
同时设置group也会解决持久化的问题,不会造成数据丢失 。若生产者发布信息4次,之后在启动没有设置group的
8802和设置了group的8803,之后8802不会消费,8803会消费
下面是分布式请求链跟踪Sleuth:需要zipkin的jar包支持
访问: http://localhost:9411/zipkin/
********************************************************************************
********************************************************************************
************************下面是SpringCloud alibaba********************************
********************************************************************************
********************************************************************************
Nacos:下载解压安装-->bin目录开启(安装在windows上,C:Users惜听documents百度网盘springcloud)
(安装了两个版本)启动后访问:http://localhost:8848/nacos
默认账号密码都是:nacos 注:项目里用到nacos的一定要先打开(自带负载均衡)
创建模块cloudalibaba-provider-payment9101
之后开启 cloudalibaba-provider-payment9101 就可以了
然后访问:http://localhost:8848/nacos 在服务管理的服务列表中可以看到
访问:http://localhost:9101/payment/nacos/1 显示:【nacos registry, serverPort: 9101 id1】
在配置两个服务提供者,一个服务消费者,并开启三者后:
访问:http://localhost:83/consumer/payment/nacos//13 显示:【
nacos registry, serverPort: 9102/9101 id13
】代表负载均衡是有的
上面是注册中心
Nacos之服务配置中心:新建模块 cloudalibaba-config-nacos-client3377 配置之后 运行这个
访问:http://localhost:3377/config/info 显示:【
from nacos config center, nacos-config-client-dev.yaml,version = 1】
对配置列表的nacos-config-client-dev.yaml中的内容:version=1改为version=2,然后保存。
再次访问:http://localhost:3377/config/info 显示:【
from nacos config center, nacos-config-client-dev.yaml,version = 2
】
对于cloudalibaba-config-nacos-client3377的application.yml的active: dev/test和nacos图形化界面的
配置管理的配置列表的nacos-config-client-dev.yaml/nacos-config-client-test.yaml和
http://localhost:3377/config/info 显示的:【
from nacos config center, nacos-config-client-dev.yaml,version = 3
】是统一的,会实时改变的,当刷新或重新运行的时候
上面是DataID方案,下面是Group方案:nacos的图形化界面修改后,模块中application.yml改为:【
active: info
】,bootstrap.yml添加:【group: TEST_GROUP】。然后运行
之后访问:http://localhost:3377/config/info 显示:【
nacos-config-client-info.yaml,TEST_GROUP】
在上述的基础上修改bootstrap.yml:【group: DEV_GROUP】
http://localhost:3377/config/info 显示:【
nacos-config-client-info.yaml,DEV_GROUP】
{{nacos支持MySQL8 操作方法:跟bin同级创建一个plugins/mysql目录,然后放入一个mysql8的驱动即可}
{P110有坑,虚拟机内存不够启动3个nacos,集群访问不了,把start.sh脚本中的JVM参数改小点,xmx xms默认是2g 太坑爹了 改成300m就够, 不然不启动3台,集群访问不了}
https://www.cnblogs.com/gyli20170901/p/11245270.html
最近nacos支持了mysql 8的驱动了,看下面的的截图,从1.3.1开始支持了mysql 8。
下面的配置nacos配置集群很大可能会出现问题
注意:对于nacos对mysql的问题:
1.改用1.3.2版本
2.在C:Users惜听documents百度网盘springcloudnacos1.3.2版bin目录下输入:
startup.cmd -m standalone 因为1.3.2默认为集群模式,同时application.propertis中添加:【
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&serverTimezone=UTC
db.user=root
db.password=123456a
】当成功后,,在nacos客户端新建信息,在mysql中可以看到
nacos集群:
nacos在/opt下
下面是sentinel:
sentinel是一个jar包 java -jar *** 就可以开启了
其默认端口为8080,与tomcat冲突,只要不启动tomcat就可以了
默认用户名密码都是:sentinel
新建模块 cloudalibaba-sentinel-service8401。启动nacos,sentinel,和这个。
sentinel的流控规则非常重要
下面是sentinel服务熔断功能
sentinel的持久化:把sentinel可视化界面设置的配置持久化,默认为当对应微服务关闭后,配置也消失。
解决上述问题的方法:与nacos结合,nacos的配置列表中新增。当然要配置pom,yml
下面是senta
senta的lib下替换了mysql-connector的jar包
TC:seata服务器
TM:@GlobalTransactional 事物的发起方
RM:一个数据库就是一个RM,事务的参与方



