微服务
微服务 将all in one的项目拆分,可以按业务拆分成独立的模块等,降低模块与模块之间的耦合性,每个微服务还能有自己独立的数据库。每个微服务在自己独立的进程中运行,不会互相干扰。异构。支持不同语言、不同类型的数据库
集群:一组集成的计算机软件连接起来
- 高性能:多台计算机完成同一工作,分摊压力
- 高可用:多台计算机工作内容、过程一致,可以相互顶替
分布式:一组计算机通过网络通信协调它们之间的行为。组件之间交互来实现一个共同的目标。
- 低耦合:模块间独立,易扩展,提高资源利用率
- 高吞吐:功能拆分,分散到不同的模块执行
集群和分布式不冲突。分布式的某个需要扩展的模块可以使用集群。
CAP:强一致性C、极致可用性A、分区容错性P。这三个不能同时满足。
微服务的特点:
- 一系列微小的服务共同组成
- 单独部署,跑在自己的进程里
- 每个服务是独立的业务开发
- 分布式的管理
不适合微服务的:
- 系统中包含很多很多强事务场景的
- 业务相对稳定,迭代周期长
- 访问压力不大,可用性不高
服务拆分的方法:
- 如何拆“功能:
- 单一职责,松耦合、高内聚
- 关注点分离
- 按职责
- 按通用性
- 按粒度级别
- 服务和数据的关系
- 先考虑业务功能,再考虑数据
- 无状态服务(数据不被服务依赖)
微服务架构
这是一种新型、轻量的架构,利用REST API来保持微服务之间的通信。与dubbo不同的是,dubbo用的是rpc通信。
维度:开发、配置与管理、消息队列、服务接口调用、治理、注册与发现、负载均衡、监控。。。。
SpringCloud微服务架构:
这里面的常用组件:
- 服务治理:Spring Cloud Eureka
- 负载均衡:Spring Cloud Ribbon
- 熔断限流:Spring Cloud Hystrix
- 服务调用:Spirng Cloud Feign
- 网关服务:Spring Cloud Zuul/Gateway
- 配置中心:Spring Cloud Config
- 消息总线:Spring Cloud Bus
- 消息驱动:Spring Cloud Stream
- 服务追踪:Spring Cloud Sleuth
Spring Cloud网关 (Zuul/GateWay)
应用场景:统一外部入口、请求路由、认证授权、请求限流、请求日志和监控
SpringCloud Zuul功能:①服务路由,②自定义过滤器,需要继承ZuulFilter并重写方法。下面的Autorizefilter模拟身份验证功能,它继承了ZuulFilter抽象类,重写了filterType filterOrder shouldFilter run方法
@Component
public class Authorizefilter extends ZuulFilter {
private static final Logger logger = LoggerFactory.getLogger(Authorizefilter.class);
private static String access_token;
public Authorizefilter(){
access_token = UUID.randomUUID().toString();
logger.info(access_token+"-==========----------");
}
/**
* 外部请求-> zuul-(pre) ->选择路由的服务-(routing) ->请求服务-(post) ->zuul
* pre:在请求路由之前执行
* routing:在请求路由之后执行
* post:在请求路由到服务之后执行
* error:在其他阶段发生错误的时候执行
* @return 过滤器的类型是什么
*/
@Override
public String filterType() {
return "pre";
}
/**
*
* @return 过滤器执行的顺序
*/
@Override
public int filterOrder() {
return 0;
}
/**
*
* @return 是否执行过滤器
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 具体逻辑
* @return Some arbitrary artifact may be returned. Current implementation ignores it.
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String access_token = request.getParameter("access_token");
// 模拟授权
if (Objects.equals(access_token,Authorizefilter.access_token)){
requestContext.setResponseStatusCode(HttpStatus.OK.value());
requestContext.setResponseBody("Authorize");
requestContext.setSendZuulResponse(false);
}else {
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
requestContext.setResponseBody(HttpStatus.UNAUTHORIZED.getReasonPhrase());
requestContext.setSendZuulResponse(false);
}
return null;
}
}
Spring Cloud GateWay出现是由于Zuul 在2版本后不维护了,它是zuul的扩展。
SpringCloud服务治理 (Eureka/Consul)
- Eureka Client:服务注册
- Eureka Server:服务发现
Eureka:保证了高可用性A
- 服务注册快,不需要等待注册信息复制到其他节点,也不保证复制成功
- 当注册信息不相同时,每个Eureka节点依然能够正常对外提供服务
Consul:保证强一致性C
- 服务注册相比Eureka会稍慢,Consul要求过半的节点都写入成功
- Leader挂掉时,在有新的Leader之前整个Consul不可用
对Eureka Server端的application使用@EnableEurekaServer注解表示加载EurekaServer的配置;
在客户端Client,对application使用@EnableDiscoveryClient注解表示加载EnableDiscoveryClientImportSelector的配置,用于被Service发现
服务发现的两种方式:客户端发现(Eureka),服务器发现(Nginx、Zookeeper、Kubernetes)
SpringCloud服务调用(Feign)
- RestTemplate 利用它的public
T getForObject(String url, Class responseType, Object... uriVariables) throws RestClientException方法 获取url地址对应接口的返回对象,后面的uriVariables是url中的参数;url中的ip可以为通信服务的application name - Feign
- 需要在Application上添加@EnableFeignClients
- 自定义一个接口,添加@FeignClient(name = "application name")注解,并且写出想要使用服务的接口
Feign 采用了基于注解的接口,是声明式REST客户端(虽然在他的接口中看不到http请求)
SpringCloud 配置中心(Config)
为啥使用配置中心?
当把配置文件都放在项目包下,不方便之后的维护;需要测试时,对配置文件修改之后,不方便另外的人员维护;配置内容中数据库的账号密码不能随意暴露给开发者;更新配置项目需要重启。
统一配置中心?
- config-server 从远端git pull下来放在本地git;如果远端git挂掉,可以使用本地git
如何配置?
-
配置Config的Server端
配置pom文件,加入spring-cloud-config-server依赖和spring-cloud-starter-netflix-eureka-client依赖
给Application文件添加@EnableConfigServer和@EnableDiscoveryClient(将它注册)
-
添加yml配置,下面的配置中basedir的目录是远程的配置拉下来的所在文件夹
spring: application: name: config cloud: config: server: git: uri: https://gitee.com/luotianhao25182/config username: 18235190623 password: iamlth0539cro basedir: F://config eureka: client: service-url: defaultZone: http://localhost:8761/eureka/
远端的配置文件的命名要对应它的application name。在配置服务器端使用url访问加上如/{name}-{profiles}.yml或/{label}/{name}-{profiles}.yml来访问远端的配置文件。
-
配置config的客户端
给pom添加spring-cloud-config-client依赖
给Application添加@EnableDiscoveryClient注解,将服务客户端注册
-
将原来的application.yml改名为bootstrap.yml,并添加如下内容。其中的enabled表示需要从配置服务端拿配置,service-id的内容表示的是配置服务中心的application name
spring: application: name: client cloud: config: discovery: enabled: true service-id: CONFIG
配置服务中心可以看作: 远端git仓库——配置中心服务端——配置客户端
在远端git仓库中,最好是将一个服务共有的配置提取出来为 如client.yml,再将不同配置放入如client-dev.yml等中。为什么要这样做?因为配置客户端会将远端的带client命名的所有yml拉下来并且合并起来,所以如果两个配置文件一样,你只改了其中一个文件是等于无效的。
SpringCloud配置中心配置同步
当我们在远端git仓库上修改了配置文件之后,其实我们的配置服务端并没有做出响应,那么也就没有说把新的配置文件传给下面的配置客户端,我们只能通过重启配置服务器来同步。但是这样做显得过于不便,现在可以使用Bus这个组件来实现配置中心配置同步。