GateWay路由网关
一般情况下,不是所有微服务都需要直接暴露给外部调用,这时可以使用路由机制,添加一层防护,让所有请求全部通过路由来转发到各个微服务,并且转发给多个微服务实例也可以实现负载均衡。
部署网关步骤如下:
-
创建一个新模块,添加如下依赖:
xml<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>-
编写配置文件
yamlserver: port: 8500 spring: application: name: gateway-service eureka: # 修改客户端设置 client: # 指向eureka服务端 service-url: defaultZone: http://localhost:8801/eureka,http://localhost:8802/eureka-
编写启动类
java@SpringBootApplication public class AppGateway { public static void main( String[] args ) { SpringApplication.run(AppGateway.class, args); } }这时就可以启动网关服务了。
-
-
配置路由服务:
yamlspring: application: name: gateway-service cloud: gateway: # 配置路由,这是一个列表 routes: - id: borrow-service # 路由名称 uri: lb://borrow-service # 路由的地址,lb表示使用负载均衡到微服务。也可以使用HTTP正常转发 predicates: # 路由规则,断言什么请求会被路由 - Path=/borrow/** #只要是访问这个路径,一律都都被路由到上面指定的服务此时,当我们访问借阅服务时,可以直接访问
http://localhost:8500/borrow/1此时会通过网关访问borrow-service服务。而且使用原来的地址
http://localhost:8301/borrow/1也可以访问。
-
路由过滤器
路由过滤器支持以某种方式修改传入的HTTP请求或返回的HTTP响应,路由过滤器的范围是某一个理由,跟之前的断言一样。Spring Cloud Gateway 内置很多的路由过滤器。
比如我们希望在请求到达时,在请求头中添加一些信息再转发给我们的服务,这时候就可以使用路由过滤器来完成,只需要对配置文件进行修改:
yaml
spring:
application:
name: gateway-service
cloud:
gateway:
# 配置路由,这是一个列表
routes:
- id: borrow-service # 路由名称
uri: lb://borrow-service # 路由的地址,lb表示使用负载均衡到微服务。也可以使用HTTP正常转发
predicates: # 路由规则,断言什么请求会被路由
- Path=/borrow/** #只要是访问这个路径,一律都都被路由到上面指定的服务
# 继续添加新的路由配置,这里以书籍管理服务为例
- id: book-service
uri: lb://book-service
predicates:
- Path=/book/**
filters: # 添加过滤器
# 添加请求头信息
- AddRequestHeader=Test, HelloWorld!
此时通过网关访问book-service服务,会自动给请求头添加Test=HelloWorld! 信息。
访问地址是:http://localhost:8500/book/1
除了针对某一个路由配置过滤器之外,也可以自定义全局过滤器。但是需要我们编写代码,比如要实现拦截没有携带指定请求参数的请求(在gateway网关项目中编写一个类实现GlobalFilter接口):
java
@Component
public class TestFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 先获取ServerHttpRequest 对象,这里不是HttpServletRequest
ServerHttpRequest request = exchange.getRequest();
// 获取所有请求的参数
MultiValueMap<String, String> queryParams = request.getQueryParams();
// 判断是否包含test参数
List<String> test = queryParams.get("test");
if (test != null && test.contains("1")) {
// 将ServerWebExchange对象传递到下一个过滤连
return chain.filter(exchange);
}else{
// 不再向下传递,直接返回响应
return exchange.getResponse().setComplete();
}
}
}
然后重启gateway服务即可生效。
过滤器可以存在多个,我们可以指定过滤器之间的顺序,需要编写一个类,实现Ordered接口:
java
@Component
public class TestFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 先获取ServerHttpRequest 对象,这里不是HttpServletRequest
ServerHttpRequest request = exchange.getRequest();
// 获取所有请求的参数
MultiValueMap<String, String> queryParams = request.getQueryParams();
// 判断是否包含test参数
List<String> test = queryParams.get("test");
if (test != null && test.contains("1")) {
// 将ServerWebExchange对象传递到下一个过滤连
return chain.filter(exchange);
}else{
// 不再向下传递,直接返回响应
return exchange.getResponse().setComplete();
}
}
// 指定此过滤器的优先级,值越小,优先级越高
@Override
public int getOrder() {
return 0;
}
}
order值越小,优先级越高。无论全局过滤器还是配置文件中的单个过滤器,都受到order值的影响(单个路由过滤器order值从上往下的顺序从1开始递增),最终都是按order顺序执行。当order一样是,全局过滤器优先于单独的路由过滤器。
Config配置中心
微服务项目需要部署很多个实例,每个实例都有自己的配置文件,这样手动改起来非常麻烦,这时就需要一种配置文件管理工具,集中的对配置文件进行配置。
Spring cloud Config 为分布式系统中的外部配置提供服务器端和客户端的支持。使用Config Server 集中管理所有环境中应用程序的外部配置。
实际上 Spring Cloud Config就是一个配置中心,所有的服务都可以从配置中心取出配置,而配置中心又可以从Github远程仓库中获取云端的配置文件,这样只需要修改Github中的配置就可以对所有服务进行配置管理。
部署配置中心的步骤如下:
-
新建一个模块,并导入依赖:
xml<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>-
编写启动类
java@SpringBootApplication @EnableConfigServer public class AppConfig { public static void main( String[] args ) { SpringApplication.run(AppConfig.class, args); } }-
编写配置文件
yamlserver: port: 8700 spring: application: name: config-service eureka: # 修改客户端设置 client: # 指向eureka服务端 service-url: defaultZone: http://localhost:8801/eureka,http://localhost:8802/eureka
-
-
-
创建一个git本地仓库,然后再文件夹中创建一些配置文件,名称最好是【服务名称】-【环境】.yml.
然后将配置信息写入配置文件中,然后提交文件。
5. 修改git配置信息yamlspring: application: name: config-service cloud: config: server: git: # 这里是本地仓库地址,远程仓库的话直接填写远程仓库地址http://git.... uri: file://D:/1_ali/code/springCloudConfig # 设置默认分支 default-label: master然后启动config服务,可通过以下格式访问:
客户端配置
现在可以从服务器端读取配置,可以删除本地的application.yml文件(也可以不删除,这样服务器配置和本地配置都会加载),改用bootstrap.yml(在application.yml之前加载)。
-
先在微服务模块引入相关依赖:
xml<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency>-
编辑bootstrap.yml文件内容:
yamlspring: cloud: config: # 名称,其实就是文件名称 name: book-service # 配置服务器的地址 uri: http://localhost:8700 # 环境 profile: dev # 分支 label: master
-
-
启动服务即可生效。
微服务CAP原则
CAP原则又称CAP定理,指在一个分布式系统中,存在Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),三者不可同时保证。最多只能保证其中的两者。
一致性(C):分布式系统中的所有数据备份,在同一时刻都是同样的值(所有节点无论何时访问都能拿到最新的值)
可用性(A): 系统中非故障节点收到的每个请求都必须得到响应
分区容错性(P): 分布式系统中,节点之间的网络是连通的,然而可能因为一些故障(网络丢包),使节点之间不连通,导致整个网络分成了几块区域,数据就散布在了这些不联通的区域中(这样可能会导致某些分区节点的数据访问失败,我们需要容忍这些不可靠的情况)。
总的来说,数据存放的节点越多,分区容忍性越高,但是复制更新的次数就越多,一致性就会降低。同时为了保持一致性,更新所有节点数据所需要的时间就越长,那么可用性就会降低。
所以说,只能存在以下三种方案:
选型 特点 典型系统 适用场景 CP 分区时强一致,但可能拒绝请求(不可用) ZooKeeper、etcd、HBase 金融、支付、配置中心 AP 分区时高可用,但数据可能不一致(最终一致) Cassandra、DynamoDB、Redis 集群 电商、社交、缓存 CA 放弃 P,仅在无分区时同时满足 C 和 A 单机数据库、小型局域网 非分布式、无网络风险场景 -