演进史:单体架构 --- 垂直架构 --- 分布式架构 --- SOA架构 --- 微服务架构
分布式架构 :将服务拆分,每个服务都单独提供访问。
SOA架构:只要将服务注册进服务总线,就可以实现互相调用,缺点:服务总线挂掉就死了
微服务架构:只要将服务注册进服务总线,就可以实现互相之间的直接调用,并不需要总线帮我们调用。只需要记录那些服务在哪里。
1.2.1微服务理念:
①“微服务”源自Microservices的博文
②微服务是系统架构上的一种设计风格,他的主旨是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务之间一般通过HTTP的RESTful API进行通信。
restful风格:数据的增删改查,使用http的不同方式,数据传入用json
③由于有了轻量级额通信协作基础,所以这些服务可以使用不同的语言来编写
1.2.2互联网大厂架构
百度:
1.3springcloud组件
服务注册与发现:EUREKA
服务负载与调用:RIBBON、FEIGN
服务熔断降级:HYSTRIX
服务网关:Zuul
服务分布式配置“Spring Cloud Config
服务开发:springboot
2.1了解springcloud
①SpringCloud是一系列框架的有序集合
②SpringCloud将各自公司开发成熟的框架组合
③通过springboot风格进行在封装屏蔽掉复杂的配置和实现原理,形成分布式系统开发工具包
④使用springboot实现基础开发(服务发现注册,配置中心,消息总线,负载均衡,断路器,数据监控等),做到一键启动和部署
⑤SpringCloud版本命名用伦敦地铁名
2.2cloud与boot版本对比
官网查询
2.3dubbo对比
相同点:Springcloud和dubbo都是实现微服务的工具
不同点:
1.dubbo只是实现了服务治理,而springcloud子项目覆盖了微服务架构下的众多部件
2.Dubbo使用RPC通信协议,SpringCloud使用RESTful风格通信,RPC效率较高
总结:
1.微服务就是将将项目的各个模块拆分为可独立运行,部署,测试的架构设计风格
2.Spring将其他公司的微服务结构整合,并使用Springboot简化其开发配置称为SpringCloud
3.SpringCloud和Dubbo都是实现微服务有效的工具,Dubbo性能更好,而SpringCloud功能更全面,Dubbo已经融入SpringCloudAlibaba这一套中。
红色:不维护
绿色:alibaba的,推荐使用
eg:实现一个商品查询的消费者和服务者模型
新建maven工程,删除掉src包,添加父依赖
父项目右键创建子工程Module maven工程
搭建springboot工程:1.pom导包,2.配置文件 3.主启动类
Spring提供的一种简单便捷的模板类,用于在java代码里访问restful服务
其功能与HttpClient类似,但是RestTemplate实现更优雅
java http客户端有很多:httpclient、okhttp 但是麻烦:建链接 发请求 断链接
注意:
1.启动项目先设置编码settings-encoding 全部设为utf-8
2.指定maven仓库,使用本地
当把远程调用链接写死在代码,如果地址更换就不能调用,所以要用注册中心。
*Eureka是Netflix公司开源的一个服务注册与发现的组件
*Eureka和其他Netflix公司的服务组件(负载均衡,熔断器,网关)一起,被SC社区整合为Spring-cloud-Netfli模块
*Eureka包含两个组件:Eureka Service(注册中心)和Eureka Client(服务提供者,服务消费者)
①创建eureka-server模块
②引入SpringCloud和eureka-server依赖
③完成eureka Server配置
①引入erueka-client、eureka-server相关依赖
②完成eureka client相关配置
③启动测试
@Autowired
DiscoveryClient discoveryClient;
@GetMapping("/add/{id}")
public Goods add(@PathVariable("id") Integer id) {
//服务发现,通过客户端获取多个机器的实例,选择最优
List instances = discoveryClient.getInstances("EUREKA-PROVIDER");
if (instances == null || instances.size() <= 0) {
return null;
}
//通过某个策略拿到一个实例
ServiceInstance serviceInstance = instances.get(0);
String host = serviceInstance.getHost();
int port = serviceInstance.getPort();
String url = "http://" + host + ":" + port + "/goods/findById/" + id;
Goods goods = restTemplate.getForObject(url, Goods.class);
return goods;
}
Eureka包含四个部分的配置
1.instance:当前Eureka Instance实例信息配置
2.client:Eureka Client客户端特性配置
3.server:Eureka Server注册中心特性配置
4.dashboard:Eureka Server注册中心仪表盘配置
eureka客户端配置&instance实例配置 eureka: instance: hostname: localhost prefer-ip-address: true #是否将自己的ip注册到eureka中 ip-address: 127.0.0.1 #配置当前实例 # instance-id: #修改instance-id显示 lease-renewal-interval-in-seconds: 30 #每次eureka client向eureka server发送心跳的时间间隔 lease-expiration-duration-in-seconds: 90 #如果90s内server没有收到client的心跳,则删除该服务 client: service-url: defaultZone: http://localhost:8761/eureka #eureka服务端地址,将来客户端使用该地址和eureka进行通信 register-with-eureka: true #是否将自己的路径 注册到eureka上 fetch-registry: true #是否需要从eureka上抓取数据
eureka服务端配置
eureka: instance: hostname: localhost client: service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka #eureka服务端地址,将来客户端使用该地址和eureka进行通信 register-with-eureka: false #是否将自己的路径 注册到eureka上。eureka server不需要的。eureka provider client需要 fetch-registry: false #是否需要从eureka中抓取路径,eureka server不需要,eureka consumer client需要 server: enable-self-preservation: true #是否开启自我保护机制 eviction-interval-timer-in-ms: 120000 #2月清理间隔(单位毫秒 默认60*1000)
1.准备两个Eureka Server
2.分别进行配置 ,相互注册
3.Eureka Client分别注册到这两个Eureka Server中
单机需修改hosts:C:\Windows\System32\drivers\etc\hosts
127.0.0.1 eureka-server1
127.0.0.1 eureka-server2
代码:spring-cloud-demo: springcloud练习https://gitee.com/xuyu294636185/spring-cloud-demo.git
Zookeeper是一个分布式协调工具,可以实现注册中心功能。dubbo,大数据组件hadoop,hive,kafka都是zk做注册中心。
下载:https://www.apache.org/
zookeeper运行自行百度
git:spring-cloud-demo: springcloud练习https://gitee.com/xuyu294636185/spring-cloud-demo.git
Consul是由HashiCorp基于GoLanguage语言开发,支持多数据中心,分布式高可用的服务发布和注册服务软件
用于实现分布式系统的服务发现于配置
官网:http://www.consul.io/
consul使用自行百度。
7.1使用
1.准备cmd输入
consul.exe agent -dev
2.搭建provider和Consumer服务
3.使用RestTemplate完成远程调用
4.将Provider服务注册到consul中
代码:spring-cloud-demo: springcloud练习https://gitee.com/xuyu294636185/spring-cloud-demo.git
组件 | 语言 | cap理论 | 健康检查 | 暴露接口 | cloud集成 |
eureka | java | ap | 支持 | http | √ |
zookeeper | java | cp | 支持 | tcp | √ |
consul | go | cp | 支持 | http | √ |
cap:c:consustency:强一致性 a:avalibility:可用性 p:partition tolerance:分区容忍性
Netflix公司推出的http和tcp的客户端负载均衡工具
ribbon:1.简化远程调用代码 2.内置很多负载均衡算法
8.1.1服务端客户端负载均衡
负载均衡算法在服务端和客户端
服务端客户端维护服务列表
服务端负载均衡:通过域名解析+nginx做负载均衡
客户端负载均衡:通过获取列表选择调用接口
1.新版eureka依赖集成了ribbon,所以不用引用
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
2.声明restTemplate时@LoadBalance
3.restTemplate请求远程服务时,ip端口替换服务名
String url = "http://EUREKA-PROVIDER/goods/findById/" + id;
Goods goods = restTemplate.getForObject(url, Goods.class);
4.改造provider,启动两个,多次刷新可以发现ribbon默认使用轮询算法,经行负载均衡调用。
内置负载均衡规则 | 规则描述 |
RoundRobinRule | 简单轮询,ribbon默认 |
AvailabilityFilteringRule | 对以下两种服务器进行忽略:百度吧 |
WeightedResponseTimeRule | 为每个服务器赋予一个权重值,服务器响应时间越长,这个服务器的权重越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
ZoneAvoidanceRule | 以区域可用的服务器为基础的进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房,一个机架等。 |
BestAvailableRule | 忽略那些短路的服务器,并选择并发数较低的服务器 |
RandomRule | 随机选择一个可用的服务器 |
Retry | 重试机制的选择逻辑 |
1.添加配置类
@Configuration
public class MyRule {
@Bean
public IRule iRule(){
return new RandomRule();
}
}
2.启动类添加注解
@SpringBootApplication
@EnableEurekaClient //eureka客户端
@RibbonClient(name = "ERREKA-PROVIDER", configuration = MyRule.class)
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
总结:
1.irule的具体实现类,看到他的几个策略写法
2.仿照策略写法可以实现自己的策略
3.调用不同的其他微服务时可以采用不同的策略@RibbonClients
4.可以在配置文件中直接配置启动
eureka-provider:
ribbon:
NFLoadBalanceRuleClassName: com.netflix.loadbalancer.RandomRule;
Feign是一个声明式的REST客户端,他用了基于接口的注解方式,方便实现客户端配置
Feigin最初是由Netflix公司提供,但不支持SpringMVC注解,后由SpringCloud对其封装,支持了SpringMVC注解,让使用者更容易接受。
1.在消费端引入open-feign依赖
org.springframework.cloud
spring-cloud-starter-openfeign
2.编写Feign调用接口
@FeignClient("EUREKA-PROVIDER")
public interface GoodsFeign {
@GetMapping("/goods/findById/{id}")
public Goods findById(@PathVariable("id") Integer id);
}
3.在启动类上加上@EnableFeignClients注解
9.3.1超时设置
Feign底层依赖于Ribbon实现负载均衡和远程调用
Ribbon默认1秒超时
超时配置:
ribbon:
connectTimeout: 1000 #链接超时时间 默认1s
readTimeout: 3000 #逻辑处理的超时时间 默认1s
9.3.2日志记录
1.Feign只能记录debug级别的日志信息
logging:
level:
com.ydlclass: debug
2.定义feignLogConfig
@Configuration
public class FeignLogConfig {
@Bean
public Logger.Level level(){
return Logger.Level.FULL; //打印日志级别
}
}
3.启用Bean
@FeignClient(value = "EUREKA-PROVIDER", configuration = FeignLogConfig.class)
public interface GoodsFeign {
@GetMapping("/goods/findById/{id}")
public Goods findById(@PathVariable("id") Integer id);
}
重点:能让服务的调用方,够快的知道被调方挂了,不至于让用户等待。
Hystix是NetFlix开源的一个延迟和容错库,用于隔离访问远程服务,第三方库,防止出现级联失败(雪崩:一个服务失败,导致整条链路的服务都失败的情形)。
Hystix主要功能:
隔离:1.线程池隔离
2.信号量隔离
降级:异常,超时
熔断
限流(一般不用,nginx或者网关中限流)
1.添加依赖
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
2.定义降级方法,使用注解
@GetMapping("/findById/{id}")
@HystrixCommand(fallbackMethod = "findById_fallback",commandProperties = {
//设置Hystrix的超时时间,默认1s
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public Goods findById(@PathVariable("id") Integer id){
System.out.println(port);
return goodsService.findById(id);
}
/**
* 定义降级方法 返回特殊对象
* 1.方法返回值要和原方法一致
* 2.方法参数和原方法一样
*/
public Goods findById_fallback(Integer id){
Goods goods = new Goods();
goods.setGoodId(-1);
goods.setTitle("provider提供降级");
goods.setPrice(-1);
goods.setStock(-1);
return goods;
}
3.启动类添加注解开启将Hystrix功能
@EnableCircuitBreaker //开启Hystrix功能
1.feign组件已经集成了Hystrix组件
2.定义feign调用接口实现类,复写方法,即降级方法
@Component
public class GoodsFeignCallback implements GoodsFeign {
@Override
public Goods findById(Integer id) {
Goods goods = new Goods();
goods.setGoodId(-1);
goods.setTitle("调用方降级");
goods.setPrice(-1);
goods.setStock(-1);
return goods;
}
}
3.在@FeignClient注解中使用fallback属性设置降级处理类
@FeignClient(value = "EUREKA-PROVIDER", configuration = FeignLogConfig.class,fallback = GoodsFeignCallback.class)
public interface GoodsFeign {
@GetMapping("/goods/findById/{id}")
public Goods findById(@PathVariable("id") Integer id);
}
4.配置开启
#开启feign对hystrix的支持
feign:
hystrix:
enabled: true
Hystrix熔断机制,用于监控微服务调用情况,当失败的情况达到预定的阈值,会打开断路器,拒绝所有的请求,知道服务恢复为止。
@HystrixCommand(fallbackMethod = "findById_fallback",commandProperties = {
//设置Hystrix的超时时间,默认1s
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
//监控时间 默认5000毫秒
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "5000"),
//失败次数 默认50次
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "20"),
//失败率 默认50%
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50")
})
Hystrix提供了Hystrix-dashboard功能,用于实时监控微服务运行状态。但是只能监控一个微服务,Netflix还提供了Turbine,进行聚合监控。
一、搭建Turbine监控模块
1.创建监控模块
创建hytrix-monitor模块。
2.引入Turbine聚合监控起步依赖
3.添加配hi文件
4.创建启动类,添加注解
二、修改被监控模块
需要修改eureka-provider和eureka-consumer模块
1.导入依赖
2.配置Bean
3.启动类上添加@EnableHystrixDashboard
三、测试
1.启动服务:eureka-server、eureka-provider、eureka-consumer、hystrix-monitor
2.访问:hhtp://localhost:8769/hystrix进入Hystrix Dashboard界面,在监控中心输入http://localhost:8769/turbine.stream,监控时间2000ms和title
网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式
在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求。
存在的问题:
客户端多次请求不同的微服务,增加 客户端的复杂性
认证复杂,每个服务都要认证
http请求不同服务的次数增加,性能不高
网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证,鉴权,监控,缓存,负载均衡,流量监控,路由转发
在目前的网关解决方案中,有Nginx+Lua、Netflix Zuul、Spring Cloud Gateway等等
uri: http://localhost:8001/
12..4.1引入eureka-clientpeizhi
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
12.4.2修改uri属性,
uri:lb://服务名称
spring:
application:
name: api-gateway-server
cloud:
#网关配置
gateway:
# 微服务配置名
discovery:
locator:
enable: true #设置为true,请求路径前可以添加微服务名称
lower-case-service-id: true #允许为小写
维度:1.内置过滤器 自定义过滤器 2. 局部过滤器 全局过滤器
过滤器种类:内置全局,内置局部,自定义全局,自定义局部
Gateway支持过滤器功能,对请求或响应进行拦截,完成一些通用操作
Gateway提供两种过滤器方式:“pre”和“post”
pre过滤器,在转发之前执行,可以做参数校验,权限校验,流量监控,日志输出,协议转换
post 过滤器,在响应之前执行,可以做相应内容,响应头的修改,日志的输出,流量监控等
Gateway还提供两种类型过滤器
GatewayFilter:局部过滤器,针对单个路由
GlobalFilter:全部过滤器,针对所有路由
内置过滤器 局部过滤器
filters:
- AddResponseHeader=foo, bar #会在请求上加上 foo:bar
内置过滤器 全局过滤器
default-filter: #要和route同级
- AddResponseHeader=xuy,xuy
自定义过滤器 局部过滤器(麻烦,少用)
自定义过滤器 全局过滤器(鉴权,记录日志)
1.定义类实现 GlobalFilter和Ordered接口
2.复写方法
3.完成逻辑处理
@Component
public class IpFilter implements GlobalFilter, Ordered {
//业务逻辑
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//禁ip
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
InetSocketAddress remoteAddress = request.getRemoteAddress();
String hostName = remoteAddress.getHostName();
InetAddress address = remoteAddress.getAddress();
String hostAddress = address.getHostAddress();
String hostName1 = address.getHostName();
if(hostAddress.equalsIgnoreCase("1.1.1.1")){
//拒绝
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
//走完,该到下一个过滤器
return chain.filter(exchange);
}
//返回数值,越小越先执行
@Override
public int getOrder() {
return 0;
}
}
git:spring-cloud-demo: springcloud练习https://gitee.com/xuyu294636185/spring-cloud-demo.git
SpringCloud Config解决了分布式场景下多环境配置文件的管理和维护
集中管理配置文件
不同环境不同配置,动态化的配置更新
配置信息改变时,不需要重启就可以更新配置信息到服务
1.使用gitee创建远程仓库,上传配置文件
2.搭建config-server模块
3.导入config-server依赖
4.编写配置,设置gitee远程仓库
5.测试访问配置文件:http://localhost:9527/master/config-dev.yml
config-client: provider
1.导入cloud config依赖
2.创建boostrap.yml,配置configserver
若要访问生效,需config客户端更新
1.在condig客户端引入actuator依赖
2.获取配置信息类上,添加@RefreshScope注解
3.添加配置开启 endpoints
4.使用curl发送post请求: curl -X POST http://localhost:8000/actuator/refresh
远程的配置文件更新了,运维只需要发一个请求,所有用到这个配置文件的几百个应用更新。
SpringCloudBus是用轻量级的消息中间件将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理,关键的思想就是消息总线可以为微服务做监控,也可以实现应用程序之间相通信。
SpringCloudBus可选的消息中间件包括RabbitMQ和Kafka
RabbitMQ三大功能:异步,解耦,削峰填谷
RabbitMQ六种模式:简单模式,work queues,Publish/Subscribe发布订阅模式,Routing路由模式,Topics主题模式,RPC远程调用模式(不太算)。
1.分别在config-server和eureka-provider中引入bus依赖
2.分别在config-server和eureka-provider中配置RabbitMQ
3.在config-server中设置暴露监控断点:bus-refresh
#暴露bus的断点
management:
endpoint:
web:
exposure:
incloud: 'bus-refresh'
4.使用curl发送post请求: curl -X POST http://localhost:8000/actuator/bus-refresh
bus自动在mq中建立交换机
Stream解决了开发人员无感知的使用消息中间件的问题,因为Stream对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至动态的切换中间件,使得微服务开发的高度解耦。
Stream组件
SpringCLoudStream构建的应用程序与消息中间件之间是通过绑定器Binder相关联的。绑定器对于应用程序而言起到了隔离作用,它使得不同消息中间件的实现细节对应用程序来说是透明的。
binding是我们通过配置把应用和SpringCloudStream的binder绑定在一起
output:发送消息Channel,内置Source接口
input:接受消息,内置Sink接口
代码:spring-cloud-demo: springcloud练习https://gitee.com/xuyu294636185/spring-cloud-demo.git
SPringCloudSleuth其实是一个工具,他在整个分布式系统中能跟踪一个用户请求的过程,捕获这些跟踪数据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
Zipkin是Twitter的一个开源项目,它致力于收集服务的定时数据,已解决微服务架构中的延迟问题,包括数据的收集,存储,查找和展现。
1.安装启动zipkin,java-jar zipkin.jar。
2.访问zipkin界面 http://localhost:9411/
3.在服务的提供方和消费方分别引入sleuth和zipkin依赖
4.分别配置服务提供方和消费方
代码:
spring-cloud-demo: springcloud练习https://gitee.com/xuyu294636185/spring-cloud-demo.git