Eureka
基本使用
在服务中添加eureka-server的依赖,配置eureka-server,在启动类上添加@EnableEurekaServer注解
# eureka服务端的名称
eureka.instance.hostname=eureka-server-7001
# 是否向注册中心注册自己
eureka.client.register-with-eureka=false
# 表示自己为注册中心,客户端的这个设置应该为true
eureka.client.fetch-registry=false
# 配置eureka集群,单一时配置自己即可,集群时配置其他eureka的地址
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
在服务中添加eureka-client的依赖,配置eureka-client,在启动类上添加@EnableEurekaClient注解
# 向eureka server注册
eureka.client.service-url.defaultZone=http://localhost:7001/eureka/
# 服务的消费者这里可以关闭,不向eureka-server中注册自己
eureka.client.register-with-eureka=false
Eureka,Zookeeper,Nacos区别
AP,CP,AP模型中的数据可能保持的不是那么的真,数据实时性不高
Zookeeper保证CP,从Zookeeper各个节点取回来的数据都是一致的;当master节点宕机,剩余节点会重新进行leader选举。在此期间无法提供注册和查询服务。
Eureka保证AP,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。只不过查到的信息可能不是最新的。
Nacos有CP和AP模式可以切换,除了服务的注册发现之外,还支持动态配置服务。
Ribbon
基本使用
在配置类中给RestTemplate Bean对象加上@LoadBalanced注解即可
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
负载均衡算法
ribbon是客户端负载均衡,因为他是在客户端进行负载均衡算法的,而nginx是一个服务端,负载均衡算法是在nginx做的,所以是服务端负载均衡。
使用自定义的负载均衡算法,写一个配置类(不要和启动类在同级目录下),返回一个IRule Bean对象,在启动类上使用该算法@RibbonClient(name="需要使用的服务名", configuration = 配置类.class)。
自带的负载均衡算法有
- RoundRobinRule(轮询,默认)
- RandomRule(随机)
- AvailabilityFilteringRule(会先过滤掉故障服务)
- RetryRule(按轮询获取服务,获取失败在指定时间内重试)
可以自己根据这些模板来进行改写。
Feign
基本使用
编写需要调用的接口,接口添加@FeignClient(value="服务名")注解,并在启动类添加@EnableFeignClients注解。在服务的消费者中直接注入这个接口的实例即可使用。
@FeignClient(name = "message", fallbackFactory = HystrixTest.class)
// @FeignClient(url = "http://localhost:port")
public interface MessageService {
// @GetMapping("/sendNewUserMessage/{name}")
// boolean sendNewUserMessage(@PathVariable String name);
@GetMapping("/sendNewUserMessage")
boolean sendNewUserMessage(@RequestParam String name);
}
当@FeignClient注解中使用url的时候,则不会去注册中心拉服务列表,而是直接单点请求。接口中的方法上需要添加@GetMapping("/sendNewUserMessage")好让Feign知道要对哪个接口发起请求。
参数传递的形式:
- @RequestParam:?param=value&...
- @PathVariable:
- 修饰的参数,在链接中有相应的{name},转换成RESTful形式
- 修饰的参数,在链接中无相应的{name},转换成Content-Type: application/json
- @RequestBody/无注解:消息体传参
- 当单个参数是基本类型或String时转换成Content-Type: text/plain;charset=UTF-8的形式
- 参数是对象类型时转换成Content-Type: application/json的形式
Hystrix
服务熔断与服务降级
熔断亦称为过载保护,是某个服务(下游服务)故障引起。降级是整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。一般需要对业务有层级之分,关闭一些对主要业务影响不大的服务。
实现熔断: 在服务提供者编写熔断的方法,在相应业务的方法上添加@HystrixCommand(fallbackMethod = "熔断方法名")注解。
实现降级: 在服务消费者结合Feign的接口,编写一个实现FallbackFactory的类,实现其create方法,返回一个新的Feign接口实体。
熔断要在启动类上添加@EnableHystrix注解,早些版本熔断是加@EnableCircuitBreaker注解。服务降级要在配置文件中配置feign.circuitbreaker.enable=true,早些版本是配置feign.hystrix.enable=true
Zuul
作用
提供动态路由,访问过滤,身份认证和安全等服务。
基本使用
添加依赖
编写配置文件
server:
port: 8000
spring:
application:
name: zuul
zuul:
routes:
# 标识你服务的名字,这里可以自己定义,一般方便和规范来讲还是跟自己服务的名字一样
EUREKA-CLIENT-PRODUCER:
# 服务映射的路径,通过这路径就可以从外部访问你的服务了,目的是为了不爆露你机器的IP
# 这里zuul是自动依赖hystrix,ribbon的,不是面向单机
path: /EUREKA-CLIENT-PROVIDER/**
# 这里一定要是你Eureka注册中心的服务的名称,是因为这里配置serviceId因为跟eureka结合了,
serviceId: EUREKA-CLIENT-PROVIDER
ignored-services: # 不可访问的服务名,可以将原有的服务名隐藏起来
eureka:
client:
service-url:
defaultZone: http://admin:123456@127.0.0.1:8761/eureka/
在启动类上添加@EnableZuulProxy注解
通过zuul访问服务的,URL地址默认格式为:http://zuulHostIp:port/服务名称/服务中的URL
# URL匹配:
# ? 单个字符
# * 任意多个字符,不包含多级路径
# ** 任意多个字符,包含多级路径
zuul.routes.eureka-application-service.path=/api/**
# 路由前缀配置
zuul.prefix=/api
# 配置不被zuul管理的原服务列表。多个服务名称使用逗号’,'分隔。下面是通配方式配置排除列表,隐藏了全部的原服务,只能通过path的路径进行请求
zuul.ignored-services=*
配置中心
Server端
编写配置文件上传到git仓库
# 默认激活的环境
spring:
profiles:
active: dev
# dev配置文件
---
spring:
profiles: dev
application:
name: spring-config-dev
# test配置文件
---
spring:
profiles: test
application:
name: springcloud-config-test
新建配置中心server的项目,编写配置,启动类上加@EnableConfigServer注解
spring.cloud.config.server.git.uri=git仓库的地址
spring.cloud.config.label=分支
client端
编写配置文件,读取云端相应的配置。在SpringCloud 2020.* 版本把bootstrap禁用了,要把bootstrap依赖导入项目才可。
spring:
cloud:
config:
name: git上读取资源的名称,不要后缀
profile: 读取配置文件中的哪个配置
label: 分支
uri: server端的访问地址http://ip:port
热部署
手动配置热更新某个服务
- 开启actuator中的refresh端点
- Controller中添加
@RefreshScope注解 - 向客户端 url
http://localhost:91/actuator/refresh发送Post请求
批量更新使用消息队列
Acuator
暂未总结
对于一些报错如何寻找根源
例如SpringCloud Ribbon 解决 No instances available。spring-cloud-starter-netflix-eureka-client 3.0版本的已经内置ribbon,再导入的spring-cloud-starter-netflix-ribbon可能会产生冲突,自己应该如何去找到这种错误的根源。
java.lang.NoClassDefFoundError
通过Debug发现问题并解决。由于jdk的ext目录下的fastjson的版本有冲突造成的。NoClassDefFoundError是由于编译能找到class但是运行时找不到class。在一些特定条件下就会出现编译时可以加载到类,运行时不可以加载到类,这时候就会出现java.lang.NoClassDefFoundError异常。