文章目录
1.架构的演变
传统架构–>水平拆分–>垂直拆分(最早的分布式)–>soa(dubbo)–>微服务(springCloud)
2.远程调用技术:rpc http
- rpc协议(传输层):自定义数据格式,限定技术,传输速度快,效率高 tcp,dubbo
http协议(应用层):统一的数据格式,不限定技术 rest接口 tcp协议 springCloud
Http客户端工具
既然微服务选择了Http,那么我们就需要考虑自己来实现对请求和响应的处理。不过开源世界已经有很多的http客户端工具,能够帮助我们做这些事情,例如:
- HttpClient
- OKHttp
- URLConnection
HttpClient远程调用技术
官网地址:http://hc.apache.org/index.html
Test/:导入资料提供的demo工程:《http-demo》
发起get请求:
发起Post请求:
序列化/反序列化
使用JacksonJson工具是SpringMVC内置的json处理工具,其中有一个
ObjectMapper
类
// 序列化
String json = mapper.writeValueAsString(user);
// 反序列化,接收两个参数:json数据,反序列化的目标类字节码
User result = mapper.readValue(json, User.class);
Spring的RestTemplate
Spring提供了一个RestTemplate模板工具类,对基于Http的客户端进行了封装,并且实现了对象与json的序列化和反序列化,非常方便。RestTemplate并没有限定Http的客户端类型,而是进行了抽象
首先在项目中注册一个RestTemplate对象,可以在启动类位置注册:
@SpringBootApplication
public class HttpDemoApplication {
public static void main(String[] args) {
SpringApplication.run(HttpDemoApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
// 默认的RestTemplate,底层是走JDK的URLConnection方式。
return new RestTemplate();
}
}
在测试类中直接@Autowired注入:
@Autowired
private RestTemplate restTemplate;
通过RestTemplate的getForObject()方法,传递url地址及实体类的字节码,RestTemplate会自动发起请求,接收响应,并且帮我们对响应结果进行反序列化。
3.什么是springCloud
官网地址:http://projects.spring.io/spring-cloud/
1.引入组件的启动器
2.覆盖默认配置
3.在引导类上添加注解,开发相关组件
Map<serviceId, Map<服务实例名,实例对象(instance)>>
微服务架构的解决方案,是很多组件的集合
eureka:注册中心,服务的注册与发现
zull:服务网关协议,路由请求,过滤器(ribbon hystrix)
ribbon:负载均衡组件
hystrix:熔断组件
feign:远程服务调用组件(ribbon hystrix)
组合注解@SpringCloudApplication
@EnableCircuitBreaker
@SpringBootApplication
@EnableDiscveryClient
传统的分布式
启动类
服务提供者:一个Provide
服务调用者:一个Consumer 调用Url
- 在consumer中,我们把url地址硬编码到了代码中,不方便后期维护
- consumer需要记忆user-service的地址,如果出现变更,可能得不到通知,地址将失效
- consumer不清楚user-service的状态,服务宕机也不知道
- user-service只有1台服务,不具备高可用性
- 即便user-service形成集群,consumer还需自己实现负载均衡
概括一下就是分布式服务必然要面临的问题:
- 服务管理
- 如何自动注册和发现
- 如何实现状态监管
- 如何实现动态路由
- 服务如何实现负载均衡
- 服务如何解决容灾问题
- 服务如何实现统一配置
以上的问题,我们都将在SpringCloud中得到答案。
*4.eureka
Eureka架构中的三个核心角色:
- 服务注册中心
Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-demo
注册中心:eureka
(1.引入启动器,
2.配置spring.application.name=eureka
3.在引导类上@EnableEurekaServer)
- 服务端(服务提供者)
提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。本例中就是我们实现的user-service-demo
1.引入服务端启动器:eureka-server
2.添加了配置
- spring. application. name: eureka-server # 应用名称,会在Eureka中显示
- eureka.client.service-url.defaultZone:http://localhost:10086/eureka
- eureka.server.eviction-interval-timer-in-ms://剔除无效连接的间隔时间
- eureka.server.enable-self-preservation//关闭自我保护
3.@EnableEurekaServer//开启eureka服务端功能
- 客户端(服务消费者)
消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。本例中就是我们实现的consumer-demo
客户端:service-provider service-consumer
(1.引入启动器:eureka-client
2.配置spring.application.name eureka.client.service-url.defaultZone=http://localhost:10086/eureka
心跳时间
过期时间
是否注册给eureka容器
是否拉取服务列表
拉取服务的间隔时间
3.@EnableDiscoveryClient(启用eureka客户端))
高可用:可复制eurek配置文件注册多个服务注册中心
抵抗高并发可能出现的宕机
5.Ribbon
ribbon: 负载均衡组件
eureka、feign以及zuul已集成
1.eureka集成了
2.@LoadBalanced:开启负载均衡在RestTemplate的@Bean方法上
3.this.restTemplate.getForObject(“http://service-provider/user/” + id, User.class);
负载均衡策略
Ribbon默认的负载均衡策略是简单的轮询(轮流)
SpringBoot也帮我们提供了修改负载均衡规则的配置入口,在service-consumer的application.yml中添加如下配置:
<服务名>.ribbon.NFLoadBalancerRuleClassName:负载均衡策略的全路径
格式是:{服务名称}.ribbon.NFLoadBalancerRuleClassName,值就是IRule的实现类。
6.Hystrix
:容错组件
降级
:检查每次请求,是否请求超时,或者连接池已满
- 1.引入hystrix启动器
- 2.添加配置,超时时间的配置(熔断时间),默认1s, 测试可以设置6s
- 3.在引导类上添加了一个注解:@EnableCircuitBreaker//启用熔断组件
组合注解@SpringCloudApplication - 4.定义熔断方法:
- 局部(要和被熔断的方法返回值和参数列表一致)
在被熔断的方法上@HystrixCommand(fallbackMethod=“熔断方法名”)
-全局(返回值类型要被熔断的方法一致,参数列表必须为空)
在类上@DefaultProperties(defaultFallbck=“全局熔断方法名”)
在具体的被熔断方法上@HystrixCommand
5.@HystrixCommand(fallbackMethod=“局部熔断方法名”):声明被熔断的方法
6.@DefaultProperties(defaultFallback=“全局熔断方法名”)
熔断
:不再发送请求
1.close:闭合状态,所有请求正常方法
2.open:打开状态,所有请求都无法访问。
触发:如果在一定时间内容,失败的比例不小于50%或者次数不少于20次
3.half open:半开状态,打开状态默认5s休眠期,在休眠期所有请求无法正常访问。过了休眠期会进入半开状态,放部分请求通过.
正常close;不正常open
*7.Feign(伪装)
feign
1.引入启动器
2.覆盖默认配置
3.在引导类上添加注解@EnableFeignClients
4.代码中使用feign
1)定义client接口
2)在接口上添加注解@feignClient ("item-service")
3)添加方法,方法使用的都是springMVC的注解
远程调用组件:集成ribbon和hystrix
不使用原始的RestTemplate,使代码更加优雅
1.引入openFeign启动器
2.feign.hystrix.enable=true,开启feign的熔断功能
3.在引导类上启用feign组件 @EnableFeignClients
4.创建一个接口,在接口添加@FeignClient(value=“服务id”, fallback=实现类.class)
5.在接口中定义一些方法,这些方法的书写方式跟之前controller类似 //实战中在接口上不要加@rm
6.创建了一个熔断类,实现feign接口,实现对应的方法,这些实现方法就是熔断方法(ctrl+T)
@component注入Spring容器
*8.Zuul网关
路由
-
1.引入zuul的启动器
-
2.配置
- 路由前缀:zuul.prefix
四种路由配置方式:
- 路由前缀:zuul.prefix
zuul.routes.<路由名称>.path=/service-provider/**
zuul.routes.<路由名称>.url=http://localhost:8082
zuul.routes.<路由名称>.path=/service-provider/**
zuul.routes.<路由名称>.serviceId=service-provider
zuul.routes.服务名=/service-provider/**
不用配置,默认服务的入口就是以服务名为前缀(默认就是服务id开头路径)
3.@EnableZuulProxy //开启zuul网关组件
过滤器
:
创建一个类继承ZuulFilter基类
重写四个方法
filterType:pre ->route ->post error
filterOrder:返回值越小优先级越高
shouldFilter:是否执行run方法。true执行
run:具体的拦截逻辑
- 网关的职责:
1)路由
把不同的路径映射到对应的服务的实例
zuul:
routes:
user-service: /user-service/**
2)负载均衡
通过Eureka根据服务名获取服务实例列表
再通过Ribbon实现负载均衡
3)鉴权
过滤器类型:pre、routing、post、error
通过前置过滤器,在路由之前判 断是否有访问的权限
用户请求 ---> Zuul --路由--> 微服务