springcloud是一系列框架的有序集合 采用http restful风格完成通信
服务治理(服务的注册与发现) 注册中心的工作 springcloud常用的注册中心有 Eureka consul nacos
@EnableEurekaServer 在Eureka服务器模块配置类上加此注解,启用Eureka服务器
1.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
2.eureka服务器基本配置如下
server:
port: 8080
#eureka的配置分四部分 1.dashboard 控制台配置 2.server 服务端配置 3.client 客户端配置 4.instance 实例配置
eureka:
instance:
hostname: localhost #本机服务器ip
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka #服务端地址,客户端连接此地址
register-with-eureka: false #自己不需要往自己上注册
fetch-registry: false #自己是服务器不需要获取注册的服务
server:
enable-self-preservation: true #开启自我保护机制,超时的客户端服务暂不移除
eviction-interval-timer-in-ms: 3000 #逐出间隔时间,多长时间扫描一次,检查服务的时间间隔
@EnableEurekaClient 在Eureka客户端(服务提供者及服务消费者都是客户端)配置类上加此注解,启用Eureka客户端
客户端的配置和服务器的类似
1.导入坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.客户端配置文件
spring:
application:
name: eureka-consumer
server:
port: 8090
# eureka的配置分四部分 1.dashboard 控制台配置 2.server 服务端配置 3.client 客户端配置 4.instance 实例配置
eureka:
instance:
hostname: localhost #主机名
prefer-ip-address: false #默认 false 默认注册的是主机名 是否将自己的ip(默认非回环ip的内网ip,如果显示其他ip则需要配置instance-address)注册到eureka中
lease-expiration-duration-in-seconds: 90 #客户端超过此时间未向服务器发送心跳则删除该服务
lease-renewal-interval-in-seconds: 30 #客户端向服务器发送心跳的时间间隔
# instance-id: 控制台展示的客户端信息格式为 ip:主机名:端口
# ip-address: 设置当前实例的ip
client:
service-url:
defaultZone: http://localhost:8080/eureka #服务端地址,客户端连接此地址
register-with-eureka: true
fetch-registry: true
客户端从服务器获取服务的ip和端口,需要用到服务发现客户端DiscoverClient,服务提供者和服务调用者都从eureka注册与发现服务,而通过服务名称实时获取服务的ip和端口等信息,降低服务提供者和调用者的耦合.
代码如下:
@RestController
public class UserController {
@Autowired
RestTemplate restTemplate;
@Autowired
DiscoveryClient discoveryClient;
@GetMapping("/user/{id}")
public User getUser(@PathVariable("id") Integer id){
List<ServiceInstance> instances = discoveryClient.getInstances("eureka-provider");
if (ObjectUtils.isEmpty(instances)){
return null;
}
String host = instances.get(0).getHost();
int port = instances.get(0).getPort();
User user = restTemplate.getForObject("http://"+host+":"+port+"/user/"+id, User.class);
return user;
}
}
本机hosts文件里不能识别下划线 hosts文件位置: C:\WINDOWS\system32\drivers\etc
eureka集群的高可用
开启多个eureka服务器,服务器之间进行相互注册. 它们的applicationname 取相同的名字 hostname需要不同
客户端从多个eureka服务器获取服务,多个服务器地址之间逗号隔开即可
consul windows版启动 下载后解压 在consul.exe 所在目录 打开cmd .\consul agent -dev 即可启动 http://localhost:8500进入管理页面
客户端需导入的坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
配合文件中
spring:
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name} #当前应用注册到consul的名称
prefer-ip-address: true #显示ip
springcloud 提供的统一的服务发现客户端,代码和eureka一样,不需要修改就可以直接使用
nacos不仅可以做注册中心也可以做配置中心
使用它做注册中心引入如下坐标
配置文件稍作修改
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848
ribbon 客户端负载均衡,简化远程调用 也是耐飞公司开源的
1.简化远程调用
原来的远程调用需要根据服务id手动获取 ip 端口,要写一段代码,然后将ip和端口拼接在url中,简化后直接 将服务名称写在url中ip:端口的位置就可以了
即如下代码
List<ServiceInstance> instances = discoveryClient.getInstances("eureka-provider");
if (ObjectUtils.isEmpty(instances)){
return null;
}
String host = instances.get(0).getHost();
int port = instances.get(0).getPort();
User user = restTemplate.getForObject("http://"+host+":"+port+"/user/"+id, User.class);
需要在定义restTemplate的地方加一个注解@LoadBalanced,这样就会启用ribbon,默认的负载均衡策略是轮询
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
简化为: User user = restTemplate.getForObject(“http://eureka-provider/user/”+id, User.class);
2.客户端负载均衡,客户端请求多台服务器的策略
负载均衡默认是轮询的策略,如果想要改有两种方式
1.配置类内定义具体的策略 注入spring 返回IRule类型 它有多个实现类即不同的策略 另在配置类上加
@RibbonClient(name="EUREKA-PROVIDER",configuration = RobbinConfig.class)
@Configuration
public class RobbinConfig {
@Bean
public IRule myRule(){
return new RandomRule();
}
}
2.配置文件中指定哪个服务采取什么样的负载均衡策略
#服务提供方的名称
eureka-provider:
ribbon:
NFloadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #策略类
feign更加的简化了RestTemplate的调用,feign是基于ribbon.
1.创建一个feign的客户端接口 name里是针对哪个服务的客户端
@FeignClient(name = "eureka-provider")
public interface FeignUserClient {
@GetMapping("/user/{id}")
User getUser(@PathVariable("id") Integer id);
}
2.在主配置类上 @EnableFeignClients 允许feign客户端生效
3.feign客户端并使用 简化了原来的代码
// String url="http://eureka-provider/user/"+id;
// User user = restTemplate.getForObject(url, User.class);
return feignUserClient.getUser(id);
4.配置文件中可以设置feign的各种参数
feign:
httpclient:
connection-timeout: 1000 连接超时时间
feign只能监控 debug级别的日志信息,需要创建一个feign的配置类,在里面注入一个feign的日志级别对象
另外这个配置类要加在这里 @FeignClient(name = “eureka-provider”,configuration= FeignConfig.class)
@Configuration
public class FeignConfig {
@Bean
public Logger.Level level(){
return Logger.Level.FULL;
}
}
使用feign后 restTemplate 注入时的 @LoadBalanced注解也不需要加了
logging:
level:
com.consumer: debug 哪个包下的日志的级别
hystrix 四个功能 1.隔离 2.降级 3.熔断 4.限流 微服务级联调用的过程中极容易出现雪崩,为了处理这样的情况,所以有了熔断机制 默认5秒降级20次则熔断
隔离分线程池隔离和信号量隔离,默认线程池隔离
降级 服务提供方和服务调用方都需要做降级方案 降级就是planB 当服务发生异常或调用超时,返回默认值
使用hystrix步骤
1.导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
2.在配置类上开启使用 @EnableCircuitBreaker 这些开启的东西在新版里只要导入了对应的jar包都默认开启了.
3.写一个降级方法,要和需要降级的方法的入参和返回值一样,在需要降级的方法上加注解 ,代码如下
@HystrixCommand(fallbackMethod = "errorMethod")
@GetMapping("/user/{id}")
public User getUser(@PathVariable("id") Integer id){
int i=1/0;
return feignUserClient.getUser(id);
}
public User errorMethod(Integer id){
User user=new User();
user.setName("我降级了~~~~");
return user;
}
这个注解里可以设置hystrix的各种属性 熔断多长时间里 多少次 失败率多少等参数 具体的属性key及默认值都在这个类里 HystrixCommandProperties
@HystrixCommand(fallbackMethod = “errorMethod”,commandProperties = {
@HystrixProperty(name = “”,value = “”)
})
gateway 网关就是系统的入口,为客户端提供统一的服务
配置文件的配置,注意uri 必须带http://
spring:
cloud:
gateway:
routes:
- id: eureka-consumer
uri: http://localhost:8090/
predicates:
- Path=/user/**
filters:
- AddRequestParameter=username,zhangsan
网关里静态配置各服务的地址,很容易经常发生改动.可以改为动态的获取 uri: http://localhost:8090/ 改为 uri: lb://服务名称 前提是网关也作为eureka的客户端连接进去
spring:
cloud:
gateway:
routes:
- id: eureka-consumer
uri: lb://eureka-consumer
predicates:
- Path=/user/**
filters: #这是局部过滤器,只对一个路径有效
- AddRequestParameter=username,zhangsan
discovery:
locator:
enabled: true #请求网关的路径中加项目名称(加不加都可以) 本来请求路径是这个 http://localhost/user/6,现在变成 http://localhost/eureka-consumer/user/6
lower-case-service-id: true #允许项目名称小写
gateway过滤器 前置过滤器,后置过滤器 全局过滤器,局部过滤器
gateway的很多功能都是通过全局过滤器来实现的,我们可以自定义全局过滤器来实现一些通用的功能,比如加解密,验签,鉴权等等.
全局过滤器需要实现 GlobalFilter和Ordered接口 一个过滤的方法,一个过滤顺序的方法
全局过滤器定义好后加一个 @Component 注解,然后gateway启动的时候就自动生效了
config分布式配置中心 配置可以放远程仓库
config服务器 依赖导入 主配置文件加注解 @EnableConfigServer
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
配置文件配置:
spring:
cloud:
config:
server:
git:
uri: https://gitee.com/sunny-husband/springboot_config.git
username: xxx
password: xxx
server:
port: 9999
在远程仓库的master分支下上传了一个conf.properties,用下面的地址就可以访问到
http://localhost:9999/master/conf.properties
config客户端可以直接将远程配置文件获取的配置缓存在本地,并用@Value获取. 在获取配置的类上加注解@RefreshScope 表示每次使用刷新缓存
@RefreshScope
@RestController
public class TestController {
@Value("${name}")
private String name;
config客户端配置如下
spring:
cloud:
config:
# 要与仓库中的配置文件的application保持一致
name: user
# 要与仓库中的配置文件的profile保持一致
profile: dev
# 要与仓库中的配置文件所属的版本(分支)一样
label: master
discovery:
# 使用配置中心
enabled: true
# 配置中心服务名
service-id: config-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
bus消息总线 和 config配合使用,避免配置文件发生改变,客户端需挨个手动刷新缓存
bus可以用消息中间件将分布式节点联系起来,用于广播配置文件的更改或服务的监控管理
1.在config客户端及服务端引入坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2.config客户端可以直接将远程配置文件获取的配置缓存在本地,并用@Value获取. 在获取配置的类上加注解@RefreshScope 表示每次使用刷新缓存
3.配置文件配置 rabbitmq信息
4.在config服务端 配置 bus-refresh 暴露监控断点(这样只在服务器调用一次刷新指令,bus自动通过rabbitmq向各客户端通知配置文件的变更,就不需要一个一个客户端去调用刷新的命令了)
management:
endpoints:
web:
exposure:
# 暴露触发消息总线的地址
include: bus-refresh
5.服务端要执行bus-refresh 命令,需要引入执行器依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
刷新缓存的命令为: curl -X POST http://config服务器的ip:端口/actuator/bus-refresh
stream消息驱动 目前只支持 rabbitmq和kafka 使用stream规范来开发,如果切换消息中间件则代码不需要修改,只需要修改配置文件即可
Spring Cloud Stream 构建的应用程序与消息中间件之间是通过绑定器 Binder 相关联的。绑定器对于应用程序而言起到了隔离作用, 它使得不同消息中间件的实现细节对应用程序来说是透明的。
binding 是我们通过配置把应用和spring cloud stream 的 binder 绑定在一起
output:发送消息 Channel,内置 Source接口
input:接收消息 Channel,内置 Sink接口
sleuth 和 zipkin(需执行客户端jar包,进入可视化页面) 链路追踪 sleuth收集数据 zipkin展示数据它已经依赖了sleuth
在各个模块都引入这两个的依赖,然后配置文件简单配置一下,就可以通过zipkin的图形化页面查看服务的调用关系及耗时等信息,实现链路追踪